Commit 42ca0993 authored by J.Bruce Fields's avatar J.Bruce Fields Committed by Linus Torvalds

[PATCH] knfsd: nfsd4: actually use all the pieces to implement referrals

Use all the pieces set up so far to implement referral support, allowing
return of NFS4ERR_MOVED and fs_locations attribute.
Signed-off-by: default avatarManoj Naik <manoj@almaden.ibm.com>
Signed-off-by: default avatarFred Isaman <iisaman@citi.umich.edu>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 81c3f413
...@@ -802,13 +802,29 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, ...@@ -802,13 +802,29 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
* require a valid current filehandle * require a valid current filehandle
*/ */
if ((!current_fh->fh_dentry) && if (!current_fh->fh_dentry) {
!((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) || if (!((op->opnum == OP_PUTFH) ||
(op->opnum == OP_SETCLIENTID) || (op->opnum == OP_PUTROOTFH) ||
(op->opnum == OP_SETCLIENTID_CONFIRM) || (op->opnum == OP_SETCLIENTID) ||
(op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) || (op->opnum == OP_SETCLIENTID_CONFIRM) ||
(op->opnum == OP_RELEASE_LOCKOWNER))) { (op->opnum == OP_RENEW) ||
op->status = nfserr_nofilehandle; (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; goto encode_op;
} }
switch (op->opnum) { switch (op->opnum) {
......
...@@ -60,6 +60,14 @@ ...@@ -60,6 +60,14 @@
#define NFSDDBG_FACILITY NFSDDBG_XDR #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 static int
check_filename(char *str, int len, int err) 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, ...@@ -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); 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 * 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, ...@@ -1407,6 +1434,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
u32 *attrlenp; u32 *attrlenp;
u32 dummy; u32 dummy;
u64 dummy64; u64 dummy64;
u32 rdattr_err = 0;
u32 *p = buffer; u32 *p = buffer;
int status; int status;
int aclsupport = 0; int aclsupport = 0;
...@@ -1416,6 +1444,12 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, ...@@ -1416,6 +1444,12 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0); BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1); 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); status = vfs_getattr(exp->ex_mnt, dentry, &stat);
if (status) if (status)
goto out_nfserr; goto out_nfserr;
...@@ -1461,12 +1495,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, ...@@ -1461,12 +1495,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
attrlenp = p++; /* to be backfilled later */ attrlenp = p++; /* to be backfilled later */
if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0;
if ((buflen -= 12) < 0) if ((buflen -= 12) < 0)
goto out_resource; goto out_resource;
if (!aclsupport)
word0 &= ~FATTR4_WORD0_ACL;
if (!exp->ex_fslocs.locations)
word0 &= ~FATTR4_WORD0_FS_LOCATIONS;
WRITE32(2); WRITE32(2);
WRITE32(aclsupport ? WRITE32(word0);
NFSD_SUPPORTED_ATTRS_WORD0 :
NFSD_SUPPORTED_ATTRS_WORD0 & ~FATTR4_WORD0_ACL);
WRITE32(NFSD_SUPPORTED_ATTRS_WORD1); WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
} }
if (bmval0 & FATTR4_WORD0_TYPE) { if (bmval0 & FATTR4_WORD0_TYPE) {
...@@ -1520,7 +1557,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, ...@@ -1520,7 +1557,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if (bmval0 & FATTR4_WORD0_FSID) { if (bmval0 & FATTR4_WORD0_FSID) {
if ((buflen -= 16) < 0) if ((buflen -= 16) < 0)
goto out_resource; 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)exp->ex_fsid);
WRITE64((u64)0); WRITE64((u64)0);
} else { } else {
...@@ -1543,7 +1583,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, ...@@ -1543,7 +1583,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
if ((buflen -= 4) < 0) if ((buflen -= 4) < 0)
goto out_resource; goto out_resource;
WRITE32(0); WRITE32(rdattr_err);
} }
if (bmval0 & FATTR4_WORD0_ACL) { if (bmval0 & FATTR4_WORD0_ACL) {
struct nfs4_ace *ace; struct nfs4_ace *ace;
...@@ -1970,7 +2010,6 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_ge ...@@ -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, nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
resp->p, &buflen, getattr->ga_bmval, resp->p, &buflen, getattr->ga_bmval,
resp->rqstp); resp->rqstp);
if (!nfserr) if (!nfserr)
resp->p += buflen; resp->p += buflen;
return nfserr; return nfserr;
......
...@@ -216,6 +216,7 @@ void nfsd_lockd_shutdown(void); ...@@ -216,6 +216,7 @@ void nfsd_lockd_shutdown(void);
#define nfserr_clid_inuse __constant_htonl(NFSERR_CLID_INUSE) #define nfserr_clid_inuse __constant_htonl(NFSERR_CLID_INUSE)
#define nfserr_stale_clientid __constant_htonl(NFSERR_STALE_CLIENTID) #define nfserr_stale_clientid __constant_htonl(NFSERR_STALE_CLIENTID)
#define nfserr_resource __constant_htonl(NFSERR_RESOURCE) #define nfserr_resource __constant_htonl(NFSERR_RESOURCE)
#define nfserr_moved __constant_htonl(NFSERR_MOVED)
#define nfserr_nofilehandle __constant_htonl(NFSERR_NOFILEHANDLE) #define nfserr_nofilehandle __constant_htonl(NFSERR_NOFILEHANDLE)
#define nfserr_minor_vers_mismatch __constant_htonl(NFSERR_MINOR_VERS_MISMATCH) #define nfserr_minor_vers_mismatch __constant_htonl(NFSERR_MINOR_VERS_MISMATCH)
#define nfserr_share_denied __constant_htonl(NFSERR_SHARE_DENIED) #define nfserr_share_denied __constant_htonl(NFSERR_SHARE_DENIED)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment