diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 6a4083d550c6cc59ce9d66f436d145e2c380a76f..c0de56ed83643b6e83f3e199282ef252c7a8c117 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -760,10 +760,17 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) LIST_HEAD(mds_list); nfs_init_cinfo_from_dreq(&cinfo, dreq); + nfs_commit_begin(cinfo.mds); nfs_scan_commit(dreq->inode, &mds_list, &cinfo); res = nfs_generic_commit_list(dreq->inode, &mds_list, 0, &cinfo); - if (res < 0) /* res == -ENOMEM */ - nfs_direct_write_reschedule(dreq); + if (res < 0) { /* res == -ENOMEM */ + spin_lock(&dreq->lock); + if (dreq->flags == 0) + dreq->flags = NFS_ODIRECT_RESCHED_WRITES; + spin_unlock(&dreq->lock); + } + if (nfs_commit_end(cinfo.mds)) + nfs_direct_write_complete(dreq); } static void nfs_direct_write_schedule_work(struct work_struct *work) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index e383d265e65b1ce2f3101e1b280780474fe565f2..e4b1ce4886373dd646f496d687c6e837ed249752 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1643,15 +1643,19 @@ static int wait_on_commit(struct nfs_mds_commit_info *cinfo) !atomic_read(&cinfo->rpcs_out)); } -static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo) +void nfs_commit_begin(struct nfs_mds_commit_info *cinfo) { atomic_inc(&cinfo->rpcs_out); } -static void nfs_commit_end(struct nfs_mds_commit_info *cinfo) +bool nfs_commit_end(struct nfs_mds_commit_info *cinfo) { - if (atomic_dec_and_test(&cinfo->rpcs_out)) + + if (atomic_dec_and_test(&cinfo->rpcs_out)) { wake_up_var(&cinfo->rpcs_out); + return true; + } + return false; } void nfs_commitdata_release(struct nfs_commit_data *data) diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 22e4ce63917d680fabc346407e6715daf5300178..beb26241fe57112a2b423f93deb9963c6b0ea031 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -545,6 +545,8 @@ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); extern int nfs_commit_inode(struct inode *, int); extern struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail); extern void nfs_commit_free(struct nfs_commit_data *data); +void nfs_commit_begin(struct nfs_mds_commit_info *cinfo); +bool nfs_commit_end(struct nfs_mds_commit_info *cinfo); static inline int nfs_have_writebacks(struct inode *inode)