diff options
author | Steven J. Magnani <steve@digidescorp.com> | 2012-10-04 17:14:45 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-06 03:05:09 +0900 |
commit | 7669e8fb09da47dd45c07a51394f01031ea81da8 (patch) | |
tree | 1112667a0606e27999a18b8dae574ae8ad01a151 /fs/fat/fat.h | |
parent | 21b6633d516c4f5d03ec02ede6374e320191003f (diff) | |
download | op-kernel-dev-7669e8fb09da47dd45c07a51394f01031ea81da8.zip op-kernel-dev-7669e8fb09da47dd45c07a51394f01031ea81da8.tar.gz |
fat (exportfs): fix dentry reconnection
Maintain an index of directory inodes by starting cluster, so that
fat_get_parent() can return the proper cached inode rather than inventing
one that cannot be traced back to the filesystem root.
Add a new msdos/vfat binary mount option "nfs" so that FAT filesystems
that are _not_ exported via NFS are not saddled with maintenance of an
index they will never use.
Finally, simplify NFS file handle generation and lookups. An
ext2-congruent implementation is adequate for FAT needs.
Signed-off-by: Steven J. Magnani <steve@digidescorp.com>
Acked-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/fat/fat.h')
-rw-r--r-- | fs/fat/fat.h | 27 |
1 files changed, 12 insertions, 15 deletions
diff --git a/fs/fat/fat.h b/fs/fat/fat.h index fb95939..ec54c3a 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -5,6 +5,7 @@ #include <linux/string.h> #include <linux/nls.h> #include <linux/fs.h> +#include <linux/hash.h> #include <linux/mutex.h> #include <linux/ratelimit.h> #include <linux/msdos_fs.h> @@ -46,7 +47,8 @@ struct fat_mount_options { usefree:1, /* Use free_clusters for FAT32 */ tz_utc:1, /* Filesystem timestamps are in UTC */ rodir:1, /* allow ATTR_RO for directory */ - discard:1; /* Issue discard requests on deletions */ + discard:1, /* Issue discard requests on deletions */ + nfs:1; /* Do extra work needed for NFS export */ }; #define FAT_HASH_BITS 8 @@ -88,6 +90,9 @@ struct msdos_sb_info { spinlock_t inode_hash_lock; struct hlist_head inode_hashtable[FAT_HASH_SIZE]; + + spinlock_t dir_hash_lock; + struct hlist_head dir_hashtable[FAT_HASH_SIZE]; }; #define FAT_CACHE_VALID 0 /* special case for valid cache */ @@ -110,6 +115,7 @@ struct msdos_inode_info { int i_attrs; /* unused attribute bits */ loff_t i_pos; /* on-disk position of directory entry or 0 */ struct hlist_node i_fat_hash; /* hash by i_location */ + struct hlist_node i_dir_hash; /* hash by i_logstart */ struct rw_semaphore truncate_lock; /* protect bmap against truncate */ struct inode vfs_inode; }; @@ -262,7 +268,7 @@ extern int fat_subdirs(struct inode *dir); extern int fat_scan(struct inode *dir, const unsigned char *name, struct fat_slot_info *sinfo); extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, - struct msdos_dir_entry **de, loff_t *i_pos); + struct msdos_dir_entry **de); extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots, struct fat_slot_info *sinfo); @@ -341,18 +347,9 @@ extern int fat_fill_super(struct super_block *sb, void *data, int silent, extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2); -static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, - struct inode *inode) +static inline unsigned long fat_dir_hash(int logstart) { - loff_t i_pos; -#if BITS_PER_LONG == 32 - spin_lock(&sbi->inode_hash_lock); -#endif - i_pos = MSDOS_I(inode)->i_pos; -#if BITS_PER_LONG == 32 - spin_unlock(&sbi->inode_hash_lock); -#endif - return i_pos; + return hash_32(logstart, FAT_HASH_BITS); } /* fat/misc.c */ @@ -382,10 +379,10 @@ void fat_cache_destroy(void); /* fat/nfs.c */ struct fid; -extern int fat_encode_fh(struct inode *inode, __u32 *fh, int *lenp, - struct inode *parent); extern struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fh_type); +extern struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type); extern struct dentry *fat_get_parent(struct dentry *child_dir); /* helper for printk */ |