Skip to content

Commit 64c2c2c

Browse files
committed
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>
1 parent 21e4e15 commit 64c2c2c

File tree

4 files changed

+18
-20
lines changed

4 files changed

+18
-20
lines changed

fs/quota/quota.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -968,31 +968,30 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
968968
return ret;
969969
}
970970

971-
SYSCALL_DEFINE4(quotactl_path, unsigned int, cmd, const char __user *,
972-
mountpoint, qid_t, id, void __user *, addr)
971+
SYSCALL_DEFINE4(quotactl_fd, unsigned int, fd, unsigned int, cmd,
972+
qid_t, id, void __user *, addr)
973973
{
974974
struct super_block *sb;
975-
struct path mountpath;
976975
unsigned int cmds = cmd >> SUBCMDSHIFT;
977976
unsigned int type = cmd & SUBCMDMASK;
977+
struct fd f;
978978
int ret;
979979

980-
if (type >= MAXQUOTAS)
981-
return -EINVAL;
980+
f = fdget_raw(fd);
981+
if (!f.file)
982+
return -EBADF;
982983

983-
ret = user_path_at(AT_FDCWD, mountpoint,
984-
LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT, &mountpath);
985-
if (ret)
986-
return ret;
987-
988-
sb = mountpath.mnt->mnt_sb;
984+
ret = -EINVAL;
985+
if (type >= MAXQUOTAS)
986+
goto out;
989987

990988
if (quotactl_cmd_write(cmds)) {
991-
ret = mnt_want_write(mountpath.mnt);
989+
ret = mnt_want_write(f.file->f_path.mnt);
992990
if (ret)
993991
goto out;
994992
}
995993

994+
sb = f.file->f_path.mnt->mnt_sb;
996995
if (quotactl_cmd_onoff(cmds))
997996
down_write(&sb->s_umount);
998997
else
@@ -1006,9 +1005,8 @@ SYSCALL_DEFINE4(quotactl_path, unsigned int, cmd, const char __user *,
10061005
up_read(&sb->s_umount);
10071006

10081007
if (quotactl_cmd_write(cmds))
1009-
mnt_drop_write(mountpath.mnt);
1008+
mnt_drop_write(f.file->f_path.mnt);
10101009
out:
1011-
path_put(&mountpath);
1012-
1010+
fdput(f);
10131011
return ret;
10141012
}

include/linux/syscalls.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,8 @@ asmlinkage long sys_pipe2(int __user *fildes, int flags);
485485
/* fs/quota.c */
486486
asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special,
487487
qid_t id, void __user *addr);
488-
asmlinkage long sys_quotactl_path(unsigned int cmd, const char __user *mountpoint,
489-
qid_t id, void __user *addr);
488+
asmlinkage long sys_quotactl_fd(unsigned int fd, unsigned int cmd, qid_t id,
489+
void __user *addr);
490490

491491
/* fs/readdir.c */
492492
asmlinkage long sys_getdents64(unsigned int fd,

include/uapi/asm-generic/unistd.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,8 +863,8 @@ __SYSCALL(__NR_process_madvise, sys_process_madvise)
863863
__SC_COMP(__NR_epoll_pwait2, sys_epoll_pwait2, compat_sys_epoll_pwait2)
864864
#define __NR_mount_setattr 442
865865
__SYSCALL(__NR_mount_setattr, sys_mount_setattr)
866-
#define __NR_quotactl_path 443
867-
__SYSCALL(__NR_quotactl_path, sys_quotactl_path)
866+
#define __NR_quotactl_fd 443
867+
__SYSCALL(__NR_quotactl_fd, sys_quotactl_fd)
868868

869869
#define __NR_landlock_create_ruleset 444
870870
__SYSCALL(__NR_landlock_create_ruleset, sys_landlock_create_ruleset)

kernel/sys_ni.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ COND_SYSCALL(flock);
9999

100100
/* fs/quota.c */
101101
COND_SYSCALL(quotactl);
102-
COND_SYSCALL(quotactl_path);
102+
COND_SYSCALL(quotactl_fd);
103103

104104
/* fs/readdir.c */
105105

0 commit comments

Comments
 (0)