Changes by: antona
Update of /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs
In directory usw-pr-cvs1:/tmp/cvs-serv4205/linux/fs/ntfs
Modified Files:
Tag: pre-95
aops.c attrib.c attrib.h compress.c debug.c debug.h dir.c
inode.c inode.h mft.c ntfs.h super.c types.h volume.h
Log Message:
vacation is over. here is the results. read the changelog for details.
Index: aops.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/aops.c,v
retrieving revision 1.53
retrieving revision 1.53.4.1
diff -U2 -r1.53 -r1.53.4.1
--- aops.c 14 Feb 2002 06:07:14 -0000 1.53
+++ aops.c 4 Mar 2002 19:04:02 -0000 1.53.4.1
@@ -100,5 +100,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) {
@@ -295,5 +297,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.65
retrieving revision 1.65.4.1
diff -U2 -r1.65 -r1.65.4.1
--- attrib.c 18 Feb 2002 01:53:00 -0000 1.65
+++ attrib.c 4 Mar 2002 19:04:02 -0000 1.65.4.1
@@ -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);
@@ -120,4 +130,6 @@
* 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,8 +137,8 @@
* -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;
@@ -164,4 +176,6 @@
* 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
*
@@ -169,8 +183,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 */
@@ -244,4 +258,6 @@
* the inserted run_list, if necesary.
*
+ * It is up to the caller to serialize access to the run lists @orig and @new.
+ *
* Return: Pointer, The new, combined, run_list
*
@@ -249,8 +265,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;
@@ -292,4 +308,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
*
@@ -297,8 +315,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);
@@ -327,4 +345,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.
@@ -347,7 +367,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. */
@@ -516,4 +536,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
@@ -533,12 +555,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. */
@@ -759,5 +781,4 @@
attr_search_context *ctx;
MFT_RECORD *mrec;
- run_list *rl;
const uchar_t *name;
u32 name_len;
@@ -796,7 +817,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);
@@ -805,12 +844,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:
@@ -828,4 +861,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:
*
@@ -838,5 +873,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;
@@ -875,5 +910,4 @@
}
-
/**
* find_attr - find (next) attribute in mft record
@@ -1044,7 +1078,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.15
retrieving revision 1.15.6.1
diff -U2 -r1.15 -r1.15.6.1
--- attrib.h 10 Feb 2002 02:22:58 -0000 1.15
+++ attrib.h 4 Mar 2002 19:04:02 -0000 1.15.6.1
@@ -66,10 +66,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,
@@ -81,5 +81,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.32
retrieving revision 1.32.4.1
diff -U2 -r1.32 -r1.32.4.1
--- compress.c 14 Feb 2002 06:07:14 -0000 1.32
+++ compress.c 4 Mar 2002 19:04:02 -0000 1.32.4.1
@@ -118,4 +118,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
@@ -135,6 +138,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,
@@ -185,4 +188,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++) {
@@ -564,5 +569,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);
@@ -623,8 +630,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()];
@@ -662,5 +668,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--;
@@ -743,5 +750,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];
@@ -770,5 +779,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: debug.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/debug.c,v
retrieving revision 1.20
retrieving revision 1.20.6.1
diff -U2 -r1.20 -r1.20.6.1
--- debug.c 13 Feb 2002 03:54:13 -0000 1.20
+++ debug.c 4 Mar 2002 19:04:02 -0000 1.20.6.1
@@ -134,5 +134,5 @@
/* Dump a run list. */
-void ntfs_debug_dump_runlist(const run_list *rl)
+void ntfs_debug_dump_runlist(run_list_element *rl)
{
int i;
Index: debug.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/debug.h,v
retrieving revision 1.4
retrieving revision 1.4.8.1
diff -U2 -r1.4 -r1.4.8.1
--- debug.h 3 Feb 2002 19:31:17 -0000 1.4
+++ debug.h 4 Mar 2002 19:04:02 -0000 1.4.8.1
@@ -52,5 +52,5 @@
__ntfs_debug(__FILE__, __LINE__, __FUNCTION__, f, ##a)
-extern void ntfs_debug_dump_runlist(const run_list *rl);
+extern void ntfs_debug_dump_runlist(run_list_element *rl);
#else /* !DEBUG */
Index: dir.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/dir.c,v
retrieving revision 1.46
retrieving revision 1.46.4.1
diff -U2 -r1.46 -r1.46.4.1
--- dir.c 14 Feb 2002 01:08:46 -0000 1.46
+++ dir.c 4 Mar 2002 19:04:02 -0000 1.46.4.1
@@ -81,5 +81,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;
@@ -188,6 +188,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;
@@ -218,5 +218,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;
@@ -224,7 +224,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,
@@ -235,8 +236,8 @@
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
dir_ni->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,
@@ -248,7 +249,7 @@
index_end = (u8*)ia + dir_ni->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);
@@ -258,6 +259,6 @@
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
if (index_end > (u8*)ia + dir_ni->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);
@@ -280,5 +281,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;
@@ -365,5 +366,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;
@@ -385,5 +386,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;
@@ -419,9 +420,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,
@@ -432,4 +442,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. */
@@ -441,12 +453,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->indexed_file) == FILE_root) {
ntfs_debug("Skipping root directory self reference entry.");
return 0;
}
+ if (MREF_LE(ie->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,
@@ -552,9 +578,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 +
@@ -612,5 +638,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;
@@ -661,5 +687,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;
@@ -669,8 +695,8 @@
~(s64)(ndir->index_block_size - 1)) >>
ndir->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->index_vcn_size_bits,
@@ -681,9 +707,9 @@
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
ndir->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->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->index_vcn_size_bits,
(unsigned long long)ndir->mft_no,
le32_to_cpu(ia->index.allocated_size) + 0x18,
@@ -694,7 +720,7 @@
index_end = (u8*)ia + ndir->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->index_vcn_size_bits,
@@ -706,6 +732,6 @@
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
if (index_end > (u8*)ia + ndir->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->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.68
retrieving revision 1.68.4.1
diff -U2 -r1.68 -r1.68.4.1
--- inode.c 14 Feb 2002 06:07:14 -0000 1.68
+++ inode.c 4 Mar 2002 19:04:02 -0000 1.68.4.1
@@ -78,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->bmp_rl = NULL;
+ INIT_RUN_LIST(&ni->attr_list_rl);
+ INIT_RUN_LIST(&ni->bmp_rl);
init_MUTEX(&ni->extent_lock);
ni->base_ntfs_ino = NULL;
@@ -376,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 "
@@ -389,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 "
@@ -447,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;
}
@@ -539,24 +546,17 @@
goto put_unm_err_out;
}
- if (!sle64_to_cpu(ctx->attr->lowest_vcn)) {
- vi->i_size = sle64_to_cpu(ctx->attr->data_size);
- ni->initialized_size = sle64_to_cpu(
- ctx->attr->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->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->data_size);
+ ni->initialized_size = sle64_to_cpu(
+ ctx->attr->initialized_size);
+ ni->allocated_size = sle64_to_cpu(ctx->attr->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);
@@ -579,24 +579,19 @@
if (ctx->attr->non_resident) {
ni->state |= 1 << NI_BmpNonResident;
- if (!sle64_to_cpu(ctx->attr->lowest_vcn))
- ni->bmp_size = sle64_to_cpu(
- ctx->attr->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->bmp_size = sle64_to_cpu(
- ctx->attr->highest_vcn)
- << vol->cluster_size_bits;
- /* Setup the run list. */
- ni->bmp_rl = decompress_mapping_pairs(vol, ctx->attr,
+ ni->bmp_size = sle64_to_cpu(
+ ctx->attr->data_size);
+ ni->bmp_initialized_size = sle64_to_cpu(
+ ctx->attr->initialized_size);
+ ni->bmp_allocated_size = sle64_to_cpu(
+ ctx->attr->allocated_size);
+ /*
+ * Setup the run list. No need for locking as we have
+ * exclusive access to the inode at this time.
+ */
+ ni->bmp_rl.rl = decompress_mapping_pairs(vol, ctx->attr,
NULL);
- if (IS_ERR(ni->bmp_rl)) {
- err = PTR_ERR(ni->bmp_rl);
- ni->bmp_rl = NULL;
+ if (IS_ERR(ni->bmp_rl.rl)) {
+ err = PTR_ERR(ni->bmp_rl.rl);
+ ni->bmp_rl.rl = NULL;
ntfs_error(vi->i_sb, "Mapping pairs "
"decompression failed with "
@@ -605,12 +600,14 @@
}
} else
- ni->bmp_size = le32_to_cpu(ctx->attr->value_length);
+ ni->bmp_size = ni->bmp_initialized_size =
+ ni->bmp_allocated_size =
+ le32_to_cpu(ctx->attr->value_length);
/* Consistency check bitmap size vs. index allocation size. */
- if (ni->bmp_size << 3 < ni->initialized_size >>
+ if (ni->bmp_size << 3 < vi->i_size >>
ni->index_block_size_bits) {
ntfs_error(vi->i_sb, "$I30 bitmap too small (0x%Lx) "
"for index allocation (0x%Lx).",
(long long)ni->bmp_size << 3,
- (long long)ni->initialized_size);
+ vi->i_size);
goto put_unm_err_out;
}
@@ -631,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
@@ -658,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;
@@ -707,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 "
@@ -719,25 +722,22 @@
}
}
- if (sle64_to_cpu(ctx->attr->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->highest_vcn) <<
- vol->cluster_size_bits;
- else {
- vi->i_size = sle64_to_cpu(ctx->attr->data_size);
- ni->initialized_size = sle64_to_cpu(
- ctx->attr->initialized_size);
- }
+ /* Setup all the sizes. */
+ vi->i_size = sle64_to_cpu(ctx->attr->data_size);
+ ni->initialized_size = sle64_to_cpu(
+ ctx->attr->initialized_size);
+ ni->allocated_size = sle64_to_cpu(
+ ctx->attr->allocated_size);
+ if (NInoCompressed(ni))
+ ni->compressed_size = sle64_to_cpu(
+ ctx->attr->compressed_size);
} else { /* Resident attribute. */
- vi->i_size = le32_to_cpu(ctx->attr->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->value_length);
}
no_data_attr_special_case:
@@ -756,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->compressed_size >> 9;
/* Done. */
put_attr_search_ctx(ctx);
@@ -917,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.",
@@ -928,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 "
@@ -1015,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. */
@@ -1036,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 "
@@ -1046,5 +1061,5 @@
goto put_err_out;
}
- ni->run_list = nrl;
+ ni->run_list.rl = nrl;
/* Are we in the first extent? */
@@ -1057,4 +1072,6 @@
ni->initialized_size =
sle64_to_cpu(attr->initialized_size);
+ ni->allocated_size =
+ sle64_to_cpu(attr->allocated_size);
/* Set the number of mft records. */
vol->nr_mft_records = vi->i_size >>
@@ -1237,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);
}
@@ -1266,6 +1291,9 @@
__ntfs_clear_inode(ni);
- if (S_ISDIR(vi->i_mode))
- ntfs_free(ni->bmp_rl);
+ if (S_ISDIR(vi->i_mode)) {
+ write_lock(&ni->bmp_rl.lock);
+ ntfs_free(ni->bmp_rl.rl);
+ write_unlock(&ni->bmp_rl.lock);
+ }
return;
}
Index: inode.h
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/inode.h,v
retrieving revision 1.15
retrieving revision 1.15.4.1
diff -U2 -r1.15 -r1.15.4.1
--- inode.h 14 Feb 2002 06:07:14 -0000 1.15
+++ inode.h 4 Mar 2002 19:04:02 -0000 1.15.4.1
@@ -35,5 +35,6 @@
*/
struct _ntfs_inode {
- s64 initialized_size; /* Copy from unnamed $DATA attribute. */
+ s64 initialized_size; /* Copy from $DATA/$INDEX_ALLOCATION. */
+ s64 allocated_size; /* Copy from $DATA/$INDEX_ALLOCATION. */
unsigned long state; /* NTFS specific flags describing this inode.
See fs/ntfs/ntfs.h:ntfs_inode_state_bits. */
@@ -42,14 +43,14 @@
atomic_t count; /* Inode reference count for book keeping. */
ntfs_volume *vol; /* Pointer to the ntfs volume of this inode. */
- run_list *run_list; /* If state has the NI_NonResident bit set,
+ run_list run_list; /* If state has the NI_NonResident bit set,
the run list of the unnamed data attribute
(if a file) or of the index allocation
- attribute (directory). If run_list is NULL,
- the run list has not been read in or has
- been unmapped. If NI_NonResident is clear,
- the unnamed data attribute is resident (file)
- or there is no $I30 index allocation
- attribute (directory). In that case run_list
- is always NULL.*/
+ attribute (directory). If run_list.rl is
+ NULL, the run list has not been read in or
+ has been unmapped. If NI_NonResident is
+ clear, the unnamed data attribute is
+ resident (file) or there is no $I30 index
+ allocation attribute (directory). In that
+ case run_list.rl is always NULL.*/
struct rw_semaphore mrec_lock; /* Lock for serializing access to the
mft record belonging to this inode. */
@@ -69,5 +70,5 @@
u32 attr_list_size; /* Length of attribute list value in bytes. */
u8 *attr_list; /* Attribute list value itself. */
- run_list *attr_list_rl; /* Run list for the attribute list value. */
+ run_list attr_list_rl; /* Run list for the attribute list value. */
union {
struct { /* It is a directory or $MFT. */
@@ -78,15 +79,18 @@
u8 index_vcn_size_bits; /* Log2 of the above. */
s64 bmp_size; /* Size of the $I30 bitmap. */
- run_list *bmp_rl; /* Run list for the $I30 bitmap
+ s64 bmp_initialized_size; /* Copy from $I30 bitmap. */
+ s64 bmp_allocated_size; /* Copy from $I30 bitmap. */
+ run_list bmp_rl; /* Run list for the $I30 bitmap
if it is non-resident. */
};
struct { /* It is a compressed file. */
- u32 compression_block_size; /* Size of a compression
- block (cb). */
+ u32 compression_block_size; /* Size of a compression
+ block (cb). */
u8 compression_block_size_bits; /* Log2 of the size of
a cb. */
- u8 compression_block_clusters; /* Number of clusters
- per compression
- block. */
+ u8 compression_block_clusters; /* Number of clusters
+ per compression
+ block. */
+ s64 compressed_size; /* Copy from $DATA. */
};
};
Index: mft.c
===================================================================
RCS file: /cvsroot/linux-ntfs/ntfs-driver-tng/linux/fs/ntfs/mft.c,v
retrieving revision 1.49
retrieving revision 1.49.4.1
diff -U2 -r1.49 -r1.49.4.1
--- mft.c 14 Feb 2002 06:07:14 -0000 1.49
+++ mft.c 4 Mar 2002 19:04:02 -0000 1.49.4.1
@@ -148,5 +148,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)
@@ -181,5 +181,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;
@@ -187,5 +187,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...");
@@ -205,5 +205,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. */
@@ -216,5 +218,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.29
retrieving revision 1.29.6.1
diff -U2 -r1.29 -r1.29.6.1
--- ntfs.h 8 Feb 2002 05:17:11 -0000 1.29
+++ ntfs.h 4 Mar 2002 19:04:02 -0000 1.29.6.1
@@ -223,6 +223,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.77
retrieving revision 1.77.4.1
diff -U2 -r1.77 -r1.77.4.1
--- super.c 25 Feb 2002 02:49:33 -0000 1.77
+++ super.c 4 Mar 2002 19:04:02 -0000 1.77.4.1
@@ -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
@@ -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->allocated_size) >>
vol->cluster_size_bits;
+ vol->mftbmp_size = sle64_to_cpu(attr->data_size);
vol->mftbmp_initialized_size =
sle64_to_cpu(attr->initialized_size);
+ vol->mftbmp_allocated_size =
+ sle64_to_cpu(attr->allocated_size);
/* Consistency check. */
- if (vol->mftbmp_initialized_size <
- (vol->nr_mft_records + 7) >> 3) {
+ if (vol->mftbmp_size < (vol->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,11 @@
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)
{
@@ -1767,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;
}
@@ -1840,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.3.8.1
diff -U2 -r1.3 -r1.3.8.1
--- types.h 3 Feb 2002 19:31:17 -0000 1.3
+++ types.h 4 Mar 2002 19:04:02 -0000 1.3.8.1
@@ -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.6
retrieving revision 1.6.4.1
diff -U2 -r1.6 -r1.6.4.1
--- volume.h 14 Feb 2002 06:12:27 -0000 1.6
+++ volume.h 4 Mar 2002 19:04:02 -0000 1.6.4.1
@@ -26,4 +26,17 @@
#include "types.h"
+/* These are used to determine which inode names are re...
[truncated message content] |