diff options
| -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 | ||
