diff --git a/fs/inode.c b/fs/inode.c index ff726d99ecc7..259ebf438893 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -2115,6 +2115,47 @@ int file_update_time(struct file *file) } EXPORT_SYMBOL(file_update_time); +/** + * file_modified_flags - handle mandated vfs changes when modifying a file + * @file: file that was modified + * @flags: kiocb flags + * + * When file has been modified ensure that special + * file privileges are removed and time settings are updated. + * + * If IOCB_NOWAIT is set, special file privileges will not be removed and + * time settings will not be updated. It will return -EAGAIN. + * + * Context: Caller must hold the file's inode lock. + * + * Return: 0 on success, negative errno on failure. + */ +static int file_modified_flags(struct file *file, int flags) +{ + int ret; + struct inode *inode = file_inode(file); + struct timespec64 now = current_time(inode); + + /* + * Clear the security bits if the process is not being run by root. + * This keeps people from modifying setuid and setgid binaries. + */ + ret = __file_remove_privs(file, flags); + if (ret) + return ret; + + if (unlikely(file->f_mode & FMODE_NOCMTIME)) + return 0; + + ret = inode_needs_update_time(inode, &now); + if (ret <= 0) + return ret; + if (flags & IOCB_NOWAIT) + return -EAGAIN; + + return __file_update_time(file, &now, ret); +} + /** * file_modified - handle mandated vfs changes when modifying a file * @file: file that was modified @@ -2128,29 +2169,27 @@ EXPORT_SYMBOL(file_update_time); */ int file_modified(struct file *file) { - int ret; - struct inode *inode = file_inode(file); - struct timespec64 now = current_time(inode); - - /* - * Clear the security bits if the process is not being run by root. - * This keeps people from modifying setuid and setgid binaries. - */ - ret = __file_remove_privs(file, 0); - if (ret) - return ret; - - if (unlikely(file->f_mode & FMODE_NOCMTIME)) - return 0; - - ret = inode_needs_update_time(inode, &now); - if (ret <= 0) - return ret; - - return __file_update_time(file, &now, ret); + return file_modified_flags(file, 0); } EXPORT_SYMBOL(file_modified); +/** + * kiocb_modified - handle mandated vfs changes when modifying a file + * @iocb: iocb that was modified + * + * When file has been modified ensure that special + * file privileges are removed and time settings are updated. + * + * Context: Caller must hold the file's inode lock. + * + * Return: 0 on success, negative errno on failure. + */ +int kiocb_modified(struct kiocb *iocb) +{ + return file_modified_flags(iocb->ki_filp, iocb->ki_flags); +} +EXPORT_SYMBOL_GPL(kiocb_modified); + int inode_needs_sync(struct inode *inode) { if (IS_SYNC(inode)) diff --git a/include/linux/fs.h b/include/linux/fs.h index bc84847c201e..c0d99b5a166b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2390,6 +2390,7 @@ static inline void file_accessed(struct file *file) } extern int file_modified(struct file *file); +int kiocb_modified(struct kiocb *iocb); int sync_inode_metadata(struct inode *inode, int wait);