summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2011-03-12 02:58:09 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-24 15:49:48 -0400
commitde4b15c7e9fe9fdd1eb6333be0a08c822db1ca0e (patch)
tree5851c3352d20c6433677da072d2fdbc63d303b8e /fs
parentcccb4d063b263ac0713ab27d98460fda3b4f83ff (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')
-rw-r--r--fs/nfs/pnfs.c30
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)
}
EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
+/*
+ * For the LAYOUT4_NFSV4_1_FILES layout type, NFS_DATA_SYNC WRITEs and
+ * NFS_UNSTABLE WRITEs with a COMMIT to data servers must store enough
+ * data to disk to allow the server to recover the data if it crashes.
+ * LAYOUTCOMMIT is only needed when the NFL4_UFLG_COMMIT_THRU_MDS flag
+ * is off, and a COMMIT is sent to a data server, or
+ * if WRITEs to a data server return NFS_DATA_SYNC.
+ */
int
pnfs_layoutcommit_inode(struct inode *inode, int sync)
{
@@ -994,10 +1002,18 @@ pnfs_layoutcommit_inode(struct inode *inode, int sync)
dprintk("--> %s inode %lu\n", __func__, inode->i_ino);
+ if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
+ return 0;
+
/* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */
data = kzalloc(sizeof(*data), GFP_NOFS);
- spin_lock(&inode->i_lock);
+ if (!data) {
+ mark_inode_dirty_sync(inode);
+ status = -ENOMEM;
+ goto out;
+ }
+ spin_lock(&inode->i_lock);
if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
spin_unlock(&inode->i_lock);
kfree(data);
@@ -1014,16 +1030,8 @@ pnfs_layoutcommit_inode(struct inode *inode, int sync)
lseg->pls_end_pos = 0;
lseg->pls_lc_cred = NULL;
- if (!data) {
- put_lseg(lseg);
- spin_unlock(&inode->i_lock);
- put_rpccred(cred);
- status = -ENOMEM;
- goto out;
- } else {
- memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data,
- sizeof(nfsi->layout->plh_stateid.data));
- }
+ memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data,
+ sizeof(nfsi->layout->plh_stateid.data));
spin_unlock(&inode->i_lock);
data->args.inode = inode;