diff options
author | Steven J. Magnani <steve@digidescorp.com> | 2012-10-04 20:14:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-05 14:05:09 -0400 |
commit | 7669e8fb09da47dd45c07a51394f01031ea81da8 (patch) | |
tree | 1112667a0606e27999a18b8dae574ae8ad01a151 /fs/fat/fat.h | |
parent | 21b6633d516c4f5d03ec02ede6374e320191003f (diff) |
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 fb95939ff870..ec54c3a7f2f7 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/string.h> | 5 | #include <linux/string.h> |
6 | #include <linux/nls.h> | 6 | #include <linux/nls.h> |
7 | #include <linux/fs.h> | 7 | #include <linux/fs.h> |
8 | #include <linux/hash.h> | ||
8 | #include <linux/mutex.h> | 9 | #include <linux/mutex.h> |
9 | #include <linux/ratelimit.h> | 10 | #include <linux/ratelimit.h> |
10 | #include <linux/msdos_fs.h> | 11 | #include <linux/msdos_fs.h> |
@@ -46,7 +47,8 @@ struct fat_mount_options { | |||
46 | usefree:1, /* Use free_clusters for FAT32 */ | 47 | usefree:1, /* Use free_clusters for FAT32 */ |
47 | tz_utc:1, /* Filesystem timestamps are in UTC */ | 48 | tz_utc:1, /* Filesystem timestamps are in UTC */ |
48 | rodir:1, /* allow ATTR_RO for directory */ | 49 | rodir:1, /* allow ATTR_RO for directory */ |
49 | discard:1; /* Issue discard requests on deletions */ | 50 | discard:1, /* Issue discard requests on deletions */ |
51 | nfs:1; /* Do extra work needed for NFS export */ | ||
50 | }; | 52 | }; |
51 | 53 | ||
52 | #define FAT_HASH_BITS 8 | 54 | #define FAT_HASH_BITS 8 |
@@ -88,6 +90,9 @@ struct msdos_sb_info { | |||
88 | 90 | ||
89 | spinlock_t inode_hash_lock; | 91 | spinlock_t inode_hash_lock; |
90 | struct hlist_head inode_hashtable[FAT_HASH_SIZE]; | 92 | struct hlist_head inode_hashtable[FAT_HASH_SIZE]; |
93 | |||
94 | spinlock_t dir_hash_lock; | ||
95 | struct hlist_head dir_hashtable[FAT_HASH_SIZE]; | ||
91 | }; | 96 | }; |
92 | 97 | ||
93 | #define FAT_CACHE_VALID 0 /* special case for valid cache */ | 98 | #define FAT_CACHE_VALID 0 /* special case for valid cache */ |
@@ -110,6 +115,7 @@ struct msdos_inode_info { | |||
110 | int i_attrs; /* unused attribute bits */ | 115 | int i_attrs; /* unused attribute bits */ |
111 | loff_t i_pos; /* on-disk position of directory entry or 0 */ | 116 | loff_t i_pos; /* on-disk position of directory entry or 0 */ |
112 | struct hlist_node i_fat_hash; /* hash by i_location */ | 117 | struct hlist_node i_fat_hash; /* hash by i_location */ |
118 | struct hlist_node i_dir_hash; /* hash by i_logstart */ | ||
113 | struct rw_semaphore truncate_lock; /* protect bmap against truncate */ | 119 | struct rw_semaphore truncate_lock; /* protect bmap against truncate */ |
114 | struct inode vfs_inode; | 120 | struct inode vfs_inode; |
115 | }; | 121 | }; |
@@ -262,7 +268,7 @@ extern int fat_subdirs(struct inode *dir); | |||
262 | extern int fat_scan(struct inode *dir, const unsigned char *name, | 268 | extern int fat_scan(struct inode *dir, const unsigned char *name, |
263 | struct fat_slot_info *sinfo); | 269 | struct fat_slot_info *sinfo); |
264 | extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, | 270 | extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, |
265 | struct msdos_dir_entry **de, loff_t *i_pos); | 271 | struct msdos_dir_entry **de); |
266 | extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); | 272 | extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); |
267 | extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots, | 273 | extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots, |
268 | struct fat_slot_info *sinfo); | 274 | struct fat_slot_info *sinfo); |
@@ -341,18 +347,9 @@ extern int fat_fill_super(struct super_block *sb, void *data, int silent, | |||
341 | 347 | ||
342 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, | 348 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, |
343 | struct inode *i2); | 349 | struct inode *i2); |
344 | static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, | 350 | static inline unsigned long fat_dir_hash(int logstart) |
345 | struct inode *inode) | ||
346 | { | 351 | { |
347 | loff_t i_pos; | 352 | return hash_32(logstart, FAT_HASH_BITS); |
348 | #if BITS_PER_LONG == 32 | ||
349 | spin_lock(&sbi->inode_hash_lock); | ||
350 | #endif | ||
351 | i_pos = MSDOS_I(inode)->i_pos; | ||
352 | #if BITS_PER_LONG == 32 | ||
353 | spin_unlock(&sbi->inode_hash_lock); | ||
354 | #endif | ||
355 | return i_pos; | ||
356 | } | 353 | } |
357 | 354 | ||
358 | /* fat/misc.c */ | 355 | /* fat/misc.c */ |
@@ -382,10 +379,10 @@ void fat_cache_destroy(void); | |||
382 | 379 | ||
383 | /* fat/nfs.c */ | 380 | /* fat/nfs.c */ |
384 | struct fid; | 381 | struct fid; |
385 | extern int fat_encode_fh(struct inode *inode, __u32 *fh, int *lenp, | ||
386 | struct inode *parent); | ||
387 | extern struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid, | 382 | extern struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid, |
388 | int fh_len, int fh_type); | 383 | int fh_len, int fh_type); |
384 | extern struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid, | ||
385 | int fh_len, int fh_type); | ||
389 | extern struct dentry *fat_get_parent(struct dentry *child_dir); | 386 | extern struct dentry *fat_get_parent(struct dentry *child_dir); |
390 | 387 | ||
391 | /* helper for printk */ | 388 | /* helper for printk */ |