aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-05-31 12:22:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-31 14:41:36 -0400
commit1d59d61f606547f0712aa6971f91f71154071c99 (patch)
treecb2fd4b9ce3e3ee9440d566d43ea350221edfc8e /fs/nfs
parent2d117403b30cd7301af60d7d54b279a9f566d10d (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.c15
-rw-r--r--fs/nfs/inode.c5
-rw-r--r--fs/nfs/internal.h4
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
457static 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)
458static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) 464static 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
582static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) 588static 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 */
370void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo, 370void nfs_init_cinfo_from_dreq(struct nfs_commit_info *cinfo,
371 struct nfs_direct_req *dreq); 371 struct nfs_direct_req *dreq);
372static inline void nfs_inode_dio_wait(struct inode *inode)
373{
374 inode_dio_wait(inode);
375}
372 376
373/* nfs4proc.c */ 377/* nfs4proc.c */
374extern void __nfs4_read_done_cb(struct nfs_read_data *); 378extern void __nfs4_read_done_cb(struct nfs_read_data *);