aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/file.c2
-rw-r--r--fs/ceph/inode.c124
-rw-r--r--fs/ceph/super.c28
-rw-r--r--fs/ceph/super.h17
4 files changed, 74 insertions, 97 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 305daf043eb0..183c37c0a8fc 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -791,7 +791,7 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req)
791 if (aio_work) { 791 if (aio_work) {
792 INIT_WORK(&aio_work->work, ceph_aio_retry_work); 792 INIT_WORK(&aio_work->work, ceph_aio_retry_work);
793 aio_work->req = req; 793 aio_work->req = req;
794 queue_work(ceph_inode_to_client(inode)->wb_wq, 794 queue_work(ceph_inode_to_client(inode)->inode_wq,
795 &aio_work->work); 795 &aio_work->work);
796 return; 796 return;
797 } 797 }
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index f85355bf49c4..3acdd3cc6039 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -33,9 +33,7 @@
33 33
34static const struct inode_operations ceph_symlink_iops; 34static const struct inode_operations ceph_symlink_iops;
35 35
36static void ceph_invalidate_work(struct work_struct *work); 36static void ceph_inode_work(struct work_struct *work);
37static void ceph_writeback_work(struct work_struct *work);
38static void ceph_vmtruncate_work(struct work_struct *work);
39 37
40/* 38/*
41 * find or create an inode, given the ceph ino number 39 * find or create an inode, given the ceph ino number
@@ -509,10 +507,8 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
509 INIT_LIST_HEAD(&ci->i_snap_realm_item); 507 INIT_LIST_HEAD(&ci->i_snap_realm_item);
510 INIT_LIST_HEAD(&ci->i_snap_flush_item); 508 INIT_LIST_HEAD(&ci->i_snap_flush_item);
511 509
512 INIT_WORK(&ci->i_wb_work, ceph_writeback_work); 510 INIT_WORK(&ci->i_work, ceph_inode_work);
513 INIT_WORK(&ci->i_pg_inv_work, ceph_invalidate_work); 511 ci->i_work_mask = 0;
514
515 INIT_WORK(&ci->i_vmtruncate_work, ceph_vmtruncate_work);
516 512
517 ceph_fscache_inode_init(ci); 513 ceph_fscache_inode_init(ci);
518 514
@@ -1746,51 +1742,62 @@ bool ceph_inode_set_size(struct inode *inode, loff_t size)
1746 */ 1742 */
1747void ceph_queue_writeback(struct inode *inode) 1743void ceph_queue_writeback(struct inode *inode)
1748{ 1744{
1745 struct ceph_inode_info *ci = ceph_inode(inode);
1746 set_bit(CEPH_I_WORK_WRITEBACK, &ci->i_work_mask);
1747
1749 ihold(inode); 1748 ihold(inode);
1750 if (queue_work(ceph_inode_to_client(inode)->wb_wq, 1749 if (queue_work(ceph_inode_to_client(inode)->inode_wq,
1751 &ceph_inode(inode)->i_wb_work)) { 1750 &ci->i_work)) {
1752 dout("ceph_queue_writeback %p\n", inode); 1751 dout("ceph_queue_writeback %p\n", inode);
1753 } else { 1752 } else {
1754 dout("ceph_queue_writeback %p failed\n", inode); 1753 dout("ceph_queue_writeback %p already queued, mask=%lx\n",
1754 inode, ci->i_work_mask);
1755 iput(inode); 1755 iput(inode);
1756 } 1756 }
1757} 1757}
1758 1758
1759static void ceph_writeback_work(struct work_struct *work)
1760{
1761 struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info,
1762 i_wb_work);
1763 struct inode *inode = &ci->vfs_inode;
1764
1765 dout("writeback %p\n", inode);
1766 filemap_fdatawrite(&inode->i_data);
1767 iput(inode);
1768}
1769
1770/* 1759/*
1771 * queue an async invalidation 1760 * queue an async invalidation
1772 */ 1761 */
1773void ceph_queue_invalidate(struct inode *inode) 1762void ceph_queue_invalidate(struct inode *inode)
1774{ 1763{
1764 struct ceph_inode_info *ci = ceph_inode(inode);
1765 set_bit(CEPH_I_WORK_INVALIDATE_PAGES, &ci->i_work_mask);
1766
1775 ihold(inode); 1767 ihold(inode);
1776 if (queue_work(ceph_inode_to_client(inode)->pg_inv_wq, 1768 if (queue_work(ceph_inode_to_client(inode)->inode_wq,
1777 &ceph_inode(inode)->i_pg_inv_work)) { 1769 &ceph_inode(inode)->i_work)) {
1778 dout("ceph_queue_invalidate %p\n", inode); 1770 dout("ceph_queue_invalidate %p\n", inode);
1779 } else { 1771 } else {
1780 dout("ceph_queue_invalidate %p failed\n", inode); 1772 dout("ceph_queue_invalidate %p already queued, mask=%lx\n",
1773 inode, ci->i_work_mask);
1781 iput(inode); 1774 iput(inode);
1782 } 1775 }
1783} 1776}
1784 1777
1785/* 1778/*
1786 * Invalidate inode pages in a worker thread. (This can't be done 1779 * Queue an async vmtruncate. If we fail to queue work, we will handle
1787 * in the message handler context.) 1780 * the truncation the next time we call __ceph_do_pending_vmtruncate.
1788 */ 1781 */
1789static void ceph_invalidate_work(struct work_struct *work) 1782void ceph_queue_vmtruncate(struct inode *inode)
1790{ 1783{
1791 struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info, 1784 struct ceph_inode_info *ci = ceph_inode(inode);
1792 i_pg_inv_work); 1785 set_bit(CEPH_I_WORK_VMTRUNCATE, &ci->i_work_mask);
1793 struct inode *inode = &ci->vfs_inode; 1786
1787 ihold(inode);
1788 if (queue_work(ceph_inode_to_client(inode)->inode_wq,
1789 &ci->i_work)) {
1790 dout("ceph_queue_vmtruncate %p\n", inode);
1791 } else {
1792 dout("ceph_queue_vmtruncate %p already queued, mask=%lx\n",
1793 inode, ci->i_work_mask);
1794 iput(inode);
1795 }
1796}
1797
1798static void ceph_do_invalidate_pages(struct inode *inode)
1799{
1800 struct ceph_inode_info *ci = ceph_inode(inode);
1794 struct ceph_fs_client *fsc = ceph_inode_to_client(inode); 1801 struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
1795 u32 orig_gen; 1802 u32 orig_gen;
1796 int check = 0; 1803 int check = 0;
@@ -1842,44 +1849,6 @@ static void ceph_invalidate_work(struct work_struct *work)
1842out: 1849out:
1843 if (check) 1850 if (check)
1844 ceph_check_caps(ci, 0, NULL); 1851 ceph_check_caps(ci, 0, NULL);
1845 iput(inode);
1846}
1847
1848
1849/*
1850 * called by trunc_wq;
1851 *
1852 * We also truncate in a separate thread as well.
1853 */
1854static void ceph_vmtruncate_work(struct work_struct *work)
1855{
1856 struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info,
1857 i_vmtruncate_work);
1858 struct inode *inode = &ci->vfs_inode;
1859
1860 dout("vmtruncate_work %p\n", inode);
1861 __ceph_do_pending_vmtruncate(inode);
1862 iput(inode);
1863}
1864
1865/*
1866 * Queue an async vmtruncate. If we fail to queue work, we will handle
1867 * the truncation the next time we call __ceph_do_pending_vmtruncate.
1868 */
1869void ceph_queue_vmtruncate(struct inode *inode)
1870{
1871 struct ceph_inode_info *ci = ceph_inode(inode);
1872
1873 ihold(inode);
1874
1875 if (queue_work(ceph_sb_to_client(inode->i_sb)->trunc_wq,
1876 &ci->i_vmtruncate_work)) {
1877 dout("ceph_queue_vmtruncate %p\n", inode);
1878 } else {
1879 dout("ceph_queue_vmtruncate %p failed, pending=%d\n",
1880 inode, ci->i_truncate_pending);
1881 iput(inode);
1882 }
1883} 1852}
1884 1853
1885/* 1854/*
@@ -1943,6 +1912,25 @@ retry:
1943 wake_up_all(&ci->i_cap_wq); 1912 wake_up_all(&ci->i_cap_wq);
1944} 1913}
1945 1914
1915static void ceph_inode_work(struct work_struct *work)
1916{
1917 struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info,
1918 i_work);
1919 struct inode *inode = &ci->vfs_inode;
1920
1921 if (test_and_clear_bit(CEPH_I_WORK_WRITEBACK, &ci->i_work_mask)) {
1922 dout("writeback %p\n", inode);
1923 filemap_fdatawrite(&inode->i_data);
1924 }
1925 if (test_and_clear_bit(CEPH_I_WORK_INVALIDATE_PAGES, &ci->i_work_mask))
1926 ceph_do_invalidate_pages(inode);
1927
1928 if (test_and_clear_bit(CEPH_I_WORK_VMTRUNCATE, &ci->i_work_mask))
1929 __ceph_do_pending_vmtruncate(inode);
1930
1931 iput(inode);
1932}
1933
1946/* 1934/*
1947 * symlinks 1935 * symlinks
1948 */ 1936 */
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 01be7c1bc4c6..d57fa60dcd43 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -672,18 +672,12 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
672 * The number of concurrent works can be high but they don't need 672 * The number of concurrent works can be high but they don't need
673 * to be processed in parallel, limit concurrency. 673 * to be processed in parallel, limit concurrency.
674 */ 674 */
675 fsc->wb_wq = alloc_workqueue("ceph-writeback", 0, 1); 675 fsc->inode_wq = alloc_workqueue("ceph-inode", WQ_UNBOUND, 0);
676 if (!fsc->wb_wq) 676 if (!fsc->inode_wq)
677 goto fail_client; 677 goto fail_client;
678 fsc->pg_inv_wq = alloc_workqueue("ceph-pg-invalid", 0, 1);
679 if (!fsc->pg_inv_wq)
680 goto fail_wb_wq;
681 fsc->trunc_wq = alloc_workqueue("ceph-trunc", 0, 1);
682 if (!fsc->trunc_wq)
683 goto fail_pg_inv_wq;
684 fsc->cap_wq = alloc_workqueue("ceph-cap", 0, 1); 678 fsc->cap_wq = alloc_workqueue("ceph-cap", 0, 1);
685 if (!fsc->cap_wq) 679 if (!fsc->cap_wq)
686 goto fail_trunc_wq; 680 goto fail_inode_wq;
687 681
688 /* set up mempools */ 682 /* set up mempools */
689 err = -ENOMEM; 683 err = -ENOMEM;
@@ -697,12 +691,8 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
697 691
698fail_cap_wq: 692fail_cap_wq:
699 destroy_workqueue(fsc->cap_wq); 693 destroy_workqueue(fsc->cap_wq);
700fail_trunc_wq: 694fail_inode_wq:
701 destroy_workqueue(fsc->trunc_wq); 695 destroy_workqueue(fsc->inode_wq);
702fail_pg_inv_wq:
703 destroy_workqueue(fsc->pg_inv_wq);
704fail_wb_wq:
705 destroy_workqueue(fsc->wb_wq);
706fail_client: 696fail_client:
707 ceph_destroy_client(fsc->client); 697 ceph_destroy_client(fsc->client);
708fail: 698fail:
@@ -715,9 +705,7 @@ fail:
715 705
716static void flush_fs_workqueues(struct ceph_fs_client *fsc) 706static void flush_fs_workqueues(struct ceph_fs_client *fsc)
717{ 707{
718 flush_workqueue(fsc->wb_wq); 708 flush_workqueue(fsc->inode_wq);
719 flush_workqueue(fsc->pg_inv_wq);
720 flush_workqueue(fsc->trunc_wq);
721 flush_workqueue(fsc->cap_wq); 709 flush_workqueue(fsc->cap_wq);
722} 710}
723 711
@@ -725,9 +713,7 @@ static void destroy_fs_client(struct ceph_fs_client *fsc)
725{ 713{
726 dout("destroy_fs_client %p\n", fsc); 714 dout("destroy_fs_client %p\n", fsc);
727 715
728 destroy_workqueue(fsc->wb_wq); 716 destroy_workqueue(fsc->inode_wq);
729 destroy_workqueue(fsc->pg_inv_wq);
730 destroy_workqueue(fsc->trunc_wq);
731 destroy_workqueue(fsc->cap_wq); 717 destroy_workqueue(fsc->cap_wq);
732 718
733 mempool_destroy(fsc->wb_pagevec_pool); 719 mempool_destroy(fsc->wb_pagevec_pool);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 6edab9a750f8..3fb866a979ce 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -109,9 +109,7 @@ struct ceph_fs_client {
109 mempool_t *wb_pagevec_pool; 109 mempool_t *wb_pagevec_pool;
110 atomic_long_t writeback_count; 110 atomic_long_t writeback_count;
111 111
112 struct workqueue_struct *wb_wq; 112 struct workqueue_struct *inode_wq;
113 struct workqueue_struct *pg_inv_wq;
114 struct workqueue_struct *trunc_wq;
115 struct workqueue_struct *cap_wq; 113 struct workqueue_struct *cap_wq;
116 114
117#ifdef CONFIG_DEBUG_FS 115#ifdef CONFIG_DEBUG_FS
@@ -387,10 +385,8 @@ struct ceph_inode_info {
387 struct list_head i_snap_realm_item; 385 struct list_head i_snap_realm_item;
388 struct list_head i_snap_flush_item; 386 struct list_head i_snap_flush_item;
389 387
390 struct work_struct i_wb_work; /* writeback work */ 388 struct work_struct i_work;
391 struct work_struct i_pg_inv_work; /* page invalidation work */ 389 unsigned long i_work_mask;
392
393 struct work_struct i_vmtruncate_work;
394 390
395#ifdef CONFIG_CEPH_FSCACHE 391#ifdef CONFIG_CEPH_FSCACHE
396 struct fscache_cookie *fscache; 392 struct fscache_cookie *fscache;
@@ -513,6 +509,13 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
513 509
514 510
515/* 511/*
512 * Masks of ceph inode work.
513 */
514#define CEPH_I_WORK_WRITEBACK 0 /* writeback */
515#define CEPH_I_WORK_INVALIDATE_PAGES 1 /* invalidate pages */
516#define CEPH_I_WORK_VMTRUNCATE 2 /* vmtruncate */
517
518/*
516 * We set the ERROR_WRITE bit when we start seeing write errors on an inode 519 * We set the ERROR_WRITE bit when we start seeing write errors on an inode
517 * and then clear it when they start succeeding. Note that we do a lockless 520 * and then clear it when they start succeeding. Note that we do a lockless
518 * check first, and only take the lock if it looks like it needs to be changed. 521 * check first, and only take the lock if it looks like it needs to be changed.