aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ.Bruce Fields <bfields@fieldses.org>2006-10-04 05:16:20 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:23 -0400
commit42ca09938157105c1f573c831a35e9c3e02eb354 (patch)
tree61533863e1adb46016015a347c70517ae9b10d3f /fs/nfsd
parent81c3f4130202a1dcb2b28ab56684eb5e9d43d8c1 (diff)
[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: 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>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4proc.c30
-rw-r--r--fs/nfsd/nfs4xdr.c51
2 files changed, 68 insertions, 13 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 38b0f91175d0..8333db12caca 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -802,13 +802,29 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
802 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH 802 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
803 * require a valid current filehandle 803 * require a valid current filehandle
804 */ 804 */
805 if ((!current_fh->fh_dentry) && 805 if (!current_fh->fh_dentry) {
806 !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) || 806 if (!((op->opnum == OP_PUTFH) ||
807 (op->opnum == OP_SETCLIENTID) || 807 (op->opnum == OP_PUTROOTFH) ||
808 (op->opnum == OP_SETCLIENTID_CONFIRM) || 808 (op->opnum == OP_SETCLIENTID) ||
809 (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) || 809 (op->opnum == OP_SETCLIENTID_CONFIRM) ||
810 (op->opnum == OP_RELEASE_LOCKOWNER))) { 810 (op->opnum == OP_RENEW) ||
811 op->status = nfserr_nofilehandle; 811 (op->opnum == OP_RESTOREFH) ||
812 (op->opnum == OP_RELEASE_LOCKOWNER))) {
813 op->status = nfserr_nofilehandle;
814 goto encode_op;
815 }
816 }
817 /* Check must be done at start of each operation, except
818 * for GETATTR and ops not listed as returning NFS4ERR_MOVED
819 */
820 else if (current_fh->fh_export->ex_fslocs.migrated &&
821 !((op->opnum == OP_GETATTR) ||
822 (op->opnum == OP_PUTROOTFH) ||
823 (op->opnum == OP_PUTPUBFH) ||
824 (op->opnum == OP_RENEW) ||
825 (op->opnum == OP_SETCLIENTID) ||
826 (op->opnum == OP_RELEASE_LOCKOWNER))) {
827 op->status = nfserr_moved;
812 goto encode_op; 828 goto encode_op;
813 } 829 }
814 switch (op->opnum) { 830 switch (op->opnum) {
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 0589852007e6..41fc241b729a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -60,6 +60,14 @@
60 60
61#define NFSDDBG_FACILITY NFSDDBG_XDR 61#define NFSDDBG_FACILITY NFSDDBG_XDR
62 62
63/*
64 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing
65 * directory in order to indicate to the client that a filesystem boundary is present
66 * We use a fixed fsid for a referral
67 */
68#define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL
69#define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL
70
63static int 71static int
64check_filename(char *str, int len, int err) 72check_filename(char *str, int len, int err)
65{ 73{
@@ -1385,6 +1393,25 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1385 return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen); 1393 return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
1386} 1394}
1387 1395
1396#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
1397 FATTR4_WORD0_RDATTR_ERROR)
1398#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
1399
1400static int fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
1401{
1402 /* As per referral draft: */
1403 if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
1404 *bmval1 & ~WORD1_ABSENT_FS_ATTRS) {
1405 if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR ||
1406 *bmval0 & FATTR4_WORD0_FS_LOCATIONS)
1407 *rdattr_err = NFSERR_MOVED;
1408 else
1409 return nfserr_moved;
1410 }
1411 *bmval0 &= WORD0_ABSENT_FS_ATTRS;
1412 *bmval1 &= WORD1_ABSENT_FS_ATTRS;
1413 return 0;
1414}
1388 1415
1389/* 1416/*
1390 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle 1417 * 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 u32 *attrlenp; 1434 u32 *attrlenp;
1408 u32 dummy; 1435 u32 dummy;
1409 u64 dummy64; 1436 u64 dummy64;
1437 u32 rdattr_err = 0;
1410 u32 *p = buffer; 1438 u32 *p = buffer;
1411 int status; 1439 int status;
1412 int aclsupport = 0; 1440 int aclsupport = 0;
@@ -1416,6 +1444,12 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1416 BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0); 1444 BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
1417 BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1); 1445 BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1);
1418 1446
1447 if (exp->ex_fslocs.migrated) {
1448 status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
1449 if (status)
1450 goto out;
1451 }
1452
1419 status = vfs_getattr(exp->ex_mnt, dentry, &stat); 1453 status = vfs_getattr(exp->ex_mnt, dentry, &stat);
1420 if (status) 1454 if (status)
1421 goto out_nfserr; 1455 goto out_nfserr;
@@ -1461,12 +1495,15 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1461 attrlenp = p++; /* to be backfilled later */ 1495 attrlenp = p++; /* to be backfilled later */
1462 1496
1463 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { 1497 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
1498 u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0;
1464 if ((buflen -= 12) < 0) 1499 if ((buflen -= 12) < 0)
1465 goto out_resource; 1500 goto out_resource;
1501 if (!aclsupport)
1502 word0 &= ~FATTR4_WORD0_ACL;
1503 if (!exp->ex_fslocs.locations)
1504 word0 &= ~FATTR4_WORD0_FS_LOCATIONS;
1466 WRITE32(2); 1505 WRITE32(2);
1467 WRITE32(aclsupport ? 1506 WRITE32(word0);
1468 NFSD_SUPPORTED_ATTRS_WORD0 :
1469 NFSD_SUPPORTED_ATTRS_WORD0 & ~FATTR4_WORD0_ACL);
1470 WRITE32(NFSD_SUPPORTED_ATTRS_WORD1); 1507 WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
1471 } 1508 }
1472 if (bmval0 & FATTR4_WORD0_TYPE) { 1509 if (bmval0 & FATTR4_WORD0_TYPE) {
@@ -1520,7 +1557,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1520 if (bmval0 & FATTR4_WORD0_FSID) { 1557 if (bmval0 & FATTR4_WORD0_FSID) {
1521 if ((buflen -= 16) < 0) 1558 if ((buflen -= 16) < 0)
1522 goto out_resource; 1559 goto out_resource;
1523 if (is_fsid(fhp, rqstp->rq_reffh)) { 1560 if (exp->ex_fslocs.migrated) {
1561 WRITE64(NFS4_REFERRAL_FSID_MAJOR);
1562 WRITE64(NFS4_REFERRAL_FSID_MINOR);
1563 } else if (is_fsid(fhp, rqstp->rq_reffh)) {
1524 WRITE64((u64)exp->ex_fsid); 1564 WRITE64((u64)exp->ex_fsid);
1525 WRITE64((u64)0); 1565 WRITE64((u64)0);
1526 } else { 1566 } else {
@@ -1543,7 +1583,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1543 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { 1583 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
1544 if ((buflen -= 4) < 0) 1584 if ((buflen -= 4) < 0)
1545 goto out_resource; 1585 goto out_resource;
1546 WRITE32(0); 1586 WRITE32(rdattr_err);
1547 } 1587 }
1548 if (bmval0 & FATTR4_WORD0_ACL) { 1588 if (bmval0 & FATTR4_WORD0_ACL) {
1549 struct nfs4_ace *ace; 1589 struct nfs4_ace *ace;
@@ -1970,7 +2010,6 @@ nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_ge
1970 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, 2010 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
1971 resp->p, &buflen, getattr->ga_bmval, 2011 resp->p, &buflen, getattr->ga_bmval,
1972 resp->rqstp); 2012 resp->rqstp);
1973
1974 if (!nfserr) 2013 if (!nfserr)
1975 resp->p += buflen; 2014 resp->p += buflen;
1976 return nfserr; 2015 return nfserr;