diff options
Diffstat (limited to 'fs/nfsd/nfsfh.c')
-rw-r--r-- | fs/nfsd/nfsfh.c | 152 |
1 files changed, 76 insertions, 76 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index c59d6fbb7a6b..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> |
@@ -20,6 +19,7 @@ | |||
20 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
21 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
22 | 21 | ||
22 | #include <linux/sunrpc/clnt.h> | ||
23 | #include <linux/sunrpc/svc.h> | 23 | #include <linux/sunrpc/svc.h> |
24 | #include <linux/nfsd/nfsd.h> | 24 | #include <linux/nfsd/nfsd.h> |
25 | 25 | ||
@@ -118,9 +118,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
118 | 118 | ||
119 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); | 119 | dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); |
120 | 120 | ||
121 | /* keep this filehandle for possible reference when encoding attributes */ | ||
122 | rqstp->rq_reffh = fh; | ||
123 | |||
124 | if (!fhp->fh_dentry) { | 121 | if (!fhp->fh_dentry) { |
125 | __u32 *datap=NULL; | 122 | __u32 *datap=NULL; |
126 | __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ | 123 | __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ |
@@ -145,10 +142,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
145 | } | 142 | } |
146 | len = key_len(fh->fh_fsid_type) / 4; | 143 | len = key_len(fh->fh_fsid_type) / 4; |
147 | if (len == 0) goto out; | 144 | if (len == 0) goto out; |
148 | if (fh->fh_fsid_type == 2) { | 145 | if (fh->fh_fsid_type == FSID_MAJOR_MINOR) { |
149 | /* deprecated, convert to type 3 */ | 146 | /* deprecated, convert to type 3 */ |
150 | len = 3; | 147 | len = key_len(FSID_ENCODE_DEV)/4; |
151 | fh->fh_fsid_type = 3; | 148 | fh->fh_fsid_type = FSID_ENCODE_DEV; |
152 | 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]))); |
153 | fh->fh_fsid[1] = fh->fh_fsid[2]; | 150 | fh->fh_fsid[1] = fh->fh_fsid[2]; |
154 | } | 151 | } |
@@ -163,8 +160,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
163 | /* assume old filehandle format */ | 160 | /* assume old filehandle format */ |
164 | xdev = old_decode_dev(fh->ofh_xdev); | 161 | xdev = old_decode_dev(fh->ofh_xdev); |
165 | xino = u32_to_ino_t(fh->ofh_xino); | 162 | xino = u32_to_ino_t(fh->ofh_xino); |
166 | mk_fsid_v0(tfh, xdev, xino); | 163 | mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL); |
167 | 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); | ||
168 | } | 166 | } |
169 | 167 | ||
170 | if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN | 168 | if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN |
@@ -180,10 +178,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
180 | /* Check if the request originated from a secure port. */ | 178 | /* Check if the request originated from a secure port. */ |
181 | error = nfserr_perm; | 179 | error = nfserr_perm; |
182 | if (!rqstp->rq_secure && EX_SECURE(exp)) { | 180 | if (!rqstp->rq_secure && EX_SECURE(exp)) { |
181 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
183 | printk(KERN_WARNING | 182 | printk(KERN_WARNING |
184 | "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n", | 183 | "nfsd: request from insecure port %s!\n", |
185 | NIPQUAD(rqstp->rq_addr.sin_addr.s_addr), | 184 | svc_print_addr(rqstp, buf, sizeof(buf))); |
186 | ntohs(rqstp->rq_addr.sin_port)); | ||
187 | goto out; | 185 | goto out; |
188 | } | 186 | } |
189 | 187 | ||
@@ -211,7 +209,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) | |||
211 | fileid_type = 2; | 209 | fileid_type = 2; |
212 | } else | 210 | } else |
213 | fileid_type = fh->fh_fileid_type; | 211 | fileid_type = fh->fh_fileid_type; |
214 | 212 | ||
215 | if (fileid_type == 0) | 213 | if (fileid_type == 0) |
216 | dentry = dget(exp->ex_dentry); | 214 | dentry = dget(exp->ex_dentry); |
217 | else { | 215 | else { |
@@ -291,7 +289,7 @@ static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, | |||
291 | __u32 *datap, int *maxsize) | 289 | __u32 *datap, int *maxsize) |
292 | { | 290 | { |
293 | 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; |
294 | 292 | ||
295 | if (dentry == exp->ex_dentry) { | 293 | if (dentry == exp->ex_dentry) { |
296 | *maxsize = 0; | 294 | *maxsize = 0; |
297 | return 0; | 295 | return 0; |
@@ -316,7 +314,8 @@ static inline void _fh_update_old(struct dentry *dentry, | |||
316 | } | 314 | } |
317 | 315 | ||
318 | __be32 | 316 | __be32 |
319 | 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) | ||
320 | { | 319 | { |
321 | /* ref_fh is a reference file handle. | 320 | /* ref_fh is a reference file handle. |
322 | * 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 |
@@ -326,12 +325,13 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st | |||
326 | * | 325 | * |
327 | */ | 326 | */ |
328 | 327 | ||
329 | u8 ref_fh_version = 0; | 328 | u8 version = 1; |
330 | u8 ref_fh_fsid_type = 0; | 329 | u8 fsid_type = 0; |
331 | struct inode * inode = dentry->d_inode; | 330 | struct inode * inode = dentry->d_inode; |
332 | struct dentry *parent = dentry->d_parent; | 331 | struct dentry *parent = dentry->d_parent; |
333 | __u32 *datap; | 332 | __u32 *datap; |
334 | 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); | ||
335 | 335 | ||
336 | 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", |
337 | MAJOR(ex_dev), MINOR(ex_dev), | 337 | MAJOR(ex_dev), MINOR(ex_dev), |
@@ -339,57 +339,64 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st | |||
339 | parent->d_name.name, dentry->d_name.name, | 339 | parent->d_name.name, dentry->d_name.name, |
340 | (inode ? inode->i_ino : 0)); | 340 | (inode ? inode->i_ino : 0)); |
341 | 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 | */ | ||
342 | if (ref_fh && ref_fh->fh_export == exp) { | 346 | if (ref_fh && ref_fh->fh_export == exp) { |
343 | ref_fh_version = ref_fh->fh_handle.fh_version; | 347 | version = ref_fh->fh_handle.fh_version; |
344 | if (ref_fh_version == 0xca) | 348 | if (version == 0xca) |
345 | ref_fh_fsid_type = 0; | 349 | fsid_type = FSID_DEV; |
346 | else | 350 | else |
347 | ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type; | 351 | fsid_type = ref_fh->fh_handle.fh_fsid_type; |
348 | if (ref_fh_fsid_type > 3) | 352 | /* We know this version/type works for this export |
349 | ref_fh_fsid_type = 0; | 353 | * so there is no need for further checks. |
350 | 354 | */ | |
351 | /* make sure ref_fh type works for given export */ | 355 | } else if (exp->ex_uuid) { |
352 | if (ref_fh_fsid_type == 1 && | 356 | if (fhp->fh_maxsize >= 64) { |
353 | !(exp->ex_flags & NFSEXP_FSID)) { | 357 | if (root_export) |
354 | /* if we don't have an fsid, we cannot provide one... */ | 358 | fsid_type = FSID_UUID16; |
355 | 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; | ||
356 | } | 366 | } |
357 | } else if (exp->ex_flags & NFSEXP_FSID) | 367 | } else if (exp->ex_flags & NFSEXP_FSID) |
358 | ref_fh_fsid_type = 1; | 368 | fsid_type = FSID_NUM; |
359 | 369 | else if (!old_valid_dev(ex_dev)) | |
360 | if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) { | ||
361 | /* for newer device numbers, we must use a newer fsid format */ | 370 | /* for newer device numbers, we must use a newer fsid format */ |
362 | ref_fh_version = 1; | 371 | fsid_type = FSID_ENCODE_DEV; |
363 | ref_fh_fsid_type = 3; | 372 | else |
364 | } | 373 | fsid_type = FSID_DEV; |
365 | if (old_valid_dev(ex_dev) && | ||
366 | (ref_fh_fsid_type == 2 || ref_fh_fsid_type == 3)) | ||
367 | /* must use type1 for smaller device numbers */ | ||
368 | ref_fh_fsid_type = 0; | ||
369 | 374 | ||
370 | if (ref_fh == fhp) | 375 | if (ref_fh == fhp) |
371 | fh_put(ref_fh); | 376 | fh_put(ref_fh); |
372 | 377 | ||
373 | if (fhp->fh_locked || fhp->fh_dentry) { | 378 | if (fhp->fh_locked || fhp->fh_dentry) { |
374 | printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", | 379 | printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", |
375 | parent->d_name.name, dentry->d_name.name); | 380 | parent->d_name.name, dentry->d_name.name); |
376 | } | 381 | } |
377 | if (fhp->fh_maxsize < NFS_FHSIZE) | 382 | if (fhp->fh_maxsize < NFS_FHSIZE) |
378 | 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", |
379 | fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name); | 384 | fhp->fh_maxsize, |
385 | parent->d_name.name, dentry->d_name.name); | ||
380 | 386 | ||
381 | fhp->fh_dentry = dget(dentry); /* our internal copy */ | 387 | fhp->fh_dentry = dget(dentry); /* our internal copy */ |
382 | fhp->fh_export = exp; | 388 | fhp->fh_export = exp; |
383 | cache_get(&exp->h); | 389 | cache_get(&exp->h); |
384 | 390 | ||
385 | if (ref_fh_version == 0xca) { | 391 | if (version == 0xca) { |
386 | /* old style filehandle please */ | 392 | /* old style filehandle please */ |
387 | memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); | 393 | memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); |
388 | fhp->fh_handle.fh_size = NFS_FHSIZE; | 394 | fhp->fh_handle.fh_size = NFS_FHSIZE; |
389 | fhp->fh_handle.ofh_dcookie = 0xfeebbaca; | 395 | fhp->fh_handle.ofh_dcookie = 0xfeebbaca; |
390 | fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); | 396 | fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); |
391 | fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; | 397 | fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; |
392 | 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); | ||
393 | 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)); |
394 | if (inode) | 401 | if (inode) |
395 | _fh_update_old(dentry, exp, &fhp->fh_handle); | 402 | _fh_update_old(dentry, exp, &fhp->fh_handle); |
@@ -398,38 +405,12 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st | |||
398 | fhp->fh_handle.fh_version = 1; | 405 | fhp->fh_handle.fh_version = 1; |
399 | fhp->fh_handle.fh_auth_type = 0; | 406 | fhp->fh_handle.fh_auth_type = 0; |
400 | datap = fhp->fh_handle.fh_auth+0; | 407 | datap = fhp->fh_handle.fh_auth+0; |
401 | fhp->fh_handle.fh_fsid_type = ref_fh_fsid_type; | 408 | fhp->fh_handle.fh_fsid_type = fsid_type; |
402 | switch (ref_fh_fsid_type) { | 409 | mk_fsid(fsid_type, datap, ex_dev, |
403 | case 0: | 410 | exp->ex_dentry->d_inode->i_ino, |
404 | /* | 411 | exp->ex_fsid, exp->ex_uuid); |
405 | * fsid_type 0: | 412 | |
406 | * 2byte major, 2byte minor, 4byte inode | 413 | len = key_len(fsid_type); |
407 | */ | ||
408 | mk_fsid_v0(datap, ex_dev, | ||
409 | exp->ex_dentry->d_inode->i_ino); | ||
410 | break; | ||
411 | case 1: | ||
412 | /* fsid_type 1 == 4 bytes filesystem id */ | ||
413 | mk_fsid_v1(datap, exp->ex_fsid); | ||
414 | break; | ||
415 | case 2: | ||
416 | /* | ||
417 | * fsid_type 2: | ||
418 | * 4byte major, 4byte minor, 4byte inode | ||
419 | */ | ||
420 | mk_fsid_v2(datap, ex_dev, | ||
421 | exp->ex_dentry->d_inode->i_ino); | ||
422 | break; | ||
423 | case 3: | ||
424 | /* | ||
425 | * fsid_type 3: | ||
426 | * 4byte devicenumber, 4byte inode | ||
427 | */ | ||
428 | mk_fsid_v3(datap, ex_dev, | ||
429 | exp->ex_dentry->d_inode->i_ino); | ||
430 | break; | ||
431 | } | ||
432 | len = key_len(ref_fh_fsid_type); | ||
433 | datap += len/4; | 414 | datap += len/4; |
434 | fhp->fh_handle.fh_size = 4 + len; | 415 | fhp->fh_handle.fh_size = 4 + len; |
435 | 416 | ||
@@ -456,7 +437,7 @@ fh_update(struct svc_fh *fhp) | |||
456 | { | 437 | { |
457 | struct dentry *dentry; | 438 | struct dentry *dentry; |
458 | __u32 *datap; | 439 | __u32 *datap; |
459 | 440 | ||
460 | if (!fhp->fh_dentry) | 441 | if (!fhp->fh_dentry) |
461 | goto out_bad; | 442 | goto out_bad; |
462 | 443 | ||
@@ -533,3 +514,22 @@ char * SVCFH_fmt(struct svc_fh *fhp) | |||
533 | fh->fh_base.fh_pad[5]); | 514 | fh->fh_base.fh_pad[5]); |
534 | return buf; | 515 | return buf; |
535 | } | 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 | } | ||