On Tue, Jun 14, 2011 at 5:19 AM, Benny Halevy <bhalevy.lists@xxxxxxxxx> wrote: > On 2011-06-12 19:44, Jim Rees wrote: >> From: Peng Tao <bergwolf@xxxxxxxxx> >> >> This gives layout driver a chance to cleanup structures they put in. >> Also ensure layoutcommit does not commit more than isize, as block layout >> driver may dirty pages beyond EOF. >> >> Signed-off-by: Andy Adamson <andros@xxxxxxxxxx> >> [fixup layout header pointer for layoutcommit] >> Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx> >> Signed-off-by: Peng Tao <bergwolf@xxxxxxxxx> >> --- >> Âfs/nfs/nfs4proc.c    |  Â1 + >> Âfs/nfs/nfs4xdr.c    Â|  Â3 ++- >> Âfs/nfs/pnfs.c      |  15 +++++++++++++++ >> Âfs/nfs/pnfs.h      |  Â4 ++++ >> Âinclude/linux/nfs_xdr.h |  Â1 + >> Â5 files changed, 23 insertions(+), 1 deletions(-) >> >> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c >> index 5246db8..e27a648 100644 >> --- a/fs/nfs/nfs4proc.c >> +++ b/fs/nfs/nfs4proc.c >> @@ -5890,6 +5890,7 @@ static void nfs4_layoutcommit_release(void *calldata) >> Â{ >>    struct nfs4_layoutcommit_data *data = calldata; >> >> +   pnfs_cleanup_layoutcommit(data->args.inode, data); > > The layout driver better be passed the status on the done method > rather than on release so that it can roll back on error. > > Although it is quite complicated to roll back after permanent errors like > NFS4ERR_BADLAYOUT where the client is really screwed and it > essentially needs to redirty and rewrite the data (to the MDS > to simplify the error handling path), rolling back from > transient errors like NFS4ERR_DELAY should be fairly easy. I agree that it can be put in layoutcommit_done. But why is it related to rolling back in error case? IMHO, layoutcommit error handling should be implemented in generic code. e.g., for NFS4ERR_DELAY, current code will retry layoutcommit in generic layer. pnfs_cleanup_layoutcommit is simply an interface for layout driver to cleanup its private data associated with this layoutcommit operation. For block layout specifically, clean up commiting extent list. Thanks, Tao > > Benny > >>    /* Matched by references in pnfs_set_layoutcommit */ >>    put_lseg(data->lseg); >>    put_rpccred(data->cred); >> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c >> index fdcbd8f..57295d1 100644 >> --- a/fs/nfs/nfs4xdr.c >> +++ b/fs/nfs/nfs4xdr.c >> @@ -1963,7 +1963,7 @@ encode_layoutcommit(struct xdr_stream *xdr, >>    *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); >>    /* Only whole file layouts */ >>    p = xdr_encode_hyper(p, 0); /* offset */ >> -   p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */ >> +   p = xdr_encode_hyper(p, args->lastbytewritten+1); /* length */ >>    *p++ = cpu_to_be32(0); /* reclaim */ >>    p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); >>    *p++ = cpu_to_be32(1); /* newoffset = TRUE */ >> @@ -5467,6 +5467,7 @@ static int decode_layoutcommit(struct xdr_stream *xdr, >>    int status; >> >>    status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); >> +   res->status = status; >>    if (status) >>        return status; >> >> diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c >> index e693718..48a06a1 100644 >> --- a/fs/nfs/pnfs.c >> +++ b/fs/nfs/pnfs.c >> @@ -1248,6 +1248,7 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) >> Â{ >>    struct nfs_inode *nfsi = NFS_I(wdata->inode); >>    loff_t end_pos = wdata->mds_offset + wdata->res.count; >> +   loff_t isize = i_size_read(wdata->inode); >>    bool mark_as_dirty = false; >> >>    spin_lock(&nfsi->vfs_inode.i_lock); >> @@ -1261,9 +1262,13 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) >>        dprintk("%s: Set layoutcommit for inode %lu ", >>            __func__, wdata->inode->i_ino); >>    } >> +   if (end_pos > isize) >> +       end_pos = isize; >>    if (end_pos > wdata->lseg->pls_end_pos) >>        wdata->lseg->pls_end_pos = end_pos; >>    spin_unlock(&nfsi->vfs_inode.i_lock); >> +   dprintk("%s: lseg %p end_pos %llu\n", >> +       __func__, wdata->lseg, wdata->lseg->pls_end_pos); >> >>    /* if pnfs_layoutcommit_inode() runs between inode locks, the next one >>    Â* will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ >> @@ -1272,6 +1277,16 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) >> Â} >> ÂEXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); >> >> +void pnfs_cleanup_layoutcommit(struct inode *inode, >> +                struct nfs4_layoutcommit_data *data) >> +{ >> +    Âstruct nfs_server *nfss = NFS_SERVER(inode); >> + >> +    Âif (nfss->pnfs_curr_ld->cleanup_layoutcommit) >> +        Ânfss->pnfs_curr_ld->cleanup_layoutcommit( >> +                    ÂNFS_I(inode)->layout, data); >> +} >> + >> Âvoid pnfs_free_fsdata(struct pnfs_fsdata *fsdata) >> Â{ >>    /* lseg refcounting handled directly in nfs_write_end */ >> diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h >> index 525ec55..5048898 100644 >> --- a/fs/nfs/pnfs.h >> +++ b/fs/nfs/pnfs.h >> @@ -127,6 +127,9 @@ struct pnfs_layoutdriver_type { >>                  Âstruct xdr_stream *xdr, >>                  Âconst struct nfs4_layoutreturn_args *args); >> >> +    Âvoid (*cleanup_layoutcommit) (struct pnfs_layout_hdr *layoutid, >> +                   Âstruct nfs4_layoutcommit_data *data); >> + >>    void (*encode_layoutcommit) (struct pnfs_layout_hdr *layoutid, >>                  Âstruct xdr_stream *xdr, >>                  Âconst struct nfs4_layoutcommit_args *args); >> @@ -213,6 +216,7 @@ void pnfs_roc_release(struct inode *ino); >> Âvoid pnfs_roc_set_barrier(struct inode *ino, u32 barrier); >> Âbool pnfs_roc_drain(struct inode *ino, u32 *barrier); >> Âvoid pnfs_set_layoutcommit(struct nfs_write_data *wdata); >> +void pnfs_cleanup_layoutcommit(struct inode *inode, struct nfs4_layoutcommit_data *data); >> Âint pnfs_layoutcommit_inode(struct inode *inode, bool sync); >> Âint _pnfs_return_layout(struct inode *); >> Âint pnfs_ld_write_done(struct nfs_write_data *); >> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h >> index a9c43ba..2c3ffda 100644 >> --- a/include/linux/nfs_xdr.h >> +++ b/include/linux/nfs_xdr.h >> @@ -270,6 +270,7 @@ struct nfs4_layoutcommit_res { >>    struct nfs_fattr *fattr; >>    const struct nfs_server *server; >>    struct nfs4_sequence_res seq_res; >> +   int status; >> Â}; >> >> Âstruct nfs4_layoutcommit_data { > -- > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at Âhttp://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html