Changes by: flatcap
Update of /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs
In directory usw-pr-cvs1:/tmp/cvs-serv25998
Modified Files:
aops.c attrib.c attrib.h compress.c dir.c inode.c mft.c ntfs.h
super.c types.h volume.h
Log Message:
merge the gcc-2.95 and Anton's changes into the trunk
Index: aops.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/aops.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -U2 -r1.54 -r1.55
--- aops.c 25 Feb 2002 04:00:58 -0000 1.54
+++ aops.c 4 Mar 2002 22:56:14 -0000 1.55
@@ -101,5 +101,7 @@
/* Convert the vcn to the corresponding logical cluster number (lcn). */
- lcn = vcn_to_lcn(ni->run_list, vcn);
+ read_lock(&ni->run_list.lock);
+ lcn = vcn_to_lcn(ni->run_list.rl, vcn);
+ read_unlock(&ni->run_list.lock);
/* Successful remap. */
if (lcn >= 0) {
@@ -296,5 +298,7 @@
return 0;
}
- lcn = vcn_to_lcn(vol->mftbmp_rl, vcn);
+ read_lock(&vol->mftbmp_rl.lock);
+ lcn = vcn_to_lcn(vol->mftbmp_rl.rl, vcn);
+ read_unlock(&vol->mftbmp_rl.lock);
ntfs_debug("lcn = 0x%Lx.", (long long)lcn);
if (lcn < 0LL) {
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/attrib.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -U2 -r1.67 -r1.68
--- attrib.c 25 Feb 2002 04:30:08 -0000 1.67
+++ attrib.c 4 Mar 2002 22:56:14 -0000 1.68
@@ -27,6 +27,8 @@
/**
* rl_mm - run_list memmove
+ *
+ * It is up to the caller to serialize access to the run list @base.
*/
-static inline void rl_mm (run_list *base, int dst, int src, int size)
+static inline void rl_mm(run_list_element *base, int dst, int src, int size)
{
if ((dst != src) && (size > 0))
@@ -36,7 +38,10 @@
/**
* rl_mc - run_list memory copy
+ *
+ * It is up to the caller to serialize access to the run lists @dstbase and
+ * @srcbase.
*/
-static inline void rl_mc (run_list *dstbase, int dst, run_list *srcbase,
- int src, int size)
+static inline void rl_mc(run_list_element *dstbase, int dst,
+ run_list_element *srcbase, int src, int size)
{
if (size > 0)
@@ -54,4 +59,6 @@
* memory, this function returns and entire page of memory.
*
+ * It is up to the caller to serialize access to the run list @orig.
+ *
* N.B. If the new allocation doesn't require a different number of pages in
* memory, the function will return the original pointer.
@@ -62,7 +69,8 @@
* -EINVAL, Invalid parameters were passed in.
*/
-static inline run_list * ntfs_rl_realloc (run_list *orig, int old, int new)
+static inline run_list_element *ntfs_rl_realloc(run_list_element *orig,
+ int old, int new)
{
- run_list *nrl;
+ run_list_element *nrl;
old = PAGE_ALIGN (old * sizeof (run_list));
@@ -90,8 +98,10 @@
* must be adjacent.
*
+ * It is up to the caller to serialize access to the run lists @one and @two.
+ *
* Return: TRUE Success, the run_lists were merged
* FALSE Failure, the run_lists were not merged
*/
-static inline BOOL ntfs_rl_merge (run_list *one, run_list *two)
+static inline BOOL ntfs_rl_merge(run_list_element *one, run_list_element *two)
{
BUG_ON (!one || !two);
@@ -117,7 +127,9 @@
*
* Append a run_list after element @loc in @orig. Merge the right end of
- * the new run_list, if necesary. Adjust the size of the hole before the
+ * the new run_list, if necessary. Adjust the size of the hole before the
* appended run_list.
*
+ * It is up to the caller to serialize access to the run lists @orig and @new.
+ *
* Return: Pointer, The new, combined, run_list
*
@@ -125,13 +137,13 @@
* -EINVAL, Invalid parameters were passed in.
*/
-static inline run_list * ntfs_rl_append (run_list *orig, int osize,
- run_list *new, int nsize, int loc)
+static inline run_list_element *ntfs_rl_append(run_list_element *orig,
+ int osize, run_list_element *new, int nsize, int loc)
{
- run_list *res;
+ run_list_element *res;
BOOL right;
BUG_ON (!orig || !new);
- /* First, merge the right hand end, if necesary. */
+ /* First, merge the right hand end, if necessary. */
right = ntfs_rl_merge (new + nsize - 1, orig + loc + 1);
@@ -164,7 +176,9 @@
*
* Insert a run_list before element @loc in @orig. Merge the left end of
- * the new run_list, if necesary. Adjust the size of the hole after the
+ * the new run_list, if necessary. Adjust the size of the hole after the
* inserted run_list.
*
+ * It is up to the caller to serialize access to the run lists @orig and @new.
+ *
* Return: Pointer, The new, combined, run_list
*
@@ -172,8 +186,8 @@
* -EINVAL, Invalid parameters were passed in.
*/
-static inline run_list * ntfs_rl_insert (run_list *orig, int osize,
- run_list *new, int nsize, int loc)
+static inline run_list_element *ntfs_rl_insert(run_list_element *orig,
+ int osize, run_list_element *new, int nsize, int loc)
{
- run_list *res;
+ run_list_element *res;
BOOL left = FALSE;
BOOL disc = FALSE; /* Discontinuity */
@@ -253,5 +267,7 @@
*
* Replace the run_list at @loc with @new. Merge the left and right ends of
- * the inserted run_list, if necesary.
+ * the inserted run_list, if necessary.
+ *
+ * It is up to the caller to serialize access to the run lists @orig and @new.
*
* Return: Pointer, The new, combined, run_list
@@ -260,8 +276,8 @@
* -EINVAL, Invalid parameters were passed in.
*/
-static inline run_list * ntfs_rl_replace (run_list *orig, int osize,
- run_list *new, int nsize, int loc)
+static inline run_list_element *ntfs_rl_replace(run_list_element *orig,
+ int osize, run_list_element *new, int nsize, int loc)
{
- run_list *res;
+ run_list_element *res;
BOOL left = FALSE;
BOOL right;
@@ -303,4 +319,6 @@
* run_lists is necessary. Adjust the size of the holes either side.
*
+ * It is up to the caller to serialize access to the run lists @orig and @new.
+ *
* Return: Pointer, The new, combined, run_list
*
@@ -308,8 +326,8 @@
* -EINVAL, Invalid parameters were passed in.
*/
-static inline run_list * ntfs_rl_split (run_list *orig, int osize,
- run_list *new, int nsize, int loc)
+static inline run_list_element *ntfs_rl_split(run_list_element *orig, int osize,
+ run_list_element *new, int nsize, int loc)
{
- run_list *res;
+ run_list_element *res;
BUG_ON (!orig || !new);
@@ -341,4 +359,6 @@
* or completely within a hole in @drl.
*
+ * It is up to the caller to serialize access to the run lists @drl and @srl.
+ *
* Merging of run lists is necessary in two cases:
* 1. When attribute lists are used and a further extent is being mapped.
@@ -361,7 +381,7 @@
* -ERANGE, The run_lists overlap and cannot be merged.
*/
-run_list * merge_run_lists (run_list *drl, run_list *srl)
+run_list_element *merge_run_lists(run_list_element *drl, run_list_element *srl)
{
- run_list *nrl; /* New run list. */
+ run_list_element *nrl; /* New run list. */
int di, si; /* Current index into @[ds]rl. */
int sstart; /* First index with lcn > LCN_RL_NOT_MAPPED. */
@@ -530,4 +550,6 @@
* longer valid.
*
+ * It is up to the caller to serialize access to the run list @old_rl.
+ *
* Check the return value for error with IS_ERR(ret_val). If this is FALSE,
* the function was successful, the return value is the new run list, and if
@@ -547,12 +569,12 @@
* run list if overlap present and return error).
*/
-run_list *decompress_mapping_pairs(const ntfs_volume *vol,
- const ATTR_RECORD *attr, run_list *old_rl)
+run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
+ const ATTR_RECORD *attr, run_list_element *old_rl)
{
VCN vcn; /* Current vcn. */
LCN lcn; /* Current lcn. */
s64 deltaxcn; /* Change in [vl]cn. */
- run_list *rl = NULL; /* The output run_list. */
- run_list *rl2; /* Temporary run_list. */
+ run_list_element *rl = NULL; /* The output run_list. */
+ run_list_element *rl2; /* Temporary run_list. */
u8 *buf; /* Current position in mapping pairs array. */
u8 *attr_end; /* End of attribute. */
@@ -773,5 +795,4 @@
attr_search_context *ctx;
MFT_RECORD *mrec;
- run_list *rl;
const uchar_t *name;
u32 name_len;
@@ -810,7 +831,25 @@
}
- /* Decode the run list. */
- rl = decompress_mapping_pairs(ni->vol, ctx->attr, ni->run_list);
+ /* Lock the run list. */
+ write_lock(&ni->run_list.lock);
+ /* Make sure someone else didn't do the work while we were spinning. */
+ if (likely(vcn_to_lcn(ni->run_list.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
+ run_list_element *rl;
+
+ /* Decode the run list. */
+ rl = decompress_mapping_pairs(ni->vol, ctx->attr,
+ ni->run_list.rl);
+
+ /* Flag any errors or set the run list if successful. */
+ if (unlikely(IS_ERR(rl)))
+ err = PTR_ERR(rl);
+ else
+ ni->run_list.rl = rl;
+ }
+
+ /* Unlock the run list. */
+ write_unlock(&ni->run_list.lock);
+
put_attr_search_ctx(ctx);
@@ -819,12 +858,6 @@
/* If an error occured, return it. */
- if (IS_ERR(rl))
- return PTR_ERR(rl);
-
- /* Everything ok, set the run list. */
- ni->run_list = rl;
-
ntfs_debug("Done.");
- return 0;
+ return err;
unm_err_out:
@@ -842,4 +875,6 @@
* corresponding lcns.
*
+ * It is up to the caller to serialize access to the run list @rl.
+ *
* Since lcns must be >= 0, we use negative return values with special meaning:
*
@@ -852,5 +887,5 @@
* -4 = LCN_EINVAL Input parameter error (if debug enabled).
*/
-LCN vcn_to_lcn(const run_list *rl, const VCN vcn)
+LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn)
{
int i;
@@ -1058,7 +1093,10 @@
* Note, @size does not need to be a multiple of the cluster size.
*
+ * It is up to the caller to serialize access to the run list @rl.
+ *
* Return 0 on success or -errno on error.
*/
-int load_attribute_list(ntfs_volume *vol, run_list *rl, u8 *al, const s64 size)
+int load_attribute_list(ntfs_volume *vol, run_list_element *rl, u8 *al,
+ const s64 size)
{
LCN lcn;
Index: attrib.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/attrib.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -U2 -r1.16 -r1.17
--- attrib.h 25 Feb 2002 04:00:58 -0000 1.16
+++ attrib.h 4 Mar 2002 22:56:14 -0000 1.17
@@ -67,10 +67,10 @@
} attr_search_context;
-extern run_list *decompress_mapping_pairs(const ntfs_volume *vol,
- const ATTR_RECORD *attr, run_list *run_list);
+extern run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
+ const ATTR_RECORD *attr, run_list_element *old_rl);
extern int map_run_list(ntfs_inode *ni, VCN vcn);
-extern LCN vcn_to_lcn(const run_list *rl, const VCN vcn);
+extern LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn);
extern BOOL find_attr(const ATTR_TYPES type, const uchar_t *name,
@@ -82,5 +82,5 @@
const u32 val_len, attr_search_context *ctx);
-extern int load_attribute_list(ntfs_volume *vol, run_list *rl, u8 *al,
+extern int load_attribute_list(ntfs_volume *vol, run_list_element *rl, u8 *al,
const s64 size);
Index: compress.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/compress.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -U2 -r1.33 -r1.34
--- compress.c 25 Feb 2002 04:00:58 -0000 1.33
+++ compress.c 4 Mar 2002 22:56:14 -0000 1.34
@@ -119,4 +119,7 @@
* @cb_size: size of compression block @cb_start in bytes (IN)
*
+ * The caller must have disabled preemption. ntfs_decompress() reenables it when
+ * the critical section is finished.
+ *
* This decompresses the compression block @cb_start into the array of
* destination pages @dest_pages starting at index @dest_index into @dest_pages
@@ -136,6 +139,6 @@
* unpredicatbly! You have been warned!
*
- * Note: This function may not sleep until it has finished accessing the
- * compression block @cb_start.
+ * Note to hackers: This function may not sleep until it has finished accessing
+ * the compression block @cb_start as it is a per-CPU buffer.
*/
static int ntfs_decompress(struct page *dest_pages[], int *dest_index,
@@ -186,4 +189,6 @@
err = 0;
return_error:
+ /* We can sleep from now on, so we reenable preemption. */
+ preempt_enable();
/* Second stage: finalize completed pages. */
for (i = 0; i < nr_completed_pages; i++) {
@@ -565,5 +570,7 @@
}
/* Find lcn of vcn and convert it into blocks. */
- lcn = vcn_to_lcn(ni->run_list, vcn);
+ read_lock(&ni->run_list.lock);
+ lcn = vcn_to_lcn(ni->run_list.rl, vcn);
+ read_unlock(&ni->run_list.lock);
ntfs_debug("Reading vcn = 0x%Lx, lcn = 0x%Lx.",
(long long)vcn, (long long)lcn);
@@ -624,8 +631,7 @@
* Get the compression buffer corresponding to the current CPU. We must
* not sleep any more until we are finished with the compression buffer.
- * If on a preemptible kernel, disable preemption.
+ * If on a preemptible kernel, now disable preemption.
*/
- // preempt_disable();
- // don't forget preempt_enable(); later!
+ preempt_disable();
cb = ntfs_compression_buffers[smp_processor_id()];
@@ -663,5 +669,6 @@
/* Sparse cb, zero out page range overlapping the cb. */
ntfs_debug("Found sparse compression block.");
- /* We can sleep from now on. */
+ /* We can sleep from now on, so we reenable preemption. */
+ preempt_enable();
if (cb_max_ofs)
cb_max_page--;
@@ -744,5 +751,7 @@
cur_ofs = cb_max_ofs;
}
- /* We can sleep from now on. Second stage: finalize pages. */
+ /* We can sleep from now on, so we reenable preemption. */
+ preempt_enable();
+ /* Second stage: finalize pages. */
for (; cur2_page < cb_max_page; cur2_page++) {
page = pages[cur2_page];
@@ -771,5 +780,8 @@
cb_max_page, cb_max_ofs, xpage, &xpage_done,
cb_pos, cb_size - (cb_pos - cb));
- /* We can sleep from now on. */
+ /*
+ * We can sleep from now on, preemption already reenabled by
+ * ntfs_decompess.
+ */
if (err) {
ntfs_error(vol->sb, "ntfs_decompress() failed with "
Index: dir.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/dir.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -U2 -r1.47 -r1.48
--- dir.c 25 Feb 2002 04:00:58 -0000 1.47
+++ dir.c 4 Mar 2002 22:56:14 -0000 1.48
@@ -82,5 +82,5 @@
ctx)) {
ntfs_error(sb, "Index root attribute missing in directory "
- "inode %Li.",
+ "inode 0x%Lx.",
(unsigned long long)dir_ni->mft_no);
err = -EIO;
@@ -189,6 +189,6 @@
if (!NInoIndexAllocPresent(dir_ni)) {
ntfs_error(sb, "No index allocation attribute but index entry "
- "requires one. Directory inode %Li is corrupt "
- "or driver bug.",
+ "requires one. Directory inode 0x%Lx is "
+ "corrupt or driver bug.",
(unsigned long long)dir_ni->mft_no);
err = -EIO;
@@ -219,5 +219,5 @@
if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) {
ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
- "inode %Li or driver bug.",
+ "inode 0x%Lx or driver bug.",
(unsigned long long)dir_ni->mft_no);
err = -EIO;
@@ -225,7 +225,8 @@
}
if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
- ntfs_error(sb, "Actual VCN (%Li) of index buffer is different "
- "from expected VCN (%Li). Directory inode %Li "
- "is corrupt or driver bug.",
+ ntfs_error(sb, "Actual VCN (0x%Lx) of index buffer is "
+ "different from expected VCN (0x%Lx). "
+ "Directory inode 0x%Lx is corrupt or driver "
+ "bug.",
(long long)sle64_to_cpu(ia->index_block_vcn),
(long long)vcn,
@@ -236,8 +237,8 @@
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
dir_ni->_IDM(index_block_size)) {
- ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %Li "
- "has a size (%u) differing from the directory "
- "specified size (%u). Directory inode is "
- "corrupt or driver bug.",
+ ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode "
+ "0x%Lx has a size (%u) differing from the "
+ "directory specified size (%u). Directory "
+ "inode is corrupt or driver bug.",
(long long)vcn,
(unsigned long long)dir_ni->mft_no,
@@ -249,7 +250,7 @@
index_end = (u8*)ia + dir_ni->_IDM(index_block_size);
if (index_end > kaddr + PAGE_CACHE_SIZE) {
- ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %Li "
- "crosses page boundary. Impossible! Cannot "
- "access! This is probably a bug in the "
+ ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode "
+ "0x%Lx crosses page boundary. Impossible! "
+ "Cannot access! This is probably a bug in the "
"driver.", (long long)vcn,
(unsigned long long)dir_ni->mft_no);
@@ -259,6 +260,6 @@
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
if (index_end > (u8*)ia + dir_ni->_IDM(index_block_size)) {
- ntfs_error(sb, "Size of index buffer (VCN %Li) of directory "
- "inode %Li exceeds maximum size.",
+ ntfs_error(sb, "Size of index buffer (VCN 0x%Lx) of directory "
+ "inode 0x%Lx exceeds maximum size.",
(long long)vcn,
(unsigned long long)dir_ni->mft_no);
@@ -281,5 +282,5 @@
index_end) {
ntfs_error(sb, "Index entry out of bounds in "
- "directory inode %Li.",
+ "directory inode 0x%Lx.",
(unsigned long long)dir_ni->mft_no);
err = -EIO;
@@ -366,5 +367,5 @@
if ((ia->index.flags & NODE_MASK) == LEAF_NODE) {
ntfs_error(sb, "Index entry with child node found in "
- "a leaf node in directory inode %Li.",
+ "a leaf node in directory inode 0x%Lx.",
(unsigned long long)dir_ni->mft_no);
err = -EIO;
@@ -386,5 +387,5 @@
}
ntfs_error(sb, "Negative child node vcn in directory inode "
- "%Li.", (unsigned long long)dir_ni->mft_no);
+ "0x%Lx.", (unsigned long long)dir_ni->mft_no);
err = -EIO;
goto unm_unm_err_out;
@@ -420,9 +421,18 @@
} INDEX_TYPE;
-/*
+/**
+ * ntfs_filldir - ntfs specific filldir method
+ * @vol: current ntfs volume
+ * @filp: open file descriptor for the current directory
+ * @ndir: ntfs inode of current directory
+ * @index_type: specifies whether @iu is an index root or an index allocation
+ * @iu: index root or index allocation attribute to which @ie belongs
+ * @ie: current index entry
+ * @name: buffer to use for the converted name
+ * @dirent: vfs filldir callback context
+ * filldir: vfs filldir callback
+ *
* Convert the Unicode name to the loaded NLS and pass it to
* the filldir callback.
- *
- * If @is_ia is TRUE, iu is an INDEX_ALLOCATION. Otherwise it is an INDEX_ROOT.
*/
static inline int ntfs_filldir(ntfs_volume *vol, struct file *filp,
@@ -433,4 +443,6 @@
int name_len;
unsigned dt_type;
+ FILE_NAME_TYPE_FLAGS name_type;
+ READDIR_OPTIONS readdir_opts;
/* Advance the position even if going to skip the entry. */
@@ -442,12 +454,26 @@
else /* if (index_type == INDEX_TYPE_ROOT) */
filp->f_pos = (u8*)ie - (u8*)iu.ir;
- if (ie->key.file_name.file_name_type == FILE_NAME_DOS) {
- ntfs_debug("Skipping DOS only name space entry.");
+ readdir_opts = vol->readdir_opts;
+ name_type = ie->key.file_name.file_name_type;
+ if (name_type == FILE_NAME_DOS && RHideDosNames(readdir_opts)) {
+ ntfs_debug("Skipping DOS name space entry.");
return 0;
}
+ if (RHideLongNames(readdir_opts)) {
+ if (name_type == FILE_NAME_WIN32 ||
+ name_type == FILE_NAME_POSIX) {
+ ntfs_debug("Skipping WIN32/POSIX name space entry.");
+ return 0;
+ }
+ }
if (MREF_LE(ie->_IIF(indexed_file)) == FILE_root) {
ntfs_debug("Skipping root directory self reference entry.");
return 0;
}
+ if (MREF_LE(ie->_IIF(indexed_file)) < FILE_first_user &&
+ RHideSystemFiles(readdir_opts)) {
+ ntfs_debug("Skipping system file.");
+ return 0;
+ }
name_len = ntfs_ucstonls(vol, (uchar_t*)&ie->key.file_name.file_name,
ie->key.file_name.file_name_length, &name,
@@ -553,9 +579,9 @@
ctx)) {
ntfs_error(sb, "Index root attribute missing in directory "
- "inode %Li.", (unsigned long long)ndir->mft_no);
+ "inode 0x%Lx.",
+ (unsigned long long)ndir->mft_no);
err = -EIO;
goto kf_unm_err_out;
}
- /* FIXME: Clean up search context. */
/* Get to the index root value (it's been verified in read_inode). */
ir = (INDEX_ROOT*)((u8*)ctx->attr +
@@ -613,5 +639,5 @@
ctx)) {
ntfs_error(sb, "Index bitmap attribute missing in "
- "directory inode %Li.",
+ "directory inode 0x%Lx.",
(unsigned long long)ndir->mft_no);
err = -EIO;
@@ -662,5 +688,5 @@
if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) {
ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
- "inode %Li or driver bug.",
+ "inode 0x%Lx or driver bug.",
(unsigned long long)ndir->mft_no);
err = -EIO;
@@ -670,8 +696,8 @@
~(s64)(ndir->_IDM(index_block_size) - 1)) >>
ndir->_IDM(index_vcn_size_bits)) {
- ntfs_error(sb, "Actual VCN (%Li) of index buffer is "
- "different from expected VCN (%Li). "
- "Directory inode %Li is corrupt or "
- "driver bug. ",
+ ntfs_error(sb, "Actual VCN (0x%Lx) of index buffer is "
+ "different from expected VCN (0x%Lx). "
+ "Directory inode 0x%Lx is corrupt or driver "
+ "bug. ",
(long long)sle64_to_cpu(ia->index_block_vcn),
(long long)ia_pos >> ndir->_IDM(index_vcn_size_bits),
@@ -682,9 +708,9 @@
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
ndir->_IDM(index_block_size)) {
- ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %Li "
- "has a size (%u) differing from the directory "
- "specified size (%u). Directory inode is "
- "corrupt or driver bug.", (long long)ia_pos >>
- ndir->_IDM(index_vcn_size_bits),
+ ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode "
+ "0x%Lx has a size (%u) differing from the "
+ "directory specified size (%u). Directory "
+ "inode is corrupt or driver bug.",
+ (long long)ia_pos >> ndir->_IDM(index_vcn_size_bits),
(unsigned long long)ndir->mft_no,
le32_to_cpu(ia->index.allocated_size) + 0x18,
@@ -695,7 +721,7 @@
index_end = (u8*)ia + ndir->_IDM(index_block_size);
if (index_end > kaddr + PAGE_CACHE_SIZE) {
- ntfs_error(sb, "Index buffer (VCN %Li) of directory inode %Li "
- "crosses page boundary. Impossible! Cannot "
- "access! This is probably a bug in the "
+ ntfs_error(sb, "Index buffer (VCN 0x%Lx) of directory inode "
+ "0x%Lx crosses page boundary. Impossible! "
+ "Cannot access! This is probably a bug in the "
"driver.", (long long)ia_pos >>
ndir->_IDM(index_vcn_size_bits),
@@ -707,6 +733,6 @@
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
if (index_end > (u8*)ia + ndir->_IDM(index_block_size)) {
- ntfs_error(sb, "Size of index buffer (VCN %Li) of directory "
- "inode %Li exceeds maximum size.",
+ ntfs_error(sb, "Size of index buffer (VCN 0x%Lx) of directory "
+ "inode 0x%Lx exceeds maximum size.",
(long long)ia_pos >> ndir->_IDM(index_vcn_size_bits),
(unsigned long long)ndir->mft_no);
Index: inode.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/inode.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -U2 -r1.69 -r1.70
--- inode.c 25 Feb 2002 04:00:58 -0000 1.69
+++ inode.c 4 Mar 2002 22:56:14 -0000 1.70
@@ -3,5 +3,4 @@
*
* Copyright (c) 2001,2002 Anton Altaparmakov.
- * Copyright (C) 2002 Richard Russon.
*
* This program/include file is free software; you can redistribute it and/or
@@ -79,11 +78,11 @@
atomic_set(&ni->count, 1);
ni->vol = NULL;
- ni->run_list = NULL;
+ INIT_RUN_LIST(&ni->run_list);
init_rwsem(&ni->mrec_lock);
atomic_set(&ni->mft_count, 0);
ni->page = NULL;
ni->attr_list = NULL;
- ni->attr_list_rl = NULL;
- ni->_IDM(bmp_rl) = NULL;
+ INIT_RUN_LIST(&ni->attr_list_rl);
+ INIT_RUN_LIST(&ni->_IDM(bmp_rl));
init_MUTEX(&ni->extent_lock);
ni->_INE(base_ntfs_ino) = NULL;
@@ -377,10 +376,13 @@
if (ctx->attr->non_resident) {
ni->state |= 1 << NI_AttrListNonResident;
- /* Setup the run list. */
- ni->attr_list_rl = decompress_mapping_pairs(vol,
+ /*
+ * Setup the run list. No need for locking as we have
+ * exclusive access to the inode at this time.
+ */
+ ni->attr_list_rl.rl = decompress_mapping_pairs(vol,
ctx->attr, NULL);
- if (IS_ERR(ni->attr_list_rl)) {
- err = PTR_ERR(ni->attr_list_rl);
- ni->attr_list_rl = NULL;
+ if (IS_ERR(ni->attr_list_rl.rl)) {
+ err = PTR_ERR(ni->attr_list_rl.rl);
+ ni->attr_list_rl.rl = NULL;
ntfs_error(vi->i_sb, "Mapping pairs "
"decompression failed with "
@@ -390,6 +392,9 @@
goto ec_put_unm_err_out;
}
- /* Now load the attribute list. */
- if ((err = load_attribute_list(vol, ni->attr_list_rl,
+ /*
+ * Now load the attribute list. Again no need for
+ * locking as above.
+ */
+ if ((err = load_attribute_list(vol, ni->attr_list_rl.rl,
ni->attr_list, ni->attr_list_size))) {
ntfs_error(vi->i_sb, "Failed to load "
@@ -448,5 +453,6 @@
if (ctx->attr->flags & ATTR_COMPRESSION_MASK) {
ntfs_error(vi->i_sb, "Found encrypted and "
- "compressed data.");
+ "compressed attribute. Not "
+ "allowed.");
goto put_unm_err_out;
}
@@ -540,24 +546,17 @@
goto put_unm_err_out;
}
- if (!sle64_to_cpu(ctx->attr->_ANR(lowest_vcn))) {
- vi->i_size = sle64_to_cpu(ctx->attr->_ANR(data_size));
- ni->initialized_size = sle64_to_cpu(
- ctx->attr->_ANR(initialized_size));
- } else
- /*
- * Just a rough guess as ->*_size are not defined for
- * attribute extents. We could just find the base
- * attribute extent but this way is faster and not too
- * much off unless the directory is ridiculously big or
- * very fragmented or sparse.
- */
- vi->i_size = ni->initialized_size =
- sle64_to_cpu(ctx->attr->_ANR(highest_vcn))
- << vol->cluster_size_bits;
- /* Setup the run list. */
- ni->run_list = decompress_mapping_pairs(vol, ctx->attr, NULL);
- if (IS_ERR(ni->run_list)) {
- err = PTR_ERR(ni->run_list);
- ni->run_list = NULL;
+ vi->i_size = sle64_to_cpu(ctx->attr->_ANR(data_size));
+ ni->initialized_size = sle64_to_cpu(
+ ctx->attr->_ANR(initialized_size));
+ ni->allocated_size = sle64_to_cpu(ctx->attr->_ANR(allocated_size));
+ /*
+ * Setup the run list. No need for locking as we have exclusive
+ * access to the inode at this time.
+ */
+ ni->run_list.rl = decompress_mapping_pairs(vol, ctx->attr,
+ NULL);
+ if (IS_ERR(ni->run_list.rl)) {
+ err = PTR_ERR(ni->run_list.rl);
+ ni->run_list.rl = NULL;
ntfs_error(vi->i_sb, "Mapping pairs decompression "
"failed with error code %i.", -err);
@@ -580,24 +579,19 @@
if (ctx->attr->non_resident) {
ni->state |= 1 << NI_BmpNonResident;
- if (!sle64_to_cpu(ctx->attr->_ANR(lowest_vcn)))
- ni->_IDM(bmp_size) = sle64_to_cpu(
- ctx->attr->_ANR(data_size));
- else
- /*
- * Just a rough guess as ->*_size are not
- * defined for extents. We could just find the
- * base extent but this way is faster and not
- * too much off unless the directory is
- * ridiculously big / very fragmented or sparse.
- */
- ni->_IDM(bmp_size) = sle64_to_cpu(
- ctx->attr->_ANR(highest_vcn))
- << vol->cluster_size_bits;
- /* Setup the run list. */
- ni->_IDM(bmp_rl) = decompress_mapping_pairs(vol, ctx->attr,
+ ni->_IDM(bmp_size) = sle64_to_cpu(
+ ctx->attr->_ANR(data_size));
+ ni->_IDM(bmp_initialized_size) = sle64_to_cpu(
+ ctx->attr->_ANR(initialized_size));
+ ni->_IDM(bmp_allocated_size) = sle64_to_cpu(
+ ctx->attr->_ANR(allocated_size));
+ /*
+ * Setup the run list. No need for locking as we have
+ * exclusive access to the inode at this time.
+ */
+ ni->_IDM(bmp_rl).rl = decompress_mapping_pairs(vol, ctx->attr,
NULL);
- if (IS_ERR(ni->_IDM(bmp_rl))) {
- err = PTR_ERR(ni->_IDM(bmp_rl));
- ni->_IDM(bmp_rl) = NULL;
+ if (IS_ERR(ni->_IDM(bmp_rl).rl)) {
+ err = PTR_ERR(ni->_IDM(bmp_rl).rl);
+ ni->_IDM(bmp_rl).rl = NULL;
ntfs_error(vi->i_sb, "Mapping pairs "
"decompression failed with "
@@ -606,12 +600,14 @@
}
} else
- ni->_IDM(bmp_size) = le32_to_cpu(ctx->attr->_ARA(value_length));
+ ni->_IDM(bmp_size) = ni->_IDM(bmp_initialized_size) =
+ ni->_IDM(bmp_allocated_size) =
+ le32_to_cpu(ctx->attr->_ARA(value_length));
/* Consistency check bitmap size vs. index allocation size. */
- if (ni->_IDM(bmp_size) << 3 < ni->initialized_size >>
+ if (ni->_IDM(bmp_size) << 3 < vi->i_size >>
ni->_IDM(index_block_size_bits)) {
ntfs_error(vi->i_sb, "$I30 bitmap too small (0x%Lx) "
"for index allocation (0x%Lx).",
(long long)ni->_IDM(bmp_size) << 3,
- (long long)ni->initialized_size);
+ vi->i_size);
goto put_unm_err_out;
}
@@ -632,8 +628,9 @@
vi->i_mapping->a_ops = &ntfs_dir_aops;
} else {
- /* It is a file, find the unnamed data attribute. */
+ /* It is a file: find first extent of unnamed data attribute. */
reinit_attr_search_ctx(ctx);
if (!lookup_attr(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx)) {
- vi->i_size = ni->initialized_size = 0LL;
+ vi->i_size = ni->initialized_size =
+ ni->allocated_size = 0LL;
/*
* FILE_Secure does not have an unnamed $DATA
@@ -659,5 +656,5 @@
goto put_unm_err_out;
}
- /* Set up the state. */
+ /* Setup the state. */
if (ctx->attr->non_resident) {
ni->state |= 1 << NI_NonResident;
@@ -708,9 +705,14 @@
/* $MFT is special as we have the run_list already. */
if (likely(vi->i_ino != FILE_MFT)) {
- ni->run_list = decompress_mapping_pairs(vol,
+ /*
+ * Setup the run list. No need for locking as
+ * we have exclusive access to the inode at
+ * this time.
+ */
+ ni->run_list.rl = decompress_mapping_pairs(vol,
ctx->attr, NULL);
- if (IS_ERR(ni->run_list)) {
- err = PTR_ERR(ni->run_list);
- ni->run_list = NULL;
+ if (IS_ERR(ni->run_list.rl)) {
+ err = PTR_ERR(ni->run_list.rl);
+ ni->run_list.rl = NULL;
ntfs_error(vi->i_sb, "Mapping pairs "
"decompression failed "
@@ -720,25 +722,22 @@
}
}
- if (sle64_to_cpu(ctx->attr->_ANR(lowest_vcn)))
- /*
- * Just a rough guess as ->*_size are not
- * defined for attribute extents. We could
- * just find the base attribute extent but
- * this way is faster and not too much off,
- * unless the file is ridiculously big or very
- * fragmented or compressed or sparse.
- */
- vi->i_size = ni->initialized_size =
- sle64_to_cpu(
- ctx->attr->_ANR(highest_vcn)) <<
- vol->cluster_size_bits;
- else {
- vi->i_size = sle64_to_cpu(ctx->attr->_ANR(data_size));
- ni->initialized_size = sle64_to_cpu(
- ctx->attr->_ANR(initialized_size));
- }
+ /* Setup all the sizes. */
+ vi->i_size = sle64_to_cpu(ctx->attr->_ANR(data_size));
+ ni->initialized_size = sle64_to_cpu(
+ ctx->attr->_ANR(initialized_size));
+ ni->allocated_size = sle64_to_cpu(
+ ctx->attr->_ANR(allocated_size));
+ if (NInoCompressed(ni))
+ ni->_ICF(compressed_size) = sle64_to_cpu(
+ ctx->attr->_ANR(compressed_size));
} else { /* Resident attribute. */
- vi->i_size = le32_to_cpu(ctx->attr->_ARA(value_length));
- ni->initialized_size = 0LL;
+ /*
+ * Make all sizes equal for simplicity in read code
+ * paths. FIXME: Need to keep this in mind when
+ * converting to non-resident attribute in write code
+ * path. (Probably only affects truncate().)
+ */
+ vi->i_size = ni->initialized_size = ni->allocated_size =
+ le32_to_cpu(ctx->attr->_ARA(value_length));
}
no_data_attr_special_case:
@@ -757,6 +756,19 @@
vi->i_mapping->a_ops = &ntfs_file_aops;
}
- /* The number of 512-byte blocks (for stat). */
- vi->i_blocks = vi->i_size >> 9;
+ /*
+ * The number of 512-byte blocks used on disk (for stat). This is in so
+ * far inaccurate as it doesn't account for any named streams or other
+ * special non-resident attributes, but that is how Windows works, too,
+ * so we are at least consistent with Windows, if not entirely
+ * consistent with the Linux Way. Doing it the Linux Way would cause a
+ * significant slowdown as it would involve iterating over all
+ * attributes in the mft record and adding the allocated/compressed
+ * sizes of all non-resident attributes present to give us the Linux
+ * correct size that should go into i_blocks (after division by 512).
+ */
+ if (!NInoCompressed(ni))
+ vi->i_blocks = ni->allocated_size >> 9;
+ else
+ vi->i_blocks = ni->_ICF(compressed_size) >> 9;
/* Done. */
put_attr_search_ctx(ctx);
@@ -918,9 +930,9 @@
ni->state |= 1 << NI_AttrListNonResident;
/* Setup the run list. */
- ni->attr_list_rl = decompress_mapping_pairs(vol,
+ ni->attr_list_rl.rl = decompress_mapping_pairs(vol,
ctx->attr, NULL);
- if (IS_ERR(ni->attr_list_rl)) {
- err = PTR_ERR(ni->attr_list_rl);
- ni->attr_list_rl = NULL;
+ if (IS_ERR(ni->attr_list_rl.rl)) {
+ err = PTR_ERR(ni->attr_list_rl.rl);
+ ni->attr_list_rl.rl = NULL;
ntfs_error(sb, "Mapping pairs decompression "
"failed with error code %i.",
@@ -929,5 +941,5 @@
}
/* Now load the attribute list. */
- if ((err = load_attribute_list(vol, ni->attr_list_rl,
+ if ((err = load_attribute_list(vol, ni->attr_list_rl.rl,
ni->attr_list, ni->attr_list_size))) {
ntfs_error(sb, "Failed to load attribute list "
@@ -1016,5 +1028,5 @@
next_vcn = last_vcn = highest_vcn = 0;
while (lookup_attr(AT_DATA, NULL, 0, 0, next_vcn, NULL, 0, ctx)) {
- run_list *nrl;
+ run_list_element *nrl;
/* Cache the current attribute. */
@@ -1037,8 +1049,10 @@
}
/*
- * Decompress the mapping pairs array of this extent
- * and merge the result into the existing run list.
+ * Decompress the mapping pairs array of this extent and merge
+ * the result into the existing run list. No need for locking
+ * as we have exclusive access to the inode at this time and we
+ * are a mount in progress task, too.
*/
- nrl = decompress_mapping_pairs(vol, attr, ni->run_list);
+ nrl = decompress_mapping_pairs(vol, attr, ni->run_list.rl);
if (IS_ERR(nrl)) {
ntfs_error(sb, "decompress_mapping_pairs() failed with "
@@ -1047,5 +1061,5 @@
goto put_err_out;
}
- ni->run_list = nrl;
+ ni->run_list.rl = nrl;
/* Are we in the first extent? */
@@ -1058,4 +1072,6 @@
ni->initialized_size =
sle64_to_cpu(attr->_ANR(initialized_size));
+ ni->allocated_size =
+ sle64_to_cpu(attr->_ANR(allocated_size));
/* Set the number of mft records. */
vol->_VMM(nr_mft_records) = vi->i_size >>
@@ -1238,7 +1254,15 @@
}
/* Free all alocated memory. */
- ntfs_free(ni->run_list);
+ write_lock(&ni->run_list.lock);
+ ntfs_free(ni->run_list.rl);
+ ni->run_list.rl = NULL;
+ write_unlock(&ni->run_list.lock);
+
ntfs_free(ni->attr_list);
- ntfs_free(ni->attr_list_rl);
+
+ write_lock(&ni->attr_list_rl.lock);
+ ntfs_free(ni->attr_list_rl.rl);
+ ni->attr_list_rl.rl = NULL;
+ write_unlock(&ni->attr_list_rl.lock);
}
@@ -1267,6 +1291,9 @@
__ntfs_clear_inode(ni);
- if (S_ISDIR(vi->i_mode))
- ntfs_free(ni->_IDM(bmp_rl));
+ if (S_ISDIR(vi->i_mode)) {
+ write_lock(&ni->_IDM(bmp_rl).lock);
+ ntfs_free(ni->_IDM(bmp_rl).rl);
+ write_unlock(&ni->_IDM(bmp_rl).lock);
+ }
return;
}
Index: mft.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/mft.c,v
retrieving revision 1.50
retrieving revision 1.51
diff -U2 -r1.50 -r1.51
--- mft.c 25 Feb 2002 04:00:58 -0000 1.50
+++ mft.c 4 Mar 2002 22:56:14 -0000 1.51
@@ -149,5 +149,5 @@
* Note, we only setup asynchronous I/O on the page and return. I/O completion
* is signalled via our asynchronous I/O completion handler
- * end_buffer_read_mft_async().
+ * end_buffer_read_index_async().
*/
static int ntfs_mft_readpage(struct file *file, struct page *page)
@@ -182,5 +182,5 @@
blocks = PAGE_CACHE_SIZE >> blocksize_bits;
iblock = page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
- lblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits;
+ lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits;
bh = head = page->buffers;
@@ -188,5 +188,5 @@
#ifdef DEBUG
- if (!ni->run_list)
+ if (!ni->run_list.rl)
panic("NTFS: $MFT/$DATA run list has been unmapped! This is a "
"very serious bug! Cannot continue...");
@@ -206,5 +206,7 @@
vol->cluster_size_mask;
/* Convert the vcn to the corresponding lcn. */
- lcn = vcn_to_lcn(ni->run_list, vcn);
+ read_lock(&ni->run_list.lock);
+ lcn = vcn_to_lcn(ni->run_list.rl, vcn);
+ read_unlock(&ni->run_list.lock);
if (lcn >= 0) {
/* Setup buffer head to correct block. */
@@ -217,5 +219,5 @@
}
ntfs_error(sb, "vcn_to_lcn(vcn = 0x%Lx) failed with "
- "error code %Li.", (long long)vcn,
+ "error code 0x%Lx.", (long long)vcn,
(long long)-lcn);
// FIXME: Depending on vol->on_errors, do something.
Index: ntfs.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/ntfs.h,v
retrieving revision 1.30
retrieving revision 1.31
diff -U2 -r1.30 -r1.31
--- ntfs.h 25 Feb 2002 04:00:58 -0000 1.30
+++ ntfs.h 4 Mar 2002 22:56:14 -0000 1.31
@@ -25,11 +25,4 @@
#define _LINUX_NTFS_H
-/* Make sure gcc-2.96 or higher is being used. */
-/*
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
-# error The NTFS driver can only be compiled with gcc-2.96 or later.
-#endif
-*/
-
#include <linux/version.h>
@@ -226,6 +219,6 @@
int val;
char *str;
-} on_errors_str;
-extern on_errors_str on_errors_arr[];
+} option_t;
+extern const option_t on_errors_arr[];
/* From fs/ntfs/compress.c */
Index: super.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/super.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -U2 -r1.78 -r1.79
--- super.c 25 Feb 2002 04:00:58 -0000 1.78
+++ super.c 4 Mar 2002 22:56:15 -0000 1.79
@@ -35,5 +35,5 @@
static unsigned long ntfs_nr_compression_users = 0;
-/* Error constants/strings from super.c used in inode.c::ntfs_show_options(). */
+/* Error constants/strings used in inode.c::ntfs_show_options(). */
typedef enum {
ON_ERRORS_PANIC = 0x01,
@@ -43,16 +43,47 @@
} ON_ERRORS_ACTIONS;
-on_errors_str on_errors_arr[] = {
- { ON_ERRORS_PANIC, "panic" },
- { ON_ERRORS_REMOUNT_RO, "remount-ro", },
- { ON_ERRORS_CONTINUE, "continue", },
- { ON_ERRORS_RECOVER, "recover" },
- { ON_ERRORS_RECOVER || ON_ERRORS_PANIC, "recover_or_panic" },
- { ON_ERRORS_RECOVER || ON_ERRORS_REMOUNT_RO, "recover_or_remount-ro" },
- { ON_ERRORS_RECOVER || ON_ERRORS_CONTINUE, "recover_or_continue" },
- { 0, NULL }
+const option_t on_errors_arr[] = {
+ { ON_ERRORS_PANIC, "panic" },
+ { ON_ERRORS_REMOUNT_RO, "remount-ro", },
+ { ON_ERRORS_CONTINUE, "continue", },
+ { ON_ERRORS_RECOVER, "recover" },
+ { ON_ERRORS_RECOVER | ON_ERRORS_PANIC, "recover_or_panic" },
+ { ON_ERRORS_RECOVER | ON_ERRORS_REMOUNT_RO, "recover_or_remount-ro" },
+ { ON_ERRORS_RECOVER | ON_ERRORS_CONTINUE, "recover_or_continue" },
+ { 0, NULL }
+};
+
+static const option_t readdir_opts_arr[] = {
+ { SHOW_SYSTEM, "system" },
+ { SHOW_WIN32, "win32" },
+ { SHOW_WIN32, "long" },
+ { SHOW_DOS, "dos" },
+ { SHOW_DOS, "short" },
+ { SHOW_POSIX, "posix" },
+ { SHOW_ALL, "all" },
+ { 0, NULL }
};
/**
+ * simple_getbool -
+ *
+ * Copied from old ntfs driver (which copied from vfat driver).
+ */
+static int simple_getbool(char *s, BOOL *setval)
+{
+ if (s) {
+ if (!strcmp(s, "1") || !strcmp(s, "yes") || !strcmp(s, "true"))
+ *setval = TRUE;
+ else if (!strcmp(s, "0") || !strcmp(s, "no") ||
+ !strcmp(s, "false"))
+ *setval = FALSE;
+ else
+ return 0;
+ } else
+ *setval = TRUE;
+ return 1;
+}
+
+/**
* parse_options - parse the (re)mount options
* @vol: ntfs volume
@@ -64,10 +95,11 @@
{
char *p, *v, *ov;
+ static char *utf8 = "utf8";
int errors = 0, sloppy = 0;
uid_t uid = (uid_t)-1;
gid_t gid = (gid_t)-1;
mode_t fmask = (mode_t)-1, dmask = (mode_t)-1;
- int mft_zone_multiplier = -1, on_errors = -1;
- struct nls_table *nls_map = NULL;
+ int mft_zone_multiplier = -1, on_errors = -1, readdir_opts = -1;
+ struct nls_table *nls_map = NULL, *old_nls;
/* I am lazy... (-8 */
@@ -120,8 +152,49 @@
else NTFS_GETOPT_OPTIONS_ARRAY("errors", on_errors,
on_errors_arr)
- else if (!strcmp(p, "nls") || !strcmp(p, "iocharset")) {
- struct nls_table *old_nls;
+ else NTFS_GETOPT_OPTIONS_ARRAY("show_inodes", readdir_opts,
+ readdir_opts_arr)
+ else if (!strcmp(p, "show_system_files")) {
+ BOOL val = FALSE;
+ ntfs_warning(vol->sb, "Option show_system_files is "
+ "deprecated. Please use option "
+ "show_inodes=system in the future.");
+ if (!v || !*v)
+ val = TRUE;
+ else if (!simple_getbool(v, &val))
+ goto needs_bool;
+ if (val) {
+ if (readdir_opts == -1)
+ readdir_opts = 0;
+ readdir_opts |= SHOW_SYSTEM;
+ }
+ } else if (!strcmp(p, "posix")) {
+ BOOL val = FALSE;
+ ntfs_warning(vol->sb, "Option posix is deprecated. "
+ "Please use option show_inodes=posix "
+ "instead. Be aware that some userspace "
+ "applications may be confused by this, "
+ "since the short and long names of "
+ "directory inodes will have the same inode "
+ "numbers, yet each will only have a link "
+ "count of 1 due to Linux not supporting "
+ "directory hard links.");
+ if (!v || !*v)
+ goto needs_arg;
+ else if (!simple_getbool(v, &val))
+ goto needs_bool;
+ if (val) {
+ if (readdir_opts == -1)
+ readdir_opts = 0;
+ readdir_opts |= SHOW_POSIX;
+ }
+ } else if (!strcmp(p, "nls") || !strcmp(p, "iocharset")) {
+ if (!strcmp(p, "iocharset"))
+ ntfs_warning(vol->sb, "Option iocharset is "
+ "deprecated. Please use "
+ "option nls=<charsetname> in "
+ "the future.");
if (!v || !*v)
goto needs_arg;
+use_utf8:
old_nls = nls_map;
nls_map = load_nls(v);
@@ -140,4 +213,19 @@
unload_nls(old_nls);
}
+ } else if (!strcmp(p, "utf8")) {
+ BOOL val = FALSE;
+ ntfs_warning(vol->sb, "Option utf8 is no longer "
+ "supported, using option nls=utf8. Please "
+ "use option nls=utf8 in the future and "
+ "make sure utf8 is compiled either as a "
+ "module or into the kernel.");
+ if (!v || !*v)
+ val = TRUE;
+ else if (!simple_getbool(v, &val))
+ goto needs_bool;
+ if (val) {
+ v = utf8;
+ goto use_utf8;
+ }
} else {
ntfs_error(vol->sb, "Unrecognized mount option %s.", p);
@@ -211,8 +299,13 @@
if (dmask != (mode_t)-1)
vol->dmask = dmask;
+ if (readdir_opts != -1)
+ vol->readdir_opts = readdir_opts;
return TRUE;
needs_arg:
ntfs_error(vol->sb, "The %s option requires an argument.", p);
return FALSE;
+needs_bool:
+ ntfs_error(vol->sb, "The %s option requires a boolean argument.", p);
+ return FALSE;
needs_val:
ntfs_error(vol->sb, "Invalid %s option argument: %s", p, ov);
@@ -339,28 +432,4 @@
/**
- * get_nr_blocks - get the number of NTFS_BLOCK_SIZE blocks on a device
- * @dev: device
- *
- * Get the number of NTFS_BLOCK_SIZE bytes sized blocks on the device @dev and
- * return it if successful or return 0 on error.
- *
- * FIXME: At the moment, we are happy as the kernel uses 512 byte blocks, which
- * also happens to be the NTFS_BLOCK_SIZE. In the future, when the kernel
- * implementation changes, this function will need to change to convert the
- * number into NTFS_BLOCK_SIZE sized blocks.
- */
-static long get_nr_blocks(const kdev_t dev)
-{
- struct gendisk *gd = get_gendisk(dev);
-
- if (gd)
- return gd->part[minor(dev)].nr_sects;
- if ((major(dev) == LOOP_MAJOR) && blk_size[major(dev)])
- return blk_size[major(dev)][minor(dev)] << BLOCK_SIZE_BITS
- >> NTFS_BLOCK_SIZE_BITS;
- return (long)0;
-}
-
-/**
* read_boot_sector - read the NTFS boot sector of a device
* @sb: super block of device to read the boot sector from
@@ -562,5 +631,5 @@
}
vol->_VCL(nr_clusters) = ll;
- ntfs_debug("vol->_VCL(nr_clusters) = 0x%Lx", (long long)vol->_VCL(nr_clusters));
+ ntfs_debug("vol->nr_clusters = 0x%Lx", (long long)vol->_VCL(nr_clusters));
ll = sle64_to_cpu(b->mft_lcn);
if (ll >= vol->_VCL(nr_clusters)) {
@@ -618,5 +687,5 @@
/**
- * load_and_init_upcase -
+ * load_and_init_upcase - load the upcase table for an ntfs volume
* @vol: ntfs super block describing device whose upcase to load
*
@@ -654,24 +723,12 @@
size = PAGE_CACHE_SIZE;
while (index < max_index) {
+ /* Read the upcase table and copy it into the linear buffer. */
read_partial_upcase_page:
- /*
- * Read the page from page cache, getting it from backing store
- * if necessary, and increment the use count.
- */
- page = read_cache_page(ino->i_mapping, index, (filler_t*)
- ino->i_mapping->a_ops->readpage, NULL);
+ page = ntfs_map_page(ino->i_mapping, index);
if (IS_ERR(page))
- /* Sync io failed. */
- goto iput_upcase_failed;
- wait_on_page(page);
- if (!Page_Uptodate(page)) {
- /* Async io failed. */
- page_cache_release(page);
goto iput_upcase_failed;
- }
memcpy((char*)vol->upcase + (index++ << PAGE_CACHE_SHIFT),
- kmap(page), size);
- kunmap(page);
- page_cache_release(page);
+ page_address(page), size);
+ ntfs_unmap_page(page);
};
if (size == PAGE_CACHE_SIZE) {
@@ -680,5 +737,5 @@
goto read_partial_upcase_page;
}
- vol->upcase_len = ino->i_size >> 1 /* uchar_t_size_shift */;
+ vol->upcase_len = ino->i_size >> UCHAR_T_SIZE_BITS;
ntfs_debug("Read %Lu bytes from $UpCase (expected %u bytes).",
ino->i_size, 64 * 1024 * sizeof(uchar_t));
@@ -692,5 +749,5 @@
}
max = default_upcase_len;
- if (vol->upcase_len < default_upcase_len)
+ if (max > vol->upcase_len)
max = vol->upcase_len;
for (i = 0; i < max; i++)
@@ -749,5 +806,5 @@
VOLUME_INFORMATION *vi;
attr_search_context *ctx;
- run_list *rl;
+ run_list_element *rl;
ntfs_debug("Entering.");
@@ -770,5 +827,5 @@
next_vcn = last_vcn = highest_vcn = 0;
while (lookup_attr(AT_BITMAP, NULL, 0, 0, next_vcn, NULL, 0, ctx)) {
- run_list *nrl;
+ run_list_element *nrl;
/* Cache the current attribute extent. */
@@ -792,5 +849,7 @@
/*
* Decompress the mapping pairs array of this extent
- * and merge the result into the existing run list.
+ * and merge the result into the existing run list. Note we
+ * don't need any locking at this stage as we are already
+ * running exclusively as we are mount in progress task.
*/
nrl = decompress_mapping_pairs(vol, attr, rl);
@@ -808,9 +867,11 @@
last_vcn = sle64_to_cpu(attr->_ANR(allocated_size)) >>
vol->cluster_size_bits;
+ vol->mftbmp_size = sle64_to_cpu(attr->_ANR(data_size));
vol->mftbmp_initialized_size =
sle64_to_cpu(attr->_ANR(initialized_size));
+ vol->mftbmp_allocated_size =
+ sle64_to_cpu(attr->_ANR(allocated_size));
/* Consistency check. */
- if (vol->mftbmp_initialized_size <
- (vol->_VMM(nr_mft_records) + 7) >> 3) {
+ if (vol->mftbmp_size < (vol->_VMM(nr_mft_records) + 7) >> 3) {
ntfs_error(sb, "$MFT/$BITMAP is too short to "
"contain a complete mft "
@@ -862,8 +923,6 @@
}
- down_write(&vol->mftbmp_lock);
-
/* Setup the run list and the address space in the volume structure. */
- vol->mftbmp_rl = rl;
+ vol->mftbmp_rl.rl = rl;
vol->mftbmp_mapping.a_ops = &ntfs_mftbmp_aops;
@@ -871,6 +930,4 @@
vol->mftbmp_mapping.host = NULL;
- up_write(&vol->mftbmp_lock);
-
// FIXME: If mounting read-only, it would be ok to ignore errors when
// loading the mftbmp but we then need to make sure nobody remounts the
@@ -891,8 +948,10 @@
if (!load_and_init_upcase(vol))
goto iput_mirr_err_out;
- /* Get the cluster allocation bitmap inode and verify the size. */
- down_write(&vol->lcnbmp_lock);
+ /*
+ * Get the cluster allocation bitmap inode and verify the size, no
+ * need for any locking at this stage as we are already running
+ * exclusively as we are mount in progress task.
+ */
vol->lcnbmp_ino = iget(sb, FILE_Bitmap);
- up_write(&vol->lcnbmp_lock);
if (!vol->lcnbmp_ino || is_bad_inode(vol->lcnbmp_ino)) {
if (is_bad_inode(vol->lcnbmp_ino))
@@ -1066,17 +1125,20 @@
/*
* Clean up mft bitmap address space. Ignore the _inode_ bit in the
- * name...
+ * name of the function... FIXME: What does this do with dirty pages?
+ * (ask Al Viro)
*/
truncate_inode_pages(&vol->mftbmp_mapping, 0);
vol->mftbmp_mapping.a_ops = NULL;
vol->mftbmp_mapping.host = NULL;
- ntfs_free(vol->mftbmp_rl);
- vol->mftbmp_rl = NULL;
up_write(&vol->mftbmp_lock);
+ write_lock(&vol->mftbmp_rl.lock);
+ ntfs_free(vol->mftbmp_rl.rl);
+ vol->mftbmp_rl.rl = NULL;
+ write_unlock(&vol->mftbmp_rl.lock);
vol->upcase_len = 0;
/*
* Decrease the number of mounts and destroy the global default upcase
* table if necessary. Also decrease the number of upcase users if we
- * are were user.
+ * are a user.
*/
down(&ntfs_lock);
@@ -1391,10 +1453,10 @@
/**
- * ntfs_read_super - mount an ntfs files system
+ * ntfs_fill_super - mount an ntfs files system
* @sb: super block of ntfs file system to mount
* @opt: string containing the mount options
* @silent: silence error output
*
- * ntfs_read_super() is called by the VFS to mount the device described by @sb
+ * ntfs_fill_super() is called by the VFS to mount the device described by @sb
* with the mount otions in @data with the NTFS file system.
*
@@ -1408,6 +1470,5 @@
* NOTE: @sb->s_flags contains the mount options flags.
*/
-struct super_block *ntfs_read_super(struct super_block *sb, void *opt,
- const int silent)
+static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
{
extern int *blksize_size[];
@@ -1426,5 +1487,5 @@
ntfs_error(sb, "Allocation of NTFS volume structure "
"failed. Aborting mount...");
- goto imm_err_out_now;
+ return -ENOMEM;
}
/* Initialize ntfs_volume structure. */
@@ -1442,5 +1503,5 @@
vol->mftbmp_mapping.i_mmap_shared = NULL;
spin_lock_init(&vol->mftbmp_mapping.i_shared_lock);
- vol->mftbmp_rl = NULL;
+ INIT_RUN_LIST(&vol->mftbmp_rl);
vol->mftmirr_ino = NULL;
vol->lcnbmp_ino = NULL;
@@ -1453,4 +1514,5 @@
vol->mft_zone_multiplier = 0;
vol->nls_map = NULL;
+
/*
* Default is group and other don't have write/execute access to files
@@ -1460,4 +1522,10 @@
vol->dmask = 0022;
+ /*
+ * Default is to show long file names (including POSIX file names), and
+ * not to show system files and short file names.
+ */
+ vol->readdir_opts = SHOW_WIN32;
+
/* Important to get the mount options dealt with now. */
if (!parse_options(vol, (char*)opt))
@@ -1488,10 +1556,6 @@
}
- /* Get the size of the device in NTFS_BLOCK_SIZE byte blocks. */
- if (!(vol->nr_blocks = get_nr_blocks(dev))) {
- if (!silent)
- ntfs_error(sb, "Unable to determine device size.");
- goto set_blk_size_err_out_now;
- }
+ /* Get the size of the device in units of NTFS_BLOCK_SIZE bytes. */
+ vol->nr_blocks = sb->s_bdev->bd_inode->i_size >> NTFS_BLOCK_SIZE_BITS;
/* Read the boot sector and return unlocked buffer head to it. */
@@ -1524,5 +1588,14 @@
/* Setup remaining fields in the super block. */
sb->s_magic = NTFS_SB_MAGIC;
- sb->s_maxbytes = ~0ULL >> 1;
+
+ /*
+ * Ntfs allows 63 bits for the file size, i.e. correct would be:
+ * sb->s_maxbytes = ~0ULL >> 1;
+ * But the kernel uses a long as the page cache page index which on
+ * 32-bit architectures is only 32-bits. MAX_LFS_FILESIZE is kernel
+ * defined to the maximum the page cache page index can cope with
+ * without overflowing the index or to 2^63 - 1, whichever is smaller.
+ */
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
/*
@@ -1609,5 +1682,5 @@
}
up(&ntfs_lock);
- return sb;
+ return 0;
}
ntfs_error(sb, "Failed to allocate root directory.");
@@ -1626,6 +1699,9 @@
iput(vol->mftmirr_ino);
vol->mftmirr_ino = NULL;
- ntfs_free(vol->mftbmp_rl);
- vol->mftbmp_rl = NULL;
+ truncate_inode_pages(&vol->mftbmp_mapping, 0);
+ vol->mftbmp_mapping.a_ops = NULL;
+ vol->mftbmp_mapping.host = NULL;
+ ntfs_free(vol->mftbmp_rl.rl);
+ vol->mftbmp_rl.rl = NULL;
vol->upcase_len = 0;
if (vol->upcase != default_upcase)
@@ -1678,7 +1754,6 @@
sb->u.generic_sbp = NULL;
kfree(vol);
-imm_err_out_now:
- ntfs_debug("Exiting, status failed.");
- return NULL;
+ ntfs_debug("Failed, returning -EINVAL.");
+ return -EINVAL;
}
@@ -1721,18 +1796,6 @@
DECLARE_MUTEX(ntfs_lock);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,4)
-static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);
-#else
-
-int ntfs_fill_super(struct super_block *sb, void *opt, int silent)
-{
- if (ntfs_read_super(sb, opt, silent))
- return 0;
- else
- return -EINVAL;
-}
-
static struct super_block *ntfs_get_sb(struct file_system_type *fs_type,
- int flags, char *dev_name, void *data)
+ int flags, char *dev_name, void *data)
{
return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super);
@@ -1745,5 +1808,10 @@
fs_flags: FS_REQUIRES_DEV,
};
-#endif /* VERSION >= 2.5.4 */
+
+/* Stable names for the slab caches. */
+static const char *ntfs_attr_ctx_cache_name = "ntfs_attr_ctx_cache";
+static const char *ntfs_name_cache_name = "ntfs_name_cache";
+static const char *ntfs_inode_cache_name = "ntfs_inode_cache";
+static const char *ntfs_big_inode_cache_name = "ntfs_big_inode_cache";
static int __init init_ntfs_fs(void)
@@ -1768,34 +1836,36 @@
ntfs_debug("Debug messages are enabled.");
- ntfs_attr_ctx_cache = kmem_cache_create("ntfs_actx_cache",
+ ntfs_attr_ctx_cache = kmem_cache_create(ntfs_attr_ctx_cache_name,
sizeof(attr_search_context), 0 /* offset */,
SLAB_HWCACHE_ALIGN, NULL /* ctor */, NULL /* dtor */);
if (!ntfs_attr_ctx_cache) {
- printk(KERN_CRIT "NTFS: Failed to create "
- "ntfs_actx_cache!\n");
+ printk(KERN_CRIT "NTFS: Failed to create %s!\n",
+ ntfs_attr_ctx_cache_name);
goto ctx_err_out;
}
- ntfs_name_cache = kmem_cache_create("ntfs_name_cache",
+ ntfs_name_cache = kmem_cache_create(ntfs_name_cache_name,
(NTFS_MAX_NAME_LEN+1) * sizeof(uchar_t), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!ntfs_name_cache) {
- printk(KERN_CRIT "NTFS: Failed to create ntfs_name_cache!\n");
+ printk(KERN_CRIT "NTFS: Failed to create %s!\n",
+ ntfs_name_cache_name);
goto name_err_out;
}
- ntfs_inode_cache = kmem_cache_create("ntfs_inode_cache",
+ ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name,
sizeof(ntfs_inode), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!ntfs_inode_cache) {
- printk(KERN_CRIT "NTFS: Failed to create ntfs_inode_cache!\n");
+ printk(KERN_CRIT "NTFS: Failed to create %s!\n",
+ ntfs_inode_cache_name);
goto inode_err_out;
}
- ntfs_big_inode_cache = kmem_cache_create("ntfs_b_inode_cache",
+ ntfs_big_inode_cache = kmem_cache_create(ntfs_big_inode_cache_name,
sizeof(big_ntfs_inode), 0, SLAB_HWCACHE_ALIGN,
ntfs_big_inode_init_once, NULL);
if (!ntfs_big_inode_cache) {
- printk(KERN_CRIT "NTFS: Failed to create "
- "ntfs_big_inode_cache!\n");
+ printk(KERN_CRIT "NTFS: Failed to create %s!\n",
+ ntfs_big_inode_cache_name);
goto big_inode_err_out;
}
@@ -1841,12 +1911,15 @@
if (kmem_cache_destroy(ntfs_big_inode_cache) && (err = 1))
- printk(KERN_CRIT "NTFS: Failed to destroy "
- "ntfs_big_inode_cache.\n");
+ printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
+ ntfs_big_inode_cache_name);
if (kmem_cache_destroy(ntfs_inode_cache) && (err = 1))
- printk(KERN_CRIT "NTFS: Failed to destroy ntfs_inode_cache.\n");
+ printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
+ ntfs_inode_cache_name);
if (kmem_cache_destroy(ntfs_name_cache) && (err = 1))
- printk(KERN_CRIT "NTFS: Failed to destroy ntfs_name_cache.\n");
+ printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
+ ntfs_name_cache_name);
if (kmem_cache_destroy(ntfs_attr_ctx_cache) && (err = 1))
- printk(KERN_CRIT "NTFS: Failed to destroy ntfs_actx_cache.\n");
+ printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
+ ntfs_attr_ctx_cache_name);
if (err)
printk(KERN_CRIT "NTFS: This causes memory to leak! There is "
Index: types.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/types.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -U2 -r1.3 -r1.4
--- types.h 3 Feb 2002 19:31:17 -0000 1.3
+++ types.h 4 Mar 2002 22:56:15 -0000 1.4
@@ -26,4 +26,5 @@
/* 2-byte Unicode character type. */
typedef u16 uchar_t;
+#define UCHAR_T_SIZE_BITS 1
/*
@@ -35,5 +36,5 @@
/**
- * run_list - in memory vcn to lcn mapping array
+ * run_list_element - in memory vcn to lcn mapping array element
* @vcn: starting vcn of the current array element
* @lcn: starting lcn of the current array element
@@ -49,5 +50,26 @@
LCN lcn; /* lcn = Starting logical cluster number. */
s64 length; /* Run length in clusters. */
+} run_list_element;
+
+/**
+ * run_list - in memory vcn to lcn mapping array including a read/write lock
+ * @rl: pointer to an array of run list elements
+ * @lock: read/write spinlock for serializing access to @rl
+ *
+ */
+typedef struct {
+ run_list_element *rl;
+ rwlock_t lock;
} run_list;
+
+#define RUN_LIST_INIT { NULL, RW_LOCK_UNLOCKED }
+
+#define RUN_LIST(name) run_list name = RUN_LIST_INIT
+
+#define INIT_RUN_LIST(runlist) do { \
+ run_list *___rl = runlist; \
+ ___rl->rl = NULL; \
+ ___rl->lock = RW_LOCK_UNLOCKED; \
+ } while (0)
typedef enum {
Index: volume.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/volume.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -U2 -r1.7 -r1.8
--- volume.h 25 Feb 2002 04:00:58 -0000 1.7
+++ volume.h 4 Mar 2002 22:56:15 -0000 1.8
@@ -27,4 +27,17 @@
#include "types.h"
+/* These are used to determine which inode names are returned by readdir(). */
+typedef enum {
+ SHOW_SYSTEM = 1,
+ SHOW_WIN32 = 2,
+ SHOW_DOS = 4,
+ SHOW_POSIX = SHOW_WIN32 | SHOW_DOS,
+ SHOW_ALL = SHOW_SYSTEM | SHOW_POSIX,
+} READDIR_OPTIONS;
+
+#define RHideSystemFiles(x) (!((x) & SHOW_SYSTEM))
+#define RHideLongNames(x) (!((x) & SHOW_WIN32))
+#define RHideDosNames(x) (!((x) & SHOW_DOS))
+
/*
* The NTFS in memory super block structure.
@@ -50,4 +63,5 @@
mode_t dmask; /* The mask for directory
permissions. */
+ READDIR_OPTIONS readdir_opts; /* Namespace of inode names to show. */
u8 mft_zone_multiplier; /* Initial mft zone multiplier. */
u8 on_errors; /* What to do on file system errors. */
@@ -84,6 +98,8 @@
} SN(vmm);
struct address_space mftbmp_mapping; /* Page cache for $MFT/$BITMAP. */
- run_list *mftbmp_rl; /* Run list for $MFT/$BITMAP. */
+ run_list mftbmp_rl; /* Run list for $MFT/$BITMAP. */
+ s64 mftbmp_size; /* Data size of $MFT/$BITMAP. */
s64 mftbmp_initialized_size; /* Initialized size of $MFT/$BITMAP. */
+ s64 mftbmp_allocated_size; /* Allocated size of $MFT/$BITMAP. */
struct inode *mftmirr_ino; /* The VFS inode of $MFTMirr. */
struct inode *lcnbmp_ino; /* The VFS inode of $Bitmap. */
|