From: Ann Koehler Date: Fri, 8 Feb 2019 21:41:37 +0000 (-0600) Subject: LU-11944 llite: Lock inode on tiny write if setuid/setgid set X-Git-Tag: 2.12.52~14 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=f39a552922ca2db0c6974374fa3a917a34a4a747 LU-11944 llite: Lock inode on tiny write if setuid/setgid set During a write, the setuid/setgid bits must be reset if they are enabled and the user does not have the correct permissions. Setting any file attributes, including setuid and setgid, requires the inode to be locked. Writes became lockless with the introduction of LU-1669. Locking the inode in the setuid/setgid case was added to vvp_io_write_start() as a special case. The inode locking was not included when support for tiny writes was added with LU-9409. This mod adds the necessary inode lock/unlock calls to ll_do_tiny_write(). If the inode is not locked when setuid/setgid are reset, the kernel will issue a one time warning and Lustre may hang trying to get the inode lock in ll_setattr_raw(). Signed-off-by: Ann Koehler Change-Id: I5e8a98789828de52dbff4226958741320aba92e6 Reviewed-on: https://review.whamcloud.com/34218 Reviewed-by: Patrick Farrell Reviewed-by: Ben Evans Tested-by: Jenkins Reviewed-by: James Simmons Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 6af68fa..fe8c450 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1601,8 +1601,9 @@ out: static ssize_t ll_do_tiny_write(struct kiocb *iocb, struct iov_iter *iter) { ssize_t count = iov_iter_count(iter); - struct file *file = iocb->ki_filp; - struct inode *inode = file_inode(file); + struct file *file = iocb->ki_filp; + struct inode *inode = file_inode(file); + bool lock_inode = !IS_NOSEC(inode); ssize_t result = 0; ENTRY; @@ -1614,8 +1615,13 @@ static ssize_t ll_do_tiny_write(struct kiocb *iocb, struct iov_iter *iter) (iocb->ki_pos & (PAGE_SIZE-1)) + count > PAGE_SIZE) RETURN(0); + if (unlikely(lock_inode)) + inode_lock(inode); result = __generic_file_write_iter(iocb, iter); + if (unlikely(lock_inode)) + inode_unlock(inode); + /* If the page is not already dirty, ll_tiny_write_begin returns * -ENODATA. We continue on to normal write. */ diff --git a/lustre/llite/vvp_io.c b/lustre/llite/vvp_io.c index 22bf50e..212ac9d 100644 --- a/lustre/llite/vvp_io.c +++ b/lustre/llite/vvp_io.c @@ -1092,13 +1092,13 @@ static int vvp_io_write_start(const struct lu_env *env, * consistency, proper locking to protect against writes, * trucates, etc. is handled in the higher layers of lustre. */ - bool lock_node = !IS_NOSEC(inode); + lock_inode = !IS_NOSEC(inode); - if (lock_node) + if (unlikely(lock_inode)) inode_lock(inode); result = __generic_file_write_iter(vio->vui_iocb, vio->vui_iter); - if (lock_node) + if (unlikely(lock_inode)) inode_unlock(inode); if (result > 0 || result == -EIOCBQUEUED)