fs/kernel_read_file.c | 6 +++++- include/linux/fs.h | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/fs/kernel_read_file.c b/fs/kernel_read_file.c index 5d826274570c..ff3e894f8cd4 100644 --- a/fs/kernel_read_file.c +++ b/fs/kernel_read_file.c @@ -48,7 +48,11 @@ ssize_t kernel_read_file(struct file *file, loff_t offset, void **buf, if (!S_ISREG(file_inode(file)->i_mode)) return -EINVAL; - ret = deny_write_access(file); + /* Module reading wants *exclusive* access to the file */ + if (id == READING_MODULE) + ret = exclusive_deny_write_access(file); + else + ret = deny_write_access(file); if (ret) return ret; diff --git a/include/linux/fs.h b/include/linux/fs.h index 21a981680856..722b42a77d51 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2566,6 +2566,12 @@ static inline int deny_write_access(struct file *file) struct inode *inode = file_inode(file); return atomic_dec_unless_positive(&inode->i_writecount) ? 0 : -ETXTBSY; } +static inline int exclusive_deny_write_access(struct file *file) +{ + int old = 0; + struct inode *inode = file_inode(file); + return atomic_try_cmpxchg(&inode->i_writecount, &old, -1) ? 0 : -ETXTBSY; +} static inline void put_write_access(struct inode * inode) { atomic_dec(&inode->i_writecount);