aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs3xdr.c1
-rw-r--r--fs/nfsd/nfs4xdr.c63
-rw-r--r--include/linux/nfsd/nfsfh.h7
-rw-r--r--include/linux/nfsd/xdr4.h17
4 files changed, 63 insertions, 25 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 17d0dd997204..01d4ec1c88e0 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -272,6 +272,7 @@ void fill_post_wcc(struct svc_fh *fhp)
272 272
273 err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, 273 err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
274 &fhp->fh_post_attr); 274 &fhp->fh_post_attr);
275 fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
275 if (err) 276 if (err)
276 fhp->fh_post_saved = 0; 277 fhp->fh_post_saved = 0;
277 else 278 else
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 4a71fcd3f036..12d36a7361cd 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1490,13 +1490,41 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1490 memcpy(p, ptr, nbytes); \ 1490 memcpy(p, ptr, nbytes); \
1491 p += XDR_QUADLEN(nbytes); \ 1491 p += XDR_QUADLEN(nbytes); \
1492}} while (0) 1492}} while (0)
1493#define WRITECINFO(c) do { \ 1493
1494 *p++ = htonl(c.atomic); \ 1494static void write32(__be32 **p, u32 n)
1495 *p++ = htonl(c.before_ctime_sec); \ 1495{
1496 *p++ = htonl(c.before_ctime_nsec); \ 1496 *(*p)++ = n;
1497 *p++ = htonl(c.after_ctime_sec); \ 1497}
1498 *p++ = htonl(c.after_ctime_nsec); \ 1498
1499} while (0) 1499static void write64(__be32 **p, u64 n)
1500{
1501 write32(p, (u32)(n >> 32));
1502 write32(p, (u32)n);
1503}
1504
1505static void write_change(__be32 **p, struct kstat *stat, struct inode *inode)
1506{
1507 if (IS_I_VERSION(inode)) {
1508 write64(p, inode->i_version);
1509 } else {
1510 write32(p, stat->ctime.tv_sec);
1511 write32(p, stat->ctime.tv_nsec);
1512 }
1513}
1514
1515static void write_cinfo(__be32 **p, struct nfsd4_change_info *c)
1516{
1517 write32(p, c->atomic);
1518 if (c->change_supported) {
1519 write64(p, c->before_change);
1520 write64(p, c->after_change);
1521 } else {
1522 write32(p, c->before_ctime_sec);
1523 write32(p, c->before_ctime_nsec);
1524 write32(p, c->after_ctime_sec);
1525 write32(p, c->after_ctime_nsec);
1526 }
1527}
1500 1528
1501#define RESERVE_SPACE(nbytes) do { \ 1529#define RESERVE_SPACE(nbytes) do { \
1502 p = resp->p; \ 1530 p = resp->p; \
@@ -1849,16 +1877,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1849 WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME); 1877 WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
1850 } 1878 }
1851 if (bmval0 & FATTR4_WORD0_CHANGE) { 1879 if (bmval0 & FATTR4_WORD0_CHANGE) {
1852 /*
1853 * Note: This _must_ be consistent with the scheme for writing
1854 * change_info, so any changes made here must be reflected there
1855 * as well. (See xdr4.h:set_change_info() and the WRITECINFO()
1856 * macro above.)
1857 */
1858 if ((buflen -= 8) < 0) 1880 if ((buflen -= 8) < 0)
1859 goto out_resource; 1881 goto out_resource;
1860 WRITE32(stat.ctime.tv_sec); 1882 write_change(&p, &stat, dentry->d_inode);
1861 WRITE32(stat.ctime.tv_nsec);
1862 } 1883 }
1863 if (bmval0 & FATTR4_WORD0_SIZE) { 1884 if (bmval0 & FATTR4_WORD0_SIZE) {
1864 if ((buflen -= 8) < 0) 1885 if ((buflen -= 8) < 0)
@@ -2364,7 +2385,7 @@ nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
2364 2385
2365 if (!nfserr) { 2386 if (!nfserr) {
2366 RESERVE_SPACE(32); 2387 RESERVE_SPACE(32);
2367 WRITECINFO(create->cr_cinfo); 2388 write_cinfo(&p, &create->cr_cinfo);
2368 WRITE32(2); 2389 WRITE32(2);
2369 WRITE32(create->cr_bmval[0]); 2390 WRITE32(create->cr_bmval[0]);
2370 WRITE32(create->cr_bmval[1]); 2391 WRITE32(create->cr_bmval[1]);
@@ -2475,7 +2496,7 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_li
2475 2496
2476 if (!nfserr) { 2497 if (!nfserr) {
2477 RESERVE_SPACE(20); 2498 RESERVE_SPACE(20);
2478 WRITECINFO(link->li_cinfo); 2499 write_cinfo(&p, &link->li_cinfo);
2479 ADJUST_ARGS(); 2500 ADJUST_ARGS();
2480 } 2501 }
2481 return nfserr; 2502 return nfserr;
@@ -2493,7 +2514,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
2493 2514
2494 nfsd4_encode_stateid(resp, &open->op_stateid); 2515 nfsd4_encode_stateid(resp, &open->op_stateid);
2495 RESERVE_SPACE(40); 2516 RESERVE_SPACE(40);
2496 WRITECINFO(open->op_cinfo); 2517 write_cinfo(&p, &open->op_cinfo);
2497 WRITE32(open->op_rflags); 2518 WRITE32(open->op_rflags);
2498 WRITE32(2); 2519 WRITE32(2);
2499 WRITE32(open->op_bmval[0]); 2520 WRITE32(open->op_bmval[0]);
@@ -2771,7 +2792,7 @@ nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
2771 2792
2772 if (!nfserr) { 2793 if (!nfserr) {
2773 RESERVE_SPACE(20); 2794 RESERVE_SPACE(20);
2774 WRITECINFO(remove->rm_cinfo); 2795 write_cinfo(&p, &remove->rm_cinfo);
2775 ADJUST_ARGS(); 2796 ADJUST_ARGS();
2776 } 2797 }
2777 return nfserr; 2798 return nfserr;
@@ -2784,8 +2805,8 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
2784 2805
2785 if (!nfserr) { 2806 if (!nfserr) {
2786 RESERVE_SPACE(40); 2807 RESERVE_SPACE(40);
2787 WRITECINFO(rename->rn_sinfo); 2808 write_cinfo(&p, &rename->rn_sinfo);
2788 WRITECINFO(rename->rn_tinfo); 2809 write_cinfo(&p, &rename->rn_tinfo);
2789 ADJUST_ARGS(); 2810 ADJUST_ARGS();
2790 } 2811 }
2791 return nfserr; 2812 return nfserr;
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index afa19016c4a8..8f641c908450 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -151,9 +151,15 @@ typedef struct svc_fh {
151 __u64 fh_pre_size; /* size before operation */ 151 __u64 fh_pre_size; /* size before operation */
152 struct timespec fh_pre_mtime; /* mtime before oper */ 152 struct timespec fh_pre_mtime; /* mtime before oper */
153 struct timespec fh_pre_ctime; /* ctime before oper */ 153 struct timespec fh_pre_ctime; /* ctime before oper */
154 /*
155 * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode)
156 * to find out if it is valid.
157 */
158 u64 fh_pre_change;
154 159
155 /* Post-op attributes saved in fh_unlock */ 160 /* Post-op attributes saved in fh_unlock */
156 struct kstat fh_post_attr; /* full attrs after operation */ 161 struct kstat fh_post_attr; /* full attrs after operation */
162 u64 fh_post_change; /* nfsv4 change; see above */
157#endif /* CONFIG_NFSD_V3 */ 163#endif /* CONFIG_NFSD_V3 */
158 164
159} svc_fh; 165} svc_fh;
@@ -298,6 +304,7 @@ fill_pre_wcc(struct svc_fh *fhp)
298 fhp->fh_pre_mtime = inode->i_mtime; 304 fhp->fh_pre_mtime = inode->i_mtime;
299 fhp->fh_pre_ctime = inode->i_ctime; 305 fhp->fh_pre_ctime = inode->i_ctime;
300 fhp->fh_pre_size = inode->i_size; 306 fhp->fh_pre_size = inode->i_size;
307 fhp->fh_pre_change = inode->i_version;
301 fhp->fh_pre_saved = 1; 308 fhp->fh_pre_saved = 1;
302 } 309 }
303} 310}
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index f80d6013fdc3..d0f050f01eca 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -64,10 +64,13 @@ static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs)
64 64
65struct nfsd4_change_info { 65struct nfsd4_change_info {
66 u32 atomic; 66 u32 atomic;
67 bool change_supported;
67 u32 before_ctime_sec; 68 u32 before_ctime_sec;
68 u32 before_ctime_nsec; 69 u32 before_ctime_nsec;
70 u64 before_change;
69 u32 after_ctime_sec; 71 u32 after_ctime_sec;
70 u32 after_ctime_nsec; 72 u32 after_ctime_nsec;
73 u64 after_change;
71}; 74};
72 75
73struct nfsd4_access { 76struct nfsd4_access {
@@ -503,10 +506,16 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
503{ 506{
504 BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved); 507 BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
505 cinfo->atomic = 1; 508 cinfo->atomic = 1;
506 cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; 509 cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
507 cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; 510 if (cinfo->change_supported) {
508 cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec; 511 cinfo->before_change = fhp->fh_pre_change;
509 cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; 512 cinfo->after_change = fhp->fh_post_change;
513 } else {
514 cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
515 cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
516 cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
517 cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
518 }
510} 519}
511 520
512int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); 521int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);