diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2009-04-14 13:48:41 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-04-15 06:10:12 -0400 |
commit | 61e0d47c33cc371f725bcda4a47ae0efe652dba8 (patch) | |
tree | e00f99b506f1c1a16e3ba987e3390deda6bd2e03 | |
parent | f8cc774ce4844811a55e2352f1443055e3994e28 (diff) |
splice: add helpers for locking pipe inode
There are lots of sequences like this, especially in splice code:
if (pipe->inode)
mutex_lock(&pipe->inode->i_mutex);
/* do something */
if (pipe->inode)
mutex_unlock(&pipe->inode->i_mutex);
so introduce helpers which do the conditional locking and unlocking.
Also replace the inode_double_lock() call with a pipe_double_lock()
helper to avoid spreading the use of this functionality beyond the
pipe code.
This patch is just a cleanup, and should cause no behavioral changes.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | fs/inode.c | 36 | ||||
-rw-r--r-- | fs/pipe.c | 42 | ||||
-rw-r--r-- | fs/splice.c | 50 | ||||
-rw-r--r-- | include/linux/fs.h | 3 | ||||
-rw-r--r-- | include/linux/pipe_fs_i.h | 5 |
5 files changed, 64 insertions, 72 deletions
diff --git a/fs/inode.c b/fs/inode.c index d06d6d268de9..6ad14a1cd8c9 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1470,42 +1470,6 @@ static void __wait_on_freeing_inode(struct inode *inode) | |||
1470 | spin_lock(&inode_lock); | 1470 | spin_lock(&inode_lock); |
1471 | } | 1471 | } |
1472 | 1472 | ||
1473 | /* | ||
1474 | * We rarely want to lock two inodes that do not have a parent/child | ||
1475 | * relationship (such as directory, child inode) simultaneously. The | ||
1476 | * vast majority of file systems should be able to get along fine | ||
1477 | * without this. Do not use these functions except as a last resort. | ||
1478 | */ | ||
1479 | void inode_double_lock(struct inode *inode1, struct inode *inode2) | ||
1480 | { | ||
1481 | if (inode1 == NULL || inode2 == NULL || inode1 == inode2) { | ||
1482 | if (inode1) | ||
1483 | mutex_lock(&inode1->i_mutex); | ||
1484 | else if (inode2) | ||
1485 | mutex_lock(&inode2->i_mutex); | ||
1486 | return; | ||
1487 | } | ||
1488 | |||
1489 | if (inode1 < inode2) { | ||
1490 | mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); | ||
1491 | mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); | ||
1492 | } else { | ||
1493 | mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT); | ||
1494 | mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD); | ||
1495 | } | ||
1496 | } | ||
1497 | EXPORT_SYMBOL(inode_double_lock); | ||
1498 | |||
1499 | void inode_double_unlock(struct inode *inode1, struct inode *inode2) | ||
1500 | { | ||
1501 | if (inode1) | ||
1502 | mutex_unlock(&inode1->i_mutex); | ||
1503 | |||
1504 | if (inode2 && inode2 != inode1) | ||
1505 | mutex_unlock(&inode2->i_mutex); | ||
1506 | } | ||
1507 | EXPORT_SYMBOL(inode_double_unlock); | ||
1508 | |||
1509 | static __initdata unsigned long ihash_entries; | 1473 | static __initdata unsigned long ihash_entries; |
1510 | static int __init set_ihash_entries(char *str) | 1474 | static int __init set_ihash_entries(char *str) |
1511 | { | 1475 | { |
@@ -37,6 +37,42 @@ | |||
37 | * -- Manfred Spraul <manfred@colorfullife.com> 2002-05-09 | 37 | * -- Manfred Spraul <manfred@colorfullife.com> 2002-05-09 |
38 | */ | 38 | */ |
39 | 39 | ||
40 | static void pipe_lock_nested(struct pipe_inode_info *pipe, int subclass) | ||
41 | { | ||
42 | if (pipe->inode) | ||
43 | mutex_lock_nested(&pipe->inode->i_mutex, subclass); | ||
44 | } | ||
45 | |||
46 | void pipe_lock(struct pipe_inode_info *pipe) | ||
47 | { | ||
48 | /* | ||
49 | * pipe_lock() nests non-pipe inode locks (for writing to a file) | ||
50 | */ | ||
51 | pipe_lock_nested(pipe, I_MUTEX_PARENT); | ||
52 | } | ||
53 | EXPORT_SYMBOL(pipe_lock); | ||
54 | |||
55 | void pipe_unlock(struct pipe_inode_info *pipe) | ||
56 | { | ||
57 | if (pipe->inode) | ||
58 | mutex_unlock(&pipe->inode->i_mutex); | ||
59 | } | ||
60 | EXPORT_SYMBOL(pipe_unlock); | ||
61 | |||
62 | void pipe_double_lock(struct pipe_inode_info *pipe1, | ||
63 | struct pipe_inode_info *pipe2) | ||
64 | { | ||
65 | BUG_ON(pipe1 == pipe2); | ||
66 | |||
67 | if (pipe1 < pipe2) { | ||
68 | pipe_lock_nested(pipe1, I_MUTEX_PARENT); | ||
69 | pipe_lock_nested(pipe2, I_MUTEX_CHILD); | ||
70 | } else { | ||
71 | pipe_lock_nested(pipe2, I_MUTEX_CHILD); | ||
72 | pipe_lock_nested(pipe1, I_MUTEX_PARENT); | ||
73 | } | ||
74 | } | ||
75 | |||
40 | /* Drop the inode semaphore and wait for a pipe event, atomically */ | 76 | /* Drop the inode semaphore and wait for a pipe event, atomically */ |
41 | void pipe_wait(struct pipe_inode_info *pipe) | 77 | void pipe_wait(struct pipe_inode_info *pipe) |
42 | { | 78 | { |
@@ -47,12 +83,10 @@ void pipe_wait(struct pipe_inode_info *pipe) | |||
47 | * is considered a noninteractive wait: | 83 | * is considered a noninteractive wait: |
48 | */ | 84 | */ |
49 | prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE); | 85 | prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE); |
50 | if (pipe->inode) | 86 | pipe_unlock(pipe); |
51 | mutex_unlock(&pipe->inode->i_mutex); | ||
52 | schedule(); | 87 | schedule(); |
53 | finish_wait(&pipe->wait, &wait); | 88 | finish_wait(&pipe->wait, &wait); |
54 | if (pipe->inode) | 89 | pipe_lock(pipe); |
55 | mutex_lock(&pipe->inode->i_mutex); | ||
56 | } | 90 | } |
57 | 91 | ||
58 | static int | 92 | static int |
diff --git a/fs/splice.c b/fs/splice.c index 128ee36a719b..5384a90665d0 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -182,8 +182,7 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe, | |||
182 | do_wakeup = 0; | 182 | do_wakeup = 0; |
183 | page_nr = 0; | 183 | page_nr = 0; |
184 | 184 | ||
185 | if (pipe->inode) | 185 | pipe_lock(pipe); |
186 | mutex_lock(&pipe->inode->i_mutex); | ||
187 | 186 | ||
188 | for (;;) { | 187 | for (;;) { |
189 | if (!pipe->readers) { | 188 | if (!pipe->readers) { |
@@ -245,15 +244,13 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe, | |||
245 | pipe->waiting_writers--; | 244 | pipe->waiting_writers--; |
246 | } | 245 | } |
247 | 246 | ||
248 | if (pipe->inode) { | 247 | pipe_unlock(pipe); |
249 | mutex_unlock(&pipe->inode->i_mutex); | ||
250 | 248 | ||
251 | if (do_wakeup) { | 249 | if (do_wakeup) { |
252 | smp_mb(); | 250 | smp_mb(); |
253 | if (waitqueue_active(&pipe->wait)) | 251 | if (waitqueue_active(&pipe->wait)) |
254 | wake_up_interruptible(&pipe->wait); | 252 | wake_up_interruptible(&pipe->wait); |
255 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); | 253 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); |
256 | } | ||
257 | } | 254 | } |
258 | 255 | ||
259 | while (page_nr < spd_pages) | 256 | while (page_nr < spd_pages) |
@@ -801,11 +798,9 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
801 | .u.file = out, | 798 | .u.file = out, |
802 | }; | 799 | }; |
803 | 800 | ||
804 | if (pipe->inode) | 801 | pipe_lock(pipe); |
805 | mutex_lock(&pipe->inode->i_mutex); | ||
806 | ret = __splice_from_pipe(pipe, &sd, actor); | 802 | ret = __splice_from_pipe(pipe, &sd, actor); |
807 | if (pipe->inode) | 803 | pipe_unlock(pipe); |
808 | mutex_unlock(&pipe->inode->i_mutex); | ||
809 | 804 | ||
810 | return ret; | 805 | return ret; |
811 | } | 806 | } |
@@ -837,8 +832,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
837 | }; | 832 | }; |
838 | ssize_t ret; | 833 | ssize_t ret; |
839 | 834 | ||
840 | if (pipe->inode) | 835 | pipe_lock(pipe); |
841 | mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT); | ||
842 | 836 | ||
843 | splice_from_pipe_begin(&sd); | 837 | splice_from_pipe_begin(&sd); |
844 | do { | 838 | do { |
@@ -854,8 +848,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
854 | } while (ret > 0); | 848 | } while (ret > 0); |
855 | splice_from_pipe_end(pipe, &sd); | 849 | splice_from_pipe_end(pipe, &sd); |
856 | 850 | ||
857 | if (pipe->inode) | 851 | pipe_unlock(pipe); |
858 | mutex_unlock(&pipe->inode->i_mutex); | ||
859 | 852 | ||
860 | if (sd.num_spliced) | 853 | if (sd.num_spliced) |
861 | ret = sd.num_spliced; | 854 | ret = sd.num_spliced; |
@@ -1348,8 +1341,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov, | |||
1348 | if (!pipe) | 1341 | if (!pipe) |
1349 | return -EBADF; | 1342 | return -EBADF; |
1350 | 1343 | ||
1351 | if (pipe->inode) | 1344 | pipe_lock(pipe); |
1352 | mutex_lock(&pipe->inode->i_mutex); | ||
1353 | 1345 | ||
1354 | error = ret = 0; | 1346 | error = ret = 0; |
1355 | while (nr_segs) { | 1347 | while (nr_segs) { |
@@ -1404,8 +1396,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov, | |||
1404 | iov++; | 1396 | iov++; |
1405 | } | 1397 | } |
1406 | 1398 | ||
1407 | if (pipe->inode) | 1399 | pipe_unlock(pipe); |
1408 | mutex_unlock(&pipe->inode->i_mutex); | ||
1409 | 1400 | ||
1410 | if (!ret) | 1401 | if (!ret) |
1411 | ret = error; | 1402 | ret = error; |
@@ -1533,7 +1524,7 @@ static int link_ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags) | |||
1533 | return 0; | 1524 | return 0; |
1534 | 1525 | ||
1535 | ret = 0; | 1526 | ret = 0; |
1536 | mutex_lock(&pipe->inode->i_mutex); | 1527 | pipe_lock(pipe); |
1537 | 1528 | ||
1538 | while (!pipe->nrbufs) { | 1529 | while (!pipe->nrbufs) { |
1539 | if (signal_pending(current)) { | 1530 | if (signal_pending(current)) { |
@@ -1551,7 +1542,7 @@ static int link_ipipe_prep(struct pipe_inode_info *pipe, unsigned int flags) | |||
1551 | pipe_wait(pipe); | 1542 | pipe_wait(pipe); |
1552 | } | 1543 | } |
1553 | 1544 | ||
1554 | mutex_unlock(&pipe->inode->i_mutex); | 1545 | pipe_unlock(pipe); |
1555 | return ret; | 1546 | return ret; |
1556 | } | 1547 | } |
1557 | 1548 | ||
@@ -1571,7 +1562,7 @@ static int link_opipe_prep(struct pipe_inode_info *pipe, unsigned int flags) | |||
1571 | return 0; | 1562 | return 0; |
1572 | 1563 | ||
1573 | ret = 0; | 1564 | ret = 0; |
1574 | mutex_lock(&pipe->inode->i_mutex); | 1565 | pipe_lock(pipe); |
1575 | 1566 | ||
1576 | while (pipe->nrbufs >= PIPE_BUFFERS) { | 1567 | while (pipe->nrbufs >= PIPE_BUFFERS) { |
1577 | if (!pipe->readers) { | 1568 | if (!pipe->readers) { |
@@ -1592,7 +1583,7 @@ static int link_opipe_prep(struct pipe_inode_info *pipe, unsigned int flags) | |||
1592 | pipe->waiting_writers--; | 1583 | pipe->waiting_writers--; |
1593 | } | 1584 | } |
1594 | 1585 | ||
1595 | mutex_unlock(&pipe->inode->i_mutex); | 1586 | pipe_unlock(pipe); |
1596 | return ret; | 1587 | return ret; |
1597 | } | 1588 | } |
1598 | 1589 | ||
@@ -1608,10 +1599,10 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
1608 | 1599 | ||
1609 | /* | 1600 | /* |
1610 | * Potential ABBA deadlock, work around it by ordering lock | 1601 | * Potential ABBA deadlock, work around it by ordering lock |
1611 | * grabbing by inode address. Otherwise two different processes | 1602 | * grabbing by pipe info address. Otherwise two different processes |
1612 | * could deadlock (one doing tee from A -> B, the other from B -> A). | 1603 | * could deadlock (one doing tee from A -> B, the other from B -> A). |
1613 | */ | 1604 | */ |
1614 | inode_double_lock(ipipe->inode, opipe->inode); | 1605 | pipe_double_lock(ipipe, opipe); |
1615 | 1606 | ||
1616 | do { | 1607 | do { |
1617 | if (!opipe->readers) { | 1608 | if (!opipe->readers) { |
@@ -1662,7 +1653,8 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
1662 | if (!ret && ipipe->waiting_writers && (flags & SPLICE_F_NONBLOCK)) | 1653 | if (!ret && ipipe->waiting_writers && (flags & SPLICE_F_NONBLOCK)) |
1663 | ret = -EAGAIN; | 1654 | ret = -EAGAIN; |
1664 | 1655 | ||
1665 | inode_double_unlock(ipipe->inode, opipe->inode); | 1656 | pipe_unlock(ipipe); |
1657 | pipe_unlock(opipe); | ||
1666 | 1658 | ||
1667 | /* | 1659 | /* |
1668 | * If we put data in the output pipe, wakeup any potential readers. | 1660 | * If we put data in the output pipe, wakeup any potential readers. |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 907d8f56c6fa..e766be0d4329 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -797,9 +797,6 @@ enum inode_i_mutex_lock_class | |||
797 | I_MUTEX_QUOTA | 797 | I_MUTEX_QUOTA |
798 | }; | 798 | }; |
799 | 799 | ||
800 | extern void inode_double_lock(struct inode *inode1, struct inode *inode2); | ||
801 | extern void inode_double_unlock(struct inode *inode1, struct inode *inode2); | ||
802 | |||
803 | /* | 800 | /* |
804 | * NOTE: in a 32bit arch with a preemptable kernel and | 801 | * NOTE: in a 32bit arch with a preemptable kernel and |
805 | * an UP compile the i_size_read/write must be atomic | 802 | * an UP compile the i_size_read/write must be atomic |
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 8e4120285f72..c8f038554e80 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h | |||
@@ -134,6 +134,11 @@ struct pipe_buf_operations { | |||
134 | memory allocation, whereas PIPE_BUF makes atomicity guarantees. */ | 134 | memory allocation, whereas PIPE_BUF makes atomicity guarantees. */ |
135 | #define PIPE_SIZE PAGE_SIZE | 135 | #define PIPE_SIZE PAGE_SIZE |
136 | 136 | ||
137 | /* Pipe lock and unlock operations */ | ||
138 | void pipe_lock(struct pipe_inode_info *); | ||
139 | void pipe_unlock(struct pipe_inode_info *); | ||
140 | void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); | ||
141 | |||
137 | /* Drop the inode semaphore and wait for a pipe event, atomically */ | 142 | /* Drop the inode semaphore and wait for a pipe event, atomically */ |
138 | void pipe_wait(struct pipe_inode_info *pipe); | 143 | void pipe_wait(struct pipe_inode_info *pipe); |
139 | 144 | ||