aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsfh.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2007-10-21 19:42:03 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-22 11:13:19 -0400
commit6e91ea2bb0b6a3ddf6d4faeb54a9c20d4e20bc42 (patch)
tree3f20a72d6c36620d071c485206b39e2e32546fc6 /fs/nfsd/nfsfh.c
parent00bf4098beb15ca174b54f3af1f1e1908d7d18a3 (diff)
exportfs: add fid type
This patchset is a medium scale rewrite of the export operations interface. The goal is to make the interface less complex, and easier to understand from the filesystem side, aswell as preparing generic support for exporting of 64bit inode numbers. This touches all nfs exporting filesystems, and I've done testing on all of the filesystems I have here locally (xfs, ext2, ext3, reiserfs, jfs) This patch: Add a structured fid type so that we don't have to pass an array of u32 values around everywhere. It's a union of possible layouts. As a start there's only the u32 array and the traditional 32bit inode format, but there will be more in one of my next patchset when I start to document the various filehandle formats we have in lowlevel filesystems better. Also add an enum that gives the various filehandle types human- readable names. Note: Some people might think the struct containing an anonymous union is ugly, but I didn't want to pass around a raw union type. Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Neil Brown <neilb@suse.de> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: <linux-ext4@vger.kernel.org> Cc: Dave Kleikamp <shaggy@austin.ibm.com> Cc: Anton Altaparmakov <aia21@cantab.net> Cc: David Chinner <dgc@sgi.com> Cc: Timothy Shimmin <tes@sgi.com> Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Cc: Hugh Dickins <hugh@veritas.com> Cc: Chris Mason <mason@suse.com> Cc: Jeff Mahoney <jeffm@suse.com> Cc: "Vladimir V. Saveliev" <vs@namesys.com> Cc: Steven Whitehouse <swhiteho@redhat.com> Cc: Mark Fasheh <mark.fasheh@oracle.com> 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.c67
1 files changed, 31 insertions, 36 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 7011d62acfc8..4f712e970584 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -115,8 +115,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
115 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); 115 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
116 116
117 if (!fhp->fh_dentry) { 117 if (!fhp->fh_dentry) {
118 __u32 *datap=NULL; 118 struct fid *fid = NULL, sfid;
119 __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */
120 int fileid_type; 119 int fileid_type;
121 int data_left = fh->fh_size/4; 120 int data_left = fh->fh_size/4;
122 121
@@ -128,7 +127,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
128 127
129 if (fh->fh_version == 1) { 128 if (fh->fh_version == 1) {
130 int len; 129 int len;
131 datap = fh->fh_auth;
132 if (--data_left<0) goto out; 130 if (--data_left<0) goto out;
133 switch (fh->fh_auth_type) { 131 switch (fh->fh_auth_type) {
134 case 0: break; 132 case 0: break;
@@ -144,9 +142,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
144 fh->fh_fsid[1] = fh->fh_fsid[2]; 142 fh->fh_fsid[1] = fh->fh_fsid[2];
145 } 143 }
146 if ((data_left -= len)<0) goto out; 144 if ((data_left -= len)<0) goto out;
147 exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap); 145 exp = rqst_exp_find(rqstp, fh->fh_fsid_type,
148 datap += len; 146 fh->fh_auth);
147 fid = (struct fid *)(fh->fh_auth + len);
149 } else { 148 } else {
149 __u32 tfh[2];
150 dev_t xdev; 150 dev_t xdev;
151 ino_t xino; 151 ino_t xino;
152 if (fh->fh_size != NFS_FHSIZE) 152 if (fh->fh_size != NFS_FHSIZE)
@@ -190,22 +190,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
190 error = nfserr_badhandle; 190 error = nfserr_badhandle;
191 191
192 if (fh->fh_version != 1) { 192 if (fh->fh_version != 1) {
193 tfh[0] = fh->ofh_ino; 193 sfid.i32.ino = fh->ofh_ino;
194 tfh[1] = fh->ofh_generation; 194 sfid.i32.gen = fh->ofh_generation;
195 tfh[2] = fh->ofh_dirino; 195 sfid.i32.parent_ino = fh->ofh_dirino;
196 datap = tfh; 196 fid = &sfid;
197 data_left = 3; 197 data_left = 3;
198 if (fh->ofh_dirino == 0) 198 if (fh->ofh_dirino == 0)
199 fileid_type = 1; 199 fileid_type = FILEID_INO32_GEN;
200 else 200 else
201 fileid_type = 2; 201 fileid_type = FILEID_INO32_GEN_PARENT;
202 } else 202 } else
203 fileid_type = fh->fh_fileid_type; 203 fileid_type = fh->fh_fileid_type;
204 204
205 if (fileid_type == 0) 205 if (fileid_type == FILEID_ROOT)
206 dentry = dget(exp->ex_dentry); 206 dentry = dget(exp->ex_dentry);
207 else { 207 else {
208 dentry = exportfs_decode_fh(exp->ex_mnt, datap, 208 dentry = exportfs_decode_fh(exp->ex_mnt, fid,
209 data_left, fileid_type, 209 data_left, fileid_type,
210 nfsd_acceptable, exp); 210 nfsd_acceptable, exp);
211 } 211 }
@@ -286,16 +286,21 @@ out:
286 * an inode. In this case a call to fh_update should be made 286 * an inode. In this case a call to fh_update should be made
287 * before the fh goes out on the wire ... 287 * before the fh goes out on the wire ...
288 */ 288 */
289static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, 289static void _fh_update(struct svc_fh *fhp, struct svc_export *exp,
290 __u32 *datap, int *maxsize) 290 struct dentry *dentry)
291{ 291{
292 if (dentry == exp->ex_dentry) { 292 if (dentry != exp->ex_dentry) {
293 *maxsize = 0; 293 struct fid *fid = (struct fid *)
294 return 0; 294 (fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1);
295 } 295 int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
296 int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK);
296 297
297 return exportfs_encode_fh(dentry, datap, maxsize, 298 fhp->fh_handle.fh_fileid_type =
298 !(exp->ex_flags & NFSEXP_NOSUBTREECHECK)); 299 exportfs_encode_fh(dentry, fid, &maxsize, subtreecheck);
300 fhp->fh_handle.fh_size += maxsize * 4;
301 } else {
302 fhp->fh_handle.fh_fileid_type = FILEID_ROOT;
303 }
299} 304}
300 305
301/* 306/*
@@ -457,12 +462,8 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
457 datap += len/4; 462 datap += len/4;
458 fhp->fh_handle.fh_size = 4 + len; 463 fhp->fh_handle.fh_size = 4 + len;
459 464
460 if (inode) { 465 if (inode)
461 int size = (fhp->fh_maxsize-len-4)/4; 466 _fh_update(fhp, exp, dentry);
462 fhp->fh_handle.fh_fileid_type =
463 _fh_update(dentry, exp, datap, &size);
464 fhp->fh_handle.fh_size += size*4;
465 }
466 if (fhp->fh_handle.fh_fileid_type == 255) 467 if (fhp->fh_handle.fh_fileid_type == 255)
467 return nfserr_opnotsupp; 468 return nfserr_opnotsupp;
468 } 469 }
@@ -479,7 +480,6 @@ __be32
479fh_update(struct svc_fh *fhp) 480fh_update(struct svc_fh *fhp)
480{ 481{
481 struct dentry *dentry; 482 struct dentry *dentry;
482 __u32 *datap;
483 483
484 if (!fhp->fh_dentry) 484 if (!fhp->fh_dentry)
485 goto out_bad; 485 goto out_bad;
@@ -490,15 +490,10 @@ fh_update(struct svc_fh *fhp)
490 if (fhp->fh_handle.fh_version != 1) { 490 if (fhp->fh_handle.fh_version != 1) {
491 _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); 491 _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
492 } else { 492 } else {
493 int size; 493 if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
494 if (fhp->fh_handle.fh_fileid_type != 0)
495 goto out; 494 goto out;
496 datap = fhp->fh_handle.fh_auth+ 495
497 fhp->fh_handle.fh_size/4 -1; 496 _fh_update(fhp, fhp->fh_export, dentry);
498 size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
499 fhp->fh_handle.fh_fileid_type =
500 _fh_update(dentry, fhp->fh_export, datap, &size);
501 fhp->fh_handle.fh_size += size*4;
502 if (fhp->fh_handle.fh_fileid_type == 255) 497 if (fhp->fh_handle.fh_fileid_type == 255)
503 return nfserr_opnotsupp; 498 return nfserr_opnotsupp;
504 } 499 }