diff options
author | Christoph Hellwig <hch@infradead.org> | 2013-11-14 11:50:29 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-01-13 17:29:48 -0500 |
commit | 2a009ec98cce440c0992fc9a2353e96cdb0b048b (patch) | |
tree | e2cb12a379834aa6283b1a5b01b52ab542e2885c /fs/nfs | |
parent | 9811cd57f4c6b5b60ec104de68a88303717e3106 (diff) |
nfs: defer inode_dio_done call until size update is done
We need to have the I/O fully finished before telling the truncate code
that we are done.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/direct.c | 32 |
1 files changed, 15 insertions, 17 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index ce52a9774ec1..75ed2a90b0f2 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -226,21 +226,27 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write) | |||
226 | { | 226 | { |
227 | struct inode *inode = dreq->inode; | 227 | struct inode *inode = dreq->inode; |
228 | 228 | ||
229 | if (dreq->iocb) { | 229 | if (dreq->iocb && write) { |
230 | loff_t pos = dreq->iocb->ki_pos + dreq->count; | 230 | loff_t pos = dreq->iocb->ki_pos + dreq->count; |
231 | |||
232 | spin_lock(&inode->i_lock); | ||
233 | if (i_size_read(inode) < pos) | ||
234 | i_size_write(inode, pos); | ||
235 | spin_unlock(&inode->i_lock); | ||
236 | } | ||
237 | |||
238 | if (write) { | ||
239 | nfs_zap_mapping(inode, inode->i_mapping); | ||
240 | inode_dio_done(inode); | ||
241 | } | ||
242 | |||
243 | if (dreq->iocb) { | ||
231 | long res = (long) dreq->error; | 244 | long res = (long) dreq->error; |
232 | if (!res) | 245 | if (!res) |
233 | res = (long) dreq->count; | 246 | res = (long) dreq->count; |
234 | |||
235 | if (write) { | ||
236 | spin_lock(&inode->i_lock); | ||
237 | if (i_size_read(inode) < pos) | ||
238 | i_size_write(inode, pos); | ||
239 | spin_unlock(&inode->i_lock); | ||
240 | } | ||
241 | |||
242 | aio_complete(dreq->iocb, res, 0); | 247 | aio_complete(dreq->iocb, res, 0); |
243 | } | 248 | } |
249 | |||
244 | complete_all(&dreq->completion); | 250 | complete_all(&dreq->completion); |
245 | 251 | ||
246 | nfs_direct_req_release(dreq); | 252 | nfs_direct_req_release(dreq); |
@@ -483,12 +489,6 @@ out: | |||
483 | return result; | 489 | return result; |
484 | } | 490 | } |
485 | 491 | ||
486 | static void nfs_inode_dio_write_done(struct inode *inode) | ||
487 | { | ||
488 | nfs_zap_mapping(inode, inode->i_mapping); | ||
489 | inode_dio_done(inode); | ||
490 | } | ||
491 | |||
492 | #if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) | 492 | #if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) |
493 | static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | 493 | static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) |
494 | { | 494 | { |
@@ -604,7 +604,6 @@ static void nfs_direct_write_schedule_work(struct work_struct *work) | |||
604 | nfs_direct_write_reschedule(dreq); | 604 | nfs_direct_write_reschedule(dreq); |
605 | break; | 605 | break; |
606 | default: | 606 | default: |
607 | nfs_inode_dio_write_done(dreq->inode); | ||
608 | nfs_direct_complete(dreq, true); | 607 | nfs_direct_complete(dreq, true); |
609 | } | 608 | } |
610 | } | 609 | } |
@@ -621,7 +620,6 @@ static void nfs_direct_write_schedule_work(struct work_struct *work) | |||
621 | 620 | ||
622 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) | 621 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) |
623 | { | 622 | { |
624 | nfs_inode_dio_write_done(inode); | ||
625 | nfs_direct_complete(dreq, true); | 623 | nfs_direct_complete(dreq, true); |
626 | } | 624 | } |
627 | #endif | 625 | #endif |