From 4149be7bda7e1b922896599dd9cee7a3ed8cf38b Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Sat, 16 Jul 2022 21:35:31 -0700 Subject: fs/lock: Don't allocate file_lock in flock_make_lock(). Two functions, flock syscall and locks_remove_flock(), call flock_make_lock(). It allocates struct file_lock from slab cache if its argument fl is NULL. When we call flock syscall, we pass NULL to allocate memory for struct file_lock. However, we always free it at the end by locks_free_lock(). We need not allocate it and instead should use a local variable as locks_remove_flock() does. Also, the validation for flock_translate_cmd() is not necessary for locks_remove_flock(). So we move the part to flock syscall and make flock_make_lock() return nothing. Signed-off-by: Kuniyuki Iwashima Reviewed-by: Chuck Lever Signed-off-by: Jeff Layton --- fs/locks.c | 46 +++++++++++++++------------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) (limited to 'fs') diff --git a/fs/locks.c b/fs/locks.c index ca28e0e50e56..b134eaefd7d6 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -425,21 +425,9 @@ static inline int flock_translate_cmd(int cmd) { } /* Fill in a file_lock structure with an appropriate FLOCK lock. */ -static struct file_lock * -flock_make_lock(struct file *filp, unsigned int cmd, struct file_lock *fl) +static void flock_make_lock(struct file *filp, struct file_lock *fl, int type) { - int type = flock_translate_cmd(cmd); - - if (type < 0) - return ERR_PTR(type); - - if (fl == NULL) { - fl = locks_alloc_lock(); - if (fl == NULL) - return ERR_PTR(-ENOMEM); - } else { - locks_init_lock(fl); - } + locks_init_lock(fl); fl->fl_file = filp; fl->fl_owner = filp; @@ -447,8 +435,6 @@ flock_make_lock(struct file *filp, unsigned int cmd, struct file_lock *fl) fl->fl_flags = FL_FLOCK; fl->fl_type = type; fl->fl_end = OFFSET_MAX; - - return fl; } static int assign_type(struct file_lock *fl, long type) @@ -2097,10 +2083,9 @@ EXPORT_SYMBOL(locks_lock_inode_wait); */ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) { + int can_sleep, error, unlock, type; struct fd f = fdget(fd); - struct file_lock *lock; - int can_sleep, unlock; - int error; + struct file_lock fl; error = -EBADF; if (!f.file) @@ -2127,28 +2112,27 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) goto out_putf; } - lock = flock_make_lock(f.file, cmd, NULL); - if (IS_ERR(lock)) { - error = PTR_ERR(lock); + type = flock_translate_cmd(cmd); + if (type < 0) { + error = type; goto out_putf; } + flock_make_lock(f.file, &fl, type); + if (can_sleep) - lock->fl_flags |= FL_SLEEP; + fl.fl_flags |= FL_SLEEP; - error = security_file_lock(f.file, lock->fl_type); + error = security_file_lock(f.file, fl.fl_type); if (error) - goto out_free; + goto out_putf; if (f.file->f_op->flock) error = f.file->f_op->flock(f.file, (can_sleep) ? F_SETLKW : F_SETLK, - lock); + &fl); else - error = locks_lock_file_wait(f.file, lock); - - out_free: - locks_free_lock(lock); + error = locks_lock_file_wait(f.file, &fl); out_putf: fdput(f); @@ -2614,7 +2598,7 @@ locks_remove_flock(struct file *filp, struct file_lock_context *flctx) if (list_empty(&flctx->flc_flock)) return; - flock_make_lock(filp, LOCK_UN, &fl); + flock_make_lock(filp, &fl, F_UNLCK); fl.fl_flags |= FL_CLOSE; if (filp->f_op->flock) -- cgit v1.2.3 From db4abb4a32ec979ea5deea4d0095fa22ec99a623 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Sat, 16 Jul 2022 21:35:32 -0700 Subject: fs/lock: Rearrange ops in flock syscall. The previous patch added flock_translate_cmd() in flock syscall. The test and the other one for LOCK_MAND do not depend on struct fd and are cheaper, so we can put them at the top and defer fdget() after that. Also, we can remove the unlock variable and use type instead. While at it, we fix this checkpatch error. CHECK: spaces preferred around that '|' (ctx:VxV) #45: FILE: fs/locks.c:2099: + if (type != F_UNLCK && !(f.file->f_mode & (FMODE_READ|FMODE_WRITE))) ^ Finally, we can move the can_sleep part just before we use it. Signed-off-by: Kuniyuki Iwashima Signed-off-by: Jeff Layton --- fs/locks.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) (limited to 'fs') diff --git a/fs/locks.c b/fs/locks.c index b134eaefd7d6..c266cfdc3291 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -2083,20 +2083,9 @@ EXPORT_SYMBOL(locks_lock_inode_wait); */ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) { - int can_sleep, error, unlock, type; - struct fd f = fdget(fd); + int can_sleep, error, type; struct file_lock fl; - - error = -EBADF; - if (!f.file) - goto out; - - can_sleep = !(cmd & LOCK_NB); - cmd &= ~LOCK_NB; - unlock = (cmd == LOCK_UN); - - if (!unlock && !(f.file->f_mode & (FMODE_READ|FMODE_WRITE))) - goto out_putf; + struct fd f; /* * LOCK_MAND locks were broken for a long time in that they never @@ -2108,35 +2097,41 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) */ if (cmd & LOCK_MAND) { pr_warn_once("Attempt to set a LOCK_MAND lock via flock(2). This support has been removed and the request ignored.\n"); - error = 0; - goto out_putf; + return 0; } - type = flock_translate_cmd(cmd); - if (type < 0) { - error = type; + type = flock_translate_cmd(cmd & ~LOCK_NB); + if (type < 0) + return type; + + error = -EBADF; + f = fdget(fd); + if (!f.file) + return error; + + if (type != F_UNLCK && !(f.file->f_mode & (FMODE_READ | FMODE_WRITE))) goto out_putf; - } flock_make_lock(f.file, &fl, type); - if (can_sleep) - fl.fl_flags |= FL_SLEEP; - error = security_file_lock(f.file, fl.fl_type); if (error) goto out_putf; + can_sleep = !(cmd & LOCK_NB); + if (can_sleep) + fl.fl_flags |= FL_SLEEP; + if (f.file->f_op->flock) error = f.file->f_op->flock(f.file, - (can_sleep) ? F_SETLKW : F_SETLK, + (can_sleep) ? F_SETLKW : F_SETLK, &fl); else error = locks_lock_file_wait(f.file, &fl); out_putf: fdput(f); - out: + return error; } -- cgit v1.2.3