diff options
author | Andy Adamson <andros@netapp.com> | 2011-03-12 02:58:09 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-24 15:49:48 -0400 |
commit | de4b15c7e9fe9fdd1eb6333be0a08c822db1ca0e (patch) | |
tree | 5851c3352d20c6433677da072d2fdbc63d303b8e /fs/nfs/pnfs.c | |
parent | cccb4d063b263ac0713ab27d98460fda3b4f83ff (diff) |
NFSv4.1 pnfs_layoutcommit_inode fixes
Test NFS_INO_LAYOUTCOMMIT before kzalloc
Mark inode dirty to retry LAYOUTCOMMIT on kzalloc failure.
Add comments.
Signed-off-by: Andy Adamson <andros@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 | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 2a08ca0dddc1..ac7112574790 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -982,6 +982,14 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) | |||
982 | } | 982 | } |
983 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); | 983 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); |
984 | 984 | ||
985 | /* | ||
986 | * For the LAYOUT4_NFSV4_1_FILES layout type, NFS_DATA_SYNC WRITEs and | ||
987 | * NFS_UNSTABLE WRITEs with a COMMIT to data servers must store enough | ||
988 | * data to disk to allow the server to recover the data if it crashes. | ||
989 | * LAYOUTCOMMIT is only needed when the NFL4_UFLG_COMMIT_THRU_MDS flag | ||
990 | * is off, and a COMMIT is sent to a data server, or | ||
991 | * if WRITEs to a data server return NFS_DATA_SYNC. | ||
992 | */ | ||
985 | int | 993 | int |
986 | pnfs_layoutcommit_inode(struct inode *inode, int sync) | 994 | pnfs_layoutcommit_inode(struct inode *inode, int sync) |
987 | { | 995 | { |
@@ -994,10 +1002,18 @@ pnfs_layoutcommit_inode(struct inode *inode, int sync) | |||
994 | 1002 | ||
995 | dprintk("--> %s inode %lu\n", __func__, inode->i_ino); | 1003 | dprintk("--> %s inode %lu\n", __func__, inode->i_ino); |
996 | 1004 | ||
1005 | if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) | ||
1006 | return 0; | ||
1007 | |||
997 | /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ | 1008 | /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ |
998 | data = kzalloc(sizeof(*data), GFP_NOFS); | 1009 | data = kzalloc(sizeof(*data), GFP_NOFS); |
999 | spin_lock(&inode->i_lock); | 1010 | if (!data) { |
1011 | mark_inode_dirty_sync(inode); | ||
1012 | status = -ENOMEM; | ||
1013 | goto out; | ||
1014 | } | ||
1000 | 1015 | ||
1016 | spin_lock(&inode->i_lock); | ||
1001 | if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | 1017 | if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { |
1002 | spin_unlock(&inode->i_lock); | 1018 | spin_unlock(&inode->i_lock); |
1003 | kfree(data); | 1019 | kfree(data); |
@@ -1014,16 +1030,8 @@ pnfs_layoutcommit_inode(struct inode *inode, int sync) | |||
1014 | lseg->pls_end_pos = 0; | 1030 | lseg->pls_end_pos = 0; |
1015 | lseg->pls_lc_cred = NULL; | 1031 | lseg->pls_lc_cred = NULL; |
1016 | 1032 | ||
1017 | if (!data) { | 1033 | memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data, |
1018 | put_lseg(lseg); | 1034 | sizeof(nfsi->layout->plh_stateid.data)); |
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); | 1035 | spin_unlock(&inode->i_lock); |
1028 | 1036 | ||
1029 | data->args.inode = inode; | 1037 | data->args.inode = inode; |