aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2009-04-16 17:33:25 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-04-29 11:35:49 -0400
commitc654b8a9cba6002aad1c01919e4928a79a4a6dcf (patch)
treefee411bb42ec86e72a9e843529551e559c1f2749 /fs/nfsd
parent3352d2c2d0540955a7bbb3421a28330af7f9d79c (diff)
nfsd: support ext4 i_version
ext4 supports a real NFSv4 change attribute, which is bumped whenever the ctime would be updated, including times when two updates arrive within a jiffy of each other. (Note that although ext4 has space for nanosecond-precision ctime, the real resolution is lower: it actually uses jiffies as the time-source.) This ensures clients will invalidate their caches when they need to. There is some fear that keeping the i_version up-to-date could have performance drawbacks, so for now it's turned on only by a mount option. We hope to do something better eventually. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Cc: Theodore Tso <tytso@mit.edu>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs3xdr.c1
-rw-r--r--fs/nfsd/nfs4xdr.c63
2 files changed, 43 insertions, 21 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;