* [PATCH] permit fs->get_sb() to return alternative root
@ 2004-05-18 14:14 ` David Howells
2004-05-18 14:43 ` Trond Myklebust
[not found] ` <20040518152426.GY17014@parcelfarce.linux.theplanet.co.uk>
0 siblings, 2 replies; 4+ messages in thread
From: David Howells @ 2004-05-18 14:14 UTC (permalink / raw)
To: viro, Linus Torvalds, Trond Myklebust; +Cc: linux-fsdevel
Hi Al, Linux,
Here's a patch to add an extra argument to the get_sb() method of struct
file_system_type that allows a filesystem to suggest an alternative dentry to
be attached to the vfsmount structure. If no such suggestion is made,
sb->s_root is selected as usual.
The reason I want this is so that the NFS fs can be improved such that two
mounts made from the same server will be able to use the same superblock, the
same inodes and the same dentries (as I've been discussing with Trond), this
eliminating aliasing at the client end.
This deals with the case of doing, for instance:
mount file:/export/home0/dhowells /home/dhowells
mount file:/export/home0/dwmw2 /home/dwmw2
And then finding you've got files hard-linked across the two.
In effect, you get a sort of bind mount.
It also means that local on-disc caching becomes feasible with cachefs.
David
diff -uNr linux-2.6.6/include/linux/fs.h linux-2.6.6-getsb/include/linux/fs.h
--- linux-2.6.6/include/linux/fs.h 2004-05-11 11:28:57.000000000 +0100
+++ linux-2.6.6-getsb/include/linux/fs.h 2004-05-18 11:35:07.000000000 +0100
@@ -1086,7 +1086,7 @@
const char *name;
int fs_flags;
struct super_block *(*get_sb) (struct file_system_type *, int,
- const char *, void *);
+ const char *, void *, struct dentry **);
void (*kill_sb) (struct super_block *);
struct module *owner;
struct file_system_type * next;
diff -uNr linux-2.6.6/fs/super.c linux-2.6.6-getsb/fs/super.c
--- linux-2.6.6/fs/super.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/super.c 2004-05-18 13:55:58.000000000 +0100
@@ -738,6 +738,7 @@
struct file_system_type *type = get_fs_type(fstype);
struct super_block *sb = ERR_PTR(-ENOMEM);
struct vfsmount *mnt;
+ struct dentry *root;
int error;
char *secdata = NULL;
@@ -762,15 +763,18 @@
}
}
- sb = type->get_sb(type, flags, name, data);
+ root = NULL;
+ sb = type->get_sb(type, flags, name, data, &root);
if (IS_ERR(sb))
goto out_free_secdata;
+ if (!root)
+ root = sb->s_root;
error = security_sb_kern_mount(sb, secdata);
if (error)
goto out_sb;
mnt->mnt_sb = sb;
- mnt->mnt_root = dget(sb->s_root);
- mnt->mnt_mountpoint = sb->s_root;
+ mnt->mnt_root = dget(root);
+ mnt->mnt_mountpoint = mnt->mnt_root;
mnt->mnt_parent = mnt;
up_write(&sb->s_umount);
put_filesystem(type);
diff -uNr linux-2.6.6/arch/ia64/kernel/perfmon.c linux-2.6.6-getsb/arch/ia64/kernel/perfmon.c
--- linux-2.6.6/arch/ia64/kernel/perfmon.c 2004-05-11 11:28:36.000000000 +0100
+++ linux-2.6.6-getsb/arch/ia64/kernel/perfmon.c 2004-05-18 13:35:17.000000000 +0100
@@ -592,7 +592,8 @@
static struct super_block *
-pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
+pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data,
+ struct dentry **_root)
{
return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC);
}
diff -uNr linux-2.6.6/arch/ia64/sn/io/hwgfs/ramfs.c linux-2.6.6-getsb/arch/ia64/sn/io/hwgfs/ramfs.c
--- linux-2.6.6/arch/ia64/sn/io/hwgfs/ramfs.c 2004-05-11 11:28:14.000000000 +0100
+++ linux-2.6.6-getsb/arch/ia64/sn/io/hwgfs/ramfs.c 2004-05-18 13:35:35.000000000 +0100
@@ -165,7 +165,7 @@
}
static struct super_block *hwgfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, hwgfs_fill_super);
}
diff -uNr linux-2.6.6/drivers/isdn/capi/capifs.c linux-2.6.6-getsb/drivers/isdn/capi/capifs.c
--- linux-2.6.6/drivers/isdn/capi/capifs.c 2004-05-11 11:26:21.000000000 +0100
+++ linux-2.6.6-getsb/drivers/isdn/capi/capifs.c 2004-05-18 13:37:35.000000000 +0100
@@ -118,7 +118,7 @@
}
static struct super_block *capifs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, capifs_fill_super);
}
diff -uNr linux-2.6.6/drivers/misc/ibmasm/ibmasmfs.c linux-2.6.6-getsb/drivers/misc/ibmasm/ibmasmfs.c
--- linux-2.6.6/drivers/misc/ibmasm/ibmasmfs.c 2004-05-11 11:26:31.000000000 +0100
+++ linux-2.6.6-getsb/drivers/misc/ibmasm/ibmasmfs.c 2004-05-18 13:38:51.000000000 +0100
@@ -103,7 +103,8 @@
static struct super_block *ibmasmfs_get_super(struct file_system_type *fst,
- int flags, const char *name, void *data)
+ int flags, const char *name, void *data,
+ struct dentry **_root)
{
return get_sb_single(fst, flags, data, ibmasmfs_fill_super);
}
diff -uNr linux-2.6.6/drivers/oprofile/oprofilefs.c linux-2.6.6-getsb/drivers/oprofile/oprofilefs.c
--- linux-2.6.6/drivers/oprofile/oprofilefs.c 2004-05-11 11:26:28.000000000 +0100
+++ linux-2.6.6-getsb/drivers/oprofile/oprofilefs.c 2004-05-18 13:38:25.000000000 +0100
@@ -300,7 +300,7 @@
static struct super_block *oprofilefs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, oprofilefs_fill_super);
}
diff -uNr linux-2.6.6/drivers/usb/core/inode.c linux-2.6.6-getsb/drivers/usb/core/inode.c
--- linux-2.6.6/drivers/usb/core/inode.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/drivers/usb/core/inode.c 2004-05-18 13:37:48.000000000 +0100
@@ -497,7 +497,7 @@
static struct file_system_type usbdevice_fs_type;
static struct super_block *usb_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, usbfs_fill_super);
}
diff -uNr linux-2.6.6/drivers/usb/gadget/inode.c linux-2.6.6-getsb/drivers/usb/gadget/inode.c
--- linux-2.6.6/drivers/usb/gadget/inode.c 2004-05-11 11:26:25.000000000 +0100
+++ linux-2.6.6-getsb/drivers/usb/gadget/inode.c 2004-05-18 13:38:08.000000000 +0100
@@ -1842,7 +1842,7 @@
/* "mount -t gadgetfs path /dev/gadget" ends up here */
static struct super_block *
gadgetfs_get_sb (struct file_system_type *t, int flags,
- const char *path, void *opts)
+ const char *path, void *opts, struct dentry **_root)
{
return get_sb_single (t, flags, opts, gadgetfs_fill_super);
}
diff -uNr linux-2.6.6/fs/adfs/super.c linux-2.6.6-getsb/fs/adfs/super.c
--- linux-2.6.6/fs/adfs/super.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/adfs/super.c 2004-05-18 13:17:45.000000000 +0100
@@ -470,7 +470,7 @@
}
static struct super_block *adfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super);
}
diff -uNr linux-2.6.6/fs/affs/super.c linux-2.6.6-getsb/fs/affs/super.c
--- linux-2.6.6/fs/affs/super.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/affs/super.c 2004-05-18 13:20:59.000000000 +0100
@@ -546,7 +546,7 @@
}
static struct super_block *affs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super);
}
diff -uNr linux-2.6.6/fs/afs/super.c linux-2.6.6-getsb/fs/afs/super.c
--- linux-2.6.6/fs/afs/super.c 2004-05-11 11:28:30.000000000 +0100
+++ linux-2.6.6-getsb/fs/afs/super.c 2004-05-18 13:14:07.000000000 +0100
@@ -40,7 +40,7 @@
static struct super_block *afs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
- void *data);
+ void *data, struct dentry **_root);
static struct inode *afs_alloc_inode(struct super_block *sb);
@@ -299,7 +299,8 @@
static struct super_block *afs_get_sb(struct file_system_type *fs_type,
int flags,
const char *dev_name,
- void *options)
+ void *options,
+ struct dentry **_root)
{
struct afs_mount_params params;
struct super_block *sb;
diff -uNr linux-2.6.6/fs/autofs/init.c linux-2.6.6-getsb/fs/autofs/init.c
--- linux-2.6.6/fs/autofs/init.c 2004-05-11 11:26:07.000000000 +0100
+++ linux-2.6.6-getsb/fs/autofs/init.c 2004-05-18 13:20:44.000000000 +0100
@@ -15,7 +15,7 @@
#include "autofs_i.h"
static struct super_block *autofs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_nodev(fs_type, flags, data, autofs_fill_super);
}
diff -uNr linux-2.6.6/fs/autofs4/init.c linux-2.6.6-getsb/fs/autofs4/init.c
--- linux-2.6.6/fs/autofs4/init.c 2004-05-11 11:26:06.000000000 +0100
+++ linux-2.6.6-getsb/fs/autofs4/init.c 2004-05-18 13:19:25.000000000 +0100
@@ -15,7 +15,7 @@
#include "autofs_i.h"
static struct super_block *autofs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_nodev(fs_type, flags, data, autofs4_fill_super);
}
diff -uNr linux-2.6.6/fs/befs/linuxvfs.c linux-2.6.6-getsb/fs/befs/linuxvfs.c
--- linux-2.6.6/fs/befs/linuxvfs.c 2004-05-11 11:26:06.000000000 +0100
+++ linux-2.6.6-getsb/fs/befs/linuxvfs.c 2004-05-18 13:19:00.000000000 +0100
@@ -928,7 +928,7 @@
static struct super_block *
befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name,
- void *data)
+ void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super);
}
diff -uNr linux-2.6.6/fs/bfs/inode.c linux-2.6.6-getsb/fs/bfs/inode.c
--- linux-2.6.6/fs/bfs/inode.c 2004-05-11 11:26:06.000000000 +0100
+++ linux-2.6.6-getsb/fs/bfs/inode.c 2004-05-18 13:18:05.000000000 +0100
@@ -381,7 +381,7 @@
}
static struct super_block *bfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super);
}
diff -uNr linux-2.6.6/fs/binfmt_misc.c linux-2.6.6-getsb/fs/binfmt_misc.c
--- linux-2.6.6/fs/binfmt_misc.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/binfmt_misc.c 2004-05-18 13:21:41.000000000 +0100
@@ -622,7 +622,7 @@
}
static struct super_block *bm_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, bm_fill_super);
}
diff -uNr linux-2.6.6/fs/cifs/cifsfs.c linux-2.6.6-getsb/fs/cifs/cifsfs.c
--- linux-2.6.6/fs/cifs/cifsfs.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/cifs/cifsfs.c 2004-05-18 13:16:00.000000000 +0100
@@ -398,7 +398,7 @@
static struct super_block *
cifs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, , struct dentry **_root)
{
int rc;
struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
diff -uNr linux-2.6.6/fs/coda/inode.c linux-2.6.6-getsb/fs/coda/inode.c
--- linux-2.6.6/fs/coda/inode.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/coda/inode.c 2004-05-18 13:16:59.000000000 +0100
@@ -306,7 +306,7 @@
/* init_coda: used by filesystems.c to register coda */
static struct super_block *coda_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_nodev(fs_type, flags, data, coda_fill_super);
}
diff -uNr linux-2.6.6/fs/cramfs/inode.c linux-2.6.6-getsb/fs/cramfs/inode.c
--- linux-2.6.6/fs/cramfs/inode.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/cramfs/inode.c 2004-05-18 13:19:48.000000000 +0100
@@ -494,7 +494,7 @@
};
static struct super_block *cramfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super);
}
diff -uNr linux-2.6.6/fs/devfs/base.c linux-2.6.6-getsb/fs/devfs/base.c
--- linux-2.6.6/fs/devfs/base.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/devfs/base.c 2004-05-18 13:20:27.000000000 +0100
@@ -2566,7 +2566,7 @@
static struct super_block *devfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
- void *data)
+ void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, devfs_fill_super);
}
diff -uNr linux-2.6.6/fs/devpts/inode.c linux-2.6.6-getsb/fs/devpts/inode.c
--- linux-2.6.6/fs/devpts/inode.c 2004-05-11 11:26:07.000000000 +0100
+++ linux-2.6.6-getsb/fs/devpts/inode.c 2004-05-18 13:21:07.000000000 +0100
@@ -109,7 +109,7 @@
}
static struct super_block *devpts_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, devpts_fill_super);
}
diff -uNr linux-2.6.6/fs/efs/super.c linux-2.6.6-getsb/fs/efs/super.c
--- linux-2.6.6/fs/efs/super.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/efs/super.c 2004-05-18 13:21:14.000000000 +0100
@@ -16,7 +16,7 @@
#include <linux/vfs.h>
static struct super_block *efs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super);
}
diff -uNr linux-2.6.6/fs/eventpoll.c linux-2.6.6-getsb/fs/eventpoll.c
--- linux-2.6.6/fs/eventpoll.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/eventpoll.c 2004-05-18 13:21:51.000000000 +0100
@@ -326,7 +326,7 @@
static struct inode *ep_eventpoll_inode(void);
static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
- void *data);
+ void *data, struct dentry **_root);
/*
* This semaphore is used to serialize ep_free() and eventpoll_release_file().
@@ -1679,7 +1679,7 @@
static struct super_block *
eventpollfs_get_sb(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *data)
+ const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC);
}
diff -uNr linux-2.6.6/fs/ext2/super.c linux-2.6.6-getsb/fs/ext2/super.c
--- linux-2.6.6/fs/ext2/super.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/ext2/super.c 2004-05-18 13:20:40.000000000 +0100
@@ -1008,7 +1008,7 @@
}
static struct super_block *ext2_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super);
}
diff -uNr linux-2.6.6/fs/ext3/super.c linux-2.6.6-getsb/fs/ext3/super.c
--- linux-2.6.6/fs/ext3/super.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/ext3/super.c 2004-05-18 13:20:08.000000000 +0100
@@ -2280,7 +2280,7 @@
#endif
static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super);
}
diff -uNr linux-2.6.6/fs/freevxfs/vxfs_super.c linux-2.6.6-getsb/fs/freevxfs/vxfs_super.c
--- linux-2.6.6/fs/freevxfs/vxfs_super.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/freevxfs/vxfs_super.c 2004-05-18 13:19:52.000000000 +0100
@@ -243,7 +243,7 @@
* The usual module blurb.
*/
static struct super_block *vxfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super);
}
diff -uNr linux-2.6.6/fs/hfs/super.c linux-2.6.6-getsb/fs/hfs/super.c
--- linux-2.6.6/fs/hfs/super.c 2004-05-11 11:28:55.000000000 +0100
+++ linux-2.6.6-getsb/fs/hfs/super.c 2004-05-18 13:21:20.000000000 +0100
@@ -316,7 +316,8 @@
}
static struct super_block *hfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data,
+ struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super);
}
diff -uNr linux-2.6.6/fs/hfsplus/super.c linux-2.6.6-getsb/fs/hfsplus/super.c
--- linux-2.6.6/fs/hfsplus/super.c 2004-05-11 11:26:06.000000000 +0100
+++ linux-2.6.6-getsb/fs/hfsplus/super.c 2004-05-18 13:18:00.000000000 +0100
@@ -441,7 +441,8 @@
#define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info)
static struct super_block *hfsplus_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data,
+ struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super);
}
diff -uNr linux-2.6.6/fs/hpfs/super.c linux-2.6.6-getsb/fs/hpfs/super.c
--- linux-2.6.6/fs/hpfs/super.c 2004-05-11 11:28:31.000000000 +0100
+++ linux-2.6.6-getsb/fs/hpfs/super.c 2004-05-18 13:19:36.000000000 +0100
@@ -661,7 +661,7 @@
}
static struct super_block *hpfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super);
}
diff -uNr linux-2.6.6/fs/hugetlbfs/inode.c linux-2.6.6-getsb/fs/hugetlbfs/inode.c
--- linux-2.6.6/fs/hugetlbfs/inode.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/hugetlbfs/inode.c 2004-05-18 13:21:25.000000000 +0100
@@ -670,7 +670,7 @@
}
static struct super_block *hugetlbfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super);
}
diff -uNr linux-2.6.6/fs/intermezzo/super.c linux-2.6.6-getsb/fs/intermezzo/super.c
--- linux-2.6.6/fs/intermezzo/super.c 2004-05-11 11:26:06.000000000 +0100
+++ linux-2.6.6-getsb/fs/intermezzo/super.c 2004-05-18 13:17:06.000000000 +0100
@@ -188,7 +188,7 @@
mount options to cache FS */
struct super_block *
presto_get_sb(struct file_system_type *izo_type, int flags,
- const char *devname, void *data)
+ const char *devname, void *data, struct dentry **_root)
{
struct file_system_type *fstype;
struct presto_cache *cache = NULL;
diff -uNr linux-2.6.6/fs/isofs/inode.c linux-2.6.6-getsb/fs/isofs/inode.c
--- linux-2.6.6/fs/isofs/inode.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/isofs/inode.c 2004-05-18 13:20:49.000000000 +0100
@@ -1419,7 +1419,7 @@
#endif
static struct super_block *isofs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
}
diff -uNr linux-2.6.6/fs/jffs/inode-v23.c linux-2.6.6-getsb/fs/jffs/inode-v23.c
--- linux-2.6.6/fs/jffs/inode-v23.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/jffs/inode-v23.c 2004-05-18 13:22:10.000000000 +0100
@@ -1788,7 +1788,7 @@
};
static struct super_block *jffs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super);
}
diff -uNr linux-2.6.6/fs/jffs2/super.c linux-2.6.6-getsb/fs/jffs2/super.c
--- linux-2.6.6/fs/jffs2/super.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/jffs2/super.c 2004-05-18 13:16:54.000000000 +0100
@@ -167,7 +167,7 @@
static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
- void *data)
+ void *data, struct dentry **_root)
{
int err;
struct nameidata nd;
diff -uNr linux-2.6.6/fs/jfs/super.c linux-2.6.6-getsb/fs/jfs/super.c
--- linux-2.6.6/fs/jfs/super.c 2004-05-11 11:28:31.000000000 +0100
+++ linux-2.6.6-getsb/fs/jfs/super.c 2004-05-18 13:15:46.000000000 +0100
@@ -494,7 +494,7 @@
}
static struct super_block *jfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super);
}
diff -uNr linux-2.6.6/fs/minix/inode.c linux-2.6.6-getsb/fs/minix/inode.c
--- linux-2.6.6/fs/minix/inode.c 2004-05-11 11:26:07.000000000 +0100
+++ linux-2.6.6-getsb/fs/minix/inode.c 2004-05-18 13:21:10.000000000 +0100
@@ -556,7 +556,7 @@
}
static struct super_block *minix_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super);
}
diff -uNr linux-2.6.6/fs/msdos/namei.c linux-2.6.6-getsb/fs/msdos/namei.c
--- linux-2.6.6/fs/msdos/namei.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/msdos/namei.c 2004-05-18 13:22:30.000000000 +0100
@@ -596,7 +596,7 @@
}
static struct super_block *msdos_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
}
diff -uNr linux-2.6.6/fs/ncpfs/inode.c linux-2.6.6-getsb/fs/ncpfs/inode.c
--- linux-2.6.6/fs/ncpfs/inode.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/ncpfs/inode.c 2004-05-18 13:19:57.000000000 +0100
@@ -963,7 +963,7 @@
#endif
static struct super_block *ncp_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_nodev(fs_type, flags, data, ncp_fill_super);
}
diff -uNr linux-2.6.6/fs/nfs/inode.c linux-2.6.6-getsb/fs/nfs/inode.c
--- linux-2.6.6/fs/nfs/inode.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/nfs/inode.c 2004-05-18 13:14:47.000000000 +0100
@@ -1305,7 +1305,7 @@
}
static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data)
+ int flags, const char *dev_name, void *raw_data, struct dentry **_root)
{
int error;
struct nfs_server *server;
@@ -1623,7 +1623,7 @@
}
static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *raw_data)
+ int flags, const char *dev_name, void *raw_data, struct dentry **_root)
{
int error;
struct nfs_server *server;
diff -uNr linux-2.6.6/fs/nfsd/nfsctl.c linux-2.6.6-getsb/fs/nfsd/nfsctl.c
--- linux-2.6.6/fs/nfsd/nfsctl.c 2004-05-11 11:26:05.000000000 +0100
+++ linux-2.6.6-getsb/fs/nfsd/nfsctl.c 2004-05-18 13:22:50.000000000 +0100
@@ -417,7 +417,7 @@
}
static struct super_block *nfsd_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, nfsd_fill_super);
}
diff -uNr linux-2.6.6/fs/ntfs/super.c linux-2.6.6-getsb/fs/ntfs/super.c
--- linux-2.6.6/fs/ntfs/super.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/ntfs/super.c 2004-05-18 13:19:44.000000000 +0100
@@ -1999,7 +1999,7 @@
DECLARE_MUTEX(ntfs_lock);
static struct super_block *ntfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super);
}
diff -uNr linux-2.6.6/fs/openpromfs/inode.c linux-2.6.6-getsb/fs/openpromfs/inode.c
--- linux-2.6.6/fs/openpromfs/inode.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/openpromfs/inode.c 2004-05-18 13:22:05.000000000 +0100
@@ -1054,7 +1054,7 @@
}
static struct super_block *openprom_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, openprom_fill_super);
}
diff -uNr linux-2.6.6/fs/pipe.c linux-2.6.6-getsb/fs/pipe.c
--- linux-2.6.6/fs/pipe.c 2004-05-11 11:28:31.000000000 +0100
+++ linux-2.6.6-getsb/fs/pipe.c 2004-05-18 13:22:19.000000000 +0100
@@ -696,7 +696,7 @@
*/
static struct super_block *pipefs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
}
diff -uNr linux-2.6.6/fs/proc/root.c linux-2.6.6-getsb/fs/proc/root.c
--- linux-2.6.6/fs/proc/root.c 2004-05-11 11:28:31.000000000 +0100
+++ linux-2.6.6-getsb/fs/proc/root.c 2004-05-18 13:20:31.000000000 +0100
@@ -25,7 +25,7 @@
#endif
static struct super_block *proc_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, proc_fill_super);
}
diff -uNr linux-2.6.6/fs/qnx4/inode.c linux-2.6.6-getsb/fs/qnx4/inode.c
--- linux-2.6.6/fs/qnx4/inode.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/qnx4/inode.c 2004-05-18 13:21:56.000000000 +0100
@@ -559,7 +559,7 @@
}
static struct super_block *qnx4_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super);
}
diff -uNr linux-2.6.6/fs/ramfs/inode.c linux-2.6.6-getsb/fs/ramfs/inode.c
--- linux-2.6.6/fs/ramfs/inode.c 2004-05-11 11:26:07.000000000 +0100
+++ linux-2.6.6-getsb/fs/ramfs/inode.c 2004-05-18 13:21:33.000000000 +0100
@@ -199,13 +199,13 @@
}
static struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_nodev(fs_type, flags, data, ramfs_fill_super);
}
static struct super_block *rootfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super);
}
diff -uNr linux-2.6.6/fs/reiserfs/super.c linux-2.6.6-getsb/fs/reiserfs/super.c
--- linux-2.6.6/fs/reiserfs/super.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/reiserfs/super.c 2004-05-18 13:18:52.000000000 +0100
@@ -1509,7 +1509,7 @@
static struct super_block*
get_super_block (struct file_system_type *fs_type, int flags,
- const char *dev_name, void *data)
+ const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super);
}
diff -uNr linux-2.6.6/fs/romfs/inode.c linux-2.6.6-getsb/fs/romfs/inode.c
--- linux-2.6.6/fs/romfs/inode.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/romfs/inode.c 2004-05-18 13:21:03.000000000 +0100
@@ -607,7 +607,7 @@
};
static struct super_block *romfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super);
}
diff -uNr linux-2.6.6/fs/smbfs/inode.c linux-2.6.6-getsb/fs/smbfs/inode.c
--- linux-2.6.6/fs/smbfs/inode.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/smbfs/inode.c 2004-05-18 13:20:21.000000000 +0100
@@ -776,7 +776,7 @@
#endif
static struct super_block *smb_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_nodev(fs_type, flags, data, smb_fill_super);
}
diff -uNr linux-2.6.6/fs/sysfs/mount.c linux-2.6.6-getsb/fs/sysfs/mount.c
--- linux-2.6.6/fs/sysfs/mount.c 2004-05-11 11:26:06.000000000 +0100
+++ linux-2.6.6-getsb/fs/sysfs/mount.c 2004-05-18 13:18:10.000000000 +0100
@@ -55,7 +55,7 @@
}
static struct super_block *sysfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, sysfs_fill_super);
}
diff -uNr linux-2.6.6/fs/sysv/super.c linux-2.6.6-getsb/fs/sysv/super.c
--- linux-2.6.6/fs/sysv/super.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/sysv/super.c 2004-05-18 13:19:16.000000000 +0100
@@ -499,13 +499,13 @@
/* Every kernel module contains stuff like this. */
static struct super_block *sysv_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super);
}
static struct super_block *v7_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super);
}
diff -uNr linux-2.6.6/fs/udf/super.c linux-2.6.6-getsb/fs/udf/super.c
--- linux-2.6.6/fs/udf/super.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/udf/super.c 2004-05-18 13:17:49.000000000 +0100
@@ -100,7 +100,7 @@
/* UDF filesystem type */
static struct super_block *udf_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super);
}
diff -uNr linux-2.6.6/fs/ufs/super.c linux-2.6.6-getsb/fs/ufs/super.c
--- linux-2.6.6/fs/ufs/super.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/ufs/super.c 2004-05-18 13:14:57.000000000 +0100
@@ -1209,7 +1209,7 @@
};
static struct super_block *ufs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super);
}
diff -uNr linux-2.6.6/fs/vfat/namei.c linux-2.6.6-getsb/fs/vfat/namei.c
--- linux-2.6.6/fs/vfat/namei.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/vfat/namei.c 2004-05-18 13:22:25.000000000 +0100
@@ -1121,7 +1121,7 @@
}
static struct super_block *vfat_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
}
diff -uNr linux-2.6.6/fs/xfs/linux/xfs_super.c linux-2.6.6-getsb/fs/xfs/linux/xfs_super.c
--- linux-2.6.6/fs/xfs/linux/xfs_super.c 2004-05-11 11:28:56.000000000 +0100
+++ linux-2.6.6-getsb/fs/xfs/linux/xfs_super.c 2004-05-18 13:22:42.000000000 +0100
@@ -745,7 +745,8 @@
struct file_system_type *fs_type,
int flags,
const char *dev_name,
- void *data)
+ void *data,
+ struct dentry **_root)
{
return get_sb_bdev(fs_type, flags, dev_name, data, linvfs_fill_super);
}
diff -uNr linux-2.6.6/ipc/mqueue.c linux-2.6.6-getsb/ipc/mqueue.c
--- linux-2.6.6/ipc/mqueue.c 2004-05-11 11:28:57.000000000 +0100
+++ linux-2.6.6-getsb/ipc/mqueue.c 2004-05-18 13:35:59.000000000 +0100
@@ -168,7 +168,7 @@
static struct super_block *mqueue_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
- void *data)
+ void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, mqueue_fill_super);
}
diff -uNr linux-2.6.6/kernel/futex.c linux-2.6.6-getsb/kernel/futex.c
--- linux-2.6.6/kernel/futex.c 2004-05-11 11:27:00.000000000 +0100
+++ linux-2.6.6-getsb/kernel/futex.c 2004-05-18 13:34:41.000000000 +0100
@@ -674,7 +674,7 @@
static struct super_block *
futexfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA);
}
diff -uNr linux-2.6.6/mm/shmem.c linux-2.6.6-getsb/mm/shmem.c
--- linux-2.6.6/mm/shmem.c 2004-05-11 11:28:57.000000000 +0100
+++ linux-2.6.6-getsb/mm/shmem.c 2004-05-18 13:36:22.000000000 +0100
@@ -1879,7 +1879,7 @@
};
static struct super_block *shmem_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_nodev(fs_type, flags, data, shmem_fill_super);
}
diff -uNr linux-2.6.6/net/socket.c linux-2.6.6-getsb/net/socket.c
--- linux-2.6.6/net/socket.c 2004-05-11 11:28:58.000000000 +0100
+++ linux-2.6.6-getsb/net/socket.c 2004-05-18 13:33:37.000000000 +0100
@@ -323,7 +323,7 @@
};
static struct super_block *sockfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC);
}
diff -uNr linux-2.6.6/net/sunrpc/rpc_pipe.c linux-2.6.6-getsb/net/sunrpc/rpc_pipe.c
--- linux-2.6.6/net/sunrpc/rpc_pipe.c 2004-05-11 11:26:46.000000000 +0100
+++ linux-2.6.6-getsb/net/sunrpc/rpc_pipe.c 2004-05-18 13:34:18.000000000 +0100
@@ -793,7 +793,7 @@
static struct super_block *
rpc_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data, struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, rpc_fill_super);
}
diff -uNr linux-2.6.6/security/selinux/selinuxfs.c linux-2.6.6-getsb/security/selinux/selinuxfs.c
--- linux-2.6.6/security/selinux/selinuxfs.c 2004-05-11 11:28:58.000000000 +0100
+++ linux-2.6.6-getsb/security/selinux/selinuxfs.c 2004-05-18 13:36:43.000000000 +0100
@@ -1088,7 +1088,8 @@
}
static struct super_block *sel_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+ int flags, const char *dev_name, void *data,
+ struct dentry **_root)
{
return get_sb_single(fs_type, flags, data, sel_fill_super);
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] permit fs->get_sb() to return alternative root
2004-05-18 14:14 ` [PATCH] permit fs->get_sb() to return alternative root David Howells
@ 2004-05-18 14:43 ` Trond Myklebust
[not found] ` <20040518152426.GY17014@parcelfarce.linux.theplanet.co.uk>
1 sibling, 0 replies; 4+ messages in thread
From: Trond Myklebust @ 2004-05-18 14:43 UTC (permalink / raw)
To: David Howells; +Cc: Alexander Viro, Linus Torvalds, linux-fsdevel
På ty , 18/05/2004 klokka 10:14, skreiv David Howells:
> Hi Al, Linux,
>
> Here's a patch to add an extra argument to the get_sb() method of struct
> file_system_type that allows a filesystem to suggest an alternative dentry to
> be attached to the vfsmount structure. If no such suggestion is made,
> sb->s_root is selected as usual.
Cool..
> @@ -762,15 +763,18 @@
> }
> }
>
> - sb = type->get_sb(type, flags, name, data);
> + root = NULL;
> + sb = type->get_sb(type, flags, name, data, &root);
> if (IS_ERR(sb))
> goto out_free_secdata;
> + if (!root)
> + root = sb->s_root;
> error = security_sb_kern_mount(sb, secdata);
> if (error)
> goto out_sb;
> mnt->mnt_sb = sb;
> - mnt->mnt_root = dget(sb->s_root);
> - mnt->mnt_mountpoint = sb->s_root;
> + mnt->mnt_root = dget(root);
> + mnt->mnt_mountpoint = mnt->mnt_root;
This looks a bit iffy... Shouldn't that be
+ if (!root)
+ root = dget(sb->s_root);
....
+ mnt->mnt_root = root;
Unless the filesystem has taken a reference to the dentry in "root", it
just won't be guaranteed to still exist.
Cheers,
Trond
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] permit fs->get_sb() to return alternative root
[not found] ` <20040518174808.GD17014@parcelfarce.linux.theplanet.co.uk>
@ 2004-05-20 11:22 ` David Howells
2004-05-28 8:52 ` David Howells
1 sibling, 0 replies; 4+ messages in thread
From: David Howells @ 2004-05-20 11:22 UTC (permalink / raw)
To: Trond Myklebust; +Cc: Alexander Viro, Linus Torvalds, linux-fsdevel
[-- Attachment #1: Type: text/plain, Size: 1052 bytes --]
> På ty , 18/05/2004 klokka 13:48, skreiv
> viro@parcelfarce.linux.theplanet.co.uk:
> > Details, please. Preferably with a patch that could be read...
>
> Needs work (and adaptation to NFSv4), but the basic algorithm would go
> along the lines of the following
Okay... I've worked on your patch somewhat. The attached patch permits
superblock sharing:
[root@host135 root]# mount hades:/hades /mnt
[root@host135 root]# mount hades:/usr /afs
[root@host135 root]# mount hades:/hades /x
[root@host135 root]# mount hades:/ /y
[root@host135 root]# stat /mnt /afs /x /y /y/hades | grep ^Device
Device: eh/14d Inode: 3925361 Links: 46
Device: eh/14d Inode: 327041 Links: 19
Device: eh/14d Inode: 3925361 Links: 46
Device: eh/14d Inode: 2 Links: 33
Device: eh/14d Inode: 3925361 Links: 46
And on an NFS export from a different server:
[root@host135 root]# stat /home/dhowells/Mail | grep ^Device
Device: 10h/16d Inode: 3620912 Links: 40
However, df doesn't work:-/
David
[-- Attachment #2: nfs-266.diff --]
[-- Type: application/octet-stream, Size: 11833 bytes --]
diff -uNr linux-2.6.6-getsb/fs/dcache.c linux-2.6.6-nfs/fs/dcache.c
--- linux-2.6.6-getsb/fs/dcache.c 2004-05-17 15:07:41.000000000 +0100
+++ linux-2.6.6-nfs/fs/dcache.c 2004-05-19 17:12:25.000000000 +0100
@@ -1247,6 +1247,23 @@
}
/**
+ * d_materialise_dentry - connect a disconnected dentry into the tree
+ * @dentry: dentry to replace
+ * @anon: dentry to place into the tree
+ *
+ * Prepare an anonymous dentry for life in the superblock's dentry tree as a
+ * named dentry in place of the dentry to be replaced.
+ */
+void d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
+{
+ switch_names(dentry, anon);
+ do_switch(dentry->d_name.len, anon->d_name.len);
+ do_switch(dentry->d_name.hash, anon->d_name.hash);
+ do_switch(dentry->d_parent, anon->d_parent);
+ anon->d_flags &= ~DCACHE_DISCONNECTED;
+}
+
+/**
* d_path - return the path of a dentry
* @dentry: dentry to report
* @vfsmnt: vfsmnt to which the dentry belongs
@@ -1659,6 +1676,7 @@
EXPORT_SYMBOL(d_invalidate);
EXPORT_SYMBOL(d_lookup);
EXPORT_SYMBOL(d_move);
+EXPORT_SYMBOL(d_materialise_dentry);
EXPORT_SYMBOL(d_path);
EXPORT_SYMBOL(d_prune_aliases);
EXPORT_SYMBOL(d_rehash);
diff -uNr linux-2.6.6-getsb/fs/nfs/dir.c linux-2.6.6-nfs/fs/nfs/dir.c
--- linux-2.6.6-getsb/fs/nfs/dir.c 2004-05-17 15:07:34.000000000 +0100
+++ linux-2.6.6-nfs/fs/nfs/dir.c 2004-05-19 17:18:40.000000000 +0100
@@ -710,10 +710,12 @@
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
+ struct dentry *anon;
struct inode *inode = NULL;
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
+ int found_alias = 0;
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -746,6 +748,30 @@
inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
if (!inode)
goto out_unlock;
+
+ /* Search for directory aliases arising from multiple mounts from one server */
+ if (S_ISDIR(inode->i_mode) && (anon = d_find_alias(inode))) {
+ spin_lock(&anon->d_lock);
+ /* Is this a mountpoint that we could splice into our tree? */
+ if (IS_ROOT(anon)) {
+ /* Yes! Convert into an ordinary dentry */
+ d_materialise_dentry(dentry, anon);
+ found_alias = 1;
+ } else if (anon->d_name.len == dentry->d_name.len &&
+ !memcmp(anon->d_name.name, dentry->d_name.name, dentry->d_name.len) &&
+ dentry->d_parent == anon->d_parent)
+ found_alias = 1;
+ spin_unlock(&anon->d_lock);
+ if (found_alias) {
+ d_drop(anon);
+ iput(inode);
+ d_rehash(anon);
+ return anon;
+ }
+ /* Doh! Server appears to be aliasing directories */
+ dput(anon);
+ }
+
no_entry:
error = 0;
d_add(dentry, inode);
diff -uNr linux-2.6.6-getsb/fs/nfs/inode.c linux-2.6.6-nfs/fs/nfs/inode.c
--- linux-2.6.6-getsb/fs/nfs/inode.c 2004-05-18 13:14:47.000000000 +0100
+++ linux-2.6.6-nfs/fs/nfs/inode.c 2004-05-20 11:33:11.518537943 +0100
@@ -228,33 +228,90 @@
/*
* Obtain the root inode of the file system.
*/
-static struct inode *
-nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo)
+static int
+nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh, struct nfs_fsinfo *fsinfo,
+ struct dentry **_root)
{
- struct nfs_server *server = NFS_SB(sb);
- struct inode *rooti;
- int error;
+ struct nfs_server *server = NFS_SB(sb);
+ struct dentry *root;
+ struct inode *inode;
+ int error;
- error = server->rpc_ops->getroot(server, rootfh, fsinfo);
+ error = server->rpc_ops->getroot(server, mntfh, fsinfo);
if (error < 0) {
printk(KERN_NOTICE "nfs_get_root: getattr error = %d\n", -error);
- return ERR_PTR(error);
+ return error;
}
- rooti = nfs_fhget(sb, rootfh, fsinfo->fattr);
- if (!rooti)
- return ERR_PTR(-ENOMEM);
- return rooti;
+ inode = nfs_fhget(sb, mntfh, fsinfo->fattr);
+ if (!inode) {
+ printk("nfs_get_another_root: get root inode failed\n");
+ return -ENOMEM;
+ }
+
+ /* Root dentries start off anonymous */
+ root = d_alloc_anon(inode);
+ if (!root) {
+ printk("nfs_get_another_root: get root dentry failed\n");
+ iput(inode);
+ return -ENOMEM;
+ }
+
+ if (!root->d_op)
+ root->d_op = server->rpc_ops->dentry_ops;
+ *_root = root;
+ return 0;
+}
+
+/*
+ * Get the root dentry for a new mountpoint in an existing superblock
+ */
+static int
+nfs_get_another_root(struct super_block *sb, struct nfs_fh *mntfh, struct dentry **_root)
+{
+ struct nfs_fattr fattr;
+ struct nfs_fsinfo fsinfo = {
+ .fattr = &fattr,
+ };
+
+ return nfs_get_root(sb, mntfh, &fsinfo, _root);
+}
+
+/*
+ * create a dummy root dentry with dummy inode
+ */
+static int
+nfs_make_dummy_root(struct super_block *sb)
+{
+ struct dentry *root;
+ struct inode *inode;
+
+ inode = new_inode(sb);
+ if (!inode)
+ return -ENOMEM;
+
+ inode->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
+ inode->i_uid = inode->i_gid = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+
+ root = d_alloc_root(inode);
+ if (!root) {
+ iput(inode);
+ return -ENOMEM;
+ }
+
+ sb->s_root = root;
+ return 0;
}
/*
* Do NFS version-independent mount processing, and sanity checking
*/
static int
-nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
+nfs_sb_init(struct super_block *sb, struct nfs_fh *mntfh, rpc_authflavor_t authflavor,
+ struct dentry **_root)
{
struct nfs_server *server;
- struct inode *root_inode;
struct nfs_fattr fattr;
struct nfs_fsinfo fsinfo = {
.fattr = &fattr,
@@ -263,26 +320,29 @@
.fattr = &fattr,
};
+ int error;
+
/* We probably want something more informative here */
snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
- server = NFS_SB(sb);
+ sb->s_magic = NFS_SUPER_MAGIC;
- sb->s_magic = NFS_SUPER_MAGIC;
+ error = nfs_make_dummy_root(sb);
+ if (error < 0)
+ return error;
- root_inode = nfs_get_root(sb, &server->fh, &fsinfo);
- /* Did getting the root inode fail? */
- if (IS_ERR(root_inode))
- goto out_no_root;
- sb->s_root = d_alloc_root(root_inode);
- if (!sb->s_root)
- goto out_no_root;
+ error = nfs_get_root(sb, mntfh, &fsinfo, _root);
+ if (error < 0) {
+ dput(sb->s_root);
+ sb->s_root = NULL;
+ return error;
+ }
- sb->s_root->d_op = server->rpc_ops->dentry_ops;
+ server = NFS_SB(sb);
/* Get some general file system info */
if (server->namelen == 0 &&
- server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
+ server->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
server->namelen = pathinfo.max_namelen;
/* Work out a lot of parameters */
if (server->rsize == 0)
@@ -335,12 +395,6 @@
/* We're airborne Set socket buffersize */
rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
return 0;
- /* Yargs. It didn't work out. */
-out_no_root:
- printk("nfs_read_super: get root inode failed\n");
- if (!IS_ERR(root_inode))
- iput(root_inode);
- return -EINVAL;
}
/*
@@ -398,7 +452,8 @@
* daemon. We stash these away in the private superblock fields.
*/
static int
-nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
+nfs_fill_super(struct super_block *sb, struct nfs_fh *mntfh, struct nfs_mount_data *data,
+ int silent, struct dentry **_root)
{
struct nfs_server *server;
int err = -EIO;
@@ -473,7 +528,7 @@
}
sb->s_op = &nfs_sops;
- err = nfs_sb_init(sb, authflavor);
+ err = nfs_sb_init(sb, mntfh, authflavor, _root);
if (err != 0)
goto out_noinit;
@@ -1284,6 +1339,11 @@
/*
* File system information
+ * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a
+ * particular server are held in the same superblock
+ * - NFS superblocks can have several effective roots to the dentry tree
+ * - directory type roots are spliced into the tree when a path from one root reaches the root
+ * of another (see nfs_lookup())
*/
static int nfs_set_super(struct super_block *s, void *data)
@@ -1301,7 +1361,7 @@
return 0;
if (old->addr.sin_port != server->addr.sin_port)
return 0;
- return !memcmp(&old->fh, &server->fh, sizeof(struct nfs_fh));
+ return 1;
}
static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
@@ -1310,7 +1370,7 @@
int error;
struct nfs_server *server;
struct super_block *s;
- struct nfs_fh *root;
+ struct nfs_fh mntfh;
struct nfs_mount_data *data = raw_data;
if (!data) {
@@ -1325,10 +1385,9 @@
/* Zero out the NFS state stuff */
init_nfsv4_state(server);
- root = &server->fh;
- memcpy(root, &data->root, sizeof(*root));
- if (root->size < sizeof(root->data))
- memset(root->data+root->size, 0, sizeof(root->data)-root->size);
+ memcpy(&mntfh, &data->root, sizeof(mntfh));
+ if (mntfh.size < sizeof(mntfh.data))
+ memset(mntfh.data+mntfh.size, 0, sizeof(mntfh.data)-mntfh.size);
if (data->version != NFS_MOUNT_VERSION) {
printk("nfs warning: mount version %s than kernel\n",
@@ -1339,15 +1398,15 @@
data->bsize = 0;
if (data->version < 4) {
data->flags &= ~NFS_MOUNT_VER3;
- memset(root, 0, sizeof(*root));
- root->size = NFS2_FHSIZE;
- memcpy(root->data, data->old_root.data, NFS2_FHSIZE);
+ memset(&mntfh, 0, sizeof(mntfh));
+ mntfh.size = NFS2_FHSIZE;
+ memcpy(mntfh.data, data->old_root.data, NFS2_FHSIZE);
}
if (data->version < 5)
data->flags &= ~NFS_MOUNT_SECFLAVOUR;
}
- if (root->size > sizeof(root->data)) {
+ if (mntfh.size > sizeof(mntfh.data)) {
printk("nfs_get_sb: invalid root filehandle\n");
kfree(server);
return ERR_PTR(-EINVAL);
@@ -1360,22 +1419,33 @@
return ERR_PTR(-EINVAL);
}
+ /* Get a superblock - note that we may end up sharing one that already exists */
s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
-
- if (IS_ERR(s) || s->s_root) {
+ if (IS_ERR(s)) {
kfree(server);
return s;
}
- s->s_flags = flags;
+ if (!s->s_root) {
+ s->s_flags = flags;
- error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
- if (error) {
- up_write(&s->s_umount);
- deactivate_super(s);
- return ERR_PTR(error);
+ error = nfs_fill_super(s, &mntfh, data, flags & MS_VERBOSE ? 1 : 0, _root);
+ if (error) {
+ up_write(&s->s_umount);
+ deactivate_super(s);
+ return ERR_PTR(error);
+ }
+ s->s_flags |= MS_ACTIVE;
}
- s->s_flags |= MS_ACTIVE;
+ else {
+ error = nfs_get_another_root(s, &mntfh, _root);
+ if (error) {
+ up_write(&s->s_umount);
+ deactivate_super(s);
+ return ERR_PTR(error);
+ }
+ }
+
return s;
}
diff -uNr linux-2.6.6-getsb/include/linux/dcache.h linux-2.6.6-nfs/include/linux/dcache.h
--- linux-2.6.6-getsb/include/linux/dcache.h 2004-05-17 15:08:42.000000000 +0100
+++ linux-2.6.6-nfs/include/linux/dcache.h 2004-05-19 17:13:03.000000000 +0100
@@ -198,6 +198,7 @@
*/
extern void d_instantiate(struct dentry *, struct inode *);
extern void d_delete(struct dentry *);
+extern void d_materialise_dentry(struct dentry *, struct dentry *);
/* allocate/de-allocate */
extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
diff -uNr linux-2.6.6-getsb/include/linux/nfs_fs_sb.h linux-2.6.6-nfs/include/linux/nfs_fs_sb.h
--- linux-2.6.6-getsb/include/linux/nfs_fs_sb.h 2004-05-17 15:08:42.000000000 +0100
+++ linux-2.6.6-nfs/include/linux/nfs_fs_sb.h 2004-05-19 19:45:38.000000000 +0100
@@ -26,14 +26,14 @@
unsigned int acdirmax;
unsigned int namelen;
char * hostname; /* remote hostname */
- struct nfs_fh fh;
+// struct nfs_fh fh;
struct sockaddr_in addr;
#ifdef CONFIG_NFS_V4
/* Our own IP address, as a null-terminated string.
* This is used to generate the clientid, and the callback address.
*/
char ip_addr[16];
- char * mnt_path;
+// char * mnt_path;
struct nfs4_client * nfs4_state; /* all NFSv4 state starts here */
struct list_head nfs4_siblings; /* List of other nfs_server structs
* that share the same clientid
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] permit fs->get_sb() to return alternative root
[not found] ` <20040518174808.GD17014@parcelfarce.linux.theplanet.co.uk>
2004-05-20 11:22 ` David Howells
@ 2004-05-28 8:52 ` David Howells
1 sibling, 0 replies; 4+ messages in thread
From: David Howells @ 2004-05-28 8:52 UTC (permalink / raw)
To: Trond Myklebust
Cc: Alexander Viro, Linus Torvalds, linux-fsdevel, linux-kernel
Content-Type: text/plain; charset=ISO-8859-1text/plain; charset=US-ASCII
Content-Transfer-Encoding: quoted-printable
> P=E5 ty , 18/05/2004 klokka 13:48, skreiv
> viro@parcelfarce.linux.theplanet.co.uk:
> > Details, please. Preferably with a patch that could be read...
>
> Needs work (and adaptation to NFSv4), but the basic algorithm would go
> along the lines of the following
Okay... I've worked on your patch somewhat. The attached patch permits
superblock sharing:
[root@host135 root]# mount hades:/hades /mnt
[root@host135 root]# mount hades:/usr /afs
[root@host135 root]# mount hades:/hades /x
[root@host135 root]# mount hades:/ /y
[root@host135 root]# stat /mnt /afs /x /y /y/hades | grep ^Device
Device: eh/14d Inode: 3925361 Links: 46
Device: eh/14d Inode: 327041 Links: 19
Device: eh/14d Inode: 3925361 Links: 46
Device: eh/14d Inode: 2 Links: 33
Device: eh/14d Inode: 3925361 Links: 46
And on an NFS export from a different server:
[root@host135 root]# stat /home/dhowells/Mail | grep ^Device
Device: 10h/16d Inode: 3620912 Links: 40
However, df doesn't work on NFS:-/
David
--Multipart_Thu_May_20_12:22:58_2004-1
Content-Type: text/plain; type=patch
Content-Disposition: attachment; filename="nfs-266.diff"
Content-Transfer-Encoding: 7bit
diff -uNr linux-2.6.6-getsb/fs/dcache.c linux-2.6.6-nfs/fs/dcache.c
--- linux-2.6.6-getsb/fs/dcache.c 2004-05-17 15:07:41.000000000 +0100
+++ linux-2.6.6-nfs/fs/dcache.c 2004-05-19 17:12:25.000000000 +0100
@@ -1247,6 +1247,23 @@
}
/**
+ * d_materialise_dentry - connect a disconnected dentry into the tree
+ * @dentry: dentry to replace
+ * @anon: dentry to place into the tree
+ *
+ * Prepare an anonymous dentry for life in the superblock's dentry tree as a
+ * named dentry in place of the dentry to be replaced.
+ */
+void d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
+{
+ switch_names(dentry, anon);
+ do_switch(dentry->d_name.len, anon->d_name.len);
+ do_switch(dentry->d_name.hash, anon->d_name.hash);
+ do_switch(dentry->d_parent, anon->d_parent);
+ anon->d_flags &= ~DCACHE_DISCONNECTED;
+}
+
+/**
* d_path - return the path of a dentry
* @dentry: dentry to report
* @vfsmnt: vfsmnt to which the dentry belongs
@@ -1659,6 +1676,7 @@
EXPORT_SYMBOL(d_invalidate);
EXPORT_SYMBOL(d_lookup);
EXPORT_SYMBOL(d_move);
+EXPORT_SYMBOL(d_materialise_dentry);
EXPORT_SYMBOL(d_path);
EXPORT_SYMBOL(d_prune_aliases);
EXPORT_SYMBOL(d_rehash);
diff -uNr linux-2.6.6-getsb/fs/nfs/dir.c linux-2.6.6-nfs/fs/nfs/dir.c
--- linux-2.6.6-getsb/fs/nfs/dir.c 2004-05-17 15:07:34.000000000 +0100
+++ linux-2.6.6-nfs/fs/nfs/dir.c 2004-05-19 17:18:40.000000000 +0100
@@ -710,10 +710,12 @@
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
+ struct dentry *anon;
struct inode *inode = NULL;
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
+ int found_alias = 0;
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -746,6 +748,30 @@
inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
if (!inode)
goto out_unlock;
+
+ /* Search for directory aliases arising from multiple mounts from one server */
+ if (S_ISDIR(inode->i_mode) && (anon = d_find_alias(inode))) {
+ spin_lock(&anon->d_lock);
+ /* Is this a mountpoint that we could splice into our tree? */
+ if (IS_ROOT(anon)) {
+ /* Yes! Convert into an ordinary dentry */
+ d_materialise_dentry(dentry, anon);
+ found_alias = 1;
+ } else if (anon->d_name.len == dentry->d_name.len &&
+ !memcmp(anon->d_name.name, dentry->d_name.name, dentry->d_name.len) &&
+ dentry->d_parent == anon->d_parent)
+ found_alias = 1;
+ spin_unlock(&anon->d_lock);
+ if (found_alias) {
+ d_drop(anon);
+ iput(inode);
+ d_rehash(anon);
+ return anon;
+ }
+ /* Doh! Server appears to be aliasing directories */
+ dput(anon);
+ }
+
no_entry:
error = 0;
d_add(dentry, inode);
diff -uNr linux-2.6.6-getsb/fs/nfs/inode.c linux-2.6.6-nfs/fs/nfs/inode.c
--- linux-2.6.6-getsb/fs/nfs/inode.c 2004-05-18 13:14:47.000000000 +0100
+++ linux-2.6.6-nfs/fs/nfs/inode.c 2004-05-20 11:33:11.518537943 +0100
@@ -228,33 +228,90 @@
/*
* Obtain the root inode of the file system.
*/
-static struct inode *
-nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo)
+static int
+nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh, struct nfs_fsinfo *fsinfo,
+ struct dentry **_root)
{
- struct nfs_server *server = NFS_SB(sb);
- struct inode *rooti;
- int error;
+ struct nfs_server *server = NFS_SB(sb);
+ struct dentry *root;
+ struct inode *inode;
+ int error;
- error = server->rpc_ops->getroot(server, rootfh, fsinfo);
+ error = server->rpc_ops->getroot(server, mntfh, fsinfo);
if (error < 0) {
printk(KERN_NOTICE "nfs_get_root: getattr error = %d\n", -error);
- return ERR_PTR(error);
+ return error;
}
- rooti = nfs_fhget(sb, rootfh, fsinfo->fattr);
- if (!rooti)
- return ERR_PTR(-ENOMEM);
- return rooti;
+ inode = nfs_fhget(sb, mntfh, fsinfo->fattr);
+ if (!inode) {
+ printk("nfs_get_another_root: get root inode failed\n");
+ return -ENOMEM;
+ }
+
+ /* Root dentries start off anonymous */
+ root = d_alloc_anon(inode);
+ if (!root) {
+ printk("nfs_get_another_root: get root dentry failed\n");
+ iput(inode);
+ return -ENOMEM;
+ }
+
+ if (!root->d_op)
+ root->d_op = server->rpc_ops->dentry_ops;
+ *_root = root;
+ return 0;
+}
+
+/*
+ * Get the root dentry for a new mountpoint in an existing superblock
+ */
+static int
+nfs_get_another_root(struct super_block *sb, struct nfs_fh *mntfh, struct dentry **_root)
+{
+ struct nfs_fattr fattr;
+ struct nfs_fsinfo fsinfo = {
+ .fattr = &fattr,
+ };
+
+ return nfs_get_root(sb, mntfh, &fsinfo, _root);
+}
+
+/*
+ * create a dummy root dentry with dummy inode
+ */
+static int
+nfs_make_dummy_root(struct super_block *sb)
+{
+ struct dentry *root;
+ struct inode *inode;
+
+ inode = new_inode(sb);
+ if (!inode)
+ return -ENOMEM;
+
+ inode->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
+ inode->i_uid = inode->i_gid = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+
+ root = d_alloc_root(inode);
+ if (!root) {
+ iput(inode);
+ return -ENOMEM;
+ }
+
+ sb->s_root = root;
+ return 0;
}
/*
* Do NFS version-independent mount processing, and sanity checking
*/
static int
-nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
+nfs_sb_init(struct super_block *sb, struct nfs_fh *mntfh, rpc_authflavor_t authflavor,
+ struct dentry **_root)
{
struct nfs_server *server;
- struct inode *root_inode;
struct nfs_fattr fattr;
struct nfs_fsinfo fsinfo = {
.fattr = &fattr,
@@ -263,26 +320,29 @@
.fattr = &fattr,
};
+ int error;
+
/* We probably want something more informative here */
snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
- server = NFS_SB(sb);
+ sb->s_magic = NFS_SUPER_MAGIC;
- sb->s_magic = NFS_SUPER_MAGIC;
+ error = nfs_make_dummy_root(sb);
+ if (error < 0)
+ return error;
- root_inode = nfs_get_root(sb, &server->fh, &fsinfo);
- /* Did getting the root inode fail? */
- if (IS_ERR(root_inode))
- goto out_no_root;
- sb->s_root = d_alloc_root(root_inode);
- if (!sb->s_root)
- goto out_no_root;
+ error = nfs_get_root(sb, mntfh, &fsinfo, _root);
+ if (error < 0) {
+ dput(sb->s_root);
+ sb->s_root = NULL;
+ return error;
+ }
- sb->s_root->d_op = server->rpc_ops->dentry_ops;
+ server = NFS_SB(sb);
/* Get some general file system info */
if (server->namelen == 0 &&
- server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
+ server->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
server->namelen = pathinfo.max_namelen;
/* Work out a lot of parameters */
if (server->rsize == 0)
@@ -335,12 +395,6 @@
/* We're airborne Set socket buffersize */
rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
return 0;
- /* Yargs. It didn't work out. */
-out_no_root:
- printk("nfs_read_super: get root inode failed\n");
- if (!IS_ERR(root_inode))
- iput(root_inode);
- return -EINVAL;
}
/*
@@ -398,7 +452,8 @@
* daemon. We stash these away in the private superblock fields.
*/
static int
-nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
+nfs_fill_super(struct super_block *sb, struct nfs_fh *mntfh, struct nfs_mount_data *data,
+ int silent, struct dentry **_root)
{
struct nfs_server *server;
int err = -EIO;
@@ -473,7 +528,7 @@
}
sb->s_op = &nfs_sops;
- err = nfs_sb_init(sb, authflavor);
+ err = nfs_sb_init(sb, mntfh, authflavor, _root);
if (err != 0)
goto out_noinit;
@@ -1284,6 +1339,11 @@
/*
* File system information
+ * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a
+ * particular server are held in the same superblock
+ * - NFS superblocks can have several effective roots to the dentry tree
+ * - directory type roots are spliced into the tree when a path from one root reaches the root
+ * of another (see nfs_lookup())
*/
static int nfs_set_super(struct super_block *s, void *data)
@@ -1301,7 +1361,7 @@
return 0;
if (old->addr.sin_port != server->addr.sin_port)
return 0;
- return !memcmp(&old->fh, &server->fh, sizeof(struct nfs_fh));
+ return 1;
}
static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
@@ -1310,7 +1370,7 @@
int error;
struct nfs_server *server;
struct super_block *s;
- struct nfs_fh *root;
+ struct nfs_fh mntfh;
struct nfs_mount_data *data = raw_data;
if (!data) {
@@ -1325,10 +1385,9 @@
/* Zero out the NFS state stuff */
init_nfsv4_state(server);
- root = &server->fh;
- memcpy(root, &data->root, sizeof(*root));
- if (root->size < sizeof(root->data))
- memset(root->data+root->size, 0, sizeof(root->data)-root->size);
+ memcpy(&mntfh, &data->root, sizeof(mntfh));
+ if (mntfh.size < sizeof(mntfh.data))
+ memset(mntfh.data+mntfh.size, 0, sizeof(mntfh.data)-mntfh.size);
if (data->version != NFS_MOUNT_VERSION) {
printk("nfs warning: mount version %s than kernel\n",
@@ -1339,15 +1398,15 @@
data->bsize = 0;
if (data->version < 4) {
data->flags &= ~NFS_MOUNT_VER3;
- memset(root, 0, sizeof(*root));
- root->size = NFS2_FHSIZE;
- memcpy(root->data, data->old_root.data, NFS2_FHSIZE);
+ memset(&mntfh, 0, sizeof(mntfh));
+ mntfh.size = NFS2_FHSIZE;
+ memcpy(mntfh.data, data->old_root.data, NFS2_FHSIZE);
}
if (data->version < 5)
data->flags &= ~NFS_MOUNT_SECFLAVOUR;
}
- if (root->size > sizeof(root->data)) {
+ if (mntfh.size > sizeof(mntfh.data)) {
printk("nfs_get_sb: invalid root filehandle\n");
kfree(server);
return ERR_PTR(-EINVAL);
@@ -1360,22 +1419,33 @@
return ERR_PTR(-EINVAL);
}
+ /* Get a superblock - note that we may end up sharing one that already exists */
s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
-
- if (IS_ERR(s) || s->s_root) {
+ if (IS_ERR(s)) {
kfree(server);
return s;
}
- s->s_flags = flags;
+ if (!s->s_root) {
+ s->s_flags = flags;
- error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
- if (error) {
- up_write(&s->s_umount);
- deactivate_super(s);
- return ERR_PTR(error);
+ error = nfs_fill_super(s, &mntfh, data, flags & MS_VERBOSE ? 1 : 0, _root);
+ if (error) {
+ up_write(&s->s_umount);
+ deactivate_super(s);
+ return ERR_PTR(error);
+ }
+ s->s_flags |= MS_ACTIVE;
}
- s->s_flags |= MS_ACTIVE;
+ else {
+ error = nfs_get_another_root(s, &mntfh, _root);
+ if (error) {
+ up_write(&s->s_umount);
+ deactivate_super(s);
+ return ERR_PTR(error);
+ }
+ }
+
return s;
}
diff -uNr linux-2.6.6-getsb/include/linux/dcache.h linux-2.6.6-nfs/include/linux/dcache.h
--- linux-2.6.6-getsb/include/linux/dcache.h 2004-05-17 15:08:42.000000000 +0100
+++ linux-2.6.6-nfs/include/linux/dcache.h 2004-05-19 17:13:03.000000000 +0100
@@ -198,6 +198,7 @@
*/
extern void d_instantiate(struct dentry *, struct inode *);
extern void d_delete(struct dentry *);
+extern void d_materialise_dentry(struct dentry *, struct dentry *);
/* allocate/de-allocate */
extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
diff -uNr linux-2.6.6-getsb/include/linux/nfs_fs_sb.h linux-2.6.6-nfs/include/linux/nfs_fs_sb.h
--- linux-2.6.6-getsb/include/linux/nfs_fs_sb.h 2004-05-17 15:08:42.000000000 +0100
+++ linux-2.6.6-nfs/include/linux/nfs_fs_sb.h 2004-05-19 19:45:38.000000000 +0100
@@ -26,14 +26,14 @@
unsigned int acdirmax;
unsigned int namelen;
char * hostname; /* remote hostname */
- struct nfs_fh fh;
+// struct nfs_fh fh;
struct sockaddr_in addr;
#ifdef CONFIG_NFS_V4
/* Our own IP address, as a null-terminated string.
* This is used to generate the clientid, and the callback address.
*/
char ip_addr[16];
- char * mnt_path;
+// char * mnt_path;
struct nfs4_client * nfs4_state; /* all NFSv4 state starts here */
struct list_head nfs4_siblings; /* List of other nfs_server structs
* that share the same clientid
--Multipart_Thu_May_20_12:22:58_2004-1--
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2004-05-28 8:53 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1084905576.5215.150.camel@lade.trondhjem.org>
2004-05-18 14:14 ` [PATCH] permit fs->get_sb() to return alternative root David Howells
2004-05-18 14:43 ` Trond Myklebust
[not found] ` <20040518152426.GY17014@parcelfarce.linux.theplanet.co.uk>
[not found] ` <1084895260.5215.22.camel@lade.trondhjem.org>
[not found] ` <20040518162812.GZ17014@parcelfarce.linux.theplanet.co.uk>
[not found] ` <1084898393.5215.43.camel@lade.trondhjem.org>
[not found] ` <Pine.LNX.4.58.0405180948190.25502@ppc970.osdl.org>
[not found] ` <1084899447.5215.49.camel@lade.trondhjem.org>
[not found] ` <20040518170410.GA17014@parcelfarce.linux.theplanet.co.uk>
[not found] ` <1084902342.5215.94.camel@lade.trondhjem.org>
[not found] ` <20040518174808.GD17014@parcelfarce.linux.theplanet.co.uk>
2004-05-20 11:22 ` David Howells
2004-05-28 8:52 ` David Howells
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).