aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-06-23 05:02:57 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-23 10:42:45 -0400
commit454e2398be9b9fa30433fccc548db34d19aa9958 (patch)
tree1f61cb0c3716a33b661cfc8977e9beeb480a322c /include/linux
parent1ad5544098a69d7dc1fa508cbb17e13a7a952fd8 (diff)
[PATCH] VFS: Permit filesystem to override root dentry on mount
Extend the get_sb() filesystem operation to take an extra argument that permits the VFS to pass in the target vfsmount that defines the mountpoint. The filesystem is then required to manually set the superblock and root dentry pointers. For most filesystems, this should be done with simple_set_mnt() which will set the superblock pointer and then set the root dentry to the superblock's s_root (as per the old default behaviour). The get_sb() op now returns an integer as there's now no need to return the superblock pointer. This patch permits a superblock to be implicitly shared amongst several mount points, such as can be done with NFS to avoid potential inode aliasing. In such a case, simple_set_mnt() would not be called, and instead the mnt_root and mnt_sb would be set directly. The patch also makes the following changes: (*) the get_sb_*() convenience functions in the core kernel now take a vfsmount pointer argument and return an integer, so most filesystems have to change very little. (*) If one of the convenience function is not used, then get_sb() should normally call simple_set_mnt() to instantiate the vfsmount. This will always return 0, and so can be tail-called from get_sb(). (*) generic_shutdown_super() now calls shrink_dcache_sb() to clean up the dcache upon superblock destruction rather than shrink_dcache_anon(). This is required because the superblock may now have multiple trees that aren't actually bound to s_root, but that still need to be cleaned up. The currently called functions assume that the whole tree is rooted at s_root, and that anonymous dentries are not the roots of trees which results in dentries being left unculled. However, with the way NFS superblock sharing are currently set to be implemented, these assumptions are violated: the root of the filesystem is simply a dummy dentry and inode (the real inode for '/' may well be inaccessible), and all the vfsmounts are rooted on anonymous[*] dentries with child trees. [*] Anonymous until discovered from another tree. (*) The documentation has been adjusted, including the additional bit of changing ext2_* into foo_* in the documentation. [akpm@osdl.org: convert ipath_fs, do other stuff] Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Cc: Nathan Scott <nathans@sgi.com> Cc: Roland Dreier <rolandd@cisco.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/fs.h25
-rw-r--r--include/linux/ramfs.h4
3 files changed, 17 insertions, 13 deletions
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 46d0e079735d..0dd1610a94a9 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -217,7 +217,6 @@ extern struct dentry * d_alloc_anon(struct inode *);
217extern struct dentry * d_splice_alias(struct inode *, struct dentry *); 217extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
218extern void shrink_dcache_sb(struct super_block *); 218extern void shrink_dcache_sb(struct super_block *);
219extern void shrink_dcache_parent(struct dentry *); 219extern void shrink_dcache_parent(struct dentry *);
220extern void shrink_dcache_anon(struct super_block *);
221extern int d_invalidate(struct dentry *); 220extern int d_invalidate(struct dentry *);
222 221
223/* only used at mount-time */ 222/* only used at mount-time */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 73c7d6f04b31..3e50dd24af87 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1269,23 +1269,26 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
1269struct file_system_type { 1269struct file_system_type {
1270 const char *name; 1270 const char *name;
1271 int fs_flags; 1271 int fs_flags;
1272 struct super_block *(*get_sb) (struct file_system_type *, int, 1272 int (*get_sb) (struct file_system_type *, int,
1273 const char *, void *); 1273 const char *, void *, struct vfsmount *);
1274 void (*kill_sb) (struct super_block *); 1274 void (*kill_sb) (struct super_block *);
1275 struct module *owner; 1275 struct module *owner;
1276 struct file_system_type * next; 1276 struct file_system_type * next;
1277 struct list_head fs_supers; 1277 struct list_head fs_supers;
1278}; 1278};
1279 1279
1280struct super_block *get_sb_bdev(struct file_system_type *fs_type, 1280extern int get_sb_bdev(struct file_system_type *fs_type,
1281 int flags, const char *dev_name, void *data, 1281 int flags, const char *dev_name, void *data,
1282 int (*fill_super)(struct super_block *, void *, int)); 1282 int (*fill_super)(struct super_block *, void *, int),
1283struct super_block *get_sb_single(struct file_system_type *fs_type, 1283 struct vfsmount *mnt);
1284extern int get_sb_single(struct file_system_type *fs_type,
1284 int flags, void *data, 1285 int flags, void *data,
1285 int (*fill_super)(struct super_block *, void *, int)); 1286 int (*fill_super)(struct super_block *, void *, int),
1286struct super_block *get_sb_nodev(struct file_system_type *fs_type, 1287 struct vfsmount *mnt);
1288extern int get_sb_nodev(struct file_system_type *fs_type,
1287 int flags, void *data, 1289 int flags, void *data,
1288 int (*fill_super)(struct super_block *, void *, int)); 1290 int (*fill_super)(struct super_block *, void *, int),
1291 struct vfsmount *mnt);
1289void generic_shutdown_super(struct super_block *sb); 1292void generic_shutdown_super(struct super_block *sb);
1290void kill_block_super(struct super_block *sb); 1293void kill_block_super(struct super_block *sb);
1291void kill_anon_super(struct super_block *sb); 1294void kill_anon_super(struct super_block *sb);
@@ -1296,8 +1299,10 @@ struct super_block *sget(struct file_system_type *type,
1296 int (*test)(struct super_block *,void *), 1299 int (*test)(struct super_block *,void *),
1297 int (*set)(struct super_block *,void *), 1300 int (*set)(struct super_block *,void *),
1298 void *data); 1301 void *data);
1299struct super_block *get_sb_pseudo(struct file_system_type *, char *, 1302extern int get_sb_pseudo(struct file_system_type *, char *,
1300 struct super_operations *ops, unsigned long); 1303 struct super_operations *ops, unsigned long,
1304 struct vfsmount *mnt);
1305extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
1301int __put_super(struct super_block *sb); 1306int __put_super(struct super_block *sb);
1302int __put_super_and_need_restart(struct super_block *sb); 1307int __put_super_and_need_restart(struct super_block *sb);
1303void unnamed_dev_init(void); 1308void unnamed_dev_init(void);
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index 78ecfa28b1c2..00b340ba6612 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -2,8 +2,8 @@
2#define _LINUX_RAMFS_H 2#define _LINUX_RAMFS_H
3 3
4struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev); 4struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev);
5struct super_block *ramfs_get_sb(struct file_system_type *fs_type, 5extern int ramfs_get_sb(struct file_system_type *fs_type,
6 int flags, const char *dev_name, void *data); 6 int flags, const char *dev_name, void *data, struct vfsmount *mnt);
7 7
8#ifndef CONFIG_MMU 8#ifndef CONFIG_MMU
9extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file, 9extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file,