Skip to content

Commit

Permalink
[PATCH] knfsd: nfsd4: actually use all the pieces to implement referrals
Browse files Browse the repository at this point in the history
Use all the pieces set up so far to implement referral support, allowing
return of NFS4ERR_MOVED and fs_locations attribute.

Signed-off-by: Manoj Naik <manoj@almaden.ibm.com>
Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
J.Bruce Fields authored and Linus Torvalds committed Oct 4, 2006
1 parent 81c3f41 commit 42ca099
Showing 3 changed files with 69 additions and 13 deletions.
30 changes: 23 additions & 7 deletions fs/nfsd/nfs4proc.c
Original file line number Diff line number Diff line change
@@ -802,13 +802,29 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
* require a valid current filehandle
*/
if ((!current_fh->fh_dentry) &&
!((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
(op->opnum == OP_SETCLIENTID) ||
(op->opnum == OP_SETCLIENTID_CONFIRM) ||
(op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
(op->opnum == OP_RELEASE_LOCKOWNER))) {
op->status = nfserr_nofilehandle;
if (!current_fh->fh_dentry) {
if (!((op->opnum == OP_PUTFH) ||
(op->opnum == OP_PUTROOTFH) ||
(op->opnum == OP_SETCLIENTID) ||
(op->opnum == OP_SETCLIENTID_CONFIRM) ||
(op->opnum == OP_RENEW) ||
(op->opnum == OP_RESTOREFH) ||
(op->opnum == OP_RELEASE_LOCKOWNER))) {
op->status = nfserr_nofilehandle;
goto encode_op;
}
}
/* Check must be done at start of each operation, except
* for GETATTR and ops not listed as returning NFS4ERR_MOVED
*/
else if (current_fh->fh_export->ex_fslocs.migrated &&
!((op->opnum == OP_GETATTR) ||
(op->opnum == OP_PUTROOTFH) ||
(op->opnum == OP_PUTPUBFH) ||
(op->opnum == OP_RENEW) ||
(op->opnum == OP_SETCLIENTID) ||
(op->opnum == OP_RELEASE_LOCKOWNER))) {
op->status = nfserr_moved;
goto encode_op;
}
switch (op->opnum) {
51 changes: 45 additions & 6 deletions fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
@@ -60,6 +60,14 @@

#define NFSDDBG_FACILITY NFSDDBG_XDR

/*
* As per referral draft, the fsid for a referral MUST be different from the fsid of the containing
* directory in order to indicate to the client that a filesystem boundary is present
* We use a fixed fsid for a referral
*/
#define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL
#define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL

static int
check_filename(char *str, int len, int err)
{
@@ -1385,6 +1393,25 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
}

#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
FATTR4_WORD0_RDATTR_ERROR)
#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID

static int fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
{
/* As per referral draft: */
if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
*bmval1 & ~WORD1_ABSENT_FS_ATTRS) {
if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR ||
*bmval0 & FATTR4_WORD0_FS_LOCATIONS)
*rdattr_err = NFSERR_MOVED;
else
return nfserr_moved;
}
*bmval0 &= WORD0_ABSENT_FS_ATTRS;
*bmval1 &= WORD1_ABSENT_FS_ATTRS;
return 0;
}

/*
* Note: @fhp can be NULL; in this case, we might have to compose the filehandle
@@ -1407,6 +1434,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
u32 *attrlenp;
u32 dummy;
u64 dummy64;
u32 rdattr_err = 0;
u32 *p = buffer;
int status;
int aclsupport = 0;
@@ -1416,6 +1444,12 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1);

if (exp->ex_fslocs.migrated) {
status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
if (status)
goto out;
}

status = vfs_getattr(exp->ex_mnt, dentry, &stat);
if (status)
goto out_nfserr;
@@ -1461,12 +1495,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
attrlenp = p++; /* to be backfilled later */

if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0;
if ((buflen -= 12) < 0)
goto out_resource;
if (!aclsupport)
word0 &= ~FATTR4_WORD0_ACL;
if (!exp->ex_fslocs.locations)
word0 &= ~FATTR4_WORD0_FS_LOCATIONS;
WRITE32(2);
WRITE32(aclsupport ?
NFSD_SUPPORTED_ATTRS_WORD0 :
NFSD_SUPPORTED_ATTRS_WORD0 & ~FATTR4_WORD0_ACL);
WRITE32(word0);
WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
}
if (bmval0 & FATTR4_WORD0_TYPE) {
@@ -1520,7 +1557,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if (bmval0 & FATTR4_WORD0_FSID) {
if ((buflen -= 16) < 0)
goto out_resource;
if (is_fsid(fhp, rqstp->rq_reffh)) {
if (exp->ex_fslocs.migrated) {
WRITE64(NFS4_REFERRAL_FSID_MAJOR);
WRITE64(NFS4_REFERRAL_FSID_MINOR);
} else if (is_fsid(fhp, rqstp->rq_reffh)) {
WRITE64((u64)exp->ex_fsid);
WRITE64((u64)0);
} else {
@@ -1543,7 +1583,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
if ((buflen -= 4) < 0)
goto out_resource;
WRITE32(0);
WRITE32(rdattr_err);
}
if (bmval0 & FATTR4_WORD0_ACL) {
struct nfs4_ace *ace;
@@ -1970,7 +2010,6 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_ge
nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
resp->p, &buflen, getattr->ga_bmval,
resp->rqstp);

if (!nfserr)
resp->p += buflen;
return nfserr;
1 change: 1 addition & 0 deletions include/linux/nfsd/nfsd.h
Original file line number Diff line number Diff line change
@@ -216,6 +216,7 @@ void nfsd_lockd_shutdown(void);
#define nfserr_clid_inuse __constant_htonl(NFSERR_CLID_INUSE)
#define nfserr_stale_clientid __constant_htonl(NFSERR_STALE_CLIENTID)
#define nfserr_resource __constant_htonl(NFSERR_RESOURCE)
#define nfserr_moved __constant_htonl(NFSERR_MOVED)
#define nfserr_nofilehandle __constant_htonl(NFSERR_NOFILEHANDLE)
#define nfserr_minor_vers_mismatch __constant_htonl(NFSERR_MINOR_VERS_MISMATCH)
#define nfserr_share_denied __constant_htonl(NFSERR_SHARE_DENIED)

0 comments on commit 42ca099

Please sign in to comment.