aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsfh.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2007-02-14 03:33:12 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-14 11:09:53 -0500
commitaf6a4e280e3ff453653f39190b57b345ff0bec16 (patch)
tree4895c90613737db7354f43431ed10a55dc0c98f0 /fs/nfsd/nfsfh.c
parent982aedfd091e6d9831216f8519f12242091be4fd (diff)
[PATCH] knfsd: add some new fsid types
Add support for using a filesystem UUID to identify and export point in the filehandle. For NFSv2, this UUID is xor-ed down to 4 or 8 bytes so that it doesn't take up too much room. For NFSv3+, we use the full 16 bytes, and possibly also a 64bit inode number for exports beneath the root of a filesystem. When generating an fsid to return in 'stat' information, use the UUID (hashed down to size) if it is available and a small 'fsid' was not specifically provided. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nfsd/nfsfh.c')
-rw-r--r--fs/nfsd/nfsfh.c88
1 files changed, 46 insertions, 42 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 12c5e7421374..286bc4d356f4 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -119,9 +119,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
119 119
120 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); 120 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
121 121
122 /* keep this filehandle for possible reference when encoding attributes */
123 rqstp->rq_reffh = fh;
124
125 if (!fhp->fh_dentry) { 122 if (!fhp->fh_dentry) {
126 __u32 *datap=NULL; 123 __u32 *datap=NULL;
127 __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ 124 __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */
@@ -146,10 +143,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
146 } 143 }
147 len = key_len(fh->fh_fsid_type) / 4; 144 len = key_len(fh->fh_fsid_type) / 4;
148 if (len == 0) goto out; 145 if (len == 0) goto out;
149 if (fh->fh_fsid_type == 2) { 146 if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
150 /* deprecated, convert to type 3 */ 147 /* deprecated, convert to type 3 */
151 len = 3; 148 len = key_len(FSID_ENCODE_DEV)/4;
152 fh->fh_fsid_type = 3; 149 fh->fh_fsid_type = FSID_ENCODE_DEV;
153 fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1]))); 150 fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
154 fh->fh_fsid[1] = fh->fh_fsid[2]; 151 fh->fh_fsid[1] = fh->fh_fsid[2];
155 } 152 }
@@ -164,8 +161,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
164 /* assume old filehandle format */ 161 /* assume old filehandle format */
165 xdev = old_decode_dev(fh->ofh_xdev); 162 xdev = old_decode_dev(fh->ofh_xdev);
166 xino = u32_to_ino_t(fh->ofh_xino); 163 xino = u32_to_ino_t(fh->ofh_xino);
167 mk_fsid_v0(tfh, xdev, xino); 164 mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
168 exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle); 165 exp = exp_find(rqstp->rq_client, FSID_DEV, tfh,
166 &rqstp->rq_chandle);
169 } 167 }
170 168
171 if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN 169 if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
@@ -334,6 +332,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
334 struct dentry *parent = dentry->d_parent; 332 struct dentry *parent = dentry->d_parent;
335 __u32 *datap; 333 __u32 *datap;
336 dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev; 334 dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev;
335 int root_export = (exp->ex_dentry == exp->ex_dentry->d_sb->s_root);
337 336
338 dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", 337 dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
339 MAJOR(ex_dev), MINOR(ex_dev), 338 MAJOR(ex_dev), MINOR(ex_dev),
@@ -348,19 +347,31 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
348 if (ref_fh && ref_fh->fh_export == exp) { 347 if (ref_fh && ref_fh->fh_export == exp) {
349 version = ref_fh->fh_handle.fh_version; 348 version = ref_fh->fh_handle.fh_version;
350 if (version == 0xca) 349 if (version == 0xca)
351 fsid_type = 0; 350 fsid_type = FSID_DEV;
352 else 351 else
353 fsid_type = ref_fh->fh_handle.fh_fsid_type; 352 fsid_type = ref_fh->fh_handle.fh_fsid_type;
354 /* We know this version/type works for this export 353 /* We know this version/type works for this export
355 * so there is no need for further checks. 354 * so there is no need for further checks.
356 */ 355 */
356 } else if (exp->ex_uuid) {
357 if (fhp->fh_maxsize >= 64) {
358 if (root_export)
359 fsid_type = FSID_UUID16;
360 else
361 fsid_type = FSID_UUID16_INUM;
362 } else {
363 if (root_export)
364 fsid_type = FSID_UUID8;
365 else
366 fsid_type = FSID_UUID4_INUM;
367 }
357 } else if (exp->ex_flags & NFSEXP_FSID) 368 } else if (exp->ex_flags & NFSEXP_FSID)
358 fsid_type = 1; 369 fsid_type = FSID_NUM;
359 else if (!old_valid_dev(ex_dev)) 370 else if (!old_valid_dev(ex_dev))
360 /* for newer device numbers, we must use a newer fsid format */ 371 /* for newer device numbers, we must use a newer fsid format */
361 fsid_type = 3; 372 fsid_type = FSID_ENCODE_DEV;
362 else 373 else
363 fsid_type = 0; 374 fsid_type = FSID_DEV;
364 375
365 if (ref_fh == fhp) 376 if (ref_fh == fhp)
366 fh_put(ref_fh); 377 fh_put(ref_fh);
@@ -396,36 +407,10 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
396 fhp->fh_handle.fh_auth_type = 0; 407 fhp->fh_handle.fh_auth_type = 0;
397 datap = fhp->fh_handle.fh_auth+0; 408 datap = fhp->fh_handle.fh_auth+0;
398 fhp->fh_handle.fh_fsid_type = fsid_type; 409 fhp->fh_handle.fh_fsid_type = fsid_type;
399 switch (fsid_type) { 410 mk_fsid(fsid_type, datap, ex_dev,
400 case 0: 411 exp->ex_dentry->d_inode->i_ino,
401 /* 412 exp->ex_fsid, exp->ex_uuid);
402 * fsid_type 0: 413
403 * 2byte major, 2byte minor, 4byte inode
404 */
405 mk_fsid_v0(datap, ex_dev,
406 exp->ex_dentry->d_inode->i_ino);
407 break;
408 case 1:
409 /* fsid_type 1 == 4 bytes filesystem id */
410 mk_fsid_v1(datap, exp->ex_fsid);
411 break;
412 case 2:
413 /*
414 * fsid_type 2:
415 * 4byte major, 4byte minor, 4byte inode
416 */
417 mk_fsid_v2(datap, ex_dev,
418 exp->ex_dentry->d_inode->i_ino);
419 break;
420 case 3:
421 /*
422 * fsid_type 3:
423 * 4byte devicenumber, 4byte inode
424 */
425 mk_fsid_v3(datap, ex_dev,
426 exp->ex_dentry->d_inode->i_ino);
427 break;
428 }
429 len = key_len(fsid_type); 414 len = key_len(fsid_type);
430 datap += len/4; 415 datap += len/4;
431 fhp->fh_handle.fh_size = 4 + len; 416 fhp->fh_handle.fh_size = 4 + len;
@@ -530,3 +515,22 @@ char * SVCFH_fmt(struct svc_fh *fhp)
530 fh->fh_base.fh_pad[5]); 515 fh->fh_base.fh_pad[5]);
531 return buf; 516 return buf;
532} 517}
518
519enum fsid_source fsid_source(struct svc_fh *fhp)
520{
521 if (fhp->fh_handle.fh_version != 1)
522 return FSIDSOURCE_DEV;
523 switch(fhp->fh_handle.fh_fsid_type) {
524 case FSID_DEV:
525 case FSID_ENCODE_DEV:
526 case FSID_MAJOR_MINOR:
527 return FSIDSOURCE_DEV;
528 case FSID_NUM:
529 return FSIDSOURCE_FSID;
530 default:
531 if (fhp->fh_export->ex_flags & NFSEXP_FSID)
532 return FSIDSOURCE_FSID;
533 else
534 return FSIDSOURCE_UUID;
535 }
536}