quota: Change quotactl_path() systcall to an fd-based one
Some users have pointed out that path-based syscalls are problematic in some environments and at least directory fd argument and possibly also resolve flags are desirable for such syscalls. Rather than reimplementing all details of pathname lookup and following where it may eventually evolve, let's go for full file descriptor based syscall similar to how ioctl(2) works since the beginning. Managing of quotas isn't performance sensitive so the extra overhead of open does not matter and we are able to consume O_PATH descriptors as well which makes open cheap anyway. Also for frequent operations (such as retrieving usage information for all users) we can reuse single fd and in fact get even better performance as well as avoiding races with possible remounts etc. Tested-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Christian Brauner <christian.brauner@ubuntu.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
21e4e15a84
commit
64c2c2c62f
@ -968,31 +968,30 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE4(quotactl_path, unsigned int, cmd, const char __user *,
|
||||
mountpoint, qid_t, id, void __user *, addr)
|
||||
SYSCALL_DEFINE4(quotactl_fd, unsigned int, fd, unsigned int, cmd,
|
||||
qid_t, id, void __user *, addr)
|
||||
{
|
||||
struct super_block *sb;
|
||||
struct path mountpath;
|
||||
unsigned int cmds = cmd >> SUBCMDSHIFT;
|
||||
unsigned int type = cmd & SUBCMDMASK;
|
||||
struct fd f;
|
||||
int ret;
|
||||
|
||||
f = fdget_raw(fd);
|
||||
if (!f.file)
|
||||
return -EBADF;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (type >= MAXQUOTAS)
|
||||
return -EINVAL;
|
||||
|
||||
ret = user_path_at(AT_FDCWD, mountpoint,
|
||||
LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT, &mountpath);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sb = mountpath.mnt->mnt_sb;
|
||||
goto out;
|
||||
|
||||
if (quotactl_cmd_write(cmds)) {
|
||||
ret = mnt_want_write(mountpath.mnt);
|
||||
ret = mnt_want_write(f.file->f_path.mnt);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sb = f.file->f_path.mnt->mnt_sb;
|
||||
if (quotactl_cmd_onoff(cmds))
|
||||
down_write(&sb->s_umount);
|
||||
else
|
||||
@ -1006,9 +1005,8 @@ SYSCALL_DEFINE4(quotactl_path, unsigned int, cmd, const char __user *,
|
||||
up_read(&sb->s_umount);
|
||||
|
||||
if (quotactl_cmd_write(cmds))
|
||||
mnt_drop_write(mountpath.mnt);
|
||||
mnt_drop_write(f.file->f_path.mnt);
|
||||
out:
|
||||
path_put(&mountpath);
|
||||
|
||||
fdput(f);
|
||||
return ret;
|
||||
}
|
||||
|
@ -485,8 +485,8 @@ asmlinkage long sys_pipe2(int __user *fildes, int flags);
|
||||
/* fs/quota.c */
|
||||
asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special,
|
||||
qid_t id, void __user *addr);
|
||||
asmlinkage long sys_quotactl_path(unsigned int cmd, const char __user *mountpoint,
|
||||
qid_t id, void __user *addr);
|
||||
asmlinkage long sys_quotactl_fd(unsigned int fd, unsigned int cmd, qid_t id,
|
||||
void __user *addr);
|
||||
|
||||
/* fs/readdir.c */
|
||||
asmlinkage long sys_getdents64(unsigned int fd,
|
||||
|
@ -863,8 +863,8 @@ __SYSCALL(__NR_process_madvise, sys_process_madvise)
|
||||
__SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2)
|
||||
#define __NR_mount_setattr 442
|
||||
__SYSCALL(__NR_mount_setattr, sys_mount_setattr)
|
||||
#define __NR_quotactl_path 443
|
||||
__SYSCALL(__NR_quotactl_path, sys_quotactl_path)
|
||||
#define __NR_quotactl_fd 443
|
||||
__SYSCALL(__NR_quotactl_fd, sys_quotactl_fd)
|
||||
|
||||
#define __NR_landlock_create_ruleset 444
|
||||
__SYSCALL(__NR_landlock_create_ruleset, sys_landlock_create_ruleset)
|
||||
|
@ -99,7 +99,7 @@ COND_SYSCALL(flock);
|
||||
|
||||
/* fs/quota.c */
|
||||
COND_SYSCALL(quotactl);
|
||||
COND_SYSCALL(quotactl_path);
|
||||
COND_SYSCALL(quotactl_fd);
|
||||
|
||||
/* fs/readdir.c */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user