aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorPeter Staubach <staubach@redhat.com>2007-08-16 12:10:07 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2007-10-09 18:31:57 -0400
commit40ee5dc6af351c1b3de245abed4bd8e6a4a5646a (patch)
tree5558d5f2b3df23e745b152c439e731a7aeff7ab6 /fs/nfsd
parent21fcd02be34f73bbc94db267b4db6ccd7332923d (diff)
knfsd: 64 bit ino support for NFS server
Modify the NFS server code to support 64 bit ino's, as appropriate for the system and the NFS protocol version. The gist of the changes is to query the underlying file system for attributes and not just to use the cached attributes in the inode. For this specific purpose, the inode only contains an ino field which unsigned long, which is large enough on 64 bit platforms, but is not large enough on 32 bit platforms. I haven't been able to find any reason why ->getattr can't be called while i_mutex. The specification indicates that i_mutex is not required to be held in order to invoke ->getattr, but it doesn't say that i_mutex can't be held while invoking ->getattr. I also haven't come to any conclusions regarding the value of lease_get_mtime() and whether it should or should not be invoked by fill_post_wcc() too. I chose not to change this because I thought that it was safer to leave well enough alone. If we decide to make a change, it can be done separately. Signed-off-by: Peter Staubach <staubach@redhat.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Acked-by: Neil Brown <neilb@suse.de>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs3xdr.c59
-rw-r--r--fs/nfsd/nfs4xdr.c17
-rw-r--r--fs/nfsd/nfsxdr.c4
3 files changed, 39 insertions, 41 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 10f6e7dcf633..2d116d2298f8 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -174,9 +174,6 @@ static __be32 *
174encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, 174encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
175 struct kstat *stat) 175 struct kstat *stat)
176{ 176{
177 struct dentry *dentry = fhp->fh_dentry;
178 struct timespec time;
179
180 *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); 177 *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
181 *p++ = htonl((u32) stat->mode); 178 *p++ = htonl((u32) stat->mode);
182 *p++ = htonl((u32) stat->nlink); 179 *p++ = htonl((u32) stat->nlink);
@@ -191,10 +188,9 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
191 *p++ = htonl((u32) MAJOR(stat->rdev)); 188 *p++ = htonl((u32) MAJOR(stat->rdev));
192 *p++ = htonl((u32) MINOR(stat->rdev)); 189 *p++ = htonl((u32) MINOR(stat->rdev));
193 p = encode_fsid(p, fhp); 190 p = encode_fsid(p, fhp);
194 p = xdr_encode_hyper(p, (u64) stat->ino); 191 p = xdr_encode_hyper(p, stat->ino);
195 p = encode_time3(p, &stat->atime); 192 p = encode_time3(p, &stat->atime);
196 lease_get_mtime(dentry->d_inode, &time); 193 p = encode_time3(p, &stat->mtime);
197 p = encode_time3(p, &time);
198 p = encode_time3(p, &stat->ctime); 194 p = encode_time3(p, &stat->ctime);
199 195
200 return p; 196 return p;
@@ -203,31 +199,9 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
203static __be32 * 199static __be32 *
204encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 200encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
205{ 201{
206 struct inode *inode = fhp->fh_dentry->d_inode;
207
208 /* Attributes to follow */ 202 /* Attributes to follow */
209 *p++ = xdr_one; 203 *p++ = xdr_one;
210 204 return encode_fattr3(rqstp, p, fhp, &fhp->fh_post_attr);
211 *p++ = htonl(nfs3_ftypes[(fhp->fh_post_mode & S_IFMT) >> 12]);
212 *p++ = htonl((u32) fhp->fh_post_mode);
213 *p++ = htonl((u32) fhp->fh_post_nlink);
214 *p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid));
215 *p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid));
216 if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) {
217 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
218 } else {
219 p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
220 }
221 p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
222 *p++ = fhp->fh_post_rdev[0];
223 *p++ = fhp->fh_post_rdev[1];
224 p = encode_fsid(p, fhp);
225 p = xdr_encode_hyper(p, (u64) inode->i_ino);
226 p = encode_time3(p, &fhp->fh_post_atime);
227 p = encode_time3(p, &fhp->fh_post_mtime);
228 p = encode_time3(p, &fhp->fh_post_ctime);
229
230 return p;
231} 205}
232 206
233/* 207/*
@@ -246,6 +220,7 @@ encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
246 err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat); 220 err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat);
247 if (!err) { 221 if (!err) {
248 *p++ = xdr_one; /* attributes follow */ 222 *p++ = xdr_one; /* attributes follow */
223 lease_get_mtime(dentry->d_inode, &stat.mtime);
249 return encode_fattr3(rqstp, p, fhp, &stat); 224 return encode_fattr3(rqstp, p, fhp, &stat);
250 } 225 }
251 } 226 }
@@ -284,6 +259,23 @@ encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
284 return encode_post_op_attr(rqstp, p, fhp); 259 return encode_post_op_attr(rqstp, p, fhp);
285} 260}
286 261
262/*
263 * Fill in the post_op attr for the wcc data
264 */
265void fill_post_wcc(struct svc_fh *fhp)
266{
267 int err;
268
269 if (fhp->fh_post_saved)
270 printk("nfsd: inode locked twice during operation.\n");
271
272 err = vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry,
273 &fhp->fh_post_attr);
274 if (err)
275 fhp->fh_post_saved = 0;
276 else
277 fhp->fh_post_saved = 1;
278}
287 279
288/* 280/*
289 * XDR decode functions 281 * XDR decode functions
@@ -643,8 +635,11 @@ int
643nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, 635nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p,
644 struct nfsd3_attrstat *resp) 636 struct nfsd3_attrstat *resp)
645{ 637{
646 if (resp->status == 0) 638 if (resp->status == 0) {
639 lease_get_mtime(resp->fh.fh_dentry->d_inode,
640 &resp->stat.mtime);
647 p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat); 641 p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat);
642 }
648 return xdr_ressize_check(rqstp, p); 643 return xdr_ressize_check(rqstp, p);
649} 644}
650 645
@@ -802,7 +797,7 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p,
802 797
803static __be32 * 798static __be32 *
804encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, 799encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
805 int namlen, ino_t ino) 800 int namlen, u64 ino)
806{ 801{
807 *p++ = xdr_one; /* mark entry present */ 802 *p++ = xdr_one; /* mark entry present */
808 p = xdr_encode_hyper(p, ino); /* file id */ 803 p = xdr_encode_hyper(p, ino); /* file id */
@@ -873,7 +868,7 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
873#define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2)) 868#define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
874static int 869static int
875encode_entry(struct readdir_cd *ccd, const char *name, int namlen, 870encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
876 loff_t offset, ino_t ino, unsigned int d_type, int plus) 871 loff_t offset, u64 ino, unsigned int d_type, int plus)
877{ 872{
878 struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, 873 struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres,
879 common); 874 common);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 8ef0964179bc..9cf900740c76 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1679,7 +1679,7 @@ out_acl:
1679 if (bmval0 & FATTR4_WORD0_FILEID) { 1679 if (bmval0 & FATTR4_WORD0_FILEID) {
1680 if ((buflen -= 8) < 0) 1680 if ((buflen -= 8) < 0)
1681 goto out_resource; 1681 goto out_resource;
1682 WRITE64((u64) stat.ino); 1682 WRITE64(stat.ino);
1683 } 1683 }
1684 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { 1684 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
1685 if ((buflen -= 8) < 0) 1685 if ((buflen -= 8) < 0)
@@ -1821,16 +1821,15 @@ out_acl:
1821 WRITE32(stat.mtime.tv_nsec); 1821 WRITE32(stat.mtime.tv_nsec);
1822 } 1822 }
1823 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { 1823 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
1824 struct dentry *mnt_pnt, *mnt_root;
1825
1826 if ((buflen -= 8) < 0) 1824 if ((buflen -= 8) < 0)
1827 goto out_resource; 1825 goto out_resource;
1828 mnt_root = exp->ex_mnt->mnt_root; 1826 if (exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) {
1829 if (mnt_root->d_inode == dentry->d_inode) { 1827 err = vfs_getattr(exp->ex_mnt->mnt_parent,
1830 mnt_pnt = exp->ex_mnt->mnt_mountpoint; 1828 exp->ex_mnt->mnt_mountpoint, &stat);
1831 WRITE64((u64) mnt_pnt->d_inode->i_ino); 1829 if (err)
1832 } else 1830 goto out_nfserr;
1833 WRITE64((u64) stat.ino); 1831 }
1832 WRITE64(stat.ino);
1834 } 1833 }
1835 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 1834 *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1836 *countp = p - buffer; 1835 *countp = p - buffer;
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index cb3e7fadb772..986f9b32083c 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -523,6 +523,10 @@ nfssvc_encode_entry(void *ccdv, const char *name,
523 cd->common.err = nfserr_toosmall; 523 cd->common.err = nfserr_toosmall;
524 return -EINVAL; 524 return -EINVAL;
525 } 525 }
526 if (ino > ~((u32) 0)) {
527 cd->common.err = nfserr_fbig;
528 return -EINVAL;
529 }
526 *p++ = xdr_one; /* mark entry present */ 530 *p++ = xdr_one; /* mark entry present */
527 *p++ = htonl((u32) ino); /* file id */ 531 *p++ = htonl((u32) ino); /* file id */
528 p = xdr_encode_array(p, name, namlen);/* name length & name */ 532 p = xdr_encode_array(p, name, namlen);/* name length & name */