diff options
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 1 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 63 | ||||
-rw-r--r-- | include/linux/nfsd/nfsfh.h | 7 | ||||
-rw-r--r-- | include/linux/nfsd/xdr4.h | 17 |
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); \ | 1494 | static 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) | 1499 | static void write64(__be32 **p, u64 n) |
1500 | { | ||
1501 | write32(p, (u32)(n >> 32)); | ||
1502 | write32(p, (u32)n); | ||
1503 | } | ||
1504 | |||
1505 | static 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 | |||
1515 | static 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 | ||
65 | struct nfsd4_change_info { | 65 | struct 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 | ||
73 | struct nfsd4_access { | 76 | struct 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 | ||
512 | int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); | 521 | int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); |