patch-2.4.20 linux-2.4.20/fs/nfsd/nfsfh.c

Next file: linux-2.4.20/fs/nfsd/nfsproc.c
Previous file: linux-2.4.20/fs/nfsd/nfscache.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/fs/nfsd/nfsfh.c linux-2.4.20/fs/nfsd/nfsfh.c
@@ -273,7 +273,9 @@
 	/* I'm going to assume that if the returned dentry is different, then
 	 * it is well connected.  But nobody returns different dentrys do they?
 	 */
+	down(&child->d_inode->i_sem);
 	pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
+	up(&child->d_inode->i_sem);
 	d_drop(tdentry); /* we never want ".." hashed */
 	if (!pdentry && tdentry->d_inode == NULL) {
 		/* File system cannot find ".." ... sad but possible */
@@ -534,12 +536,17 @@
 
 	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
 
+	/* keep this filehandle for possible reference  when encoding attributes */
+	rqstp->rq_reffh = fh;
+
 	if (!fhp->fh_dentry) {
-		kdev_t xdev;
-		ino_t xino;
+		kdev_t xdev = NODEV;
+		ino_t xino = 0;
 		__u32 *datap=NULL;
 		int data_left = fh->fh_size/4;
 		int nfsdev;
+		int fsid = 0;
+
 		error = nfserr_stale;
 		if (rqstp->rq_vers == 3)
 			error = nfserr_badhandle;
@@ -559,6 +566,10 @@
 				xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
 				xino = *datap++;
 				break;
+			case 1:
+				if ((data_left-=1)<0) goto out;
+				fsid = *datap++;
+				break;
 			default:
 				goto out;
 			}
@@ -574,7 +585,10 @@
 		 * Look up the export entry.
 		 */
 		error = nfserr_stale; 
-		exp = exp_get(rqstp->rq_client, xdev, xino);
+		if (fh->fh_version == 1 && fh->fh_fsid_type == 1)
+			exp = exp_get_fsid(rqstp->rq_client, fsid);
+		else
+			exp = exp_get(rqstp->rq_client, xdev, xino);
 
 		if (!exp)
 			/* export entry revoked */
@@ -818,12 +832,20 @@
 	} else {
 		fhp->fh_handle.fh_version = 1;
 		fhp->fh_handle.fh_auth_type = 0;
-		fhp->fh_handle.fh_fsid_type = 0;
 		datap = fhp->fh_handle.fh_auth+0;
-		/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
-		*datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
-		*datap++ = ino_t_to_u32(exp->ex_ino);
-		fhp->fh_handle.fh_size = 3*4;
+		if ((exp->ex_flags & NFSEXP_FSID) &&
+		    (!ref_fh || ref_fh->fh_handle.fh_fsid_type == 1)) {
+			fhp->fh_handle.fh_fsid_type = 1;
+			/* fsid_type 1 == 4 bytes filesystem id */
+			*datap++ = exp->ex_fsid;
+			fhp->fh_handle.fh_size = 2*4;
+		} else {
+			fhp->fh_handle.fh_fsid_type = 0;
+			/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
+			*datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
+			*datap++ = ino_t_to_u32(exp->ex_ino);
+			fhp->fh_handle.fh_size = 3*4;
+		}
 		if (inode) {
 			int size = fhp->fh_maxsize/4 - 3;
 			fhp->fh_handle.fh_fileid_type =

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)