pNFS: Files and flexfiles always need to commit before layoutcommit
authorTrond Myklebust <trond.myklebust@primarydata.com>
Sun, 26 Jun 2016 22:54:58 +0000 (18:54 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 5 Jul 2016 23:08:01 +0000 (19:08 -0400)
So ensure that we mark the layout for commit once the write is done,
and then ensure that the commit to ds is finished before sending
layoutcommit.

Note that by doing this, we're able to optimise away the commit
for the case of servers that don't need layoutcommit in order to
return updated attributes.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/filelayout/filelayout.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/nfs4xdr.c
fs/nfs/pnfs.c
fs/nfs/pnfs_nfs.c

index b4c1407e8fe4d2df74558ef46da9c18a1a55d693..25bd91a6e0884f8df879b0bedcceed5f1a6bc37a 100644 (file)
@@ -255,13 +255,16 @@ static int filelayout_read_done_cb(struct rpc_task *task,
 static void
 filelayout_set_layoutcommit(struct nfs_pgio_header *hdr)
 {
+       loff_t end_offs = 0;
 
        if (FILELAYOUT_LSEG(hdr->lseg)->commit_through_mds ||
-           hdr->res.verf->committed != NFS_DATA_SYNC)
+           hdr->res.verf->committed == NFS_FILE_SYNC)
                return;
+       if (hdr->res.verf->committed == NFS_DATA_SYNC)
+               end_offs = hdr->mds_offset + (loff_t)hdr->res.count;
 
-       pnfs_set_layoutcommit(hdr->inode, hdr->lseg,
-                       hdr->mds_offset + hdr->res.count);
+       /* Note: if the write is unstable, don't set end_offs until commit */
+       pnfs_set_layoutcommit(hdr->inode, hdr->lseg, end_offs);
        dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino,
                (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb);
 }
index 14f2ed3f1a5b49bc1c92e3f538be3394443a75a1..e6206eaf2bdf34e4aa11d23dbf68b6e7c0c4684e 100644 (file)
@@ -1470,6 +1470,7 @@ static void ff_layout_read_release(void *data)
 static int ff_layout_write_done_cb(struct rpc_task *task,
                                struct nfs_pgio_header *hdr)
 {
+       loff_t end_offs = 0;
        int err;
 
        trace_nfs4_pnfs_write(hdr, task->tk_status);
@@ -1495,8 +1496,10 @@ static int ff_layout_write_done_cb(struct rpc_task *task,
 
        if (hdr->res.verf->committed == NFS_FILE_SYNC ||
            hdr->res.verf->committed == NFS_DATA_SYNC)
-               ff_layout_set_layoutcommit(hdr->inode, hdr->lseg,
-                               hdr->mds_offset + (loff_t)hdr->res.count);
+               end_offs = hdr->mds_offset + (loff_t)hdr->res.count;
+
+       /* Note: if the write is unstable, don't set end_offs until commit */
+       ff_layout_set_layoutcommit(hdr->inode, hdr->lseg, end_offs);
 
        /* zero out fattr since we don't care DS attr at all */
        hdr->fattr.valid = 0;
index 661e753fe1c93d0c6be59fd26c0339316d50ee12..7bd3a5c09d3185856e85bbe8c5484fccfee3651f 100644 (file)
@@ -1985,9 +1985,14 @@ encode_layoutcommit(struct xdr_stream *xdr,
        p = xdr_encode_hyper(p, args->lastbytewritten + 1);     /* length */
        *p = cpu_to_be32(0); /* reclaim */
        encode_nfs4_stateid(xdr, &args->stateid);
-       p = reserve_space(xdr, 20);
-       *p++ = cpu_to_be32(1); /* newoffset = TRUE */
-       p = xdr_encode_hyper(p, args->lastbytewritten);
+       if (args->lastbytewritten != U64_MAX) {
+               p = reserve_space(xdr, 20);
+               *p++ = cpu_to_be32(1); /* newoffset = TRUE */
+               p = xdr_encode_hyper(p, args->lastbytewritten);
+       } else {
+               p = reserve_space(xdr, 12);
+               *p++ = cpu_to_be32(0); /* newoffset = FALSE */
+       }
        *p++ = cpu_to_be32(0); /* Never send time_modify_changed */
        *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */
 
index 0c7e0d45a4de6ee1fba11c40417d3fb01678049b..62553182514e2dd95746b18518edb1055076857e 100644 (file)
@@ -2378,7 +2378,10 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
        nfs_fattr_init(&data->fattr);
        data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
        data->res.fattr = &data->fattr;
-       data->args.lastbytewritten = end_pos - 1;
+       if (end_pos != 0)
+               data->args.lastbytewritten = end_pos - 1;
+       else
+               data->args.lastbytewritten = U64_MAX;
        data->res.server = NFS_SERVER(inode);
 
        if (ld->prepare_layoutcommit) {
index 0dfc476da3e10918bcf0242d779cda343e6dac61..0d10cc280a2394271c59b9067b2898fecbfa56d9 100644 (file)
@@ -932,6 +932,13 @@ EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit);
 int
 pnfs_nfs_generic_sync(struct inode *inode, bool datasync)
 {
+       int ret;
+
+       if (!pnfs_layoutcommit_outstanding(inode))
+               return 0;
+       ret = nfs_commit_inode(inode, FLUSH_SYNC);
+       if (ret < 0)
+               return ret;
        if (datasync)
                return 0;
        return pnfs_layoutcommit_inode(inode, true);