From b9e6be22b85f3534720a1d85cbea6063180a7ef6 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov <aia21@cantab.net> Date: Thu, 27 Jun 2002 14:28:05 +0100 Subject: [PATCH] NTFS: 2.0.13 - Use iget5_locked() in preparation for fake inodes and small cleanups. - Remove nr_mft_bits and the now superfluous union with nr_mft_records from ntfs_volume structure. - Remove nr_lcn_bits and the now superfluous union with nr_clusters from ntfs_volume structure. - Use iget5_locked() and friends instead of conventional iget(). Wrap the call in fs/ntfs/inode.c::ntfs_iget() and update callers of iget() to use ntfs_iget(). Leave only one iget() call at mount time so we don't need an ntfs_iget_mount(). - Change fs/ntfs/inode.c::ntfs_new_extent_inode() to take mft_no as an additional argument. --- Documentation/filesystems/ntfs.txt | 3 + fs/ntfs/ChangeLog | 17 +- fs/ntfs/Makefile | 2 +- fs/ntfs/inode.c | 254 ++++++++++++++++++++++++++--- fs/ntfs/inode.h | 6 +- fs/ntfs/mft.c | 3 +- fs/ntfs/namei.c | 24 +-- fs/ntfs/super.c | 108 ++++++------ fs/ntfs/volume.h | 17 +- 9 files changed, 321 insertions(+), 113 deletions(-) diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index b2ee0cd9a863..4827bc2cda6f 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt @@ -247,6 +247,9 @@ ChangeLog Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. +2.0.13: + - Internal changes towards using iget5_locked() in preparation for + fake inodes and small cleanups to ntfs_volume structure. 2.0.12: - Internal cleanups in address space operations made possible by the changes introduced in the previous release. diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 4e3d51fee2bd..e921ef9d19ff 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -22,10 +22,25 @@ ToDo: based attribute i/o is further developed. - CLEANUP: Modularising code in aops.c a bit, e.g. a-la get_block(), will be cleaner and make code reuse easier. + - Modify ntfs_read_locked_inode() to return an error code and update + callers, i.e. ntfs_iget(), to pass that error code up instead of just + using -EIO. - Enable NFS exporting of NTFS. - - Use iget5_locked() and friends instead of conventional iget(). - Use fake inodes for address space i/o. +2.0.13 - Use iget5_locked() in preparation for fake inodes and small cleanups. + + - Remove nr_mft_bits and the now superfluous union with nr_mft_records + from ntfs_volume structure. + - Remove nr_lcn_bits and the now superfluous union with nr_clusters + from ntfs_volume structure. + - Use iget5_locked() and friends instead of conventional iget(). Wrap + the call in fs/ntfs/inode.c::ntfs_iget() and update callers of iget() + to use ntfs_iget(). Leave only one iget() call at mount time so we + don't need an ntfs_iget_mount(). + - Change fs/ntfs/inode.c::ntfs_new_extent_inode() to take mft_no as an + additional argument. + 2.0.12 - Initial cleanup of address space operations following 2.0.11 changes. - Merge fs/ntfs/aops.c::end_buffer_read_mst_async() and diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index b6211f4d9e8d..e6fe82353289 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \ mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o -EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.12\" +EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.13\" ifeq ($(CONFIG_NTFS_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 2b040e07135e..1af023c419d1 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -24,6 +24,178 @@ #include "ntfs.h" #include "dir.h" +#include "inode.h" +#include "attrib.h" + +/** + * ntfs_attr - ntfs in memory attribute structure + * @mft_no: mft record number of the base mft record of this attribute + * @name: Unicode name of the attribute (NULL if unnamed) + * @name_len: length of @name in Unicode characters (0 if unnamed) + * @type: attribute type (see layout.h) + * + * This structure exists only to provide a small structure for the + * ntfs_iget()/ntfs_test_inode()/ntfs_init_locked_inode() mechanism. + * + * NOTE: Elements are ordered by size to make the structure as compact as + * possible on all architectures. + */ +typedef struct { + unsigned long mft_no; + uchar_t *name; + u32 name_len; + ATTR_TYPES type; +} ntfs_attr; + +/** + * ntfs_test_inode - compare two (possibly fake) inodes for equality + * @vi: vfs inode which to test + * @na: ntfs attribute which is being tested with + * + * Compare the ntfs attribute embedded in the ntfs specific part of the vfs + * inode @vi for equality with the ntfs attribute @na. + * + * If searching for the normal file/directory inode, set @na->type to AT_UNUSED. + * @na->name and @na->name_len are then ignored. + * + * Return 1 if the attributes match and 0 if not. + * + * NOTE: This function runs with the inode_lock spin lock held so it is not + * allowed to sleep. + */ +static int ntfs_test_inode(struct inode *vi, ntfs_attr *na) +{ + ntfs_inode *ni; + + if (vi->i_ino != na->mft_no) + return 0; + ni = NTFS_I(vi); + /* If !NInoAttr(ni), @vi is a normal file or directory inode. */ + if (likely(!NInoAttr(ni))) { + /* If not looking for a normal inode this is a mismatch. */ + if (unlikely(na->type != AT_UNUSED)) + return 0; + } else { + /* A fake inode describing an attribute. */ + if (ni->type != na->type) + return 0; + if (ni->name_len != na->name_len) + return 0; + if (na->name_len && memcmp(ni->name, na->name, + na->name_len * sizeof(uchar_t))) + return 0; + } + /* Match! */ + return 1; +} + +/** + * ntfs_init_locked_inode - initialize an inode + * @vi: vfs inode to initialize + * @na: ntfs attribute which to initialize @vi to + * + * Initialize the vfs inode @vi with the values from the ntfs attribute @na in + * order to enable ntfs_test_inode() to do its work. + * + * If initializing the normal file/directory inode, set @na->type to AT_UNUSED. + * In that case, @na->name and @na->name_len should be set to NULL and 0, + * respectively. Although that is not strictly necessary as + * ntfs_read_inode_locked() will fill them in later. + * + * Return 0 on success and -errno on error. + * + * NOTE: This function runs with the inode_lock spin lock held so it is not + * allowed to sleep. (Hence the GFP_ATOMIC allocation.) + */ +static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na) +{ + ntfs_inode *ni = NTFS_I(vi); + + vi->i_ino = na->mft_no; + ni->type = na->type; + ni->name = na->name; + ni->name_len = na->name_len; + /* If initializing a normal inode, we are done. */ + if (likely(na->type == AT_UNUSED)) + return 0; + /* It is a fake inode. */ + NInoSetAttr(ni); + /* + * We have I30 global constant as an optimization as it is the name + * in >99.9% of named attributes! The other <0.1% incur a GFP_ATOMIC + * allocation but that is ok. And most attributes are unnamed anyway, + * thus the fraction of named attributes with name != I30 is actually + * absolutely tiny. + */ + if (na->name && na->name_len && na->name != I30) { + unsigned int i; + + i = na->name_len * sizeof(uchar_t); + ni->name = (uchar_t*)kmalloc(i + sizeof(uchar_t), GFP_ATOMIC); + if (!ni->name) + return -ENOMEM; + memcpy(ni->name, na->name, i); + ni->name[i] = cpu_to_le16('\0'); + } + return 0; +} + +typedef int (*test_t)(struct inode *, void *); +typedef int (*set_t)(struct inode *, void *); +static void ntfs_read_locked_inode(struct inode *vi); + +/** + * ntfs_iget - obtain a struct inode corresponding to a specific normal inode + * @sb: super block of mounted volume + * @mft_no: mft record number / inode number to obtain + * + * Obtain the struct inode corresponding to a specific normal inode (i.e. a + * file or directory). + * + * If the inode is in the cache, it is just returned with an increased + * reference count. Otherwise, a new struct inode is allocated and initialized, + * and finally ntfs_read_locked_inode() is called to read in the inode and + * fill in the remainder of the inode structure. + * + * Return the struct inode on success. Check the return value with IS_ERR() and + * if true, the function failed and the error code is obtained from PTR_ERR(). + */ +struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no) +{ + struct inode *vi; + ntfs_attr na; + + na.mft_no = mft_no; + na.type = AT_UNUSED; + na.name = NULL; + na.name_len = 0; + + vi = iget5_locked(sb, mft_no, (test_t)ntfs_test_inode, + (set_t)ntfs_init_locked_inode, &na); + if (!vi) + return ERR_PTR(-ENOMEM); + + /* If this is a freshly allocated inode, need to read it now. */ + if (vi->i_state & I_NEW) { + ntfs_read_locked_inode(vi); + unlock_new_inode(vi); + } +#if 0 + // TODO: Enable this and do the follow up cleanup, i.e. remove all the + // bad inode checks. -- BUT: Do we actually want to do this? -- It may + // result in repeated attemps to read a bad inode which is not + // desirable. (AIA) + /* + * There is no point in keeping bad inodes around. This also simplifies + * things in that we never need to check for bad inodes elsewhere. + */ + if (is_bad_inode(vi)) { + iput(vi); + vi = ERR_PTR(-EIO); + } +#endif + return vi; +} struct inode *ntfs_alloc_big_inode(struct super_block *sb) { @@ -32,12 +204,12 @@ struct inode *ntfs_alloc_big_inode(struct super_block *sb) ntfs_debug("Entering."); ni = (ntfs_inode *)kmem_cache_alloc(ntfs_big_inode_cache, SLAB_NOFS); - if (!ni) { - ntfs_error(sb, "Allocation of NTFS big inode structure " - "failed."); - return NULL; + if (likely(ni != NULL)) { + ni->state = 0; + return VFS_I(ni); } - return VFS_I(ni); + ntfs_error(sb, "Allocation of NTFS big inode structure failed."); + return NULL; } void ntfs_destroy_big_inode(struct inode *inode) @@ -49,14 +221,17 @@ void ntfs_destroy_big_inode(struct inode *inode) kmem_cache_free(ntfs_big_inode_cache, NTFS_I(inode)); } -ntfs_inode *ntfs_alloc_extent_inode(void) +static ntfs_inode *ntfs_alloc_extent_inode(void) { ntfs_inode *ni = (ntfs_inode *)kmem_cache_alloc(ntfs_inode_cache, SLAB_NOFS); ntfs_debug("Entering."); - if (unlikely(!ni)) - ntfs_error(NULL, "Allocation of NTFS inode structure failed."); - return ni; + if (likely(ni != NULL)) { + ni->state = 0; + return ni; + } + ntfs_error(NULL, "Allocation of NTFS inode structure failed."); + return NULL; } void ntfs_destroy_extent_inode(ntfs_inode *ni) @@ -68,27 +243,42 @@ void ntfs_destroy_extent_inode(ntfs_inode *ni) /** * __ntfs_init_inode - initialize ntfs specific part of an inode + * @sb: super block of mounted volume + * @ni: freshly allocated ntfs inode which to initialize * * Initialize an ntfs inode to defaults. * + * NOTE: ni->mft_no, ni->state, ni->type, ni->name, and ni->name_len are left + * untouched. Make sure to initialize them elsewhere. + * * Return zero on success and -ENOMEM on error. */ static void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni) { ntfs_debug("Entering."); - memset(ni, 0, sizeof(ntfs_inode)); + ni->initialized_size = ni->allocated_size = 0; + ni->seq_no = 0; atomic_set(&ni->count, 1); - ni->vol = NULL; + ni->vol = NTFS_SB(sb); init_run_list(&ni->run_list); init_rwsem(&ni->mrec_lock); atomic_set(&ni->mft_count, 0); ni->page = NULL; + ni->page_ofs = 0; + ni->attr_list_size = 0; ni->attr_list = NULL; init_run_list(&ni->attr_list_rl); + ni->_IDM(index_block_size) = 0; + ni->_IDM(index_vcn_size) = 0; + ni->_IDM(bmp_size) = 0; + ni->_IDM(bmp_initialized_size) = 0; + ni->_IDM(bmp_allocated_size) = 0; init_run_list(&ni->_IDM(bmp_rl)); + ni->_IDM(index_block_size_bits) = 0; + ni->_IDM(index_vcn_size_bits) = 0; init_MUTEX(&ni->extent_lock); + ni->nr_extents = 0; ni->_INE(base_ntfs_ino) = NULL; - ni->vol = NTFS_SB(sb); return; } @@ -102,13 +292,18 @@ static void ntfs_init_big_inode(struct inode *vi) return; } -ntfs_inode *ntfs_new_extent_inode(struct super_block *sb) +ntfs_inode *ntfs_new_extent_inode(struct super_block *sb, unsigned long mft_no) { ntfs_inode *ni = ntfs_alloc_extent_inode(); ntfs_debug("Entering."); - if (ni) + if (likely(ni != NULL)) { __ntfs_init_inode(sb, ni); + ni->mft_no = mft_no; + ni->type = AT_UNUSED; + ni->name = NULL; + ni->name_len = 0; + } return ni; } @@ -189,18 +384,20 @@ static int ntfs_is_extended_system_file(attr_search_context *ctx) } /** - * ntfs_read_inode - read an inode from its device + * ntfs_read_locked_inode - read an inode from its device * @vi: inode to read * - * ntfs_read_inode() is called from the VFS iget() function to read the inode + * ntfs_read_locked_inode() is called from the ntfs_iget() to read the inode * described by @vi into memory from the device. * * The only fields in @vi that we need to/can look at when the function is * called are i_sb, pointing to the mounted device's super block, and i_ino, - * the number of the inode to load. + * the number of the inode to load. If this is a fake inode, i.e. NInoAttr(), + * then the fields type, name, and name_len are also valid, and describe the + * attribute which this fake inode represents. * - * ntfs_read_inode() maps, pins and locks the mft record number i_ino for - * reading and sets up the necessary @vi fields as well as initializing + * ntfs_read_locked_inode() maps, pins and locks the mft record number i_ino + * for reading and sets up the necessary @vi fields as well as initializing * the ntfs inode. * * Q: What locks are held when the function is called? @@ -209,9 +406,9 @@ static int ntfs_is_extended_system_file(attr_search_context *ctx) * i_flags is set to 0 and we have no business touching it. Only an ioctl() * is allowed to write to them. We should of course be honouring them but * we need to do that using the IS_* macros defined in include/linux/fs.h. - * In any case ntfs_read_inode() has nothing to do with i_flags at all. + * In any case ntfs_read_locked_inode() has nothing to do with i_flags. */ -void ntfs_read_inode(struct inode *vi) +static void ntfs_read_locked_inode(struct inode *vi) { ntfs_volume *vol = NTFS_SB(vi->i_sb); ntfs_inode *ni; @@ -661,7 +858,7 @@ void ntfs_read_inode(struct inode *vi) vi->i_fop = &ntfs_dir_ops; vi->i_mapping->a_ops = &ntfs_dir_aops; } else { - /* It is a file: find first extent of unnamed data attribute. */ + /* It is a file. */ reinit_attr_search_ctx(ctx); /* Setup the data attribute, even if not present. */ @@ -669,6 +866,7 @@ void ntfs_read_inode(struct inode *vi) ni->name = NULL; ni->name_len = 0; + /* Find first extent of the unnamed data attribute. */ if (!lookup_attr(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx)) { vi->i_size = ni->initialized_size = ni->allocated_size = 0LL; @@ -877,15 +1075,17 @@ void ntfs_read_inode_mount(struct inode *vi) ntfs_debug("Entering."); - /* Initialize the ntfs specific part of @vi. */ - ntfs_init_big_inode(vi); - ni = NTFS_I(vi); if (vi->i_ino != FILE_MFT) { ntfs_error(sb, "Called for inode 0x%lx but only inode %d " "allowed.", vi->i_ino, FILE_MFT); goto err_out; } + /* Initialize the ntfs specific part of @vi. */ + ntfs_init_big_inode(vi); + + ni = NTFS_I(vi); + /* Setup the data attribute. It is special as it is mst protected. */ NInoSetNonResident(ni); NInoSetMstProtected(ni); @@ -1158,7 +1358,7 @@ void ntfs_read_inode_mount(struct inode *vi) ntfs_error(sb, "$MFT is too big! Aborting."); goto put_err_out; } - vol->_VMM(nr_mft_records) = ll; + vol->nr_mft_records = ll; /* * We have got the first extent of the run_list for * $MFT which means it is now relatively safe to call @@ -1184,7 +1384,7 @@ void ntfs_read_inode_mount(struct inode *vi) * ntfs_read_inode() on extents of $MFT/$DATA. But lets * hope this never happens... */ - ntfs_read_inode(vi); + ntfs_read_locked_inode(vi); if (is_bad_inode(vi)) { ntfs_error(sb, "ntfs_read_inode() of $MFT " "failed. BUG or corrupt $MFT. " diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h index 2c97dd2b353e..0025b9026633 100644 --- a/fs/ntfs/inode.h +++ b/fs/ntfs/inode.h @@ -231,14 +231,16 @@ static inline struct inode *VFS_I(ntfs_inode *ni) return &((big_ntfs_inode*)ni)->vfs_inode; } +extern struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no); + extern struct inode *ntfs_alloc_big_inode(struct super_block *sb); extern void ntfs_destroy_big_inode(struct inode *inode); extern void ntfs_clear_big_inode(struct inode *vi); -extern ntfs_inode *ntfs_new_extent_inode(struct super_block *sb); +extern ntfs_inode *ntfs_new_extent_inode(struct super_block *sb, + unsigned long mft_no); extern void ntfs_clear_extent_inode(ntfs_inode *ni); -extern void ntfs_read_inode(struct inode *vi); extern void ntfs_read_inode_mount(struct inode *vi); extern void ntfs_dirty_inode(struct inode *vi); diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index bede95895c11..efece0f373a6 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -417,14 +417,13 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref, return m; } /* Record wasn't there. Get a new ntfs inode and initialize it. */ - ni = ntfs_new_extent_inode(base_ni->vol->sb); + ni = ntfs_new_extent_inode(base_ni->vol->sb, mft_no); if (!ni) { up(&base_ni->extent_lock); atomic_dec(&base_ni->count); return ERR_PTR(-ENOMEM); } ni->vol = base_ni->vol; - ni->mft_no = mft_no; ni->seq_no = seq_no; ni->nr_extents = -1; ni->_INE(base_ntfs_ino) = base_ni; diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index 87b31ccd22bd..060e2c27f00d 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -38,8 +38,8 @@ * supplying the name of the inode in @dent->d_name.name. ntfs_lookup() * converts the name to Unicode and walks the contents of the directory inode * @dir_ino looking for the converted Unicode name. If the name is found in the - * directory, the corresponding inode is loaded by calling iget() on its inode - * number and the inode is associated with the dentry @dent via a call to + * directory, the corresponding inode is loaded by calling ntfs_iget() on its + * inode number and the inode is associated with the dentry @dent via a call to * d_add(). * * If the name is not found in the directory, a NULL inode is inserted into the @@ -111,9 +111,9 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent) kmem_cache_free(ntfs_name_cache, uname); if (!IS_ERR_MREF(mref)) { dent_ino = MREF(mref); - ntfs_debug("Found inode 0x%lx. Calling iget.", dent_ino); - dent_inode = iget(vol->sb, dent_ino); - if (dent_inode) { + ntfs_debug("Found inode 0x%lx. Calling ntfs_iget.", dent_ino); + dent_inode = ntfs_iget(vol->sb, dent_ino); + if (likely(!IS_ERR(dent_inode))) { /* Consistency check. */ if (MSEQNO(mref) == NTFS_I(dent_inode)->seq_no || dent_ino == FILE_MFT) { @@ -132,16 +132,19 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent) ntfs_error(vol->sb, "Found stale reference to inode " "0x%lx (reference sequence number = " "0x%x, inode sequence number = 0x%x, " - "returning -EACCES. Run chkdsk.", + "returning -EIO. Run chkdsk.", dent_ino, MSEQNO(mref), NTFS_I(dent_inode)->seq_no); iput(dent_inode); + dent_inode = ERR_PTR(-EIO); } else - ntfs_error(vol->sb, "iget(0x%lx) failed, returning " - "-EACCES.", dent_ino); + ntfs_error(vol->sb, "ntfs_iget(0x%lx) failed with " + "error code %li.", dent_ino, + PTR_ERR(dent_inode)); if (name) kfree(name); - return ERR_PTR(-EACCES); + /* Return the error code. */ + return (struct dentry *)dent_inode; } /* It is guaranteed that name is no longer allocated at this point. */ if (MREF_ERR(mref) == -ENOENT) { @@ -256,7 +259,8 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent) BUG_ON(real_dent->d_inode != dent_inode); /* * Already have the inode and the dentry attached, decrement - * the reference count to balance the iget() we did earlier on. + * the reference count to balance the ntfs_iget() we did + * earlier on. */ iput(dent_inode); return real_dent; diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 50632b950fb8..94cc54668d87 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -605,17 +605,17 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b) sizeof(unsigned long) * 4); return FALSE; } - vol->_VCL(nr_clusters) = ll; - ntfs_debug("vol->nr_clusters = 0x%Lx", (long long)vol->_VCL(nr_clusters)); + vol->nr_clusters = ll; + ntfs_debug("vol->nr_clusters = 0x%Lx", (long long)vol->nr_clusters); ll = sle64_to_cpu(b->mft_lcn); - if (ll >= vol->_VCL(nr_clusters)) { + if (ll >= vol->nr_clusters) { ntfs_error(vol->sb, "MFT LCN is beyond end of volume. Weird."); return FALSE; } vol->mft_lcn = ll; ntfs_debug("vol->mft_lcn = 0x%Lx", (long long)vol->mft_lcn); ll = sle64_to_cpu(b->mftmirr_lcn); - if (ll >= vol->_VCL(nr_clusters)) { + if (ll >= vol->nr_clusters) { ntfs_error(vol->sb, "MFTMirr LCN is beyond end of volume. " "Weird."); return FALSE; @@ -629,7 +629,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b) * Determine MFT zone size. This is not strictly the right place to do * this, but I am too lazy to create a function especially for it... */ - vol->mft_zone_end = vol->_VCL(nr_clusters); + vol->mft_zone_end = vol->nr_clusters; switch (vol->mft_zone_multiplier) { /* % of volume size in clusters */ case 4: vol->mft_zone_end = vol->mft_zone_end >> 1; /* 50% */ @@ -678,9 +678,9 @@ static BOOL load_and_init_upcase(ntfs_volume *vol) ntfs_debug("Entering."); /* Read upcase table and setup vol->upcase and vol->upcase_len. */ - ino = iget(sb, FILE_UpCase); - if (!ino || is_bad_inode(ino)) { - if (ino) + ino = ntfs_iget(sb, FILE_UpCase); + if (IS_ERR(ino) || is_bad_inode(ino)) { + if (!IS_ERR(ino)) iput(ino); goto upcase_failed; } @@ -848,7 +848,7 @@ static BOOL load_system_files(ntfs_volume *vol) vol->mftbmp_allocated_size = sle64_to_cpu(attr->_ANR(allocated_size)); /* Consistency check. */ - if (vol->mftbmp_size < (vol->_VMM(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 " "bitmap: impossible. $MFT is " @@ -914,9 +914,9 @@ static BOOL load_system_files(ntfs_volume *vol) // volume read-write... /* Get mft mirror inode. */ - vol->mftmirr_ino = iget(sb, FILE_MFTMirr); - if (!vol->mftmirr_ino || is_bad_inode(vol->mftmirr_ino)) { - if (is_bad_inode(vol->mftmirr_ino)) + vol->mftmirr_ino = ntfs_iget(sb, FILE_MFTMirr); + if (IS_ERR(vol->mftmirr_ino) || is_bad_inode(vol->mftmirr_ino)) { + if (!IS_ERR(vol->mftmirr_ino)) iput(vol->mftmirr_ino); ntfs_error(sb, "Failed to load $MFTMirr."); return FALSE; @@ -932,13 +932,13 @@ static BOOL load_system_files(ntfs_volume *vol) * 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); - if (!vol->lcnbmp_ino || is_bad_inode(vol->lcnbmp_ino)) { - if (is_bad_inode(vol->lcnbmp_ino)) + vol->lcnbmp_ino = ntfs_iget(sb, FILE_Bitmap); + if (IS_ERR(vol->lcnbmp_ino) || is_bad_inode(vol->lcnbmp_ino)) { + if (!IS_ERR(vol->lcnbmp_ino)) iput(vol->lcnbmp_ino); goto bitmap_failed; } - if ((vol->_VCL(nr_lcn_bits) + 7) >> 3 > vol->lcnbmp_ino->i_size) { + if ((vol->nr_clusters + 7) >> 3 > vol->lcnbmp_ino->i_size) { iput(vol->lcnbmp_ino); bitmap_failed: ntfs_error(sb, "Failed to load $Bitmap."); @@ -948,9 +948,9 @@ static BOOL load_system_files(ntfs_volume *vol) * Get the volume inode and setup our cache of the volume flags and * version. */ - vol->vol_ino = iget(sb, FILE_Volume); - if (!vol->vol_ino || is_bad_inode(vol->vol_ino)) { - if (is_bad_inode(vol->vol_ino)) + vol->vol_ino = ntfs_iget(sb, FILE_Volume); + if (IS_ERR(vol->vol_ino) || is_bad_inode(vol->vol_ino)) { + if (!IS_ERR(vol->vol_ino)) iput(vol->vol_ino); volume_failed: ntfs_error(sb, "Failed to load $Volume."); @@ -993,9 +993,9 @@ static BOOL load_system_files(ntfs_volume *vol) * Get the inode for the logfile and empty it if this is a read-write * mount. */ - tmp_ino = iget(sb, FILE_LogFile); - if (!tmp_ino || is_bad_inode(tmp_ino)) { - if (is_bad_inode(tmp_ino)) + tmp_ino = ntfs_iget(sb, FILE_LogFile); + if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { + if (!IS_ERR(tmp_ino)) iput(tmp_ino); ntfs_error(sb, "Failed to load $LogFile."); // FIMXE: We only want to empty the thing so pointless bailing @@ -1010,9 +1010,9 @@ static BOOL load_system_files(ntfs_volume *vol) * Get the inode for the attribute definitions file and parse the * attribute definitions. */ - tmp_ino = iget(sb, FILE_AttrDef); - if (!tmp_ino || is_bad_inode(tmp_ino)) { - if (is_bad_inode(tmp_ino)) + tmp_ino = ntfs_iget(sb, FILE_AttrDef); + if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { + if (!IS_ERR(tmp_ino)) iput(tmp_ino); ntfs_error(sb, "Failed to load $AttrDef."); goto iput_vol_bmp_mirr_err_out; @@ -1020,9 +1020,9 @@ static BOOL load_system_files(ntfs_volume *vol) // FIXME: Parse the attribute definitions. iput(tmp_ino); /* Get the root directory inode. */ - vol->root_ino = iget(sb, FILE_root); - if (!vol->root_ino || is_bad_inode(vol->root_ino)) { - if (is_bad_inode(vol->root_ino)) + vol->root_ino = ntfs_iget(sb, FILE_root); + if (IS_ERR(vol->root_ino) || is_bad_inode(vol->root_ino)) { + if (!IS_ERR(vol->root_ino)) iput(vol->root_ino); ntfs_error(sb, "Failed to load root directory."); goto iput_vol_bmp_mirr_err_out; @@ -1032,18 +1032,18 @@ static BOOL load_system_files(ntfs_volume *vol) return TRUE; /* NTFS 3.0+ specific initialization. */ /* Get the security descriptors inode. */ - vol->secure_ino = iget(sb, FILE_Secure); - if (!vol->secure_ino || is_bad_inode(vol->secure_ino)) { - if (is_bad_inode(vol->secure_ino)) + vol->secure_ino = ntfs_iget(sb, FILE_Secure); + if (IS_ERR(vol->secure_ino) || is_bad_inode(vol->secure_ino)) { + if (!IS_ERR(vol->secure_ino)) iput(vol->secure_ino); ntfs_error(sb, "Failed to load $Secure."); goto iput_root_vol_bmp_mirr_err_out; } // FIXME: Initialize security. /* Get the extended system files' directory inode. */ - tmp_ino = iget(sb, FILE_Extend); - if (!tmp_ino || is_bad_inode(tmp_ino)) { - if (is_bad_inode(tmp_ino)) + tmp_ino = ntfs_iget(sb, FILE_Extend); + if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) { + if (!IS_ERR(tmp_ino)) iput(tmp_ino); ntfs_error(sb, "Failed to load $Extend."); goto iput_sec_root_vol_bmp_mirr_err_out; @@ -1051,8 +1051,8 @@ static BOOL load_system_files(ntfs_volume *vol) // FIXME: Do something. E.g. want to delete the $UsnJrnl if exists. // Note we might be doing this at the wrong level; we might want to // d_alloc_root() and then do a "normal" open(2) of $Extend\$UsnJrnl - // rather than using iget here, as we don't know the inode number for - // the files in $Extend directory. + // rather than using ntfs_iget here, as we don't know the inode number + // for the files in $Extend directory. iput(tmp_ino); return TRUE; iput_sec_root_vol_bmp_mirr_err_out: @@ -1172,7 +1172,7 @@ s64 get_nr_free_clusters(ntfs_volume *vol) * Convert the number of bits into bytes rounded up, then convert into * multiples of PAGE_CACHE_SIZE. */ - max_index = (vol->_VCL(nr_clusters) + 7) >> (3 + PAGE_CACHE_SHIFT); + max_index = (vol->nr_clusters + 7) >> (3 + PAGE_CACHE_SHIFT); /* Use multiples of 4 bytes. */ max_size = PAGE_CACHE_SIZE >> 2; ntfs_debug("Reading $BITMAP, max_index = 0x%lx, max_size = 0x%x.", @@ -1211,7 +1211,7 @@ s64 get_nr_free_clusters(ntfs_volume *vol) * Get the multiples of 4 bytes in use in the final partial * page. */ - max_size = ((((vol->_VCL(nr_clusters) + 7) >> 3) & ~PAGE_CACHE_MASK) + max_size = ((((vol->nr_clusters + 7) >> 3) & ~PAGE_CACHE_MASK) + 3) >> 2; /* If there is a partial page go back and do it. */ if (max_size) { @@ -1254,7 +1254,7 @@ unsigned long get_nr_free_mft_records(ntfs_volume *vol) * Convert the number of bits into bytes rounded up, then convert into * multiples of PAGE_CACHE_SIZE. */ - max_index = (vol->_VMM(nr_mft_records) + 7) >> (3 + PAGE_CACHE_SHIFT); + max_index = (vol->nr_mft_records + 7) >> (3 + PAGE_CACHE_SHIFT); /* Use multiples of 4 bytes. */ max_size = PAGE_CACHE_SIZE >> 2; ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = " @@ -1293,12 +1293,12 @@ unsigned long get_nr_free_mft_records(ntfs_volume *vol) * Get the multiples of 4 bytes in use in the final partial * page. */ - max_size = ((((vol->_VMM(nr_mft_records) + 7) >> 3) & + max_size = ((((vol->nr_mft_records + 7) >> 3) & ~PAGE_CACHE_MASK) + 3) >> 2; /* If there is a partial page go back and do it. */ if (max_size) { /* Compensate for out of bounds zero bits. */ - if ((i = vol->_VMM(nr_mft_records) & 31)) + if ((i = vol->nr_mft_records & 31)) nr_free -= 32 - i; ntfs_debug("Handling partial page, max_size = 0x%x", max_size); @@ -1345,7 +1345,7 @@ int ntfs_statfs(struct super_block *sb, struct statfs *sfs) * inodes are also stored in data blocs ($MFT is a file) this is just * the total clusters. */ - sfs->f_blocks = vol->_VCL(nr_clusters) << vol->cluster_size_bits >> + sfs->f_blocks = vol->nr_clusters << vol->cluster_size_bits >> PAGE_CACHE_SHIFT; /* Free data blocks in file system in units of f_bsize. */ size = get_nr_free_clusters(vol) << vol->cluster_size_bits >> @@ -1394,8 +1394,6 @@ struct super_operations ntfs_mount_sops = { struct super_operations ntfs_sops = { alloc_inode: ntfs_alloc_big_inode, /* VFS: Allocate a new inode. */ destroy_inode: ntfs_destroy_big_inode, /* VFS: Deallocate an inode. */ - read_inode: ntfs_read_inode, /* VFS: Load inode from disk, - called from iget(). */ dirty_inode: ntfs_dirty_inode, /* VFS: Called from __mark_inode_dirty(). */ //write_inode: NULL, /* VFS: Write dirty inode to disk. */ @@ -1575,9 +1573,9 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) /* * Now load the metadata required for the page cache and our address * space operations to function. We do this by setting up a specialised - * read_inode method and then just calling iget() to obtain the inode - * for $MFT which is sufficient to allow our normal inode operations - * and associated address space operations to function. + * read_inode method and then just calling the normal iget() to obtain + * the inode for $MFT which is sufficient to allow our normal inode + * operations and associated address space operations to function. */ /* * Poison vol->mft_ino so we know whether iget() called into our @@ -1601,9 +1599,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) * Note: sb->s_op has already been set to &ntfs_sops by our specialized * ntfs_read_inode_mount() method when it was invoked by iget(). */ - down(&ntfs_lock); - /* * The current mount is a compression user if the cluster size is * less than or equal 4kiB. @@ -1618,7 +1614,6 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) goto iput_tmp_ino_err_out_now; } } - /* * Increment the number of mounts and generate the global default * upcase table if necessary. Also temporarily increment the number of @@ -1629,12 +1624,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) ntfs_nr_upcase_users++; up(&ntfs_lock); - /* * From now on, ignore @silent parameter. If we fail below this line, * it will be due to a corrupt fs or a system error, so we report it. */ - /* * Open the system files with normal access functions and complete * setting up the ntfs super block. @@ -1643,9 +1636,8 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) ntfs_error(sb, "Failed to load system files."); goto unl_upcase_iput_tmp_ino_err_out_now; } - if ((sb->s_root = d_alloc_root(vol->root_ino))) { - /* We increment i_count simulating an iget(). */ + /* We increment i_count simulating an ntfs_iget(). */ atomic_inc(&vol->root_ino->i_count); ntfs_debug("Exiting, status successful."); /* Release the default upcase if it has no users. */ @@ -1710,10 +1702,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) #undef OGIN /* * This is needed to get ntfs_clear_extent_inode() called for each - * inode we have ever called iget()/iput() on, otherwise we A) leak - * resources and B) a subsequent mount fails automatically due to - * iget() never calling down into our ntfs_read_inode{_mount}() methods - * again... + * inode we have ever called ntfs_iget()/iput() on, otherwise we A) + * leak resources and B) a subsequent mount fails automatically due to + * ntfs_iget() never calling down into our ntfs_read_locked_inode() + * method again... */ if (invalidate_inodes(sb)) { ntfs_error(sb, "Busy inodes left. This is most likely a NTFS " diff --git a/fs/ntfs/volume.h b/fs/ntfs/volume.h index 01b429378fad..f289335df624 100644 --- a/fs/ntfs/volume.h +++ b/fs/ntfs/volume.h @@ -3,7 +3,7 @@ * of the Linux-NTFS project. * * Copyright (c) 2001,2002 Anton Altaparmakov. - * Copyright (C) 2002 Richard Russon. + * Copyright (c) 2002 Richard Russon. * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -89,10 +89,8 @@ typedef struct { u32 index_record_size; /* in bytes */ u32 index_record_size_mask; /* index_record_size - 1 */ u8 index_record_size_bits; /* log2(index_record_size) */ - union { - LCN nr_clusters; /* Volume size in clusters. */ - LCN nr_lcn_bits; /* Number of bits in lcn bitmap. */ - } SN(vcl); + LCN nr_clusters; /* Volume size in clusters == number of + bits in lcn bitmap. */ LCN mft_lcn; /* Cluster location of mft data. */ LCN mftmirr_lcn; /* Cluster location of copy of mft. */ u64 serial_no; /* The volume serial number. */ @@ -104,10 +102,8 @@ typedef struct { struct inode *mft_ino; /* The VFS inode of $MFT. */ struct rw_semaphore mftbmp_lock; /* Lock for serializing accesses to the mft record bitmap ($MFT/$BITMAP). */ - union { - unsigned long nr_mft_records; /* Number of mft records. */ - unsigned long nr_mft_bits; /* Number of bits in mft bitmap. */ - } SN(vmm); + unsigned long nr_mft_records; /* Number of mft records == number of + bits in mft bitmap. */ struct address_space mftbmp_mapping; /* Page cache for $MFT/$BITMAP. */ run_list mftbmp_rl; /* Run list for $MFT/$BITMAP. */ s64 mftbmp_size; /* Data size of $MFT/$BITMAP. */ @@ -128,8 +124,5 @@ typedef struct { struct nls_table *nls_map; } ntfs_volume; -#define _VCL(X) SC(vcl,X) -#define _VMM(X) SC(vmm,X) - #endif /* _LINUX_NTFS_VOLUME_H */ -- 2.30.9