diff options
-rw-r--r-- | fs/direct-io.c | 44 | ||||
-rw-r--r-- | fs/inode.c | 47 | ||||
-rw-r--r-- | fs/nfs/direct.c | 15 | ||||
-rw-r--r-- | fs/nfs/inode.c | 5 | ||||
-rw-r--r-- | fs/nfs/internal.h | 4 | ||||
-rw-r--r-- | include/linux/fs.h | 9 |
6 files changed, 70 insertions, 54 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c index f4aadd15b613..0c85fae37666 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -145,50 +145,6 @@ struct dio { | |||
145 | 145 | ||
146 | static struct kmem_cache *dio_cache __read_mostly; | 146 | static struct kmem_cache *dio_cache __read_mostly; |
147 | 147 | ||
148 | static void __inode_dio_wait(struct inode *inode) | ||
149 | { | ||
150 | wait_queue_head_t *wq = bit_waitqueue(&inode->i_state, __I_DIO_WAKEUP); | ||
151 | DEFINE_WAIT_BIT(q, &inode->i_state, __I_DIO_WAKEUP); | ||
152 | |||
153 | do { | ||
154 | prepare_to_wait(wq, &q.wait, TASK_UNINTERRUPTIBLE); | ||
155 | if (atomic_read(&inode->i_dio_count)) | ||
156 | schedule(); | ||
157 | } while (atomic_read(&inode->i_dio_count)); | ||
158 | finish_wait(wq, &q.wait); | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * inode_dio_wait - wait for outstanding DIO requests to finish | ||
163 | * @inode: inode to wait for | ||
164 | * | ||
165 | * Waits for all pending direct I/O requests to finish so that we can | ||
166 | * proceed with a truncate or equivalent operation. | ||
167 | * | ||
168 | * Must be called under a lock that serializes taking new references | ||
169 | * to i_dio_count, usually by inode->i_mutex. | ||
170 | */ | ||
171 | void inode_dio_wait(struct inode *inode) | ||
172 | { | ||
173 | if (atomic_read(&inode->i_dio_count)) | ||
174 | __inode_dio_wait(inode); | ||
175 | } | ||
176 | EXPORT_SYMBOL(inode_dio_wait); | ||
177 | |||
178 | /* | ||
179 | * inode_dio_done - signal finish of a direct I/O requests | ||
180 | * @inode: inode the direct I/O happens on | ||
181 | * | ||
182 | * This is called once we've finished processing a direct I/O request, | ||
183 | * and is used to wake up callers waiting for direct I/O to be quiesced. | ||
184 | */ | ||
185 | void inode_dio_done(struct inode *inode) | ||
186 | { | ||
187 | if (atomic_dec_and_test(&inode->i_dio_count)) | ||
188 | wake_up_bit(&inode->i_state, __I_DIO_WAKEUP); | ||
189 | } | ||
190 | EXPORT_SYMBOL(inode_dio_done); | ||
191 | |||
192 | /* | 148 | /* |
193 | * How many pages are in the queue? | 149 | * How many pages are in the queue? |
194 | */ | 150 | */ |
diff --git a/fs/inode.c b/fs/inode.c index 6bc8761cc333..c474c1d7062b 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1748,3 +1748,50 @@ bool inode_owner_or_capable(const struct inode *inode) | |||
1748 | return false; | 1748 | return false; |
1749 | } | 1749 | } |
1750 | EXPORT_SYMBOL(inode_owner_or_capable); | 1750 | EXPORT_SYMBOL(inode_owner_or_capable); |
1751 | |||
1752 | /* | ||
1753 | * Direct i/o helper functions | ||
1754 | */ | ||
1755 | static void __inode_dio_wait(struct inode *inode) | ||
1756 | { | ||
1757 | wait_queue_head_t *wq = bit_waitqueue(&inode->i_state, __I_DIO_WAKEUP); | ||
1758 | DEFINE_WAIT_BIT(q, &inode->i_state, __I_DIO_WAKEUP); | ||
1759 | |||
1760 | do { | ||
1761 | prepare_to_wait(wq, &q.wait, TASK_UNINTERRUPTIBLE); | ||
1762 | if (atomic_read(&inode->i_dio_count)) | ||
1763 | schedule(); | ||
1764 | } while (atomic_read(&inode->i_dio_count)); | ||
1765 | finish_wait(wq, &q.wait); | ||
1766 | } | ||
1767 | |||
1768 | /** | ||
1769 | * inode_dio_wait - wait for outstanding DIO requests to finish | ||
1770 | * @inode: inode to wait for | ||
1771 | * | ||
1772 | * Waits for all pending direct I/O requests to finish so that we can | ||
1773 | * proceed with a truncate or equivalent operation. | ||
1774 | * | ||
1775 | * Must be called under a lock that serializes taking new references | ||
1776 | * to i_dio_count, usually by inode->i_mutex. | ||
1777 | */ | ||
1778 | void inode_dio_wait(struct inode *inode) | ||
1779 | { | ||
1780 | if (atomic_read(&inode->i_dio_count)) | ||
1781 | __inode_dio_wait(inode); | ||
1782 | } | ||
1783 | EXPORT_SYMBOL(inode_dio_wait); | ||
1784 | |||
1785 | /* | ||
1786 | * inode_dio_done - signal finish of a direct I/O requests | ||
1787 | * @inode: inode the direct I/O happens on | ||
1788 | * | ||
1789 | * This is called once we've finished processing a direct I/O request, | ||
1790 | * and is used to wake up callers waiting for direct I/O to be quiesced. | ||
1791 | */ | ||
1792 | void inode_dio_done(struct inode *inode) | ||
1793 | { | ||
1794 | if (atomic_dec_and_test(&inode->i_dio_count)) | ||
1795 | wake_up_bit(&inode->i_state, __I_DIO_WAKEUP); | ||
1796 | } | ||
1797 | EXPORT_SYMBOL(inode_dio_done); | ||
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 *); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 038076b27ea4..598a5892ff2b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2453,8 +2453,6 @@ enum { | |||
2453 | }; | 2453 | }; |
2454 | 2454 | ||
2455 | void dio_end_io(struct bio *bio, int error); | 2455 | void dio_end_io(struct bio *bio, int error); |
2456 | void inode_dio_wait(struct inode *inode); | ||
2457 | void inode_dio_done(struct inode *inode); | ||
2458 | 2456 | ||
2459 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | 2457 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, |
2460 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | 2458 | struct block_device *bdev, const struct iovec *iov, loff_t offset, |
@@ -2469,12 +2467,11 @@ static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, | |||
2469 | offset, nr_segs, get_block, NULL, NULL, | 2467 | offset, nr_segs, get_block, NULL, NULL, |
2470 | DIO_LOCKING | DIO_SKIP_HOLES); | 2468 | DIO_LOCKING | DIO_SKIP_HOLES); |
2471 | } | 2469 | } |
2472 | #else | ||
2473 | static inline void inode_dio_wait(struct inode *inode) | ||
2474 | { | ||
2475 | } | ||
2476 | #endif | 2470 | #endif |
2477 | 2471 | ||
2472 | void inode_dio_wait(struct inode *inode); | ||
2473 | void inode_dio_done(struct inode *inode); | ||
2474 | |||
2478 | extern const struct file_operations generic_ro_fops; | 2475 | extern const struct file_operations generic_ro_fops; |
2479 | 2476 | ||
2480 | #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) | 2477 | #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) |