diff options
author | Jeff Layton <jlayton@redhat.com> | 2014-03-10 09:54:15 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@redhat.com> | 2014-03-31 08:24:43 -0400 |
commit | d7a06983a01a33605191c0766857b832ac32a2b6 (patch) | |
tree | d6a0f83579e0d7a20a235ddb568d935fe54b24fb /include/linux/fs.h | |
parent | 90478939dce096ed5b239cad16237dca0a59d66f (diff) | |
download | linux-stable-d7a06983a01a33605191c0766857b832ac32a2b6.tar.gz linux-stable-d7a06983a01a33605191c0766857b832ac32a2b6.tar.bz2 linux-stable-d7a06983a01a33605191c0766857b832ac32a2b6.zip |
locks: fix locks_mandatory_locked to respect file-private locks
As Trond pointed out, you can currently deadlock yourself by setting a
file-private lock on a file that requires mandatory locking and then
trying to do I/O on it.
Avoid this problem by plumbing some knowledge of file-private locks into
the mandatory locking code. In order to do this, we must pass down
information about the struct file that's being used to
locks_verify_locked.
Reported-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Acked-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'include/linux/fs.h')
-rw-r--r-- | include/linux/fs.h | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h index ae91dce8a547..4aa81e6ae067 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1912,6 +1912,11 @@ extern int current_umask(void); extern void ihold(struct inode * inode); extern void iput(struct inode *); +static inline struct inode *file_inode(struct file *f) +{ + return f->f_inode; +} + /* /sys/fs */ extern struct kobject *fs_kobj; @@ -1921,7 +1926,7 @@ extern struct kobject *fs_kobj; #define FLOCK_VERIFY_WRITE 2 #ifdef CONFIG_FILE_LOCKING -extern int locks_mandatory_locked(struct inode *); +extern int locks_mandatory_locked(struct file *); extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t); /* @@ -1944,10 +1949,10 @@ static inline int mandatory_lock(struct inode *ino) return IS_MANDLOCK(ino) && __mandatory_lock(ino); } -static inline int locks_verify_locked(struct inode *inode) +static inline int locks_verify_locked(struct file *file) { - if (mandatory_lock(inode)) - return locks_mandatory_locked(inode); + if (mandatory_lock(file_inode(file))) + return locks_mandatory_locked(file); return 0; } @@ -2008,7 +2013,7 @@ static inline int break_deleg_wait(struct inode **delegated_inode) } #else /* !CONFIG_FILE_LOCKING */ -static inline int locks_mandatory_locked(struct inode *inode) +static inline int locks_mandatory_locked(struct file *file) { return 0; } @@ -2030,7 +2035,7 @@ static inline int mandatory_lock(struct inode *inode) return 0; } -static inline int locks_verify_locked(struct inode *inode) +static inline int locks_verify_locked(struct file *file) { return 0; } @@ -2297,11 +2302,6 @@ static inline bool execute_ok(struct inode *inode) return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode); } -static inline struct inode *file_inode(struct file *f) -{ - return f->f_inode; -} - static inline void file_start_write(struct file *file) { if (!S_ISREG(file_inode(file)->i_mode)) |