* [PATCH RFC 0/3] Enable tmpfs quotas @ 2024-01-09 13:46 cem 2024-01-09 13:46 ` [PATCH 1/3] Rename searched_dir->sd_dir to sd_isdir cem ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: cem @ 2024-01-09 13:46 UTC (permalink / raw) To: jack; +Cc: linux-fsdevel From: Carlos Maiolino <cem@kernel.org> This series enable quota tools to manage tmpfs user/group quotas now the kernel support is released in 6.6. Honza, this is just a RFC as I'd like to know your input on the approach used here. This series add 2 new helpers, one named do_quotactl(), which switches between quotactl() and quotactl_fd(), and the handle_quota() helper within quotaio, which passes quota_handle data to do_quotactl() depending on the filesystem associated with the mountpoint. The first patch is just a cleanup. So far I just did basic testing on this series, if you are fine with this approach, I'll polish it and quote Lukas as he also worked on it and deserves credit. Thanks! Carlos Maiolino (3): Rename searched_dir->sd_dir to sd_isdir Add quotactl_fd() support Enable support for tmpfs quotas Makefile.am | 1 + mntopt.h | 1 + quotacheck.c | 12 +++---- quotaio.c | 19 +++++++++-- quotaio.h | 2 ++ quotaio_generic.c | 11 +++---- quotaio_meta.c | 3 +- quotaio_v1.c | 11 +++---- quotaio_v2.c | 11 +++---- quotaio_xfs.c | 21 ++++++------ quotaon.c | 8 ++--- quotaon_xfs.c | 9 +++--- quotastats.c | 4 +-- quotasync.c | 2 +- quotasys.c | 81 ++++++++++++++++++++++++++++++++++++----------- quotasys.h | 3 ++ 16 files changed, 133 insertions(+), 66 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/3] Rename searched_dir->sd_dir to sd_isdir 2024-01-09 13:46 [PATCH RFC 0/3] Enable tmpfs quotas cem @ 2024-01-09 13:46 ` cem 2024-01-09 13:46 ` [PATCH 2/3] Add quotactl_fd() support cem 2024-01-09 13:46 ` [PATCH 3/3] Enable support for tmpfs quotas cem 2 siblings, 0 replies; 9+ messages in thread From: cem @ 2024-01-09 13:46 UTC (permalink / raw) To: jack; +Cc: linux-fsdevel From: Carlos Maiolino <cem@kernel.org> The field holds information if we are searching a directory mountpoint or a device, rename the field to something more meaningful. We could switch it to bool, but it seems pointless to include a whole header just for it, so keep the int type. Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> --- quotasys.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quotasys.c b/quotasys.c index 3f50e32..9af9932 100644 --- a/quotasys.c +++ b/quotasys.c @@ -1223,7 +1223,7 @@ int kern_quota_on(struct mount_entry *mnt, int type, int fmt) */ struct searched_dir { - int sd_dir; /* Is searched dir mountpoint or in fact device? */ + int sd_isdir; /* Is searched dir mountpoint or in fact device? */ dev_t sd_dev; /* Device mountpoint lies on */ ino_t sd_ino; /* Inode number of mountpoint */ const char *sd_name; /* Name of given dir/device */ @@ -1454,7 +1454,7 @@ static int process_dirs(int dcnt, char **dirs, int flags) errstr(_("Cannot stat() given mountpoint %s: %s\nSkipping...\n"), dirs[i], strerror(errno)); continue; } - check_dirs[check_dirs_cnt].sd_dir = S_ISDIR(st.st_mode); + check_dirs[check_dirs_cnt].sd_isdir = S_ISDIR(st.st_mode); if (S_ISDIR(st.st_mode)) { const char *realmnt = dirs[i]; @@ -1538,7 +1538,7 @@ restart: return 0; sd = check_dirs + act_checked; for (i = 0; i < mnt_entries_cnt; i++) { - if (sd->sd_dir) { + if (sd->sd_isdir) { if (sd->sd_dev == mnt_entries[i].me_dev && sd->sd_ino == mnt_entries[i].me_ino) break; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/3] Add quotactl_fd() support 2024-01-09 13:46 [PATCH RFC 0/3] Enable tmpfs quotas cem 2024-01-09 13:46 ` [PATCH 1/3] Rename searched_dir->sd_dir to sd_isdir cem @ 2024-01-09 13:46 ` cem 2024-01-17 18:08 ` Jan Kara 2024-01-09 13:46 ` [PATCH 3/3] Enable support for tmpfs quotas cem 2 siblings, 1 reply; 9+ messages in thread From: cem @ 2024-01-09 13:46 UTC (permalink / raw) To: jack; +Cc: linux-fsdevel From: Carlos Maiolino <cem@kernel.org> To be able to set quotas on filesystems without a backing device, quota tools should be able to use quotactl_fd(). To achieve that, add a new helper, do_quotactl(), to select between quotactl() and quotactl_fd(). This shouldn't change the semantics of current code. quotactl_fd() will be called if and only if the handlers contain an empty device, and a valid mountpoint. All current calls containing a value device should be still handled by quotactl(). The same is true for calls passing a NULL device on purpose, aiming to sync active quotas. Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> --- Makefile.am | 1 + quotacheck.c | 12 +++++------ quotaio.c | 4 ++-- quotaio_generic.c | 12 +++++------ quotaio_meta.c | 4 ++-- quotaio_v1.c | 10 ++++----- quotaio_v2.c | 12 +++++------ quotaio_xfs.c | 21 ++++++++++-------- quotaon.c | 8 +++---- quotaon_xfs.c | 9 ++++---- quotastats.c | 4 ++-- quotasync.c | 2 +- quotasys.c | 55 ++++++++++++++++++++++++++++++++++++----------- quotasys.h | 3 +++ 14 files changed, 98 insertions(+), 59 deletions(-) diff --git a/Makefile.am b/Makefile.am index 372eafb..13a0f06 100644 --- a/Makefile.am +++ b/Makefile.am @@ -207,6 +207,7 @@ quotastats_SOURCES = \ pot.h quotastats_LDADD = \ + libquota.a \ $(INTLLIBS) xqmstats_SOURCES = \ diff --git a/quotacheck.c b/quotacheck.c index bd62d9a..e2c3bbd 100644 --- a/quotacheck.c +++ b/quotacheck.c @@ -648,8 +648,8 @@ Please turn quotas off or use -f to force checking.\n"), type2name(type), mnt->me_dir); } /* At least sync quotas so damage will be smaller */ - if (quotactl(QCMD((kernel_iface == IFACE_GENERIC)? Q_SYNC : Q_6_5_SYNC, type), - mnt->me_devname, 0, NULL) < 0) + if (do_quotactl(QCMD((kernel_iface == IFACE_GENERIC)? Q_SYNC : Q_6_5_SYNC, type), + mnt->me_devname, mnt->me_dir, 0, NULL) < 0) die(4, _("Error while syncing quotas on %s: %s\n"), mnt->me_devname, strerror(errno)); } @@ -848,8 +848,8 @@ static int dump_to_file(struct mount_entry *mnt, int type) if (get_qf_name(mnt, type, cfmt, NF_FORMAT, &filename) < 0) errstr(_("Cannot find checked quota file for %ss on %s!\n"), _(type2name(type)), mnt->me_devname); else { - if (quotactl(QCMD((kernel_iface == IFACE_GENERIC) ? Q_QUOTAOFF : Q_6_5_QUOTAOFF, type), - mnt->me_devname, 0, NULL) < 0) + if (do_quotactl(QCMD((kernel_iface == IFACE_GENERIC) ? Q_QUOTAOFF : Q_6_5_QUOTAOFF, type), + mnt->me_devname, mnt->me_dir, 0, NULL) < 0) errstr(_("Cannot turn %s quotas off on %s: %s\nKernel won't know about changes quotacheck did.\n"), _(type2name(type)), mnt->me_devname, strerror(errno)); else { @@ -859,9 +859,9 @@ static int dump_to_file(struct mount_entry *mnt, int type) rename_files(mnt, type); if (kernel_iface == IFACE_GENERIC) - ret = quotactl(QCMD(Q_QUOTAON, type), mnt->me_devname, util2kernfmt(cfmt), filename); + ret = do_quotactl(QCMD(Q_QUOTAON, type), mnt->me_devname, mnt->me_dir, util2kernfmt(cfmt), filename); else - ret = quotactl(QCMD(Q_6_5_QUOTAON, type), mnt->me_devname, 0, filename); + ret = do_quotactl(QCMD(Q_6_5_QUOTAON, type), mnt->me_devname, mnt->me_dir, 0, filename); if (ret < 0) errstr(_("Cannot turn %s quotas on on %s: %s\nKernel won't know about changes quotacheck did.\n"), _(type2name(type)), mnt->me_devname, strerror(errno)); diff --git a/quotaio.c b/quotaio.c index 94ae458..9bebb5e 100644 --- a/quotaio.c +++ b/quotaio.c @@ -140,8 +140,8 @@ struct quota_handle *init_io(struct mount_entry *mnt, int type, int fmt, int fla if (QIO_ENABLED(h)) { /* Kernel uses same file? */ unsigned int cmd = (kernel_iface == IFACE_GENERIC) ? Q_SYNC : Q_6_5_SYNC; - if (quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, - 0, NULL) < 0) { + if (do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, + h->qh_dir, 0, NULL) < 0) { die(4, _("Cannot sync quotas on device %s: %s\n"), h->qh_quotadev, strerror(errno)); } diff --git a/quotaio_generic.c b/quotaio_generic.c index 5b23955..3c95872 100644 --- a/quotaio_generic.c +++ b/quotaio_generic.c @@ -50,7 +50,7 @@ int vfs_get_info(struct quota_handle *h) { struct if_dqinfo kinfo; - if (quotactl(QCMD(Q_GETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kinfo) < 0) { + if (do_quotactl(QCMD(Q_GETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kinfo) < 0) { errstr(_("Cannot get info for %s quota file from kernel on %s: %s\n"), type2name(h->qh_type), h->qh_quotadev, strerror(errno)); return -1; } @@ -68,7 +68,7 @@ int vfs_set_info(struct quota_handle *h, int flags) kinfo.dqi_igrace = h->qh_info.dqi_igrace; kinfo.dqi_valid = flags; - if (quotactl(QCMD(Q_SETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kinfo) < 0) { + if (do_quotactl(QCMD(Q_SETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kinfo) < 0) { errstr(_("Cannot set info for %s quota file from kernel on %s: %s\n"), type2name(h->qh_type), h->qh_quotadev, strerror(errno)); return -1; } @@ -80,7 +80,7 @@ int vfs_get_dquot(struct dquot *dquot) { struct if_dqblk kdqblk; - if (quotactl(QCMD(Q_GETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_id, (void *)&kdqblk) < 0) { + if (do_quotactl(QCMD(Q_GETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) { errstr(_("Cannot get quota for %s %d from kernel on %s: %s\n"), type2name(dquot->dq_h->qh_type), dquot->dq_id, dquot->dq_h->qh_quotadev, strerror(errno)); return -1; } @@ -95,7 +95,7 @@ int vfs_set_dquot(struct dquot *dquot, int flags) generic_util2kerndqblk(&kdqblk, &dquot->dq_dqb); kdqblk.dqb_valid = flags; - if (quotactl(QCMD(Q_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_id, (void *)&kdqblk) < 0) { + if (do_quotactl(QCMD(Q_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) { errstr(_("Cannot set quota for %s %d from kernel on %s: %s\n"), type2name(dquot->dq_h->qh_type), dquot->dq_id, dquot->dq_h->qh_quotadev, strerror(errno)); return -1; } @@ -188,8 +188,8 @@ int vfs_scan_dquots(struct quota_handle *h, dquot->dq_h = h; while (1) { - ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), - h->qh_quotadev, id, (void *)&kdqblk); + ret = do_quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), + h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk); if (ret < 0) break; diff --git a/quotaio_meta.c b/quotaio_meta.c index ad6ff7a..51ebbcf 100644 --- a/quotaio_meta.c +++ b/quotaio_meta.c @@ -59,8 +59,8 @@ static int meta_scan_dquots(struct quota_handle *h, int (*process_dquot)(struct struct if_nextdqblk kdqblk; int ret; - ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), h->qh_quotadev, 0, - (void *)&kdqblk); + ret = do_quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), h->qh_quotadev, + h->qh_dir, 0, (void *)&kdqblk); /* * Fall back to scanning using passwd if Q_GETNEXTQUOTA is not * supported diff --git a/quotaio_v1.c b/quotaio_v1.c index 6a6dc78..187a5a5 100644 --- a/quotaio_v1.c +++ b/quotaio_v1.c @@ -118,7 +118,7 @@ static int v1_init_io(struct quota_handle *h) else { struct v1_kern_dqblk kdqblk; - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) { + if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) { if (errno == EPERM) { /* We have no permission to get this information? */ h->qh_info.dqi_bgrace = h->qh_info.dqi_igrace = 0; /* It hopefully won't be needed */ } @@ -193,11 +193,11 @@ static int v1_write_info(struct quota_handle *h) else { struct v1_kern_dqblk kdqblk; - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) + if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) return -1; kdqblk.dqb_btime = h->qh_info.dqi_bgrace; kdqblk.dqb_itime = h->qh_info.dqi_igrace; - if (quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) + if (do_quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) return -1; } } @@ -237,7 +237,7 @@ static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id) else { struct v1_kern_dqblk kdqblk; - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) < 0) { + if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk) < 0) { free(dquot); return NULL; } @@ -299,7 +299,7 @@ static int v1_commit_dquot(struct dquot *dquot, int flags) else cmd = Q_V1_SETQUOTA; v1_util2kerndqblk(&kdqblk, &dquot->dq_dqb); - if (quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, dquot->dq_id, + if (do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) return -1; } diff --git a/quotaio_v2.c b/quotaio_v2.c index 56a549f..b0fe7bf 100644 --- a/quotaio_v2.c +++ b/quotaio_v2.c @@ -275,7 +275,7 @@ static int v2_init_io(struct quota_handle *h) else { struct v2_kern_dqinfo kdqinfo; - if (quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0) { + if (do_quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0) { /* Temporary check just before fix gets to kernel */ if (errno == EPERM) /* Don't have permission to get information? */ return 0; @@ -403,8 +403,8 @@ static int v2_write_info(struct quota_handle *h) kdqinfo.dqi_blocks = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks; kdqinfo.dqi_free_blk = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_blk; kdqinfo.dqi_free_entry = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_entry; - if (quotactl(QCMD(Q_V2_SETGRACE, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0 || - quotactl(QCMD(Q_V2_SETFLAGS, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0) + if (do_quotactl(QCMD(Q_V2_SETGRACE, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0 || + do_quotactl(QCMD(Q_V2_SETFLAGS, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0) return -1; } } @@ -441,7 +441,7 @@ static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id) else { struct v2_kern_dqblk kdqblk; - if (quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) < 0) { + if (do_quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk) < 0) { free(dquot); return NULL; } @@ -485,8 +485,8 @@ static int v2_commit_dquot(struct dquot *dquot, int flags) else cmd = Q_V2_SETQUOTA; v2_util2kerndqblk(&kdqblk, &dquot->dq_dqb); - if (quotactl(QCMD(cmd, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, - dquot->dq_id, (void *)&kdqblk) < 0) + if (do_quotactl(QCMD(cmd, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, + dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) return -1; } return 0; diff --git a/quotaio_xfs.c b/quotaio_xfs.c index 5abb2c2..0bf6f34 100644 --- a/quotaio_xfs.c +++ b/quotaio_xfs.c @@ -128,7 +128,7 @@ static int xfs_init_io(struct quota_handle *h) qcmd = QCMD(Q_XFS_GETQSTAT, h->qh_type); memset(&info, 0, sizeof(struct xfs_mem_dqinfo)); - if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&info) < 0) + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, 0, (void *)&info) < 0) return -1; h->qh_info.dqi_bgrace = info.qs_btimelimit; h->qh_info.dqi_igrace = info.qs_itimelimit; @@ -153,7 +153,7 @@ static int xfs_write_info(struct quota_handle *h) xdqblk.d_itimer = h->qh_info.dqi_igrace; xdqblk.d_fieldmask |= FS_DQ_TIMER_MASK; qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type); - if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&xdqblk) < 0) + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, 0, (void *)&xdqblk) < 0) return -1; return 0; } @@ -174,7 +174,8 @@ static struct dquot *xfs_read_dquot(struct quota_handle *h, qid_t id) return dquot; qcmd = QCMD(Q_XFS_GETQUOTA, h->qh_type); - if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) { + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, + id, (void *)&xdqblk) < 0) { ; } else { @@ -219,7 +220,7 @@ static int xfs_commit_dquot(struct dquot *dquot, int flags) } qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type); - if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, id, (void *)&xdqblk) < 0) return -1; return 0; } @@ -234,7 +235,9 @@ static int xfs_get_dquot(struct dquot *dq) int ret; memset(&d, 0, sizeof(d)); - ret = quotactl(qcmd, dq->dq_h->qh_quotadev, dq->dq_id, (void *)&d); + ret = do_quotactl(qcmd, dq->dq_h->qh_quotadev, dq->dq_h->qh_dir, + dq->dq_id, (void *)&d); + if (ret < 0) { if (errno == ENOENT) return 0; @@ -254,8 +257,8 @@ static int xfs_kernel_scan_dquots(struct quota_handle *h, dquot->dq_h = h; while (1) { - ret = quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), - h->qh_quotadev, id, (void *)&xdqblk); + ret = do_quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), + h->qh_quotadev, h->qh_dir, id, (void *)&xdqblk); if (ret < 0) break; @@ -286,8 +289,8 @@ static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct int ret; struct xfs_kern_dqblk xdqblk; - ret = quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), h->qh_quotadev, 0, - (void *)&xdqblk); + ret = do_quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), h->qh_quotadev, + h->qh_dir, 0, (void *)&xdqblk); if (ret < 0 && (errno == ENOSYS || errno == EINVAL)) { if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h) && !XFS_PRJQUOTA(h)) return 0; diff --git a/quotaon.c b/quotaon.c index 125b934..351c851 100644 --- a/quotaon.c +++ b/quotaon.c @@ -152,13 +152,13 @@ static int quotarsquashonoff(const char *quotadev, int type, int flags) info.dqi_flags = V1_DQF_RSQUASH; info.dqi_valid = IIF_FLAGS; - ret = quotactl(qcmd, quotadev, 0, (void *)&info); + ret = do_quotactl(qcmd, quotadev, NULL, 0, (void *)&info); } else { int mode = (flags & STATEFLAG_OFF) ? 0 : 1; int qcmd = QCMD(Q_V1_RSQUASH, type); - ret = quotactl(qcmd, quotadev, 0, (void *)&mode); + ret = do_quotactl(qcmd, quotadev, NULL, 0, (void *)&mode); } if (ret < 0) { errstr(_("set root_squash on %s: %s\n"), quotadev, strerror(errno)); @@ -184,7 +184,7 @@ static int quotaonoff(const char *quotadev, const char *quotadir, char *quotafil qcmd = QCMD(Q_QUOTAOFF, type); else qcmd = QCMD(Q_6_5_QUOTAOFF, type); - if (quotactl(qcmd, quotadev, 0, NULL) < 0) { + if (do_quotactl(qcmd, quotadev, quotadir, 0, NULL) < 0) { errstr(_("quotactl on %s [%s]: %s\n"), quotadev, quotadir, strerror(errno)); return 1; } @@ -199,7 +199,7 @@ static int quotaonoff(const char *quotadev, const char *quotadir, char *quotafil qcmd = QCMD(Q_6_5_QUOTAON, type); kqf = 0; } - if (quotactl(qcmd, quotadev, kqf, (void *)quotafile) < 0) { + if (do_quotactl(qcmd, quotadev, quotadir, kqf, (void *)quotafile) < 0) { if (errno == ENOENT) errstr(_("cannot find %s on %s [%s]\n"), quotafile, quotadev, quotadir); else diff --git a/quotaon_xfs.c b/quotaon_xfs.c index d137240..dda3023 100644 --- a/quotaon_xfs.c +++ b/quotaon_xfs.c @@ -32,7 +32,7 @@ static int xfs_state_check(int qcmd, int type, int flags, const char *dev, int r if (flags & STATEFLAG_ALL) return 0; /* noop */ - if (quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info) < 0) { + if (do_quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, NULL, 0, (void *)&info) < 0) { errstr(_("quotactl() on %s: %s\n"), dev, strerror(errno)); return -1; } @@ -156,7 +156,7 @@ static int xfs_onoff(const char *dev, int type, int flags, int roothack, int xop if (check != 1) return (check < 0); - if (quotactl(QCMD(qcmd, type), dev, 0, (void *)&xopts) < 0) { + if (do_quotactl(QCMD(qcmd, type), dev, NULL, 0, (void *)&xopts) < 0) { errstr(_("quotactl on %s: %s\n"), dev, strerror(errno)); return 1; } @@ -176,7 +176,7 @@ static int xfs_delete(const char *dev, int type, int flags, int roothack, int xo if (check != 1) return (check < 0); - if (quotactl(QCMD(qcmd, type), dev, 0, (void *)&xopts) < 0) { + if (do_quotactl(QCMD(qcmd, type), dev, NULL, 0, (void *)&xopts) < 0) { errstr(_("Failed to delete quota: %s\n"), strerror(errno)); return 1; @@ -208,7 +208,8 @@ int xfs_newstate(struct mount_entry *mnt, int type, char *xarg, int flags) struct xfs_mem_dqinfo info; u_int16_t sbflags = 0; - if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), mnt->me_devname, 0, (void *)&info)) + if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), mnt->me_devname, + mnt->me_dir, 0, (void *)&info)) sbflags = (info.qs_flags & 0xff00) >> 8; if ((type == USRQUOTA && (sbflags & XFS_QUOTA_UDQ_ACCT)) && diff --git a/quotastats.c b/quotastats.c index a059812..ee23afd 100644 --- a/quotastats.c +++ b/quotastats.c @@ -72,7 +72,7 @@ static int get_stats(struct util_dqstats *dqstats) dqstats->free_dquots = get_proc_num("free_dquots"); dqstats->syncs = get_proc_num("syncs"); } - else if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, (caddr_t)&old_dqstats) >= 0) { + else if (do_quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, NULL, 0, (caddr_t)&old_dqstats) >= 0) { /* Structures are currently the same */ memcpy(dqstats, &old_dqstats, sizeof(old_dqstats)); dqstats->version = 0; @@ -83,7 +83,7 @@ static int get_stats(struct util_dqstats *dqstats) errstr(_("Error while getting quota statistics from kernel: %s\n"), strerror(errno)); goto out; } - if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (caddr_t)&v0_dqstats) < 0) { + if (do_quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, NULL, 0, (caddr_t)&v0_dqstats) < 0) { errstr(_("Error while getting old quota statistics from kernel: %s\n"), strerror(errno)); goto out; } diff --git a/quotasync.c b/quotasync.c index 80f7e9e..cad2a20 100644 --- a/quotasync.c +++ b/quotasync.c @@ -100,7 +100,7 @@ static int sync_one(int type, char *dev) { int qcmd = QCMD(Q_SYNC, type); - return quotactl(qcmd, dev, 0, NULL); + return do_quotactl(qcmd, dev, NULL, 0, NULL); } static int syncquotas(int type) diff --git a/quotasys.c b/quotasys.c index 9af9932..903816b 100644 --- a/quotasys.c +++ b/quotasys.c @@ -25,6 +25,7 @@ #include <sys/vfs.h> #include <stdint.h> #include <sys/utsname.h> +#include <sys/syscall.h> #include "pot.h" #include "bylabel.h" @@ -670,6 +671,36 @@ const char *str2number(const char *string, qsize_t *inodes) return NULL; } +/* + * Wrappers for quotactl syscalls + */ +#ifdef SYS_quotactl_fd +int do_quotactl(int cmd, const char *dev, const char *mnt, int id, caddr_t addr) +{ + int ret = -EINVAL; + + if (mnt && !dev) { + int fd = open(mnt, O_DIRECTORY | O_PATH); + + if (fd < 0) { + errstr(_("Unable to get a filedescriptor from mountpoint: %s\n"), mnt); + return fd; + } + + ret = syscall(SYS_quotactl_fd, fd, cmd, id, addr); + close(fd); + return ret; + } + + return quotactl(cmd, dev, id, addr); +} +#else +int do_quotactl(int cmd, const char *dev, const char *mnt, int id, caddr_t addr) +{ + return quotactl(cmd, dev, id, addr); +} +#endif + /* * Wrappers for mount options processing functions */ @@ -685,7 +716,7 @@ static int hasxfsquota(const char *dev, struct mntent *mnt, int type, int flags) return QF_XFS; memset(&info, 0, sizeof(struct xfs_mem_dqinfo)); - if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) { + if (!do_quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, mnt->mnt_dir, 0, (void *)&info)) { #ifdef XFS_ROOTHACK int sbflags = (info.qs_flags & 0xff00) >> 8; #endif /* XFS_ROOTHACK */ @@ -719,7 +750,7 @@ static int hasvfsmetaquota(const char *dev, struct mntent *mnt, int type, int fl { uint32_t fmt; - if (!quotactl(QCMD(Q_GETFMT, type), dev, 0, (void *)&fmt)) + if (!do_quotactl(QCMD(Q_GETFMT, type), dev, mnt->mnt_dir, 0, (void *)&fmt)) return QF_META; return QF_ERROR; } @@ -796,7 +827,7 @@ static int hasquota(const char *dev, struct mntent *mnt, int type, int flags) if (!strcmp(mnt->mnt_type, MNTTYPE_EXT4) || !strcmp(mnt->mnt_type, MNTTYPE_F2FS)) { struct if_dqinfo kinfo; - if (quotactl(QCMD(Q_GETINFO, type), dev, 0, (void *)&kinfo) == 0) { + if (do_quotactl(QCMD(Q_GETINFO, type), dev, mnt->mnt_dir, 0, (void *)&kinfo) == 0) { if (kinfo.dqi_flags & DQF_SYS_FILE) return QF_META; } @@ -1069,11 +1100,11 @@ void init_kernel_interface(void) else { fs_quota_stat_t dummy; - if (!quotactl(QCMD(Q_XGETQSTAT, 0), "/dev/root", 0, (void *)&dummy) || + if (!do_quotactl(QCMD(Q_XGETQSTAT, 0), "/dev/root", NULL, 0, (void *)&dummy) || (errno != EINVAL && errno != ENOSYS)) kernel_qfmt[kernel_qfmt_num++] = QF_XFS; } - if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (void *)&v2_stats) >= 0) { + if (do_quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, NULL, 0, (void *)&v2_stats) >= 0) { kernel_qfmt[kernel_qfmt_num++] = QF_VFSV0; kernel_iface = IFACE_VFSV0; } @@ -1085,9 +1116,9 @@ void init_kernel_interface(void) int err_quota = 0; char tmp[1024]; /* Just temporary buffer */ - if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, tmp)) + if (do_quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, NULL, 0, tmp)) err_stat = errno; - if (quotactl(QCMD(Q_V1_GETQUOTA, 0), "/dev/null", 0, tmp)) + if (do_quotactl(QCMD(Q_V1_GETQUOTA, 0), "/dev/null", NULL, 0, tmp)) err_quota = errno; /* On a RedHat 2.4.2-2 we expect 0, EINVAL @@ -1127,7 +1158,7 @@ static int v1_kern_quota_on(const char *dev, int type) char tmp[1024]; /* Just temporary buffer */ qid_t id = (type == USRQUOTA) ? getuid() : getgid(); - if (!quotactl(QCMD(Q_V1_GETQUOTA, type), dev, id, tmp)) /* OK? */ + if (!do_quotactl(QCMD(Q_V1_GETQUOTA, type), dev, NULL, id, tmp)) /* OK? */ return 1; return 0; } @@ -1138,7 +1169,7 @@ static int v2_kern_quota_on(const char *dev, int type) char tmp[1024]; /* Just temporary buffer */ qid_t id = (type == USRQUOTA) ? getuid() : getgid(); - if (!quotactl(QCMD(Q_V2_GETQUOTA, type), dev, id, tmp)) /* OK? */ + if (!do_quotactl(QCMD(Q_V2_GETQUOTA, type), dev, NULL, id, tmp)) /* OK? */ return 1; return 0; } @@ -1155,7 +1186,7 @@ int kern_quota_state_xfs(const char *dev, int type) { struct xfs_mem_dqinfo info; - if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) { + if (!do_quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, NULL, 0, (void *)&info)) { if (type == USRQUOTA) { return !!(info.qs_flags & XFS_QUOTA_UDQ_ACCT) + !!(info.qs_flags & XFS_QUOTA_UDQ_ENFD); @@ -1199,8 +1230,8 @@ int kern_quota_on(struct mount_entry *mnt, int type, int fmt) if (kernel_iface == IFACE_GENERIC) { int actfmt; - if (quotactl(QCMD(Q_GETFMT, type), mnt->me_devname, 0, - (void *)&actfmt) >= 0) { + if (do_quotactl(QCMD(Q_GETFMT, type), mnt->me_devname, + mnt->me_dir, 0, (void *)&actfmt) >= 0) { actfmt = kern2utilfmt(actfmt); if (actfmt >= 0) return actfmt; diff --git a/quotasys.h b/quotasys.h index 841251e..b166ad2 100644 --- a/quotasys.h +++ b/quotasys.h @@ -206,6 +206,9 @@ void end_mounts_scan(void); /* Parse kernel version and return 1 if ext4 supports quota feature */ int ext4_supports_quota_feature(void); +/* Wrapper around quota syscalls, either call quotactl or quotactl_fd */ +int do_quotactl(int cmd, const char *dev, const char *mnt, int id, caddr_t addr); + /* Quota output formats */ #define QOF_ERROR -1 #define QOF_DEFAULT 0 -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] Add quotactl_fd() support 2024-01-09 13:46 ` [PATCH 2/3] Add quotactl_fd() support cem @ 2024-01-17 18:08 ` Jan Kara 2024-01-24 11:25 ` Carlos Maiolino 0 siblings, 1 reply; 9+ messages in thread From: Jan Kara @ 2024-01-17 18:08 UTC (permalink / raw) To: cem; +Cc: jack, linux-fsdevel On Tue 09-01-24 14:46:04, cem@kernel.org wrote: > From: Carlos Maiolino <cem@kernel.org> > > To be able to set quotas on filesystems without a backing device, quota tools > should be able to use quotactl_fd(). > To achieve that, add a new helper, do_quotactl(), to select between quotactl() > and quotactl_fd(). > > This shouldn't change the semantics of current code. quotactl_fd() will be > called if and only if the handlers contain an empty device, and a valid > mountpoint. > All current calls containing a value device should be still handled by quotactl(). > The same is true for calls passing a NULL device on purpose, aiming to sync > active quotas. > > Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> quota-tools work on mounted filesystems so ideally we could switch all the places to use quotactl_fd() (if the kernel supports it - we probably have to keep the fallback for some time yet). But for now what you do is fine and we can clean that up later. Honza > --- > Makefile.am | 1 + > quotacheck.c | 12 +++++------ > quotaio.c | 4 ++-- > quotaio_generic.c | 12 +++++------ > quotaio_meta.c | 4 ++-- > quotaio_v1.c | 10 ++++----- > quotaio_v2.c | 12 +++++------ > quotaio_xfs.c | 21 ++++++++++-------- > quotaon.c | 8 +++---- > quotaon_xfs.c | 9 ++++---- > quotastats.c | 4 ++-- > quotasync.c | 2 +- > quotasys.c | 55 ++++++++++++++++++++++++++++++++++++----------- > quotasys.h | 3 +++ > 14 files changed, 98 insertions(+), 59 deletions(-) > > diff --git a/Makefile.am b/Makefile.am > index 372eafb..13a0f06 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -207,6 +207,7 @@ quotastats_SOURCES = \ > pot.h > > quotastats_LDADD = \ > + libquota.a \ > $(INTLLIBS) > > xqmstats_SOURCES = \ > diff --git a/quotacheck.c b/quotacheck.c > index bd62d9a..e2c3bbd 100644 > --- a/quotacheck.c > +++ b/quotacheck.c > @@ -648,8 +648,8 @@ Please turn quotas off or use -f to force checking.\n"), > type2name(type), mnt->me_dir); > } > /* At least sync quotas so damage will be smaller */ > - if (quotactl(QCMD((kernel_iface == IFACE_GENERIC)? Q_SYNC : Q_6_5_SYNC, type), > - mnt->me_devname, 0, NULL) < 0) > + if (do_quotactl(QCMD((kernel_iface == IFACE_GENERIC)? Q_SYNC : Q_6_5_SYNC, type), > + mnt->me_devname, mnt->me_dir, 0, NULL) < 0) > die(4, _("Error while syncing quotas on %s: %s\n"), mnt->me_devname, strerror(errno)); > } > > @@ -848,8 +848,8 @@ static int dump_to_file(struct mount_entry *mnt, int type) > if (get_qf_name(mnt, type, cfmt, NF_FORMAT, &filename) < 0) > errstr(_("Cannot find checked quota file for %ss on %s!\n"), _(type2name(type)), mnt->me_devname); > else { > - if (quotactl(QCMD((kernel_iface == IFACE_GENERIC) ? Q_QUOTAOFF : Q_6_5_QUOTAOFF, type), > - mnt->me_devname, 0, NULL) < 0) > + if (do_quotactl(QCMD((kernel_iface == IFACE_GENERIC) ? Q_QUOTAOFF : Q_6_5_QUOTAOFF, type), > + mnt->me_devname, mnt->me_dir, 0, NULL) < 0) > errstr(_("Cannot turn %s quotas off on %s: %s\nKernel won't know about changes quotacheck did.\n"), > _(type2name(type)), mnt->me_devname, strerror(errno)); > else { > @@ -859,9 +859,9 @@ static int dump_to_file(struct mount_entry *mnt, int type) > rename_files(mnt, type); > > if (kernel_iface == IFACE_GENERIC) > - ret = quotactl(QCMD(Q_QUOTAON, type), mnt->me_devname, util2kernfmt(cfmt), filename); > + ret = do_quotactl(QCMD(Q_QUOTAON, type), mnt->me_devname, mnt->me_dir, util2kernfmt(cfmt), filename); > else > - ret = quotactl(QCMD(Q_6_5_QUOTAON, type), mnt->me_devname, 0, filename); > + ret = do_quotactl(QCMD(Q_6_5_QUOTAON, type), mnt->me_devname, mnt->me_dir, 0, filename); > if (ret < 0) > errstr(_("Cannot turn %s quotas on on %s: %s\nKernel won't know about changes quotacheck did.\n"), > _(type2name(type)), mnt->me_devname, strerror(errno)); > diff --git a/quotaio.c b/quotaio.c > index 94ae458..9bebb5e 100644 > --- a/quotaio.c > +++ b/quotaio.c > @@ -140,8 +140,8 @@ struct quota_handle *init_io(struct mount_entry *mnt, int type, int fmt, int fla > if (QIO_ENABLED(h)) { /* Kernel uses same file? */ > unsigned int cmd = > (kernel_iface == IFACE_GENERIC) ? Q_SYNC : Q_6_5_SYNC; > - if (quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, > - 0, NULL) < 0) { > + if (do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, > + h->qh_dir, 0, NULL) < 0) { > die(4, _("Cannot sync quotas on device %s: %s\n"), > h->qh_quotadev, strerror(errno)); > } > diff --git a/quotaio_generic.c b/quotaio_generic.c > index 5b23955..3c95872 100644 > --- a/quotaio_generic.c > +++ b/quotaio_generic.c > @@ -50,7 +50,7 @@ int vfs_get_info(struct quota_handle *h) > { > struct if_dqinfo kinfo; > > - if (quotactl(QCMD(Q_GETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kinfo) < 0) { > + if (do_quotactl(QCMD(Q_GETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kinfo) < 0) { > errstr(_("Cannot get info for %s quota file from kernel on %s: %s\n"), type2name(h->qh_type), h->qh_quotadev, strerror(errno)); > return -1; > } > @@ -68,7 +68,7 @@ int vfs_set_info(struct quota_handle *h, int flags) > kinfo.dqi_igrace = h->qh_info.dqi_igrace; > kinfo.dqi_valid = flags; > > - if (quotactl(QCMD(Q_SETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kinfo) < 0) { > + if (do_quotactl(QCMD(Q_SETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kinfo) < 0) { > errstr(_("Cannot set info for %s quota file from kernel on %s: %s\n"), type2name(h->qh_type), h->qh_quotadev, strerror(errno)); > return -1; > } > @@ -80,7 +80,7 @@ int vfs_get_dquot(struct dquot *dquot) > { > struct if_dqblk kdqblk; > > - if (quotactl(QCMD(Q_GETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_id, (void *)&kdqblk) < 0) { > + if (do_quotactl(QCMD(Q_GETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) { > errstr(_("Cannot get quota for %s %d from kernel on %s: %s\n"), type2name(dquot->dq_h->qh_type), dquot->dq_id, dquot->dq_h->qh_quotadev, strerror(errno)); > return -1; > } > @@ -95,7 +95,7 @@ int vfs_set_dquot(struct dquot *dquot, int flags) > > generic_util2kerndqblk(&kdqblk, &dquot->dq_dqb); > kdqblk.dqb_valid = flags; > - if (quotactl(QCMD(Q_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_id, (void *)&kdqblk) < 0) { > + if (do_quotactl(QCMD(Q_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) { > errstr(_("Cannot set quota for %s %d from kernel on %s: %s\n"), type2name(dquot->dq_h->qh_type), dquot->dq_id, dquot->dq_h->qh_quotadev, strerror(errno)); > return -1; > } > @@ -188,8 +188,8 @@ int vfs_scan_dquots(struct quota_handle *h, > > dquot->dq_h = h; > while (1) { > - ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), > - h->qh_quotadev, id, (void *)&kdqblk); > + ret = do_quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), > + h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk); > if (ret < 0) > break; > > diff --git a/quotaio_meta.c b/quotaio_meta.c > index ad6ff7a..51ebbcf 100644 > --- a/quotaio_meta.c > +++ b/quotaio_meta.c > @@ -59,8 +59,8 @@ static int meta_scan_dquots(struct quota_handle *h, int (*process_dquot)(struct > struct if_nextdqblk kdqblk; > int ret; > > - ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), h->qh_quotadev, 0, > - (void *)&kdqblk); > + ret = do_quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), h->qh_quotadev, > + h->qh_dir, 0, (void *)&kdqblk); > /* > * Fall back to scanning using passwd if Q_GETNEXTQUOTA is not > * supported > diff --git a/quotaio_v1.c b/quotaio_v1.c > index 6a6dc78..187a5a5 100644 > --- a/quotaio_v1.c > +++ b/quotaio_v1.c > @@ -118,7 +118,7 @@ static int v1_init_io(struct quota_handle *h) > else { > struct v1_kern_dqblk kdqblk; > > - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) { > + if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) { > if (errno == EPERM) { /* We have no permission to get this information? */ > h->qh_info.dqi_bgrace = h->qh_info.dqi_igrace = 0; /* It hopefully won't be needed */ > } > @@ -193,11 +193,11 @@ static int v1_write_info(struct quota_handle *h) > else { > struct v1_kern_dqblk kdqblk; > > - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) > + if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) > return -1; > kdqblk.dqb_btime = h->qh_info.dqi_bgrace; > kdqblk.dqb_itime = h->qh_info.dqi_igrace; > - if (quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) > + if (do_quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) > return -1; > } > } > @@ -237,7 +237,7 @@ static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id) > else { > struct v1_kern_dqblk kdqblk; > > - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) < 0) { > + if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk) < 0) { > free(dquot); > return NULL; > } > @@ -299,7 +299,7 @@ static int v1_commit_dquot(struct dquot *dquot, int flags) > else > cmd = Q_V1_SETQUOTA; > v1_util2kerndqblk(&kdqblk, &dquot->dq_dqb); > - if (quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, dquot->dq_id, > + if (do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, h->qh_dir, dquot->dq_id, > (void *)&kdqblk) < 0) > return -1; > } > diff --git a/quotaio_v2.c b/quotaio_v2.c > index 56a549f..b0fe7bf 100644 > --- a/quotaio_v2.c > +++ b/quotaio_v2.c > @@ -275,7 +275,7 @@ static int v2_init_io(struct quota_handle *h) > else { > struct v2_kern_dqinfo kdqinfo; > > - if (quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0) { > + if (do_quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0) { > /* Temporary check just before fix gets to kernel */ > if (errno == EPERM) /* Don't have permission to get information? */ > return 0; > @@ -403,8 +403,8 @@ static int v2_write_info(struct quota_handle *h) > kdqinfo.dqi_blocks = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks; > kdqinfo.dqi_free_blk = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_blk; > kdqinfo.dqi_free_entry = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_entry; > - if (quotactl(QCMD(Q_V2_SETGRACE, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0 || > - quotactl(QCMD(Q_V2_SETFLAGS, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0) > + if (do_quotactl(QCMD(Q_V2_SETGRACE, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0 || > + do_quotactl(QCMD(Q_V2_SETFLAGS, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0) > return -1; > } > } > @@ -441,7 +441,7 @@ static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id) > else { > struct v2_kern_dqblk kdqblk; > > - if (quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) < 0) { > + if (do_quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk) < 0) { > free(dquot); > return NULL; > } > @@ -485,8 +485,8 @@ static int v2_commit_dquot(struct dquot *dquot, int flags) > else > cmd = Q_V2_SETQUOTA; > v2_util2kerndqblk(&kdqblk, &dquot->dq_dqb); > - if (quotactl(QCMD(cmd, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, > - dquot->dq_id, (void *)&kdqblk) < 0) > + if (do_quotactl(QCMD(cmd, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, > + dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) > return -1; > } > return 0; > diff --git a/quotaio_xfs.c b/quotaio_xfs.c > index 5abb2c2..0bf6f34 100644 > --- a/quotaio_xfs.c > +++ b/quotaio_xfs.c > @@ -128,7 +128,7 @@ static int xfs_init_io(struct quota_handle *h) > > qcmd = QCMD(Q_XFS_GETQSTAT, h->qh_type); > memset(&info, 0, sizeof(struct xfs_mem_dqinfo)); > - if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&info) < 0) > + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, 0, (void *)&info) < 0) > return -1; > h->qh_info.dqi_bgrace = info.qs_btimelimit; > h->qh_info.dqi_igrace = info.qs_itimelimit; > @@ -153,7 +153,7 @@ static int xfs_write_info(struct quota_handle *h) > xdqblk.d_itimer = h->qh_info.dqi_igrace; > xdqblk.d_fieldmask |= FS_DQ_TIMER_MASK; > qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type); > - if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&xdqblk) < 0) > + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, 0, (void *)&xdqblk) < 0) > return -1; > return 0; > } > @@ -174,7 +174,8 @@ static struct dquot *xfs_read_dquot(struct quota_handle *h, qid_t id) > return dquot; > > qcmd = QCMD(Q_XFS_GETQUOTA, h->qh_type); > - if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) { > + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, > + id, (void *)&xdqblk) < 0) { > ; > } > else { > @@ -219,7 +220,7 @@ static int xfs_commit_dquot(struct dquot *dquot, int flags) > } > > qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type); > - if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) > + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, id, (void *)&xdqblk) < 0) > return -1; > return 0; > } > @@ -234,7 +235,9 @@ static int xfs_get_dquot(struct dquot *dq) > int ret; > > memset(&d, 0, sizeof(d)); > - ret = quotactl(qcmd, dq->dq_h->qh_quotadev, dq->dq_id, (void *)&d); > + ret = do_quotactl(qcmd, dq->dq_h->qh_quotadev, dq->dq_h->qh_dir, > + dq->dq_id, (void *)&d); > + > if (ret < 0) { > if (errno == ENOENT) > return 0; > @@ -254,8 +257,8 @@ static int xfs_kernel_scan_dquots(struct quota_handle *h, > > dquot->dq_h = h; > while (1) { > - ret = quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), > - h->qh_quotadev, id, (void *)&xdqblk); > + ret = do_quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), > + h->qh_quotadev, h->qh_dir, id, (void *)&xdqblk); > if (ret < 0) > break; > > @@ -286,8 +289,8 @@ static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct > int ret; > struct xfs_kern_dqblk xdqblk; > > - ret = quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), h->qh_quotadev, 0, > - (void *)&xdqblk); > + ret = do_quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), h->qh_quotadev, > + h->qh_dir, 0, (void *)&xdqblk); > if (ret < 0 && (errno == ENOSYS || errno == EINVAL)) { > if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h) && !XFS_PRJQUOTA(h)) > return 0; > diff --git a/quotaon.c b/quotaon.c > index 125b934..351c851 100644 > --- a/quotaon.c > +++ b/quotaon.c > @@ -152,13 +152,13 @@ static int quotarsquashonoff(const char *quotadev, int type, int flags) > > info.dqi_flags = V1_DQF_RSQUASH; > info.dqi_valid = IIF_FLAGS; > - ret = quotactl(qcmd, quotadev, 0, (void *)&info); > + ret = do_quotactl(qcmd, quotadev, NULL, 0, (void *)&info); > } > else { > int mode = (flags & STATEFLAG_OFF) ? 0 : 1; > int qcmd = QCMD(Q_V1_RSQUASH, type); > > - ret = quotactl(qcmd, quotadev, 0, (void *)&mode); > + ret = do_quotactl(qcmd, quotadev, NULL, 0, (void *)&mode); > } > if (ret < 0) { > errstr(_("set root_squash on %s: %s\n"), quotadev, strerror(errno)); > @@ -184,7 +184,7 @@ static int quotaonoff(const char *quotadev, const char *quotadir, char *quotafil > qcmd = QCMD(Q_QUOTAOFF, type); > else > qcmd = QCMD(Q_6_5_QUOTAOFF, type); > - if (quotactl(qcmd, quotadev, 0, NULL) < 0) { > + if (do_quotactl(qcmd, quotadev, quotadir, 0, NULL) < 0) { > errstr(_("quotactl on %s [%s]: %s\n"), quotadev, quotadir, strerror(errno)); > return 1; > } > @@ -199,7 +199,7 @@ static int quotaonoff(const char *quotadev, const char *quotadir, char *quotafil > qcmd = QCMD(Q_6_5_QUOTAON, type); > kqf = 0; > } > - if (quotactl(qcmd, quotadev, kqf, (void *)quotafile) < 0) { > + if (do_quotactl(qcmd, quotadev, quotadir, kqf, (void *)quotafile) < 0) { > if (errno == ENOENT) > errstr(_("cannot find %s on %s [%s]\n"), quotafile, quotadev, quotadir); > else > diff --git a/quotaon_xfs.c b/quotaon_xfs.c > index d137240..dda3023 100644 > --- a/quotaon_xfs.c > +++ b/quotaon_xfs.c > @@ -32,7 +32,7 @@ static int xfs_state_check(int qcmd, int type, int flags, const char *dev, int r > if (flags & STATEFLAG_ALL) > return 0; /* noop */ > > - if (quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info) < 0) { > + if (do_quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, NULL, 0, (void *)&info) < 0) { > errstr(_("quotactl() on %s: %s\n"), dev, strerror(errno)); > return -1; > } > @@ -156,7 +156,7 @@ static int xfs_onoff(const char *dev, int type, int flags, int roothack, int xop > if (check != 1) > return (check < 0); > > - if (quotactl(QCMD(qcmd, type), dev, 0, (void *)&xopts) < 0) { > + if (do_quotactl(QCMD(qcmd, type), dev, NULL, 0, (void *)&xopts) < 0) { > errstr(_("quotactl on %s: %s\n"), dev, strerror(errno)); > return 1; > } > @@ -176,7 +176,7 @@ static int xfs_delete(const char *dev, int type, int flags, int roothack, int xo > if (check != 1) > return (check < 0); > > - if (quotactl(QCMD(qcmd, type), dev, 0, (void *)&xopts) < 0) { > + if (do_quotactl(QCMD(qcmd, type), dev, NULL, 0, (void *)&xopts) < 0) { > errstr(_("Failed to delete quota: %s\n"), > strerror(errno)); > return 1; > @@ -208,7 +208,8 @@ int xfs_newstate(struct mount_entry *mnt, int type, char *xarg, int flags) > struct xfs_mem_dqinfo info; > u_int16_t sbflags = 0; > > - if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), mnt->me_devname, 0, (void *)&info)) > + if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), mnt->me_devname, > + mnt->me_dir, 0, (void *)&info)) > sbflags = (info.qs_flags & 0xff00) >> 8; > > if ((type == USRQUOTA && (sbflags & XFS_QUOTA_UDQ_ACCT)) && > diff --git a/quotastats.c b/quotastats.c > index a059812..ee23afd 100644 > --- a/quotastats.c > +++ b/quotastats.c > @@ -72,7 +72,7 @@ static int get_stats(struct util_dqstats *dqstats) > dqstats->free_dquots = get_proc_num("free_dquots"); > dqstats->syncs = get_proc_num("syncs"); > } > - else if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, (caddr_t)&old_dqstats) >= 0) { > + else if (do_quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, NULL, 0, (caddr_t)&old_dqstats) >= 0) { > /* Structures are currently the same */ > memcpy(dqstats, &old_dqstats, sizeof(old_dqstats)); > dqstats->version = 0; > @@ -83,7 +83,7 @@ static int get_stats(struct util_dqstats *dqstats) > errstr(_("Error while getting quota statistics from kernel: %s\n"), strerror(errno)); > goto out; > } > - if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (caddr_t)&v0_dqstats) < 0) { > + if (do_quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, NULL, 0, (caddr_t)&v0_dqstats) < 0) { > errstr(_("Error while getting old quota statistics from kernel: %s\n"), strerror(errno)); > goto out; > } > diff --git a/quotasync.c b/quotasync.c > index 80f7e9e..cad2a20 100644 > --- a/quotasync.c > +++ b/quotasync.c > @@ -100,7 +100,7 @@ static int sync_one(int type, char *dev) > { > int qcmd = QCMD(Q_SYNC, type); > > - return quotactl(qcmd, dev, 0, NULL); > + return do_quotactl(qcmd, dev, NULL, 0, NULL); > } > > static int syncquotas(int type) > diff --git a/quotasys.c b/quotasys.c > index 9af9932..903816b 100644 > --- a/quotasys.c > +++ b/quotasys.c > @@ -25,6 +25,7 @@ > #include <sys/vfs.h> > #include <stdint.h> > #include <sys/utsname.h> > +#include <sys/syscall.h> > > #include "pot.h" > #include "bylabel.h" > @@ -670,6 +671,36 @@ const char *str2number(const char *string, qsize_t *inodes) > return NULL; > } > > +/* > + * Wrappers for quotactl syscalls > + */ > +#ifdef SYS_quotactl_fd > +int do_quotactl(int cmd, const char *dev, const char *mnt, int id, caddr_t addr) > +{ > + int ret = -EINVAL; > + > + if (mnt && !dev) { > + int fd = open(mnt, O_DIRECTORY | O_PATH); > + > + if (fd < 0) { > + errstr(_("Unable to get a filedescriptor from mountpoint: %s\n"), mnt); > + return fd; > + } > + > + ret = syscall(SYS_quotactl_fd, fd, cmd, id, addr); > + close(fd); > + return ret; > + } > + > + return quotactl(cmd, dev, id, addr); > +} > +#else > +int do_quotactl(int cmd, const char *dev, const char *mnt, int id, caddr_t addr) > +{ > + return quotactl(cmd, dev, id, addr); > +} > +#endif > + > /* > * Wrappers for mount options processing functions > */ > @@ -685,7 +716,7 @@ static int hasxfsquota(const char *dev, struct mntent *mnt, int type, int flags) > return QF_XFS; > > memset(&info, 0, sizeof(struct xfs_mem_dqinfo)); > - if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) { > + if (!do_quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, mnt->mnt_dir, 0, (void *)&info)) { > #ifdef XFS_ROOTHACK > int sbflags = (info.qs_flags & 0xff00) >> 8; > #endif /* XFS_ROOTHACK */ > @@ -719,7 +750,7 @@ static int hasvfsmetaquota(const char *dev, struct mntent *mnt, int type, int fl > { > uint32_t fmt; > > - if (!quotactl(QCMD(Q_GETFMT, type), dev, 0, (void *)&fmt)) > + if (!do_quotactl(QCMD(Q_GETFMT, type), dev, mnt->mnt_dir, 0, (void *)&fmt)) > return QF_META; > return QF_ERROR; > } > @@ -796,7 +827,7 @@ static int hasquota(const char *dev, struct mntent *mnt, int type, int flags) > if (!strcmp(mnt->mnt_type, MNTTYPE_EXT4) || !strcmp(mnt->mnt_type, MNTTYPE_F2FS)) { > struct if_dqinfo kinfo; > > - if (quotactl(QCMD(Q_GETINFO, type), dev, 0, (void *)&kinfo) == 0) { > + if (do_quotactl(QCMD(Q_GETINFO, type), dev, mnt->mnt_dir, 0, (void *)&kinfo) == 0) { > if (kinfo.dqi_flags & DQF_SYS_FILE) > return QF_META; > } > @@ -1069,11 +1100,11 @@ void init_kernel_interface(void) > else { > fs_quota_stat_t dummy; > > - if (!quotactl(QCMD(Q_XGETQSTAT, 0), "/dev/root", 0, (void *)&dummy) || > + if (!do_quotactl(QCMD(Q_XGETQSTAT, 0), "/dev/root", NULL, 0, (void *)&dummy) || > (errno != EINVAL && errno != ENOSYS)) > kernel_qfmt[kernel_qfmt_num++] = QF_XFS; > } > - if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (void *)&v2_stats) >= 0) { > + if (do_quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, NULL, 0, (void *)&v2_stats) >= 0) { > kernel_qfmt[kernel_qfmt_num++] = QF_VFSV0; > kernel_iface = IFACE_VFSV0; > } > @@ -1085,9 +1116,9 @@ void init_kernel_interface(void) > int err_quota = 0; > char tmp[1024]; /* Just temporary buffer */ > > - if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, tmp)) > + if (do_quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, NULL, 0, tmp)) > err_stat = errno; > - if (quotactl(QCMD(Q_V1_GETQUOTA, 0), "/dev/null", 0, tmp)) > + if (do_quotactl(QCMD(Q_V1_GETQUOTA, 0), "/dev/null", NULL, 0, tmp)) > err_quota = errno; > > /* On a RedHat 2.4.2-2 we expect 0, EINVAL > @@ -1127,7 +1158,7 @@ static int v1_kern_quota_on(const char *dev, int type) > char tmp[1024]; /* Just temporary buffer */ > qid_t id = (type == USRQUOTA) ? getuid() : getgid(); > > - if (!quotactl(QCMD(Q_V1_GETQUOTA, type), dev, id, tmp)) /* OK? */ > + if (!do_quotactl(QCMD(Q_V1_GETQUOTA, type), dev, NULL, id, tmp)) /* OK? */ > return 1; > return 0; > } > @@ -1138,7 +1169,7 @@ static int v2_kern_quota_on(const char *dev, int type) > char tmp[1024]; /* Just temporary buffer */ > qid_t id = (type == USRQUOTA) ? getuid() : getgid(); > > - if (!quotactl(QCMD(Q_V2_GETQUOTA, type), dev, id, tmp)) /* OK? */ > + if (!do_quotactl(QCMD(Q_V2_GETQUOTA, type), dev, NULL, id, tmp)) /* OK? */ > return 1; > return 0; > } > @@ -1155,7 +1186,7 @@ int kern_quota_state_xfs(const char *dev, int type) > { > struct xfs_mem_dqinfo info; > > - if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) { > + if (!do_quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, NULL, 0, (void *)&info)) { > if (type == USRQUOTA) { > return !!(info.qs_flags & XFS_QUOTA_UDQ_ACCT) + > !!(info.qs_flags & XFS_QUOTA_UDQ_ENFD); > @@ -1199,8 +1230,8 @@ int kern_quota_on(struct mount_entry *mnt, int type, int fmt) > if (kernel_iface == IFACE_GENERIC) { > int actfmt; > > - if (quotactl(QCMD(Q_GETFMT, type), mnt->me_devname, 0, > - (void *)&actfmt) >= 0) { > + if (do_quotactl(QCMD(Q_GETFMT, type), mnt->me_devname, > + mnt->me_dir, 0, (void *)&actfmt) >= 0) { > actfmt = kern2utilfmt(actfmt); > if (actfmt >= 0) > return actfmt; > diff --git a/quotasys.h b/quotasys.h > index 841251e..b166ad2 100644 > --- a/quotasys.h > +++ b/quotasys.h > @@ -206,6 +206,9 @@ void end_mounts_scan(void); > /* Parse kernel version and return 1 if ext4 supports quota feature */ > int ext4_supports_quota_feature(void); > > +/* Wrapper around quota syscalls, either call quotactl or quotactl_fd */ > +int do_quotactl(int cmd, const char *dev, const char *mnt, int id, caddr_t addr); > + > /* Quota output formats */ > #define QOF_ERROR -1 > #define QOF_DEFAULT 0 > -- > 2.43.0 > -- Jan Kara <jack@suse.com> SUSE Labs, CR ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Re: [PATCH 2/3] Add quotactl_fd() support 2024-01-17 18:08 ` Jan Kara @ 2024-01-24 11:25 ` Carlos Maiolino 0 siblings, 0 replies; 9+ messages in thread From: Carlos Maiolino @ 2024-01-24 11:25 UTC (permalink / raw) To: Jan Kara; +Cc: linux-fsdevel On Wed, Jan 17, 2024 at 07:08:33PM +0100, Jan Kara wrote: > On Tue 09-01-24 14:46:04, cem@kernel.org wrote: > > From: Carlos Maiolino <cem@kernel.org> > > > > To be able to set quotas on filesystems without a backing device, quota tools > > should be able to use quotactl_fd(). > > To achieve that, add a new helper, do_quotactl(), to select between quotactl() > > and quotactl_fd(). > > > > This shouldn't change the semantics of current code. quotactl_fd() will be > > called if and only if the handlers contain an empty device, and a valid > > mountpoint. > > All current calls containing a value device should be still handled by quotactl(). > > The same is true for calls passing a NULL device on purpose, aiming to sync > > active quotas. > > > > Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> > > quota-tools work on mounted filesystems so ideally we could switch all the > places to use quotactl_fd() (if the kernel supports it - we probably have > to keep the fallback for some time yet). But for now what you do is fine > and we can clean that up later. Thanks for the review! I do agree with you. I can work on such cleanup later for sure. Carlos > > Honza > > > --- > > Makefile.am | 1 + > > quotacheck.c | 12 +++++------ > > quotaio.c | 4 ++-- > > quotaio_generic.c | 12 +++++------ > > quotaio_meta.c | 4 ++-- > > quotaio_v1.c | 10 ++++----- > > quotaio_v2.c | 12 +++++------ > > quotaio_xfs.c | 21 ++++++++++-------- > > quotaon.c | 8 +++---- > > quotaon_xfs.c | 9 ++++---- > > quotastats.c | 4 ++-- > > quotasync.c | 2 +- > > quotasys.c | 55 ++++++++++++++++++++++++++++++++++++----------- > > quotasys.h | 3 +++ > > 14 files changed, 98 insertions(+), 59 deletions(-) > > > > diff --git a/Makefile.am b/Makefile.am > > index 372eafb..13a0f06 100644 > > --- a/Makefile.am > > +++ b/Makefile.am > > @@ -207,6 +207,7 @@ quotastats_SOURCES = \ > > pot.h > > > > quotastats_LDADD = \ > > + libquota.a \ > > $(INTLLIBS) > > > > xqmstats_SOURCES = \ > > diff --git a/quotacheck.c b/quotacheck.c > > index bd62d9a..e2c3bbd 100644 > > --- a/quotacheck.c > > +++ b/quotacheck.c > > @@ -648,8 +648,8 @@ Please turn quotas off or use -f to force checking.\n"), > > type2name(type), mnt->me_dir); > > } > > /* At least sync quotas so damage will be smaller */ > > - if (quotactl(QCMD((kernel_iface == IFACE_GENERIC)? Q_SYNC : Q_6_5_SYNC, type), > > - mnt->me_devname, 0, NULL) < 0) > > + if (do_quotactl(QCMD((kernel_iface == IFACE_GENERIC)? Q_SYNC : Q_6_5_SYNC, type), > > + mnt->me_devname, mnt->me_dir, 0, NULL) < 0) > > die(4, _("Error while syncing quotas on %s: %s\n"), mnt->me_devname, strerror(errno)); > > } > > > > @@ -848,8 +848,8 @@ static int dump_to_file(struct mount_entry *mnt, int type) > > if (get_qf_name(mnt, type, cfmt, NF_FORMAT, &filename) < 0) > > errstr(_("Cannot find checked quota file for %ss on %s!\n"), _(type2name(type)), mnt->me_devname); > > else { > > - if (quotactl(QCMD((kernel_iface == IFACE_GENERIC) ? Q_QUOTAOFF : Q_6_5_QUOTAOFF, type), > > - mnt->me_devname, 0, NULL) < 0) > > + if (do_quotactl(QCMD((kernel_iface == IFACE_GENERIC) ? Q_QUOTAOFF : Q_6_5_QUOTAOFF, type), > > + mnt->me_devname, mnt->me_dir, 0, NULL) < 0) > > errstr(_("Cannot turn %s quotas off on %s: %s\nKernel won't know about changes quotacheck did.\n"), > > _(type2name(type)), mnt->me_devname, strerror(errno)); > > else { > > @@ -859,9 +859,9 @@ static int dump_to_file(struct mount_entry *mnt, int type) > > rename_files(mnt, type); > > > > if (kernel_iface == IFACE_GENERIC) > > - ret = quotactl(QCMD(Q_QUOTAON, type), mnt->me_devname, util2kernfmt(cfmt), filename); > > + ret = do_quotactl(QCMD(Q_QUOTAON, type), mnt->me_devname, mnt->me_dir, util2kernfmt(cfmt), filename); > > else > > - ret = quotactl(QCMD(Q_6_5_QUOTAON, type), mnt->me_devname, 0, filename); > > + ret = do_quotactl(QCMD(Q_6_5_QUOTAON, type), mnt->me_devname, mnt->me_dir, 0, filename); > > if (ret < 0) > > errstr(_("Cannot turn %s quotas on on %s: %s\nKernel won't know about changes quotacheck did.\n"), > > _(type2name(type)), mnt->me_devname, strerror(errno)); > > diff --git a/quotaio.c b/quotaio.c > > index 94ae458..9bebb5e 100644 > > --- a/quotaio.c > > +++ b/quotaio.c > > @@ -140,8 +140,8 @@ struct quota_handle *init_io(struct mount_entry *mnt, int type, int fmt, int fla > > if (QIO_ENABLED(h)) { /* Kernel uses same file? */ > > unsigned int cmd = > > (kernel_iface == IFACE_GENERIC) ? Q_SYNC : Q_6_5_SYNC; > > - if (quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, > > - 0, NULL) < 0) { > > + if (do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, > > + h->qh_dir, 0, NULL) < 0) { > > die(4, _("Cannot sync quotas on device %s: %s\n"), > > h->qh_quotadev, strerror(errno)); > > } > > diff --git a/quotaio_generic.c b/quotaio_generic.c > > index 5b23955..3c95872 100644 > > --- a/quotaio_generic.c > > +++ b/quotaio_generic.c > > @@ -50,7 +50,7 @@ int vfs_get_info(struct quota_handle *h) > > { > > struct if_dqinfo kinfo; > > > > - if (quotactl(QCMD(Q_GETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kinfo) < 0) { > > + if (do_quotactl(QCMD(Q_GETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kinfo) < 0) { > > errstr(_("Cannot get info for %s quota file from kernel on %s: %s\n"), type2name(h->qh_type), h->qh_quotadev, strerror(errno)); > > return -1; > > } > > @@ -68,7 +68,7 @@ int vfs_set_info(struct quota_handle *h, int flags) > > kinfo.dqi_igrace = h->qh_info.dqi_igrace; > > kinfo.dqi_valid = flags; > > > > - if (quotactl(QCMD(Q_SETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kinfo) < 0) { > > + if (do_quotactl(QCMD(Q_SETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kinfo) < 0) { > > errstr(_("Cannot set info for %s quota file from kernel on %s: %s\n"), type2name(h->qh_type), h->qh_quotadev, strerror(errno)); > > return -1; > > } > > @@ -80,7 +80,7 @@ int vfs_get_dquot(struct dquot *dquot) > > { > > struct if_dqblk kdqblk; > > > > - if (quotactl(QCMD(Q_GETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_id, (void *)&kdqblk) < 0) { > > + if (do_quotactl(QCMD(Q_GETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) { > > errstr(_("Cannot get quota for %s %d from kernel on %s: %s\n"), type2name(dquot->dq_h->qh_type), dquot->dq_id, dquot->dq_h->qh_quotadev, strerror(errno)); > > return -1; > > } > > @@ -95,7 +95,7 @@ int vfs_set_dquot(struct dquot *dquot, int flags) > > > > generic_util2kerndqblk(&kdqblk, &dquot->dq_dqb); > > kdqblk.dqb_valid = flags; > > - if (quotactl(QCMD(Q_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_id, (void *)&kdqblk) < 0) { > > + if (do_quotactl(QCMD(Q_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) { > > errstr(_("Cannot set quota for %s %d from kernel on %s: %s\n"), type2name(dquot->dq_h->qh_type), dquot->dq_id, dquot->dq_h->qh_quotadev, strerror(errno)); > > return -1; > > } > > @@ -188,8 +188,8 @@ int vfs_scan_dquots(struct quota_handle *h, > > > > dquot->dq_h = h; > > while (1) { > > - ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), > > - h->qh_quotadev, id, (void *)&kdqblk); > > + ret = do_quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), > > + h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk); > > if (ret < 0) > > break; > > > > diff --git a/quotaio_meta.c b/quotaio_meta.c > > index ad6ff7a..51ebbcf 100644 > > --- a/quotaio_meta.c > > +++ b/quotaio_meta.c > > @@ -59,8 +59,8 @@ static int meta_scan_dquots(struct quota_handle *h, int (*process_dquot)(struct > > struct if_nextdqblk kdqblk; > > int ret; > > > > - ret = quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), h->qh_quotadev, 0, > > - (void *)&kdqblk); > > + ret = do_quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), h->qh_quotadev, > > + h->qh_dir, 0, (void *)&kdqblk); > > /* > > * Fall back to scanning using passwd if Q_GETNEXTQUOTA is not > > * supported > > diff --git a/quotaio_v1.c b/quotaio_v1.c > > index 6a6dc78..187a5a5 100644 > > --- a/quotaio_v1.c > > +++ b/quotaio_v1.c > > @@ -118,7 +118,7 @@ static int v1_init_io(struct quota_handle *h) > > else { > > struct v1_kern_dqblk kdqblk; > > > > - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) { > > + if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) { > > if (errno == EPERM) { /* We have no permission to get this information? */ > > h->qh_info.dqi_bgrace = h->qh_info.dqi_igrace = 0; /* It hopefully won't be needed */ > > } > > @@ -193,11 +193,11 @@ static int v1_write_info(struct quota_handle *h) > > else { > > struct v1_kern_dqblk kdqblk; > > > > - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) > > + if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) > > return -1; > > kdqblk.dqb_btime = h->qh_info.dqi_bgrace; > > kdqblk.dqb_itime = h->qh_info.dqi_igrace; > > - if (quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) < 0) > > + if (do_quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) > > return -1; > > } > > } > > @@ -237,7 +237,7 @@ static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id) > > else { > > struct v1_kern_dqblk kdqblk; > > > > - if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) < 0) { > > + if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk) < 0) { > > free(dquot); > > return NULL; > > } > > @@ -299,7 +299,7 @@ static int v1_commit_dquot(struct dquot *dquot, int flags) > > else > > cmd = Q_V1_SETQUOTA; > > v1_util2kerndqblk(&kdqblk, &dquot->dq_dqb); > > - if (quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, dquot->dq_id, > > + if (do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, h->qh_dir, dquot->dq_id, > > (void *)&kdqblk) < 0) > > return -1; > > } > > diff --git a/quotaio_v2.c b/quotaio_v2.c > > index 56a549f..b0fe7bf 100644 > > --- a/quotaio_v2.c > > +++ b/quotaio_v2.c > > @@ -275,7 +275,7 @@ static int v2_init_io(struct quota_handle *h) > > else { > > struct v2_kern_dqinfo kdqinfo; > > > > - if (quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0) { > > + if (do_quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0) { > > /* Temporary check just before fix gets to kernel */ > > if (errno == EPERM) /* Don't have permission to get information? */ > > return 0; > > @@ -403,8 +403,8 @@ static int v2_write_info(struct quota_handle *h) > > kdqinfo.dqi_blocks = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks; > > kdqinfo.dqi_free_blk = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_blk; > > kdqinfo.dqi_free_entry = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_entry; > > - if (quotactl(QCMD(Q_V2_SETGRACE, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0 || > > - quotactl(QCMD(Q_V2_SETFLAGS, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) < 0) > > + if (do_quotactl(QCMD(Q_V2_SETGRACE, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0 || > > + do_quotactl(QCMD(Q_V2_SETFLAGS, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0) > > return -1; > > } > > } > > @@ -441,7 +441,7 @@ static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id) > > else { > > struct v2_kern_dqblk kdqblk; > > > > - if (quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) < 0) { > > + if (do_quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk) < 0) { > > free(dquot); > > return NULL; > > } > > @@ -485,8 +485,8 @@ static int v2_commit_dquot(struct dquot *dquot, int flags) > > else > > cmd = Q_V2_SETQUOTA; > > v2_util2kerndqblk(&kdqblk, &dquot->dq_dqb); > > - if (quotactl(QCMD(cmd, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, > > - dquot->dq_id, (void *)&kdqblk) < 0) > > + if (do_quotactl(QCMD(cmd, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, > > + dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) > > return -1; > > } > > return 0; > > diff --git a/quotaio_xfs.c b/quotaio_xfs.c > > index 5abb2c2..0bf6f34 100644 > > --- a/quotaio_xfs.c > > +++ b/quotaio_xfs.c > > @@ -128,7 +128,7 @@ static int xfs_init_io(struct quota_handle *h) > > > > qcmd = QCMD(Q_XFS_GETQSTAT, h->qh_type); > > memset(&info, 0, sizeof(struct xfs_mem_dqinfo)); > > - if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&info) < 0) > > + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, 0, (void *)&info) < 0) > > return -1; > > h->qh_info.dqi_bgrace = info.qs_btimelimit; > > h->qh_info.dqi_igrace = info.qs_itimelimit; > > @@ -153,7 +153,7 @@ static int xfs_write_info(struct quota_handle *h) > > xdqblk.d_itimer = h->qh_info.dqi_igrace; > > xdqblk.d_fieldmask |= FS_DQ_TIMER_MASK; > > qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type); > > - if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&xdqblk) < 0) > > + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, 0, (void *)&xdqblk) < 0) > > return -1; > > return 0; > > } > > @@ -174,7 +174,8 @@ static struct dquot *xfs_read_dquot(struct quota_handle *h, qid_t id) > > return dquot; > > > > qcmd = QCMD(Q_XFS_GETQUOTA, h->qh_type); > > - if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) { > > + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, > > + id, (void *)&xdqblk) < 0) { > > ; > > } > > else { > > @@ -219,7 +220,7 @@ static int xfs_commit_dquot(struct dquot *dquot, int flags) > > } > > > > qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type); > > - if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) > > + if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, id, (void *)&xdqblk) < 0) > > return -1; > > return 0; > > } > > @@ -234,7 +235,9 @@ static int xfs_get_dquot(struct dquot *dq) > > int ret; > > > > memset(&d, 0, sizeof(d)); > > - ret = quotactl(qcmd, dq->dq_h->qh_quotadev, dq->dq_id, (void *)&d); > > + ret = do_quotactl(qcmd, dq->dq_h->qh_quotadev, dq->dq_h->qh_dir, > > + dq->dq_id, (void *)&d); > > + > > if (ret < 0) { > > if (errno == ENOENT) > > return 0; > > @@ -254,8 +257,8 @@ static int xfs_kernel_scan_dquots(struct quota_handle *h, > > > > dquot->dq_h = h; > > while (1) { > > - ret = quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), > > - h->qh_quotadev, id, (void *)&xdqblk); > > + ret = do_quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), > > + h->qh_quotadev, h->qh_dir, id, (void *)&xdqblk); > > if (ret < 0) > > break; > > > > @@ -286,8 +289,8 @@ static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct > > int ret; > > struct xfs_kern_dqblk xdqblk; > > > > - ret = quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), h->qh_quotadev, 0, > > - (void *)&xdqblk); > > + ret = do_quotactl(QCMD(Q_XGETNEXTQUOTA, h->qh_type), h->qh_quotadev, > > + h->qh_dir, 0, (void *)&xdqblk); > > if (ret < 0 && (errno == ENOSYS || errno == EINVAL)) { > > if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h) && !XFS_PRJQUOTA(h)) > > return 0; > > diff --git a/quotaon.c b/quotaon.c > > index 125b934..351c851 100644 > > --- a/quotaon.c > > +++ b/quotaon.c > > @@ -152,13 +152,13 @@ static int quotarsquashonoff(const char *quotadev, int type, int flags) > > > > info.dqi_flags = V1_DQF_RSQUASH; > > info.dqi_valid = IIF_FLAGS; > > - ret = quotactl(qcmd, quotadev, 0, (void *)&info); > > + ret = do_quotactl(qcmd, quotadev, NULL, 0, (void *)&info); > > } > > else { > > int mode = (flags & STATEFLAG_OFF) ? 0 : 1; > > int qcmd = QCMD(Q_V1_RSQUASH, type); > > > > - ret = quotactl(qcmd, quotadev, 0, (void *)&mode); > > + ret = do_quotactl(qcmd, quotadev, NULL, 0, (void *)&mode); > > } > > if (ret < 0) { > > errstr(_("set root_squash on %s: %s\n"), quotadev, strerror(errno)); > > @@ -184,7 +184,7 @@ static int quotaonoff(const char *quotadev, const char *quotadir, char *quotafil > > qcmd = QCMD(Q_QUOTAOFF, type); > > else > > qcmd = QCMD(Q_6_5_QUOTAOFF, type); > > - if (quotactl(qcmd, quotadev, 0, NULL) < 0) { > > + if (do_quotactl(qcmd, quotadev, quotadir, 0, NULL) < 0) { > > errstr(_("quotactl on %s [%s]: %s\n"), quotadev, quotadir, strerror(errno)); > > return 1; > > } > > @@ -199,7 +199,7 @@ static int quotaonoff(const char *quotadev, const char *quotadir, char *quotafil > > qcmd = QCMD(Q_6_5_QUOTAON, type); > > kqf = 0; > > } > > - if (quotactl(qcmd, quotadev, kqf, (void *)quotafile) < 0) { > > + if (do_quotactl(qcmd, quotadev, quotadir, kqf, (void *)quotafile) < 0) { > > if (errno == ENOENT) > > errstr(_("cannot find %s on %s [%s]\n"), quotafile, quotadev, quotadir); > > else > > diff --git a/quotaon_xfs.c b/quotaon_xfs.c > > index d137240..dda3023 100644 > > --- a/quotaon_xfs.c > > +++ b/quotaon_xfs.c > > @@ -32,7 +32,7 @@ static int xfs_state_check(int qcmd, int type, int flags, const char *dev, int r > > if (flags & STATEFLAG_ALL) > > return 0; /* noop */ > > > > - if (quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info) < 0) { > > + if (do_quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, NULL, 0, (void *)&info) < 0) { > > errstr(_("quotactl() on %s: %s\n"), dev, strerror(errno)); > > return -1; > > } > > @@ -156,7 +156,7 @@ static int xfs_onoff(const char *dev, int type, int flags, int roothack, int xop > > if (check != 1) > > return (check < 0); > > > > - if (quotactl(QCMD(qcmd, type), dev, 0, (void *)&xopts) < 0) { > > + if (do_quotactl(QCMD(qcmd, type), dev, NULL, 0, (void *)&xopts) < 0) { > > errstr(_("quotactl on %s: %s\n"), dev, strerror(errno)); > > return 1; > > } > > @@ -176,7 +176,7 @@ static int xfs_delete(const char *dev, int type, int flags, int roothack, int xo > > if (check != 1) > > return (check < 0); > > > > - if (quotactl(QCMD(qcmd, type), dev, 0, (void *)&xopts) < 0) { > > + if (do_quotactl(QCMD(qcmd, type), dev, NULL, 0, (void *)&xopts) < 0) { > > errstr(_("Failed to delete quota: %s\n"), > > strerror(errno)); > > return 1; > > @@ -208,7 +208,8 @@ int xfs_newstate(struct mount_entry *mnt, int type, char *xarg, int flags) > > struct xfs_mem_dqinfo info; > > u_int16_t sbflags = 0; > > > > - if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), mnt->me_devname, 0, (void *)&info)) > > + if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), mnt->me_devname, > > + mnt->me_dir, 0, (void *)&info)) > > sbflags = (info.qs_flags & 0xff00) >> 8; > > > > if ((type == USRQUOTA && (sbflags & XFS_QUOTA_UDQ_ACCT)) && > > diff --git a/quotastats.c b/quotastats.c > > index a059812..ee23afd 100644 > > --- a/quotastats.c > > +++ b/quotastats.c > > @@ -72,7 +72,7 @@ static int get_stats(struct util_dqstats *dqstats) > > dqstats->free_dquots = get_proc_num("free_dquots"); > > dqstats->syncs = get_proc_num("syncs"); > > } > > - else if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, (caddr_t)&old_dqstats) >= 0) { > > + else if (do_quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, NULL, 0, (caddr_t)&old_dqstats) >= 0) { > > /* Structures are currently the same */ > > memcpy(dqstats, &old_dqstats, sizeof(old_dqstats)); > > dqstats->version = 0; > > @@ -83,7 +83,7 @@ static int get_stats(struct util_dqstats *dqstats) > > errstr(_("Error while getting quota statistics from kernel: %s\n"), strerror(errno)); > > goto out; > > } > > - if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (caddr_t)&v0_dqstats) < 0) { > > + if (do_quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, NULL, 0, (caddr_t)&v0_dqstats) < 0) { > > errstr(_("Error while getting old quota statistics from kernel: %s\n"), strerror(errno)); > > goto out; > > } > > diff --git a/quotasync.c b/quotasync.c > > index 80f7e9e..cad2a20 100644 > > --- a/quotasync.c > > +++ b/quotasync.c > > @@ -100,7 +100,7 @@ static int sync_one(int type, char *dev) > > { > > int qcmd = QCMD(Q_SYNC, type); > > > > - return quotactl(qcmd, dev, 0, NULL); > > + return do_quotactl(qcmd, dev, NULL, 0, NULL); > > } > > > > static int syncquotas(int type) > > diff --git a/quotasys.c b/quotasys.c > > index 9af9932..903816b 100644 > > --- a/quotasys.c > > +++ b/quotasys.c > > @@ -25,6 +25,7 @@ > > #include <sys/vfs.h> > > #include <stdint.h> > > #include <sys/utsname.h> > > +#include <sys/syscall.h> > > > > #include "pot.h" > > #include "bylabel.h" > > @@ -670,6 +671,36 @@ const char *str2number(const char *string, qsize_t *inodes) > > return NULL; > > } > > > > +/* > > + * Wrappers for quotactl syscalls > > + */ > > +#ifdef SYS_quotactl_fd > > +int do_quotactl(int cmd, const char *dev, const char *mnt, int id, caddr_t addr) > > +{ > > + int ret = -EINVAL; > > + > > + if (mnt && !dev) { > > + int fd = open(mnt, O_DIRECTORY | O_PATH); > > + > > + if (fd < 0) { > > + errstr(_("Unable to get a filedescriptor from mountpoint: %s\n"), mnt); > > + return fd; > > + } > > + > > + ret = syscall(SYS_quotactl_fd, fd, cmd, id, addr); > > + close(fd); > > + return ret; > > + } > > + > > + return quotactl(cmd, dev, id, addr); > > +} > > +#else > > +int do_quotactl(int cmd, const char *dev, const char *mnt, int id, caddr_t addr) > > +{ > > + return quotactl(cmd, dev, id, addr); > > +} > > +#endif > > + > > /* > > * Wrappers for mount options processing functions > > */ > > @@ -685,7 +716,7 @@ static int hasxfsquota(const char *dev, struct mntent *mnt, int type, int flags) > > return QF_XFS; > > > > memset(&info, 0, sizeof(struct xfs_mem_dqinfo)); > > - if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) { > > + if (!do_quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, mnt->mnt_dir, 0, (void *)&info)) { > > #ifdef XFS_ROOTHACK > > int sbflags = (info.qs_flags & 0xff00) >> 8; > > #endif /* XFS_ROOTHACK */ > > @@ -719,7 +750,7 @@ static int hasvfsmetaquota(const char *dev, struct mntent *mnt, int type, int fl > > { > > uint32_t fmt; > > > > - if (!quotactl(QCMD(Q_GETFMT, type), dev, 0, (void *)&fmt)) > > + if (!do_quotactl(QCMD(Q_GETFMT, type), dev, mnt->mnt_dir, 0, (void *)&fmt)) > > return QF_META; > > return QF_ERROR; > > } > > @@ -796,7 +827,7 @@ static int hasquota(const char *dev, struct mntent *mnt, int type, int flags) > > if (!strcmp(mnt->mnt_type, MNTTYPE_EXT4) || !strcmp(mnt->mnt_type, MNTTYPE_F2FS)) { > > struct if_dqinfo kinfo; > > > > - if (quotactl(QCMD(Q_GETINFO, type), dev, 0, (void *)&kinfo) == 0) { > > + if (do_quotactl(QCMD(Q_GETINFO, type), dev, mnt->mnt_dir, 0, (void *)&kinfo) == 0) { > > if (kinfo.dqi_flags & DQF_SYS_FILE) > > return QF_META; > > } > > @@ -1069,11 +1100,11 @@ void init_kernel_interface(void) > > else { > > fs_quota_stat_t dummy; > > > > - if (!quotactl(QCMD(Q_XGETQSTAT, 0), "/dev/root", 0, (void *)&dummy) || > > + if (!do_quotactl(QCMD(Q_XGETQSTAT, 0), "/dev/root", NULL, 0, (void *)&dummy) || > > (errno != EINVAL && errno != ENOSYS)) > > kernel_qfmt[kernel_qfmt_num++] = QF_XFS; > > } > > - if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (void *)&v2_stats) >= 0) { > > + if (do_quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, NULL, 0, (void *)&v2_stats) >= 0) { > > kernel_qfmt[kernel_qfmt_num++] = QF_VFSV0; > > kernel_iface = IFACE_VFSV0; > > } > > @@ -1085,9 +1116,9 @@ void init_kernel_interface(void) > > int err_quota = 0; > > char tmp[1024]; /* Just temporary buffer */ > > > > - if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, tmp)) > > + if (do_quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, NULL, 0, tmp)) > > err_stat = errno; > > - if (quotactl(QCMD(Q_V1_GETQUOTA, 0), "/dev/null", 0, tmp)) > > + if (do_quotactl(QCMD(Q_V1_GETQUOTA, 0), "/dev/null", NULL, 0, tmp)) > > err_quota = errno; > > > > /* On a RedHat 2.4.2-2 we expect 0, EINVAL > > @@ -1127,7 +1158,7 @@ static int v1_kern_quota_on(const char *dev, int type) > > char tmp[1024]; /* Just temporary buffer */ > > qid_t id = (type == USRQUOTA) ? getuid() : getgid(); > > > > - if (!quotactl(QCMD(Q_V1_GETQUOTA, type), dev, id, tmp)) /* OK? */ > > + if (!do_quotactl(QCMD(Q_V1_GETQUOTA, type), dev, NULL, id, tmp)) /* OK? */ > > return 1; > > return 0; > > } > > @@ -1138,7 +1169,7 @@ static int v2_kern_quota_on(const char *dev, int type) > > char tmp[1024]; /* Just temporary buffer */ > > qid_t id = (type == USRQUOTA) ? getuid() : getgid(); > > > > - if (!quotactl(QCMD(Q_V2_GETQUOTA, type), dev, id, tmp)) /* OK? */ > > + if (!do_quotactl(QCMD(Q_V2_GETQUOTA, type), dev, NULL, id, tmp)) /* OK? */ > > return 1; > > return 0; > > } > > @@ -1155,7 +1186,7 @@ int kern_quota_state_xfs(const char *dev, int type) > > { > > struct xfs_mem_dqinfo info; > > > > - if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) { > > + if (!do_quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, NULL, 0, (void *)&info)) { > > if (type == USRQUOTA) { > > return !!(info.qs_flags & XFS_QUOTA_UDQ_ACCT) + > > !!(info.qs_flags & XFS_QUOTA_UDQ_ENFD); > > @@ -1199,8 +1230,8 @@ int kern_quota_on(struct mount_entry *mnt, int type, int fmt) > > if (kernel_iface == IFACE_GENERIC) { > > int actfmt; > > > > - if (quotactl(QCMD(Q_GETFMT, type), mnt->me_devname, 0, > > - (void *)&actfmt) >= 0) { > > + if (do_quotactl(QCMD(Q_GETFMT, type), mnt->me_devname, > > + mnt->me_dir, 0, (void *)&actfmt) >= 0) { > > actfmt = kern2utilfmt(actfmt); > > if (actfmt >= 0) > > return actfmt; > > diff --git a/quotasys.h b/quotasys.h > > index 841251e..b166ad2 100644 > > --- a/quotasys.h > > +++ b/quotasys.h > > @@ -206,6 +206,9 @@ void end_mounts_scan(void); > > /* Parse kernel version and return 1 if ext4 supports quota feature */ > > int ext4_supports_quota_feature(void); > > > > +/* Wrapper around quota syscalls, either call quotactl or quotactl_fd */ > > +int do_quotactl(int cmd, const char *dev, const char *mnt, int id, caddr_t addr); > > + > > /* Quota output formats */ > > #define QOF_ERROR -1 > > #define QOF_DEFAULT 0 > > -- > > 2.43.0 > > > -- > Jan Kara <jack@suse.com> > SUSE Labs, CR ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/3] Enable support for tmpfs quotas 2024-01-09 13:46 [PATCH RFC 0/3] Enable tmpfs quotas cem 2024-01-09 13:46 ` [PATCH 1/3] Rename searched_dir->sd_dir to sd_isdir cem 2024-01-09 13:46 ` [PATCH 2/3] Add quotactl_fd() support cem @ 2024-01-09 13:46 ` cem 2024-01-17 17:59 ` Jan Kara 2 siblings, 1 reply; 9+ messages in thread From: cem @ 2024-01-09 13:46 UTC (permalink / raw) To: jack; +Cc: linux-fsdevel From: Carlos Maiolino <cem@kernel.org> To achieve so, add a new function handle_quota() to the quotaio subsystem, this will call do_quotactl() with or without a valid quotadev, according to the filesystem type. Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> --- mntopt.h | 1 + quotaio.c | 19 +++++++++++++++++-- quotaio.h | 2 ++ quotaio_generic.c | 11 +++++------ quotaio_meta.c | 3 +-- quotaio_v1.c | 11 +++++------ quotaio_v2.c | 11 +++++------ quotaio_xfs.c | 4 ++-- quotasys.c | 20 +++++++++++++++++--- 9 files changed, 55 insertions(+), 27 deletions(-) diff --git a/mntopt.h b/mntopt.h index 0f3b0c5..9b71990 100644 --- a/mntopt.h +++ b/mntopt.h @@ -22,6 +22,7 @@ #define MNTTYPE_MPFS "mpfs" /* EMC Celerra MPFS filesystem */ #define MNTTYPE_OCFS2 "ocfs2" /* Oracle Cluster filesystem */ #define MNTTYPE_GFS2 "gfs2" /* Red Hat Global filesystem 2 */ +#define MNTTYPE_TMPFS "tmpfs" /* tmpfs filesystem */ #ifndef MNTTYPE_NFS #define MNTTYPE_NFS "nfs" /* Network file system. */ diff --git a/quotaio.c b/quotaio.c index 9bebb5e..3cc2bb7 100644 --- a/quotaio.c +++ b/quotaio.c @@ -34,6 +34,22 @@ struct disk_dqheader { u_int32_t dqh_version; } __attribute__ ((packed)); +int handle_quota(int cmd, struct quota_handle *h, int id, void *addr) +{ + int err = -EINVAL; + + if (!h) + return err; + + if (!strcmp(h->qh_fstype, MNTTYPE_TMPFS)) + err = do_quotactl(QCMD(cmd, h->qh_type), NULL, h->qh_dir, + id, addr); + else + err = do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, + h->qh_dir, id, addr); + + return err; +} /* * Detect quota format and initialize quota IO */ @@ -140,8 +156,7 @@ struct quota_handle *init_io(struct mount_entry *mnt, int type, int fmt, int fla if (QIO_ENABLED(h)) { /* Kernel uses same file? */ unsigned int cmd = (kernel_iface == IFACE_GENERIC) ? Q_SYNC : Q_6_5_SYNC; - if (do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, - h->qh_dir, 0, NULL) < 0) { + if (handle_quota(cmd, h, 0, NULL) < 0) { die(4, _("Cannot sync quotas on device %s: %s\n"), h->qh_quotadev, strerror(errno)); } diff --git a/quotaio.h b/quotaio.h index 2c373b2..44e71c4 100644 --- a/quotaio.h +++ b/quotaio.h @@ -182,4 +182,6 @@ struct dquot *get_empty_dquot(void); /* Check whether values in current dquot can be stored on disk */ int check_dquot_range(struct dquot *dquot); +/* Use quota_handle data to call quotactl() or quotactl_fd() */ +int handle_quota(int cmd, struct quota_handle *h, int id, void *addr); #endif /* GUARD_QUOTAIO_H */ diff --git a/quotaio_generic.c b/quotaio_generic.c index 3c95872..862ab63 100644 --- a/quotaio_generic.c +++ b/quotaio_generic.c @@ -50,7 +50,7 @@ int vfs_get_info(struct quota_handle *h) { struct if_dqinfo kinfo; - if (do_quotactl(QCMD(Q_GETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kinfo) < 0) { + if (handle_quota(Q_GETINFO, h, 0, (void *)&kinfo) < 0) { errstr(_("Cannot get info for %s quota file from kernel on %s: %s\n"), type2name(h->qh_type), h->qh_quotadev, strerror(errno)); return -1; } @@ -68,7 +68,7 @@ int vfs_set_info(struct quota_handle *h, int flags) kinfo.dqi_igrace = h->qh_info.dqi_igrace; kinfo.dqi_valid = flags; - if (do_quotactl(QCMD(Q_SETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kinfo) < 0) { + if (handle_quota(Q_SETINFO, h, 0, (void *)&kinfo) < 0) { errstr(_("Cannot set info for %s quota file from kernel on %s: %s\n"), type2name(h->qh_type), h->qh_quotadev, strerror(errno)); return -1; } @@ -80,7 +80,7 @@ int vfs_get_dquot(struct dquot *dquot) { struct if_dqblk kdqblk; - if (do_quotactl(QCMD(Q_GETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) { + if (handle_quota(Q_GETQUOTA, dquot->dq_h, dquot->dq_id, (void *)&kdqblk) < 0) { errstr(_("Cannot get quota for %s %d from kernel on %s: %s\n"), type2name(dquot->dq_h->qh_type), dquot->dq_id, dquot->dq_h->qh_quotadev, strerror(errno)); return -1; } @@ -95,7 +95,7 @@ int vfs_set_dquot(struct dquot *dquot, int flags) generic_util2kerndqblk(&kdqblk, &dquot->dq_dqb); kdqblk.dqb_valid = flags; - if (do_quotactl(QCMD(Q_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) { + if (handle_quota(Q_SETQUOTA, dquot->dq_h, dquot->dq_id, (void *)&kdqblk) < 0) { errstr(_("Cannot set quota for %s %d from kernel on %s: %s\n"), type2name(dquot->dq_h->qh_type), dquot->dq_id, dquot->dq_h->qh_quotadev, strerror(errno)); return -1; } @@ -188,8 +188,7 @@ int vfs_scan_dquots(struct quota_handle *h, dquot->dq_h = h; while (1) { - ret = do_quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), - h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk); + ret = handle_quota(Q_GETNEXTQUOTA, h, id, (void *)&kdqblk); if (ret < 0) break; diff --git a/quotaio_meta.c b/quotaio_meta.c index 51ebbcf..e774c1d 100644 --- a/quotaio_meta.c +++ b/quotaio_meta.c @@ -59,8 +59,7 @@ static int meta_scan_dquots(struct quota_handle *h, int (*process_dquot)(struct struct if_nextdqblk kdqblk; int ret; - ret = do_quotactl(QCMD(Q_GETNEXTQUOTA, h->qh_type), h->qh_quotadev, - h->qh_dir, 0, (void *)&kdqblk); + ret = handle_quota(Q_GETNEXTQUOTA, h, 0, (void *)&kdqblk); /* * Fall back to scanning using passwd if Q_GETNEXTQUOTA is not * supported diff --git a/quotaio_v1.c b/quotaio_v1.c index 187a5a5..90bf5a6 100644 --- a/quotaio_v1.c +++ b/quotaio_v1.c @@ -118,7 +118,7 @@ static int v1_init_io(struct quota_handle *h) else { struct v1_kern_dqblk kdqblk; - if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) { + if (handle_quota(Q_V1_GETQUOTA, h, 0, (void *)&kdqblk) < 0) { if (errno == EPERM) { /* We have no permission to get this information? */ h->qh_info.dqi_bgrace = h->qh_info.dqi_igrace = 0; /* It hopefully won't be needed */ } @@ -193,11 +193,11 @@ static int v1_write_info(struct quota_handle *h) else { struct v1_kern_dqblk kdqblk; - if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) + if (handle_quota(Q_V1_GETQUOTA, h, 0, (void *)&kdqblk) < 0) return -1; kdqblk.dqb_btime = h->qh_info.dqi_bgrace; kdqblk.dqb_itime = h->qh_info.dqi_igrace; - if (do_quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqblk) < 0) + if (handle_quota(Q_V1_SETQUOTA, h, 0, (void *)&kdqblk) < 0) return -1; } } @@ -237,7 +237,7 @@ static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id) else { struct v1_kern_dqblk kdqblk; - if (do_quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk) < 0) { + if (handle_quota(Q_V1_GETQUOTA, h, id, (void *)&kdqblk) < 0) { free(dquot); return NULL; } @@ -299,8 +299,7 @@ static int v1_commit_dquot(struct dquot *dquot, int flags) else cmd = Q_V1_SETQUOTA; v1_util2kerndqblk(&kdqblk, &dquot->dq_dqb); - if (do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, h->qh_dir, dquot->dq_id, - (void *)&kdqblk) < 0) + if (handle_quota(cmd, h, dquot->dq_id, (void *)&kdqblk) < 0) return -1; } } diff --git a/quotaio_v2.c b/quotaio_v2.c index b0fe7bf..1100a19 100644 --- a/quotaio_v2.c +++ b/quotaio_v2.c @@ -275,7 +275,7 @@ static int v2_init_io(struct quota_handle *h) else { struct v2_kern_dqinfo kdqinfo; - if (do_quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0) { + if (handle_quota(Q_V2_GETINFO, h, 0, (void *)&kdqinfo) < 0) { /* Temporary check just before fix gets to kernel */ if (errno == EPERM) /* Don't have permission to get information? */ return 0; @@ -403,8 +403,8 @@ static int v2_write_info(struct quota_handle *h) kdqinfo.dqi_blocks = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_blocks; kdqinfo.dqi_free_blk = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_blk; kdqinfo.dqi_free_entry = h->qh_info.u.v2_mdqi.dqi_qtree.dqi_free_entry; - if (do_quotactl(QCMD(Q_V2_SETGRACE, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0 || - do_quotactl(QCMD(Q_V2_SETFLAGS, h->qh_type), h->qh_quotadev, h->qh_dir, 0, (void *)&kdqinfo) < 0) + if (handle_quota(Q_V2_SETGRACE, h, 0, (void *)&kdqinfo) < 0 || + handle_quota(Q_V2_SETFLAGS, h, 0, (void *)&kdqinfo) < 0) return -1; } } @@ -441,7 +441,7 @@ static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id) else { struct v2_kern_dqblk kdqblk; - if (do_quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, h->qh_dir, id, (void *)&kdqblk) < 0) { + if (handle_quota(Q_V2_GETQUOTA, h, id, (void *)&kdqblk) < 0) { free(dquot); return NULL; } @@ -485,8 +485,7 @@ static int v2_commit_dquot(struct dquot *dquot, int flags) else cmd = Q_V2_SETQUOTA; v2_util2kerndqblk(&kdqblk, &dquot->dq_dqb); - if (do_quotactl(QCMD(cmd, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev, - dquot->dq_h->qh_dir, dquot->dq_id, (void *)&kdqblk) < 0) + if (handle_quota(cmd, dquot->dq_h, dquot->dq_id, (void *)&kdqblk) < 0) return -1; } return 0; diff --git a/quotaio_xfs.c b/quotaio_xfs.c index 0bf6f34..34fd044 100644 --- a/quotaio_xfs.c +++ b/quotaio_xfs.c @@ -128,7 +128,7 @@ static int xfs_init_io(struct quota_handle *h) qcmd = QCMD(Q_XFS_GETQSTAT, h->qh_type); memset(&info, 0, sizeof(struct xfs_mem_dqinfo)); - if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, 0, (void *)&info) < 0) + if (handle_quota(qcmd, h, 0, (void *)&info) < 0) return -1; h->qh_info.dqi_bgrace = info.qs_btimelimit; h->qh_info.dqi_igrace = info.qs_itimelimit; @@ -153,7 +153,7 @@ static int xfs_write_info(struct quota_handle *h) xdqblk.d_itimer = h->qh_info.dqi_igrace; xdqblk.d_fieldmask |= FS_DQ_TIMER_MASK; qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type); - if (do_quotactl(qcmd, h->qh_quotadev, h->qh_dir, 0, (void *)&xdqblk) < 0) + if (handle_quota(qcmd, h, 0, (void *)&xdqblk) < 0) return -1; return 0; } diff --git a/quotasys.c b/quotasys.c index 903816b..1f66302 100644 --- a/quotasys.c +++ b/quotasys.c @@ -752,6 +752,7 @@ static int hasvfsmetaquota(const char *dev, struct mntent *mnt, int type, int fl if (!do_quotactl(QCMD(Q_GETFMT, type), dev, mnt->mnt_dir, 0, (void *)&fmt)) return QF_META; + return QF_ERROR; } @@ -816,8 +817,13 @@ static int hasquota(const char *dev, struct mntent *mnt, int type, int flags) !strcmp(mnt->mnt_type, MNTTYPE_XFS) || !strcmp(mnt->mnt_type, MNTTYPE_EXFS)) return hasxfsquota(dev, mnt, type, flags); + if (!strcmp(mnt->mnt_type, MNTTYPE_OCFS2)) return hasvfsmetaquota(dev, mnt, type, flags); + + /* tmpfs has no device, pass null here so quotactl_fd() is called */ + if (!strcmp(mnt->mnt_type, MNTTYPE_TMPFS)) + return hasvfsmetaquota(NULL, mnt, type, flags); /* * For ext4 we check whether it has quota in system files and if not, * we fall back on checking standard quotas. Furthermore we cannot use @@ -1384,7 +1390,11 @@ alloc: continue; } - if (!nfs_fstype(mnt->mnt_type)) { + /* + * If devname and mnt->mnt_fsname matches, there is no real + * underlyin device, so skip these checks + */ + if (!nfs_fstype(mnt->mnt_type) && strcmp(devname, mnt->mnt_fsname)) { if (stat(devname, &st) < 0) { /* Can't stat mounted device? */ errstr(_("Cannot stat() mounted device %s: %s\n"), devname, strerror(errno)); free((char *)devname); @@ -1398,6 +1408,7 @@ alloc: dev = st.st_rdev; for (i = 0; i < mnt_entries_cnt && mnt_entries[i].me_dev != dev; i++); } + /* Cope with network filesystems or new mountpoint */ if (nfs_fstype(mnt->mnt_type) || i == mnt_entries_cnt) { if (stat(mnt->mnt_dir, &st) < 0) { /* Can't stat mountpoint? We have better ignore it... */ @@ -1570,8 +1581,11 @@ restart: sd = check_dirs + act_checked; for (i = 0; i < mnt_entries_cnt; i++) { if (sd->sd_isdir) { - if (sd->sd_dev == mnt_entries[i].me_dev && sd->sd_ino == mnt_entries[i].me_ino) - break; + if (sd->sd_ino == mnt_entries[i].me_ino) + if ((sd->sd_dev == mnt_entries[i].me_dev) || + (!strcmp(mnt_entries[i].me_type, MNTTYPE_TMPFS))) + break; + } else if (sd->sd_dev == mnt_entries[i].me_dev) -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] Enable support for tmpfs quotas 2024-01-09 13:46 ` [PATCH 3/3] Enable support for tmpfs quotas cem @ 2024-01-17 17:59 ` Jan Kara 2024-01-24 11:42 ` Carlos Maiolino 0 siblings, 1 reply; 9+ messages in thread From: Jan Kara @ 2024-01-17 17:59 UTC (permalink / raw) To: cem; +Cc: jack, linux-fsdevel On Tue 09-01-24 14:46:05, cem@kernel.org wrote: > From: Carlos Maiolino <cem@kernel.org> > > To achieve so, add a new function handle_quota() to the quotaio subsystem, > this will call do_quotactl() with or without a valid quotadev, according to the > filesystem type. > > Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> Thanks for the patch. Some comments bewow. > diff --git a/quotaio.c b/quotaio.c > index 9bebb5e..3cc2bb7 100644 > --- a/quotaio.c > +++ b/quotaio.c > @@ -34,6 +34,22 @@ struct disk_dqheader { > u_int32_t dqh_version; > } __attribute__ ((packed)); > > +int handle_quota(int cmd, struct quota_handle *h, int id, void *addr) Call this quotactl_handle()? > +{ > + int err = -EINVAL; > + > + if (!h) > + return err; > + > + if (!strcmp(h->qh_fstype, MNTTYPE_TMPFS)) > + err = do_quotactl(QCMD(cmd, h->qh_type), NULL, h->qh_dir, > + id, addr); > + else > + err = do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, > + h->qh_dir, id, addr); > + > + return err; > +} ... > diff --git a/quotasys.c b/quotasys.c > index 903816b..1f66302 100644 > --- a/quotasys.c > +++ b/quotasys.c > @@ -1384,7 +1390,11 @@ alloc: > continue; > } > > - if (!nfs_fstype(mnt->mnt_type)) { > + /* > + * If devname and mnt->mnt_fsname matches, there is no real > + * underlyin device, so skip these checks > + */ > + if (!nfs_fstype(mnt->mnt_type) && strcmp(devname, mnt->mnt_fsname)) { > if (stat(devname, &st) < 0) { /* Can't stat mounted device? */ > errstr(_("Cannot stat() mounted device %s: %s\n"), devname, strerror(errno)); > free((char *)devname); I'm a bit uneasy about the added check because using device name the same as filesystem name is just a common agreement but not enforced in any way. So perhaps just add an explicit check for tmpfs? Later we can generalize this if there are more filesystems like this... Honza -- Jan Kara <jack@suse.com> SUSE Labs, CR ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Re: [PATCH 3/3] Enable support for tmpfs quotas 2024-01-17 17:59 ` Jan Kara @ 2024-01-24 11:42 ` Carlos Maiolino 2024-01-24 15:16 ` Jan Kara 0 siblings, 1 reply; 9+ messages in thread From: Carlos Maiolino @ 2024-01-24 11:42 UTC (permalink / raw) To: Jan Kara; +Cc: linux-fsdevel On Wed, Jan 17, 2024 at 06:59:54PM +0100, Jan Kara wrote: > On Tue 09-01-24 14:46:05, cem@kernel.org wrote: > > From: Carlos Maiolino <cem@kernel.org> > > > > To achieve so, add a new function handle_quota() to the quotaio subsystem, > > this will call do_quotactl() with or without a valid quotadev, according to the > > filesystem type. > > > > Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com> > > Thanks for the patch. Some comments bewow. > > > diff --git a/quotaio.c b/quotaio.c > > index 9bebb5e..3cc2bb7 100644 > > --- a/quotaio.c > > +++ b/quotaio.c > > @@ -34,6 +34,22 @@ struct disk_dqheader { > > u_int32_t dqh_version; > > } __attribute__ ((packed)); > > > > +int handle_quota(int cmd, struct quota_handle *h, int id, void *addr) > > Call this quotactl_handle()? > > > +{ > > + int err = -EINVAL; > > + > > + if (!h) > > + return err; > > + > > + if (!strcmp(h->qh_fstype, MNTTYPE_TMPFS)) > > + err = do_quotactl(QCMD(cmd, h->qh_type), NULL, h->qh_dir, > > + id, addr); > > + else > > + err = do_quotactl(QCMD(cmd, h->qh_type), h->qh_quotadev, > > + h->qh_dir, id, addr); > > + > > + return err; > > +} > > ... > > > diff --git a/quotasys.c b/quotasys.c > > index 903816b..1f66302 100644 > > --- a/quotasys.c > > +++ b/quotasys.c > > @@ -1384,7 +1390,11 @@ alloc: > > continue; > > } > > > > - if (!nfs_fstype(mnt->mnt_type)) { > > + /* > > + * If devname and mnt->mnt_fsname matches, there is no real > > + * underlyin device, so skip these checks > > + */ > > + if (!nfs_fstype(mnt->mnt_type) && strcmp(devname, mnt->mnt_fsname)) { > > if (stat(devname, &st) < 0) { /* Can't stat mounted device? */ > > errstr(_("Cannot stat() mounted device %s: %s\n"), devname, strerror(errno)); > > free((char *)devname); > > I'm a bit uneasy about the added check because using device name the same > as filesystem name is just a common agreement but not enforced in any way. > So perhaps just add an explicit check for tmpfs? Later we can generalize > this if there are more filesystems like this... What about adding a new tmpfs_fstype() helper, to mimic nfs_fstype, and use it here? like: if (!nfs_fstype(mnt->mnt_type) && tmpfs_fstype(mnt->mnt_type))) { /* skipe S_ISBLK && S_ISCHR checks */ } We could open code !strcmp(mnt->mnt_type, MNTTYPE_TMPFS), but it seems to me adding a new tmpfs_fstype() helper is easier on the eyes, and also OCFS2 does something similar. Perhaps that's exactly what you meant as having an explicit check for tmpfs, but I'm not really sure?! Carlos > > Honza > -- > Jan Kara <jack@suse.com> > SUSE Labs, CR ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] Enable support for tmpfs quotas 2024-01-24 11:42 ` Carlos Maiolino @ 2024-01-24 15:16 ` Jan Kara 0 siblings, 0 replies; 9+ messages in thread From: Jan Kara @ 2024-01-24 15:16 UTC (permalink / raw) To: Carlos Maiolino; +Cc: Jan Kara, linux-fsdevel On Wed 24-01-24 12:42:39, Carlos Maiolino wrote: > On Wed, Jan 17, 2024 at 06:59:54PM +0100, Jan Kara wrote: > > On Tue 09-01-24 14:46:05, cem@kernel.org wrote: > > > diff --git a/quotasys.c b/quotasys.c > > > index 903816b..1f66302 100644 > > > --- a/quotasys.c > > > +++ b/quotasys.c > > > @@ -1384,7 +1390,11 @@ alloc: > > > continue; > > > } > > > > > > - if (!nfs_fstype(mnt->mnt_type)) { > > > + /* > > > + * If devname and mnt->mnt_fsname matches, there is no real > > > + * underlyin device, so skip these checks > > > + */ > > > + if (!nfs_fstype(mnt->mnt_type) && strcmp(devname, mnt->mnt_fsname)) { > > > if (stat(devname, &st) < 0) { /* Can't stat mounted device? */ > > > errstr(_("Cannot stat() mounted device %s: %s\n"), devname, strerror(errno)); > > > free((char *)devname); > > > > I'm a bit uneasy about the added check because using device name the same > > as filesystem name is just a common agreement but not enforced in any way. > > So perhaps just add an explicit check for tmpfs? Later we can generalize > > this if there are more filesystems like this... > > What about adding a new tmpfs_fstype() helper, to mimic nfs_fstype, and use it > here? like: > > if (!nfs_fstype(mnt->mnt_type) && tmpfs_fstype(mnt->mnt_type))) { > /* skipe S_ISBLK && S_ISCHR checks */ > } > > We could open code !strcmp(mnt->mnt_type, MNTTYPE_TMPFS), but it seems to me > adding a new tmpfs_fstype() helper is easier on the eyes, and also OCFS2 does > something similar. > > Perhaps that's exactly what you meant as having an explicit check for tmpfs, but > I'm not really sure?! Yes, this would be a nice way of doing it. Honza -- Jan Kara <jack@suse.com> SUSE Labs, CR ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2024-01-24 15:17 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-01-09 13:46 [PATCH RFC 0/3] Enable tmpfs quotas cem 2024-01-09 13:46 ` [PATCH 1/3] Rename searched_dir->sd_dir to sd_isdir cem 2024-01-09 13:46 ` [PATCH 2/3] Add quotactl_fd() support cem 2024-01-17 18:08 ` Jan Kara 2024-01-24 11:25 ` Carlos Maiolino 2024-01-09 13:46 ` [PATCH 3/3] Enable support for tmpfs quotas cem 2024-01-17 17:59 ` Jan Kara 2024-01-24 11:42 ` Carlos Maiolino 2024-01-24 15:16 ` Jan Kara
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).