Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 30110
b: refs/heads/master
c: 6b97fd3
h: refs/heads/master
v: v3
  • Loading branch information
Manoj Naik authored and Trond Myklebust committed Jun 9, 2006
1 parent 893c3ee commit 46d757b
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9cdb3883c38f883436a84c2353a4cf964ff890a2
refs/heads/master: 6b97fd3da1eab2cc490cfe884c7d4956522eaf8b
5 changes: 4 additions & 1 deletion trunk/fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,10 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
/* Deal with crossing mountpoints */
if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) {
inode->i_op = &nfs_mountpoint_inode_operations;
if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
inode->i_op = &nfs_referral_inode_operations;
else
inode->i_op = &nfs_mountpoint_inode_operations;
inode->i_fop = NULL;
}
} else if (S_ISLNK(inode->i_mode))
Expand Down
9 changes: 8 additions & 1 deletion trunk/fs/nfs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
if (err != 0)
goto out_err;

mnt = nfs_do_submount(nd->mnt, nd->dentry, &fh, &fattr);
if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL)
mnt = nfs_do_refmount(nd->mnt, nd->dentry);
else
mnt = nfs_do_submount(nd->mnt, nd->dentry, &fh, &fattr);
err = PTR_ERR(mnt);
if (IS_ERR(mnt))
goto out_err;
Expand Down Expand Up @@ -94,6 +97,10 @@ struct inode_operations nfs_mountpoint_inode_operations = {
.getattr = nfs_getattr,
};

struct inode_operations nfs_referral_inode_operations = {
.follow_link = nfs_follow_mountpoint,
};

static void nfs_expire_automounts(void *data)
{
struct list_head *list = (struct list_head *)data;
Expand Down
46 changes: 46 additions & 0 deletions trunk/fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,50 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
return nfs4_map_errors(status);
}

/*
* Get locations and (maybe) other attributes of a referral.
* Note that we'll actually follow the referral later when
* we detect fsid mismatch in inode revalidation
*/
static int nfs4_get_referral(struct inode *dir, struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle)
{
int status = -ENOMEM;
struct page *page = NULL;
struct nfs4_fs_locations *locations = NULL;
struct dentry dentry = {};

page = alloc_page(GFP_KERNEL);
if (page == NULL)
goto out;
locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
if (locations == NULL)
goto out;

dentry.d_name.name = name->name;
dentry.d_name.len = name->len;
status = nfs4_proc_fs_locations(dir, &dentry, locations, page);
if (status != 0)
goto out;
/* Make sure server returned a different fsid for the referral */
if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
dprintk("%s: server did not return a different fsid for a referral at %s\n", __FUNCTION__, name->name);
status = -EIO;
goto out;
}

memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr));
fattr->valid |= NFS_ATTR_FATTR_V4_REFERRAL;
if (!fattr->mode)
fattr->mode = S_IFDIR;
memset(fhandle, 0, sizeof(struct nfs_fh));
out:
if (page)
__free_page(page);
if (locations)
kfree(locations);
return status;
}

static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs4_getattr_arg args = {
Expand Down Expand Up @@ -1566,6 +1610,8 @@ static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name,

dprintk("NFS call lookup %s\n", name->name);
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
if (status == -NFS4ERR_MOVED)
status = nfs4_get_referral(dir, name, fattr, fhandle);
dprintk("NFS reply lookup: %d\n", status);
return status;
}
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/nfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ extern void nfs_unregister_sysctl(void);
*/
extern struct list_head nfs_automount_list;
extern struct inode_operations nfs_mountpoint_inode_operations;
extern struct inode_operations nfs_referral_inode_operations;
extern int nfs_mountpoint_expiry_timeout;
extern void nfs_release_automount_timer(void);

Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/nfs_xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct nfs_fattr {
#define NFS_ATTR_FATTR 0x0002 /* post-op attributes */
#define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */
#define NFS_ATTR_FATTR_V4 0x0008 /* NFSv4 change attribute */
#define NFS_ATTR_FATTR_V4_REFERRAL 0x0010 /* NFSv4 referral */

/*
* Info on the file system
Expand Down

0 comments on commit 46d757b

Please sign in to comment.