diff options
Diffstat (limited to 'fs/nfsd/nfsfh.c')
-rw-r--r-- | fs/nfsd/nfsfh.c | 145 |
1 files changed, 72 insertions, 73 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index a0b4282cb284..c2660cbfcd96 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -9,7 +9,6 @@ | |||
9 | * ... and again Southern-Winter 2001 to support export_operations | 9 | * ... and again Southern-Winter 2001 to support export_operations |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
14 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
15 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
@@ -119,9 +118,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
119 | 118 | ||
120 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); | 119 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); |
121 | 120 | ||
122 | /* keep this filehandle for possible reference when encoding attributes */ | ||
123 | rqstp->rq_reffh = fh; | ||
124 | |||
125 | if (!fhp->fh_dentry) { | 121 | if (!fhp->fh_dentry) { |
126 | __u32 *datap=NULL; | 122 | __u32 *datap=NULL; |
127 | __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ | 123 | __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ |
@@ -146,10 +142,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
146 | } | 142 | } |
147 | len = key_len(fh->fh_fsid_type) / 4; | 143 | len = key_len(fh->fh_fsid_type) / 4; |
148 | if (len == 0) goto out; | 144 | if (len == 0) goto out; |
149 | if (fh->fh_fsid_type == 2) { | 145 | if (fh->fh_fsid_type == FSID_MAJOR_MINOR) { |
150 | /* deprecated, convert to type 3 */ | 146 | /* deprecated, convert to type 3 */ |
151 | len = 3; | 147 | len = key_len(FSID_ENCODE_DEV)/4; |
152 | fh->fh_fsid_type = 3; | 148 | 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]))); | 149 | 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]; | 150 | fh->fh_fsid[1] = fh->fh_fsid[2]; |
155 | } | 151 | } |
@@ -164,8 +160,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
164 | /* assume old filehandle format */ | 160 | /* assume old filehandle format */ |
165 | xdev = old_decode_dev(fh->ofh_xdev); | 161 | xdev = old_decode_dev(fh->ofh_xdev); |
166 | xino = u32_to_ino_t(fh->ofh_xino); | 162 | xino = u32_to_ino_t(fh->ofh_xino); |
167 | mk_fsid_v0(tfh, xdev, xino); | 163 | mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL); |
168 | exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle); | 164 | exp = exp_find(rqstp->rq_client, FSID_DEV, tfh, |
165 | &rqstp->rq_chandle); | ||
169 | } | 166 | } |
170 | 167 | ||
171 | if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN | 168 | if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN |
@@ -212,7 +209,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
212 | fileid_type = 2; | 209 | fileid_type = 2; |
213 | } else | 210 | } else |
214 | fileid_type = fh->fh_fileid_type; | 211 | fileid_type = fh->fh_fileid_type; |
215 | 212 | ||
216 | if (fileid_type == 0) | 213 | if (fileid_type == 0) |
217 | dentry = dget(exp->ex_dentry); | 214 | dentry = dget(exp->ex_dentry); |
218 | else { | 215 | else { |
@@ -292,7 +289,7 @@ static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, | |||
292 | __u32 *datap, int *maxsize) | 289 | __u32 *datap, int *maxsize) |
293 | { | 290 | { |
294 | struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op; | 291 | struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op; |
295 | 292 | ||
296 | if (dentry == exp->ex_dentry) { | 293 | if (dentry == exp->ex_dentry) { |
297 | *maxsize = 0; | 294 | *maxsize = 0; |
298 | return 0; | 295 | return 0; |
@@ -317,7 +314,8 @@ static inline void _fh_update_old(struct dentry *dentry, | |||
317 | } | 314 | } |
318 | 315 | ||
319 | __be32 | 316 | __be32 |
320 | fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) | 317 | fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, |
318 | struct svc_fh *ref_fh) | ||
321 | { | 319 | { |
322 | /* ref_fh is a reference file handle. | 320 | /* ref_fh is a reference file handle. |
323 | * if it is non-null and for the same filesystem, then we should compose | 321 | * if it is non-null and for the same filesystem, then we should compose |
@@ -327,12 +325,13 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st | |||
327 | * | 325 | * |
328 | */ | 326 | */ |
329 | 327 | ||
330 | u8 ref_fh_version = 0; | 328 | u8 version = 1; |
331 | u8 ref_fh_fsid_type = 0; | 329 | u8 fsid_type = 0; |
332 | struct inode * inode = dentry->d_inode; | 330 | struct inode * inode = dentry->d_inode; |
333 | struct dentry *parent = dentry->d_parent; | 331 | struct dentry *parent = dentry->d_parent; |
334 | __u32 *datap; | 332 | __u32 *datap; |
335 | dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev; | 333 | dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev; |
334 | int root_export = (exp->ex_dentry == exp->ex_dentry->d_sb->s_root); | ||
336 | 335 | ||
337 | dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", | 336 | dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", |
338 | MAJOR(ex_dev), MINOR(ex_dev), | 337 | MAJOR(ex_dev), MINOR(ex_dev), |
@@ -340,57 +339,64 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st | |||
340 | parent->d_name.name, dentry->d_name.name, | 339 | parent->d_name.name, dentry->d_name.name, |
341 | (inode ? inode->i_ino : 0)); | 340 | (inode ? inode->i_ino : 0)); |
342 | 341 | ||
342 | /* Choose filehandle version and fsid type based on | ||
343 | * the reference filehandle (if it is in the same export) | ||
344 | * or the export options. | ||
345 | */ | ||
343 | if (ref_fh && ref_fh->fh_export == exp) { | 346 | if (ref_fh && ref_fh->fh_export == exp) { |
344 | ref_fh_version = ref_fh->fh_handle.fh_version; | 347 | version = ref_fh->fh_handle.fh_version; |
345 | if (ref_fh_version == 0xca) | 348 | if (version == 0xca) |
346 | ref_fh_fsid_type = 0; | 349 | fsid_type = FSID_DEV; |
347 | else | 350 | else |
348 | ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type; | 351 | fsid_type = ref_fh->fh_handle.fh_fsid_type; |
349 | if (ref_fh_fsid_type > 3) | 352 | /* We know this version/type works for this export |
350 | ref_fh_fsid_type = 0; | 353 | * so there is no need for further checks. |
351 | 354 | */ | |
352 | /* make sure ref_fh type works for given export */ | 355 | } else if (exp->ex_uuid) { |
353 | if (ref_fh_fsid_type == 1 && | 356 | if (fhp->fh_maxsize >= 64) { |
354 | !(exp->ex_flags & NFSEXP_FSID)) { | 357 | if (root_export) |
355 | /* if we don't have an fsid, we cannot provide one... */ | 358 | fsid_type = FSID_UUID16; |
356 | ref_fh_fsid_type = 0; | 359 | else |
360 | fsid_type = FSID_UUID16_INUM; | ||
361 | } else { | ||
362 | if (root_export) | ||
363 | fsid_type = FSID_UUID8; | ||
364 | else | ||
365 | fsid_type = FSID_UUID4_INUM; | ||
357 | } | 366 | } |
358 | } else if (exp->ex_flags & NFSEXP_FSID) | 367 | } else if (exp->ex_flags & NFSEXP_FSID) |
359 | ref_fh_fsid_type = 1; | 368 | fsid_type = FSID_NUM; |
360 | 369 | else if (!old_valid_dev(ex_dev)) | |
361 | if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) { | ||
362 | /* for newer device numbers, we must use a newer fsid format */ | 370 | /* for newer device numbers, we must use a newer fsid format */ |
363 | ref_fh_version = 1; | 371 | fsid_type = FSID_ENCODE_DEV; |
364 | ref_fh_fsid_type = 3; | 372 | else |
365 | } | 373 | fsid_type = FSID_DEV; |
366 | if (old_valid_dev(ex_dev) && | ||
367 | (ref_fh_fsid_type == 2 || ref_fh_fsid_type == 3)) | ||
368 | /* must use type1 for smaller device numbers */ | ||
369 | ref_fh_fsid_type = 0; | ||
370 | 374 | ||
371 | if (ref_fh == fhp) | 375 | if (ref_fh == fhp) |
372 | fh_put(ref_fh); | 376 | fh_put(ref_fh); |
373 | 377 | ||
374 | if (fhp->fh_locked || fhp->fh_dentry) { | 378 | if (fhp->fh_locked || fhp->fh_dentry) { |
375 | printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", | 379 | printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", |
376 | parent->d_name.name, dentry->d_name.name); | 380 | parent->d_name.name, dentry->d_name.name); |
377 | } | 381 | } |
378 | if (fhp->fh_maxsize < NFS_FHSIZE) | 382 | if (fhp->fh_maxsize < NFS_FHSIZE) |
379 | printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n", | 383 | printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n", |
380 | fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name); | 384 | fhp->fh_maxsize, |
385 | parent->d_name.name, dentry->d_name.name); | ||
381 | 386 | ||
382 | fhp->fh_dentry = dget(dentry); /* our internal copy */ | 387 | fhp->fh_dentry = dget(dentry); /* our internal copy */ |
383 | fhp->fh_export = exp; | 388 | fhp->fh_export = exp; |
384 | cache_get(&exp->h); | 389 | cache_get(&exp->h); |
385 | 390 | ||
386 | if (ref_fh_version == 0xca) { | 391 | if (version == 0xca) { |
387 | /* old style filehandle please */ | 392 | /* old style filehandle please */ |
388 | memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); | 393 | memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); |
389 | fhp->fh_handle.fh_size = NFS_FHSIZE; | 394 | fhp->fh_handle.fh_size = NFS_FHSIZE; |
390 | fhp->fh_handle.ofh_dcookie = 0xfeebbaca; | 395 | fhp->fh_handle.ofh_dcookie = 0xfeebbaca; |
391 | fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); | 396 | fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); |
392 | fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; | 397 | fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; |
393 | fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino); | 398 | fhp->fh_handle.ofh_xino = |
399 | ino_t_to_u32(exp->ex_dentry->d_inode->i_ino); | ||
394 | fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); | 400 | fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); |
395 | if (inode) | 401 | if (inode) |
396 | _fh_update_old(dentry, exp, &fhp->fh_handle); | 402 | _fh_update_old(dentry, exp, &fhp->fh_handle); |
@@ -399,38 +405,12 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st | |||
399 | fhp->fh_handle.fh_version = 1; | 405 | fhp->fh_handle.fh_version = 1; |
400 | fhp->fh_handle.fh_auth_type = 0; | 406 | fhp->fh_handle.fh_auth_type = 0; |
401 | datap = fhp->fh_handle.fh_auth+0; | 407 | datap = fhp->fh_handle.fh_auth+0; |
402 | fhp->fh_handle.fh_fsid_type = ref_fh_fsid_type; | 408 | fhp->fh_handle.fh_fsid_type = fsid_type; |
403 | switch (ref_fh_fsid_type) { | 409 | mk_fsid(fsid_type, datap, ex_dev, |
404 | case 0: | 410 | exp->ex_dentry->d_inode->i_ino, |
405 | /* | 411 | exp->ex_fsid, exp->ex_uuid); |
406 | * fsid_type 0: | 412 | |
407 | * 2byte major, 2byte minor, 4byte inode | 413 | len = key_len(fsid_type); |
408 | */ | ||
409 | mk_fsid_v0(datap, ex_dev, | ||
410 | exp->ex_dentry->d_inode->i_ino); | ||
411 | break; | ||
412 | case 1: | ||
413 | /* fsid_type 1 == 4 bytes filesystem id */ | ||
414 | mk_fsid_v1(datap, exp->ex_fsid); | ||
415 | break; | ||
416 | case 2: | ||
417 | /* | ||
418 | * fsid_type 2: | ||
419 | * 4byte major, 4byte minor, 4byte inode | ||
420 | */ | ||
421 | mk_fsid_v2(datap, ex_dev, | ||
422 | exp->ex_dentry->d_inode->i_ino); | ||
423 | break; | ||
424 | case 3: | ||
425 | /* | ||
426 | * fsid_type 3: | ||
427 | * 4byte devicenumber, 4byte inode | ||
428 | */ | ||
429 | mk_fsid_v3(datap, ex_dev, | ||
430 | exp->ex_dentry->d_inode->i_ino); | ||
431 | break; | ||
432 | } | ||
433 | len = key_len(ref_fh_fsid_type); | ||
434 | datap += len/4; | 414 | datap += len/4; |
435 | fhp->fh_handle.fh_size = 4 + len; | 415 | fhp->fh_handle.fh_size = 4 + len; |
436 | 416 | ||
@@ -457,7 +437,7 @@ fh_update(struct svc_fh *fhp) | |||
457 | { | 437 | { |
458 | struct dentry *dentry; | 438 | struct dentry *dentry; |
459 | __u32 *datap; | 439 | __u32 *datap; |
460 | 440 | ||
461 | if (!fhp->fh_dentry) | 441 | if (!fhp->fh_dentry) |
462 | goto out_bad; | 442 | goto out_bad; |
463 | 443 | ||
@@ -534,3 +514,22 @@ char * SVCFH_fmt(struct svc_fh *fhp) | |||
534 | fh->fh_base.fh_pad[5]); | 514 | fh->fh_base.fh_pad[5]); |
535 | return buf; | 515 | return buf; |
536 | } | 516 | } |
517 | |||
518 | enum fsid_source fsid_source(struct svc_fh *fhp) | ||
519 | { | ||
520 | if (fhp->fh_handle.fh_version != 1) | ||
521 | return FSIDSOURCE_DEV; | ||
522 | switch(fhp->fh_handle.fh_fsid_type) { | ||
523 | case FSID_DEV: | ||
524 | case FSID_ENCODE_DEV: | ||
525 | case FSID_MAJOR_MINOR: | ||
526 | return FSIDSOURCE_DEV; | ||
527 | case FSID_NUM: | ||
528 | return FSIDSOURCE_FSID; | ||
529 | default: | ||
530 | if (fhp->fh_export->ex_flags & NFSEXP_FSID) | ||
531 | return FSIDSOURCE_FSID; | ||
532 | else | ||
533 | return FSIDSOURCE_UUID; | ||
534 | } | ||
535 | } | ||