aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/nfsd/nfs3xdr.c59
-rw-r--r--fs/nfsd/nfs4xdr.c17
-rw-r--r--fs/nfsd/nfsxdr.c4
-rw-r--r--include/linux/nfsd/nfsfh.h42
-rw-r--r--include/linux/nfsd/xdr4.h4
5 files changed, 45 insertions, 81 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 */
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index 11e568ee0eeb..d1941cb965e9 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -150,17 +150,7 @@ typedef struct svc_fh {
150 struct timespec fh_pre_ctime; /* ctime before oper */ 150 struct timespec fh_pre_ctime; /* ctime before oper */
151 151
152 /* Post-op attributes saved in fh_unlock */ 152 /* Post-op attributes saved in fh_unlock */
153 umode_t fh_post_mode; /* i_mode */ 153 struct kstat fh_post_attr; /* full attrs after operation */
154 nlink_t fh_post_nlink; /* i_nlink */
155 uid_t fh_post_uid; /* i_uid */
156 gid_t fh_post_gid; /* i_gid */
157 __u64 fh_post_size; /* i_size */
158 unsigned long fh_post_blocks; /* i_blocks */
159 unsigned long fh_post_blksize;/* i_blksize */
160 __be32 fh_post_rdev[2];/* i_rdev */
161 struct timespec fh_post_atime; /* i_atime */
162 struct timespec fh_post_mtime; /* i_mtime */
163 struct timespec fh_post_ctime; /* i_ctime */
164#endif /* CONFIG_NFSD_V3 */ 154#endif /* CONFIG_NFSD_V3 */
165 155
166} svc_fh; 156} svc_fh;
@@ -297,36 +287,12 @@ fill_pre_wcc(struct svc_fh *fhp)
297 if (!fhp->fh_pre_saved) { 287 if (!fhp->fh_pre_saved) {
298 fhp->fh_pre_mtime = inode->i_mtime; 288 fhp->fh_pre_mtime = inode->i_mtime;
299 fhp->fh_pre_ctime = inode->i_ctime; 289 fhp->fh_pre_ctime = inode->i_ctime;
300 fhp->fh_pre_size = inode->i_size; 290 fhp->fh_pre_size = inode->i_size;
301 fhp->fh_pre_saved = 1; 291 fhp->fh_pre_saved = 1;
302 } 292 }
303} 293}
304 294
305/* 295extern void fill_post_wcc(struct svc_fh *);
306 * Fill in the post_op attr for the wcc data
307 */
308static inline void
309fill_post_wcc(struct svc_fh *fhp)
310{
311 struct inode *inode = fhp->fh_dentry->d_inode;
312
313 if (fhp->fh_post_saved)
314 printk("nfsd: inode locked twice during operation.\n");
315
316 fhp->fh_post_mode = inode->i_mode;
317 fhp->fh_post_nlink = inode->i_nlink;
318 fhp->fh_post_uid = inode->i_uid;
319 fhp->fh_post_gid = inode->i_gid;
320 fhp->fh_post_size = inode->i_size;
321 fhp->fh_post_blksize = BLOCK_SIZE;
322 fhp->fh_post_blocks = inode->i_blocks;
323 fhp->fh_post_rdev[0] = htonl((u32)imajor(inode));
324 fhp->fh_post_rdev[1] = htonl((u32)iminor(inode));
325 fhp->fh_post_atime = inode->i_atime;
326 fhp->fh_post_mtime = inode->i_mtime;
327 fhp->fh_post_ctime = inode->i_ctime;
328 fhp->fh_post_saved = 1;
329}
330#else 296#else
331#define fill_pre_wcc(ignored) 297#define fill_pre_wcc(ignored)
332#define fill_post_wcc(notused) 298#define fill_post_wcc(notused)
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 1b653267133a..b0ddfb41c790 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -428,8 +428,8 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
428 cinfo->atomic = 1; 428 cinfo->atomic = 1;
429 cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; 429 cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
430 cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; 430 cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
431 cinfo->after_ctime_sec = fhp->fh_post_ctime.tv_sec; 431 cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
432 cinfo->after_ctime_nsec = fhp->fh_post_ctime.tv_nsec; 432 cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
433} 433}
434 434
435int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); 435int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);