diff options
author | Andy Adamson <andros@netapp.com> | 2011-03-23 09:27:54 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-23 15:29:04 -0400 |
commit | 863a3c6c686d5773f7192a4818769e15db12ce08 (patch) | |
tree | 3ff8bf04c583aa0c16ae30b0821bc9148d49a47a /fs/nfs/pnfs.c | |
parent | e0c2b3801828aadb65dec9f67f7c6b7a675ad007 (diff) |
NFSv4.1: layoutcommit
The filelayout driver sends LAYOUTCOMMIT only when COMMIT goes to
the data server (as opposed to the MDS) and the data server WRITE
is not NFS_FILE_SYNC.
Only whole file layout support means that there is only one IOMODE_RW layout
segment.
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Alexandros Batsakis <batsakis@netapp.com>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Dean Hildebrand <dhildeb@us.ibm.com>
Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
Signed-off-by: Mingyang Guo <guomingyang@nrchpc.ac.cn>
Signed-off-by: Tao Guo <guotao@nrchpc.ac.cn>
Signed-off-by: Zhang Jingwang <zhangjingwang@nrchpc.ac.cn>
Tested-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Fred Isaman <iisaman@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index c67565965f2a..2a08ca0dddc1 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -946,3 +946,97 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata, | |||
946 | dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); | 946 | dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); |
947 | return trypnfs; | 947 | return trypnfs; |
948 | } | 948 | } |
949 | |||
950 | /* | ||
951 | * Currently there is only one (whole file) write lseg. | ||
952 | */ | ||
953 | static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode) | ||
954 | { | ||
955 | struct pnfs_layout_segment *lseg, *rv = NULL; | ||
956 | |||
957 | list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) | ||
958 | if (lseg->pls_range.iomode == IOMODE_RW) | ||
959 | rv = lseg; | ||
960 | return rv; | ||
961 | } | ||
962 | |||
963 | void | ||
964 | pnfs_set_layoutcommit(struct nfs_write_data *wdata) | ||
965 | { | ||
966 | struct nfs_inode *nfsi = NFS_I(wdata->inode); | ||
967 | loff_t end_pos = wdata->args.offset + wdata->res.count; | ||
968 | |||
969 | spin_lock(&nfsi->vfs_inode.i_lock); | ||
970 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | ||
971 | /* references matched in nfs4_layoutcommit_release */ | ||
972 | get_lseg(wdata->lseg); | ||
973 | wdata->lseg->pls_lc_cred = | ||
974 | get_rpccred(wdata->args.context->state->owner->so_cred); | ||
975 | mark_inode_dirty_sync(wdata->inode); | ||
976 | dprintk("%s: Set layoutcommit for inode %lu ", | ||
977 | __func__, wdata->inode->i_ino); | ||
978 | } | ||
979 | if (end_pos > wdata->lseg->pls_end_pos) | ||
980 | wdata->lseg->pls_end_pos = end_pos; | ||
981 | spin_unlock(&nfsi->vfs_inode.i_lock); | ||
982 | } | ||
983 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); | ||
984 | |||
985 | int | ||
986 | pnfs_layoutcommit_inode(struct inode *inode, int sync) | ||
987 | { | ||
988 | struct nfs4_layoutcommit_data *data; | ||
989 | struct nfs_inode *nfsi = NFS_I(inode); | ||
990 | struct pnfs_layout_segment *lseg; | ||
991 | struct rpc_cred *cred; | ||
992 | loff_t end_pos; | ||
993 | int status = 0; | ||
994 | |||
995 | dprintk("--> %s inode %lu\n", __func__, inode->i_ino); | ||
996 | |||
997 | /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ | ||
998 | data = kzalloc(sizeof(*data), GFP_NOFS); | ||
999 | spin_lock(&inode->i_lock); | ||
1000 | |||
1001 | if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | ||
1002 | spin_unlock(&inode->i_lock); | ||
1003 | kfree(data); | ||
1004 | goto out; | ||
1005 | } | ||
1006 | /* | ||
1007 | * Currently only one (whole file) write lseg which is referenced | ||
1008 | * in pnfs_set_layoutcommit and will be found. | ||
1009 | */ | ||
1010 | lseg = pnfs_list_write_lseg(inode); | ||
1011 | |||
1012 | end_pos = lseg->pls_end_pos; | ||
1013 | cred = lseg->pls_lc_cred; | ||
1014 | lseg->pls_end_pos = 0; | ||
1015 | lseg->pls_lc_cred = NULL; | ||
1016 | |||
1017 | if (!data) { | ||
1018 | put_lseg(lseg); | ||
1019 | spin_unlock(&inode->i_lock); | ||
1020 | put_rpccred(cred); | ||
1021 | status = -ENOMEM; | ||
1022 | goto out; | ||
1023 | } else { | ||
1024 | memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data, | ||
1025 | sizeof(nfsi->layout->plh_stateid.data)); | ||
1026 | } | ||
1027 | spin_unlock(&inode->i_lock); | ||
1028 | |||
1029 | data->args.inode = inode; | ||
1030 | data->lseg = lseg; | ||
1031 | data->cred = cred; | ||
1032 | nfs_fattr_init(&data->fattr); | ||
1033 | data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; | ||
1034 | data->res.fattr = &data->fattr; | ||
1035 | data->args.lastbytewritten = end_pos - 1; | ||
1036 | data->res.server = NFS_SERVER(inode); | ||
1037 | |||
1038 | status = nfs4_proc_layoutcommit(data, sync); | ||
1039 | out: | ||
1040 | dprintk("<-- %s status %d\n", __func__, status); | ||
1041 | return status; | ||
1042 | } | ||