aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 *);