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 | |
| parent | 90478939dce096ed5b239cad16237dca0a59d66f (diff) | |
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')
| -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); | |||
| 1912 | extern void ihold(struct inode * inode); | 1912 | extern void ihold(struct inode * inode); |
| 1913 | extern void iput(struct inode *); | 1913 | extern void iput(struct inode *); |
| 1914 | 1914 | ||
| 1915 | static inline struct inode *file_inode(struct file *f) | ||
| 1916 | { | ||
| 1917 | return f->f_inode; | ||
| 1918 | } | ||
| 1919 | |||
| 1915 | /* /sys/fs */ | 1920 | /* /sys/fs */ |
| 1916 | extern struct kobject *fs_kobj; | 1921 | extern struct kobject *fs_kobj; |
| 1917 | 1922 | ||
| @@ -1921,7 +1926,7 @@ extern struct kobject *fs_kobj; | |||
| 1921 | #define FLOCK_VERIFY_WRITE 2 | 1926 | #define FLOCK_VERIFY_WRITE 2 |
| 1922 | 1927 | ||
| 1923 | #ifdef CONFIG_FILE_LOCKING | 1928 | #ifdef CONFIG_FILE_LOCKING |
| 1924 | extern int locks_mandatory_locked(struct inode *); | 1929 | extern int locks_mandatory_locked(struct file *); |
| 1925 | extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t); | 1930 | extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t); |
| 1926 | 1931 | ||
| 1927 | /* | 1932 | /* |
| @@ -1944,10 +1949,10 @@ static inline int mandatory_lock(struct inode *ino) | |||
| 1944 | return IS_MANDLOCK(ino) && __mandatory_lock(ino); | 1949 | return IS_MANDLOCK(ino) && __mandatory_lock(ino); |
| 1945 | } | 1950 | } |
| 1946 | 1951 | ||
| 1947 | static inline int locks_verify_locked(struct inode *inode) | 1952 | static inline int locks_verify_locked(struct file *file) |
| 1948 | { | 1953 | { |
| 1949 | if (mandatory_lock(inode)) | 1954 | if (mandatory_lock(file_inode(file))) |
| 1950 | return locks_mandatory_locked(inode); | 1955 | return locks_mandatory_locked(file); |
| 1951 | return 0; | 1956 | return 0; |
| 1952 | } | 1957 | } |
| 1953 | 1958 | ||
| @@ -2008,7 +2013,7 @@ static inline int break_deleg_wait(struct inode **delegated_inode) | |||
| 2008 | } | 2013 | } |
| 2009 | 2014 | ||
| 2010 | #else /* !CONFIG_FILE_LOCKING */ | 2015 | #else /* !CONFIG_FILE_LOCKING */ |
| 2011 | static inline int locks_mandatory_locked(struct inode *inode) | 2016 | static inline int locks_mandatory_locked(struct file *file) |
| 2012 | { | 2017 | { |
| 2013 | return 0; | 2018 | return 0; |
| 2014 | } | 2019 | } |
| @@ -2030,7 +2035,7 @@ static inline int mandatory_lock(struct inode *inode) | |||
| 2030 | return 0; | 2035 | return 0; |
| 2031 | } | 2036 | } |
| 2032 | 2037 | ||
| 2033 | static inline int locks_verify_locked(struct inode *inode) | 2038 | static inline int locks_verify_locked(struct file *file) |
| 2034 | { | 2039 | { |
| 2035 | return 0; | 2040 | return 0; |
| 2036 | } | 2041 | } |
| @@ -2297,11 +2302,6 @@ static inline bool execute_ok(struct inode *inode) | |||
| 2297 | return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode); | 2302 | return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode); |
| 2298 | } | 2303 | } |
| 2299 | 2304 | ||
| 2300 | static inline struct inode *file_inode(struct file *f) | ||
| 2301 | { | ||
| 2302 | return f->f_inode; | ||
| 2303 | } | ||
| 2304 | |||
| 2305 | static inline void file_start_write(struct file *file) | 2305 | static inline void file_start_write(struct file *file) |
| 2306 | { | 2306 | { |
| 2307 | if (!S_ISREG(file_inode(file)->i_mode)) | 2307 | if (!S_ISREG(file_inode(file)->i_mode)) |
