aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_aops.c39
-rw-r--r--fs/xfs/xfs_aops.h2
-rw-r--r--fs/xfs/xfs_buf.c17
-rw-r--r--fs/xfs/xfs_mount.h3
-rw-r--r--fs/xfs/xfs_super.c39
5 files changed, 51 insertions, 49 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 74b9baf36ac..540a01742c6 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -126,21 +126,15 @@ static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend)
126 126
127/* 127/*
128 * Update on-disk file size now that data has been written to disk. 128 * Update on-disk file size now that data has been written to disk.
129 *
130 * This function does not block as blocking on the inode lock in IO completion
131 * can lead to IO completion order dependency deadlocks.. If it can't get the
132 * inode ilock it will return EAGAIN. Callers must handle this.
133 */ 129 */
134STATIC int 130STATIC void
135xfs_setfilesize( 131xfs_setfilesize(
136 xfs_ioend_t *ioend) 132 struct xfs_ioend *ioend)
137{ 133{
138 xfs_inode_t *ip = XFS_I(ioend->io_inode); 134 struct xfs_inode *ip = XFS_I(ioend->io_inode);
139 xfs_fsize_t isize; 135 xfs_fsize_t isize;
140 136
141 if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) 137 xfs_ilock(ip, XFS_ILOCK_EXCL);
142 return EAGAIN;
143
144 isize = xfs_ioend_new_eof(ioend); 138 isize = xfs_ioend_new_eof(ioend);
145 if (isize) { 139 if (isize) {
146 trace_xfs_setfilesize(ip, ioend->io_offset, ioend->io_size); 140 trace_xfs_setfilesize(ip, ioend->io_offset, ioend->io_size);
@@ -149,7 +143,6 @@ xfs_setfilesize(
149 } 143 }
150 144
151 xfs_iunlock(ip, XFS_ILOCK_EXCL); 145 xfs_iunlock(ip, XFS_ILOCK_EXCL);
152 return 0;
153} 146}
154 147
155/* 148/*
@@ -163,10 +156,12 @@ xfs_finish_ioend(
163 struct xfs_ioend *ioend) 156 struct xfs_ioend *ioend)
164{ 157{
165 if (atomic_dec_and_test(&ioend->io_remaining)) { 158 if (atomic_dec_and_test(&ioend->io_remaining)) {
159 struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount;
160
166 if (ioend->io_type == IO_UNWRITTEN) 161 if (ioend->io_type == IO_UNWRITTEN)
167 queue_work(xfsconvertd_workqueue, &ioend->io_work); 162 queue_work(mp->m_unwritten_workqueue, &ioend->io_work);
168 else if (xfs_ioend_is_append(ioend)) 163 else if (xfs_ioend_is_append(ioend))
169 queue_work(xfsdatad_workqueue, &ioend->io_work); 164 queue_work(mp->m_data_workqueue, &ioend->io_work);
170 else 165 else
171 xfs_destroy_ioend(ioend); 166 xfs_destroy_ioend(ioend);
172 } 167 }
@@ -207,23 +202,9 @@ xfs_end_io(
207 * We might have to update the on-disk file size after extending 202 * We might have to update the on-disk file size after extending
208 * writes. 203 * writes.
209 */ 204 */
210 error = xfs_setfilesize(ioend); 205 xfs_setfilesize(ioend);
211 ASSERT(!error || error == EAGAIN);
212
213done: 206done:
214 /* 207 xfs_destroy_ioend(ioend);
215 * If we didn't complete processing of the ioend, requeue it to the
216 * tail of the workqueue for another attempt later. Otherwise destroy
217 * it.
218 */
219 if (error == EAGAIN) {
220 atomic_inc(&ioend->io_remaining);
221 xfs_finish_ioend(ioend);
222 /* ensure we don't spin on blocked ioends */
223 delay(1);
224 } else {
225 xfs_destroy_ioend(ioend);
226 }
227} 208}
228 209
229/* 210/*
diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h
index 116dd5c3703..06e4caf3820 100644
--- a/fs/xfs/xfs_aops.h
+++ b/fs/xfs/xfs_aops.h
@@ -18,8 +18,6 @@
18#ifndef __XFS_AOPS_H__ 18#ifndef __XFS_AOPS_H__
19#define __XFS_AOPS_H__ 19#define __XFS_AOPS_H__
20 20
21extern struct workqueue_struct *xfsdatad_workqueue;
22extern struct workqueue_struct *xfsconvertd_workqueue;
23extern mempool_t *xfs_ioend_pool; 21extern mempool_t *xfs_ioend_pool;
24 22
25/* 23/*
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 4dff85c7d7e..6819b5163e3 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -45,8 +45,6 @@ static kmem_zone_t *xfs_buf_zone;
45STATIC int xfsbufd(void *); 45STATIC int xfsbufd(void *);
46 46
47static struct workqueue_struct *xfslogd_workqueue; 47static struct workqueue_struct *xfslogd_workqueue;
48struct workqueue_struct *xfsdatad_workqueue;
49struct workqueue_struct *xfsconvertd_workqueue;
50 48
51#ifdef XFS_BUF_LOCK_TRACKING 49#ifdef XFS_BUF_LOCK_TRACKING
52# define XB_SET_OWNER(bp) ((bp)->b_last_holder = current->pid) 50# define XB_SET_OWNER(bp) ((bp)->b_last_holder = current->pid)
@@ -1793,21 +1791,8 @@ xfs_buf_init(void)
1793 if (!xfslogd_workqueue) 1791 if (!xfslogd_workqueue)
1794 goto out_free_buf_zone; 1792 goto out_free_buf_zone;
1795 1793
1796 xfsdatad_workqueue = alloc_workqueue("xfsdatad", WQ_MEM_RECLAIM, 1);
1797 if (!xfsdatad_workqueue)
1798 goto out_destroy_xfslogd_workqueue;
1799
1800 xfsconvertd_workqueue = alloc_workqueue("xfsconvertd",
1801 WQ_MEM_RECLAIM, 1);
1802 if (!xfsconvertd_workqueue)
1803 goto out_destroy_xfsdatad_workqueue;
1804
1805 return 0; 1794 return 0;
1806 1795
1807 out_destroy_xfsdatad_workqueue:
1808 destroy_workqueue(xfsdatad_workqueue);
1809 out_destroy_xfslogd_workqueue:
1810 destroy_workqueue(xfslogd_workqueue);
1811 out_free_buf_zone: 1796 out_free_buf_zone:
1812 kmem_zone_destroy(xfs_buf_zone); 1797 kmem_zone_destroy(xfs_buf_zone);
1813 out: 1798 out:
@@ -1817,8 +1802,6 @@ xfs_buf_init(void)
1817void 1802void
1818xfs_buf_terminate(void) 1803xfs_buf_terminate(void)
1819{ 1804{
1820 destroy_workqueue(xfsconvertd_workqueue);
1821 destroy_workqueue(xfsdatad_workqueue);
1822 destroy_workqueue(xfslogd_workqueue); 1805 destroy_workqueue(xfslogd_workqueue);
1823 kmem_zone_destroy(xfs_buf_zone); 1806 kmem_zone_destroy(xfs_buf_zone);
1824} 1807}
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index c082e44dad2..9eba7388782 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -211,6 +211,9 @@ typedef struct xfs_mount {
211 struct shrinker m_inode_shrink; /* inode reclaim shrinker */ 211 struct shrinker m_inode_shrink; /* inode reclaim shrinker */
212 int64_t m_low_space[XFS_LOWSP_MAX]; 212 int64_t m_low_space[XFS_LOWSP_MAX];
213 /* low free space thresholds */ 213 /* low free space thresholds */
214
215 struct workqueue_struct *m_data_workqueue;
216 struct workqueue_struct *m_unwritten_workqueue;
214} xfs_mount_t; 217} xfs_mount_t;
215 218
216/* 219/*
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 5e0d43f231a..c7f7bc2855a 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -759,6 +759,36 @@ xfs_setup_devices(
759 return 0; 759 return 0;
760} 760}
761 761
762STATIC int
763xfs_init_mount_workqueues(
764 struct xfs_mount *mp)
765{
766 mp->m_data_workqueue = alloc_workqueue("xfs-data/%s",
767 WQ_MEM_RECLAIM, 0, mp->m_fsname);
768 if (!mp->m_data_workqueue)
769 goto out;
770
771 mp->m_unwritten_workqueue = alloc_workqueue("xfs-conv/%s",
772 WQ_MEM_RECLAIM, 0, mp->m_fsname);
773 if (!mp->m_unwritten_workqueue)
774 goto out_destroy_data_iodone_queue;
775
776 return 0;
777
778out_destroy_data_iodone_queue:
779 destroy_workqueue(mp->m_data_workqueue);
780out:
781 return -ENOMEM;
782}
783
784STATIC void
785xfs_destroy_mount_workqueues(
786 struct xfs_mount *mp)
787{
788 destroy_workqueue(mp->m_data_workqueue);
789 destroy_workqueue(mp->m_unwritten_workqueue);
790}
791
762/* Catch misguided souls that try to use this interface on XFS */ 792/* Catch misguided souls that try to use this interface on XFS */
763STATIC struct inode * 793STATIC struct inode *
764xfs_fs_alloc_inode( 794xfs_fs_alloc_inode(
@@ -982,6 +1012,7 @@ xfs_fs_put_super(
982 xfs_unmountfs(mp); 1012 xfs_unmountfs(mp);
983 xfs_freesb(mp); 1013 xfs_freesb(mp);
984 xfs_icsb_destroy_counters(mp); 1014 xfs_icsb_destroy_counters(mp);
1015 xfs_destroy_mount_workqueues(mp);
985 xfs_close_devices(mp); 1016 xfs_close_devices(mp);
986 xfs_free_fsname(mp); 1017 xfs_free_fsname(mp);
987 kfree(mp); 1018 kfree(mp);
@@ -1308,10 +1339,14 @@ xfs_fs_fill_super(
1308 if (error) 1339 if (error)
1309 goto out_free_fsname; 1340 goto out_free_fsname;
1310 1341
1311 error = xfs_icsb_init_counters(mp); 1342 error = xfs_init_mount_workqueues(mp);
1312 if (error) 1343 if (error)
1313 goto out_close_devices; 1344 goto out_close_devices;
1314 1345
1346 error = xfs_icsb_init_counters(mp);
1347 if (error)
1348 goto out_destroy_workqueues;
1349
1315 error = xfs_readsb(mp, flags); 1350 error = xfs_readsb(mp, flags);
1316 if (error) 1351 if (error)
1317 goto out_destroy_counters; 1352 goto out_destroy_counters;
@@ -1374,6 +1409,8 @@ xfs_fs_fill_super(
1374 xfs_freesb(mp); 1409 xfs_freesb(mp);
1375 out_destroy_counters: 1410 out_destroy_counters:
1376 xfs_icsb_destroy_counters(mp); 1411 xfs_icsb_destroy_counters(mp);
1412out_destroy_workqueues:
1413 xfs_destroy_mount_workqueues(mp);
1377 out_close_devices: 1414 out_close_devices:
1378 xfs_close_devices(mp); 1415 xfs_close_devices(mp);
1379 out_free_fsname: 1416 out_free_fsname: