diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-05-31 12:22:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-31 14:41:36 -0400 |
commit | 1d59d61f606547f0712aa6971f91f71154071c99 (patch) | |
tree | cb2fd4b9ce3e3ee9440d566d43ea350221edfc8e /fs/nfs | |
parent | 2d117403b30cd7301af60d7d54b279a9f566d10d (diff) |
NFS: Ensure that setattr and getattr wait for O_DIRECT write completion
Use the same mechanism as the block devices are using, but move the
helper functions from fs/direct-io.c into fs/inode.c to remove the
dependency on CONFIG_BLOCK.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Fred Isaman <iisaman@netapp.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/direct.c | 15 | ||||
-rw-r--r-- | fs/nfs/inode.c | 5 | ||||
-rw-r--r-- | fs/nfs/internal.h | 4 |
3 files changed, 20 insertions, 4 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 23d170bc44f4..ad2775d3e219 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -454,6 +454,12 @@ out: | |||
454 | return result; | 454 | return result; |
455 | } | 455 | } |
456 | 456 | ||
457 | static void nfs_inode_dio_write_done(struct inode *inode) | ||
458 | { | ||
459 | nfs_zap_mapping(inode, inode->i_mapping); | ||
460 | inode_dio_done(inode); | ||
461 | } | ||
462 | |||
457 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 463 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
458 | static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | 464 | static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) |
459 | { | 465 | { |
@@ -564,7 +570,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work) | |||
564 | nfs_direct_write_reschedule(dreq); | 570 | nfs_direct_write_reschedule(dreq); |
565 | break; | 571 | break; |
566 | default: | 572 | default: |
567 | nfs_zap_mapping(dreq->inode, dreq->inode->i_mapping); | 573 | nfs_inode_dio_write_done(dreq->inode); |
568 | nfs_direct_complete(dreq); | 574 | nfs_direct_complete(dreq); |
569 | } | 575 | } |
570 | } | 576 | } |
@@ -581,7 +587,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work) | |||
581 | 587 | ||
582 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) | 588 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) |
583 | { | 589 | { |
584 | nfs_zap_mapping(inode, inode->i_mapping); | 590 | nfs_inode_dio_write_done(inode); |
585 | nfs_direct_complete(dreq); | 591 | nfs_direct_complete(dreq); |
586 | } | 592 | } |
587 | #endif | 593 | #endif |
@@ -766,14 +772,16 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
766 | loff_t pos) | 772 | loff_t pos) |
767 | { | 773 | { |
768 | struct nfs_pageio_descriptor desc; | 774 | struct nfs_pageio_descriptor desc; |
775 | struct inode *inode = dreq->inode; | ||
769 | ssize_t result = 0; | 776 | ssize_t result = 0; |
770 | size_t requested_bytes = 0; | 777 | size_t requested_bytes = 0; |
771 | unsigned long seg; | 778 | unsigned long seg; |
772 | 779 | ||
773 | nfs_pageio_init_write(&desc, dreq->inode, FLUSH_COND_STABLE, | 780 | nfs_pageio_init_write(&desc, inode, FLUSH_COND_STABLE, |
774 | &nfs_direct_write_completion_ops); | 781 | &nfs_direct_write_completion_ops); |
775 | desc.pg_dreq = dreq; | 782 | desc.pg_dreq = dreq; |
776 | get_dreq(dreq); | 783 | get_dreq(dreq); |
784 | atomic_inc(&inode->i_dio_count); | ||
777 | 785 | ||
778 | for (seg = 0; seg < nr_segs; seg++) { | 786 | for (seg = 0; seg < nr_segs; seg++) { |
779 | const struct iovec *vec = &iov[seg]; | 787 | const struct iovec *vec = &iov[seg]; |
@@ -793,6 +801,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
793 | * generic layer handle the completion. | 801 | * generic layer handle the completion. |
794 | */ | 802 | */ |
795 | if (requested_bytes == 0) { | 803 | if (requested_bytes == 0) { |
804 | inode_dio_done(inode); | ||
796 | nfs_direct_req_release(dreq); | 805 | nfs_direct_req_release(dreq); |
797 | return result < 0 ? result : -EIO; | 806 | return result < 0 ? result : -EIO; |
798 | } | 807 | } |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 2f6f78c4b42d..e605d695dbcb 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -418,8 +418,10 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
418 | return 0; | 418 | return 0; |
419 | 419 | ||
420 | /* Write all dirty data */ | 420 | /* Write all dirty data */ |
421 | if (S_ISREG(inode->i_mode)) | 421 | if (S_ISREG(inode->i_mode)) { |
422 | nfs_inode_dio_wait(inode); | ||
422 | nfs_wb_all(inode); | 423 | nfs_wb_all(inode); |
424 | } | ||
423 | 425 | ||
424 | fattr = nfs_alloc_fattr(); | 426 | fattr = nfs_alloc_fattr(); |
425 | if (fattr == NULL) | 427 | if (fattr == NULL) |
@@ -503,6 +505,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
503 | 505 | ||
504 | /* Flush out writes to the server in order to update c/mtime. */ | 506 | /* Flush out writes to the server in order to update c/mtime. */ |
505 | if (S_ISREG(inode->i_mode)) { | 507 | if (S_ISREG(inode->i_mode)) { |
508 | nfs_inode_dio_wait(inode); | ||
506 | err = filemap_write_and_wait(inode->i_mapping); | 509 | err = filemap_write_and_wait(inode->i_mapping); |
507 | if (err) | 510 | if (err) |
508 | goto out; | 511 | goto out; |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 1848a7275592..18f99ef71343 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -369,6 +369,10 @@ extern int nfs_migrate_page(struct address_space *, | |||
369 | /* direct.c */ | 369 | /* direct.c */ |
370 | void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo, | 370 | void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo, |
371 | struct nfs_direct_req *dreq); | 371 | struct nfs_direct_req *dreq); |
372 | static inline void nfs_inode_dio_wait(struct inode *inode) | ||
373 | { | ||
374 | inode_dio_wait(inode); | ||
375 | } | ||
372 | 376 | ||
373 | /* nfs4proc.c */ | 377 | /* nfs4proc.c */ |
374 | extern void __nfs4_read_done_cb(struct nfs_read_data *); | 378 | extern void __nfs4_read_done_cb(struct nfs_read_data *); |