diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-15 09:03:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-15 09:03:47 -0700 |
commit | 23da64b4714812b66ecf010e7dfb3ed1bf2eda69 (patch) | |
tree | e2736bebc916cb540b0da83296d62b342612ecbd /fs/pipe.c | |
parent | a23c218bd36e11120daf18e00a91d5dc20e288e6 (diff) | |
parent | a36e71f996e25d6213f57951f7ae1874086ec57e (diff) |
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/linux-2.6-block: (28 commits)
cfq-iosched: add close cooperator code
cfq-iosched: log responsible 'cfqq' in idle timer arm
cfq-iosched: tweak kick logic a bit more
cfq-iosched: no need to save interrupts in cfq_kick_queue()
brd: fix cacheflushing
brd: support barriers
swap: Remove code handling bio_alloc failure with __GFP_WAIT
gfs2: Remove code handling bio_alloc failure with __GFP_WAIT
ext4: Remove code handling bio_alloc failure with __GFP_WAIT
dio: Remove code handling bio_alloc failure with __GFP_WAIT
block: Remove code handling bio_alloc failure with __GFP_WAIT
bio: add documentation to bio_alloc()
splice: add helpers for locking pipe inode
splice: remove generic_file_splice_write_nolock()
ocfs2: fix i_mutex locking in ocfs2_splice_to_file()
splice: fix i_mutex locking in generic_splice_write()
splice: remove i_mutex locking in splice_from_pipe()
splice: split up __splice_from_pipe()
block: fix SG_IO to return a proper error value
cfq-iosched: don't delay queue kick for a merged request
...
Diffstat (limited to 'fs/pipe.c')
-rw-r--r-- | fs/pipe.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/fs/pipe.c b/fs/pipe.c index 4af7aa52181..13414ec45b8 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -37,6 +37,42 @@ * -- Manfred Spraul <manfred@colorfullife.com> 2002-05-09 */ +static void pipe_lock_nested(struct pipe_inode_info *pipe, int subclass) +{ + if (pipe->inode) + mutex_lock_nested(&pipe->inode->i_mutex, subclass); +} + +void pipe_lock(struct pipe_inode_info *pipe) +{ + /* + * pipe_lock() nests non-pipe inode locks (for writing to a file) + */ + pipe_lock_nested(pipe, I_MUTEX_PARENT); +} +EXPORT_SYMBOL(pipe_lock); + +void pipe_unlock(struct pipe_inode_info *pipe) +{ + if (pipe->inode) + mutex_unlock(&pipe->inode->i_mutex); +} +EXPORT_SYMBOL(pipe_unlock); + +void pipe_double_lock(struct pipe_inode_info *pipe1, + struct pipe_inode_info *pipe2) +{ + BUG_ON(pipe1 == pipe2); + + if (pipe1 < pipe2) { + pipe_lock_nested(pipe1, I_MUTEX_PARENT); + pipe_lock_nested(pipe2, I_MUTEX_CHILD); + } else { + pipe_lock_nested(pipe2, I_MUTEX_CHILD); + pipe_lock_nested(pipe1, I_MUTEX_PARENT); + } +} + /* Drop the inode semaphore and wait for a pipe event, atomically */ void pipe_wait(struct pipe_inode_info *pipe) { @@ -47,12 +83,10 @@ void pipe_wait(struct pipe_inode_info *pipe) * is considered a noninteractive wait: */ prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE); - if (pipe->inode) - mutex_unlock(&pipe->inode->i_mutex); + pipe_unlock(pipe); schedule(); finish_wait(&pipe->wait, &wait); - if (pipe->inode) - mutex_lock(&pipe->inode->i_mutex); + pipe_lock(pipe); } static int |