diff options
-rw-r--r-- | convertquota.c | 2 | ||||
-rw-r--r-- | quotaio.c | 24 | ||||
-rw-r--r-- | quotaio_generic.c | 63 | ||||
-rw-r--r-- | quotaio_generic.h | 6 | ||||
-rw-r--r-- | quotaio_meta.c | 6 | ||||
-rw-r--r-- | quotaio_xfs.c | 68 | ||||
-rw-r--r-- | quotasys.h | 2 | ||||
-rw-r--r-- | repquota.c | 4 | ||||
-rw-r--r-- | warnquota.c | 4 |
9 files changed, 104 insertions, 75 deletions
diff --git a/convertquota.c b/convertquota.c index ab16193..1e40804 100644 --- a/convertquota.c +++ b/convertquota.c @@ -312,7 +312,7 @@ static int convert_format(int type, struct mntent *mnt) struct quota_handle *qo; int ret = 0; - if (!(qo = init_io(mnt, type, infmt, IOI_OPENFILE))) { + if (!(qo = init_io(mnt, type, infmt, IOI_INITSCAN))) { errstr(_("Cannot open old format file for %ss on %s\n"), type2name(type), mnt->mnt_dir); return -1; @@ -43,6 +43,7 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags) int fd = -1, kernfmt; struct quota_handle *h = smalloc(sizeof(struct quota_handle)); const char *mnt_fsname = NULL; + int nameflag; if (!hasquota(mnt, type, 0)) goto out_handle; @@ -110,44 +111,33 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt, int flags) errstr(_("Quota not supported by the filesystem.\n")); goto out_handle; } - if (flags & IOI_OPENFILE) { - errstr(_("Operation not supported for filesystems with hidden quota files!\n")); - goto out_handle; - } h->qh_fd = -1; h->qh_fmt = fmt; goto set_ops; } + nameflag = (!QIO_ENABLED(h) || flags & IOI_INITSCAN) ? NF_FORMAT : 0; if (fmt == -1) { /* Let's try any VFSv0 quota format... */ - if (get_qf_name(mnt, type, QF_VFSV0, - (!QIO_ENABLED(h) || flags & IOI_OPENFILE) ? NF_FORMAT : 0, - &qfname) >= 0) + if (get_qf_name(mnt, type, QF_VFSV0, nameflag, &qfname) >= 0) fmt = QF_VFSV0; /* And then VFSv1 quota format... */ - else if (get_qf_name(mnt, type, QF_VFSV1, - (!QIO_ENABLED(h) || flags & IOI_OPENFILE) ? NF_FORMAT : 0, - &qfname) >= 0) + else if (get_qf_name(mnt, type, QF_VFSV1, nameflag, &qfname) >= 0) fmt = QF_VFSV1; /* And then old quota format... */ - else if (get_qf_name(mnt, type, QF_VFSOLD, - (!QIO_ENABLED(h) || flags & IOI_OPENFILE) ? NF_FORMAT : 0, - &qfname) >= 0) + else if (get_qf_name(mnt, type, QF_VFSOLD, nameflag, &qfname) >= 0) fmt = QF_VFSOLD; else { /* Don't know... */ errstr(_("Cannot find any quota file to work on.\n")); goto out_handle; } } else { - if (get_qf_name(mnt, type, fmt, - (!QIO_ENABLED(h) || flags & IOI_OPENFILE) ? NF_FORMAT : 0, - &qfname) < 0) { + if (get_qf_name(mnt, type, fmt, nameflag, &qfname) < 0) { errstr(_("Quota file not found or has wrong format.\n")); goto out_handle; } } - if (!QIO_ENABLED(h) || flags & IOI_OPENFILE) { /* Need to open file? */ + if (!QIO_ENABLED(h) || flags & IOI_INITSCAN) { /* Need to open file? */ if (QIO_ENABLED(h)) { /* Kernel uses same file? */ unsigned int cmd = (kernel_iface == IFACE_GENERIC) ? Q_SYNC : Q_6_5_SYNC; diff --git a/quotaio_generic.c b/quotaio_generic.c index e5df683..5001a56 100644 --- a/quotaio_generic.c +++ b/quotaio_generic.c @@ -8,6 +8,9 @@ #include <errno.h> #include <string.h> +#include <pwd.h> +#include <grp.h> +#include <stdlib.h> #include <sys/types.h> #include "pot.h" @@ -98,3 +101,63 @@ int vfs_set_dquot(struct dquot *dquot, int flags) } return 0; } + +static int scan_one_dquot(struct dquot *dquot, int (*get_dquot)(struct dquot *)) +{ + int ret; + struct util_dqblk *dqb = &dquot->dq_dqb; + + memset(dqb, 0, sizeof(struct util_dqblk)); + ret = get_dquot(dquot); + if (ret < 0) + return ret; + if (!dqb->dqb_bhardlimit && !dqb->dqb_bsoftlimit && !dqb->dqb_ihardlimit && !dqb->dqb_isoftlimit && !dqb->dqb_curinodes && !dqb->dqb_curspace) + return 1; + return 0; +} + +/* Generic quota scanning using passwd... */ +int generic_scan_dquots(struct quota_handle *h, + int (*process_dquot)(struct dquot *dquot, char *dqname), + int (*get_dquot)(struct dquot *dquot)) +{ + struct dquot *dquot = get_empty_dquot(); + int ret = 0; + + dquot->dq_h = h; + if (h->qh_type == USRQUOTA) { + struct passwd *usr; + + setpwent(); + while ((usr = getpwent()) != NULL) { + dquot->dq_id = usr->pw_uid; + ret = scan_one_dquot(dquot, get_dquot); + if (ret < 0) + break; + if (ret > 0) + continue; + ret = process_dquot(dquot, usr->pw_name); + if (ret < 0) + break; + } + endpwent(); + } else if (h->qh_type == GRPQUOTA) { + struct group *grp; + + setgrent(); + while ((grp = getgrent()) != NULL) { + dquot->dq_id = grp->gr_gid; + ret = scan_one_dquot(dquot, get_dquot); + if (ret < 0) + break; + if (ret > 0) + continue; + ret = process_dquot(dquot, grp->gr_name); + if (ret < 0) + break; + } + endgrent(); + } + free(dquot); + return ret; +} diff --git a/quotaio_generic.h b/quotaio_generic.h index 422fb52..5edc11c 100644 --- a/quotaio_generic.h +++ b/quotaio_generic.h @@ -21,4 +21,10 @@ int vfs_get_dquot(struct dquot *dquot); /* Set dquot in kernel */ int vfs_set_dquot(struct dquot *dquot, int flags); +/* Generic routine for scanning dquots when quota format does not have + * better way */ +int generic_scan_dquots(struct quota_handle *h, + int (*process_dquot)(struct dquot *dquot, char *dqname), + int (*get_dquot)(struct dquot *dquot)); + #endif diff --git a/quotaio_meta.c b/quotaio_meta.c index f1f714f..e52b4f4 100644 --- a/quotaio_meta.c +++ b/quotaio_meta.c @@ -53,9 +53,15 @@ static int meta_commit_dquot(struct dquot *dquot, int flags) return vfs_set_dquot(dquot, flags); } +static int meta_scan_dquots(struct quota_handle *h, int (*process_dquot)(struct dquot *dquot, char *dqname)) +{ + return generic_scan_dquots(h, process_dquot, vfs_get_dquot); +} + struct quotafile_ops quotafile_ops_meta = { init_io: meta_init_io, write_info: meta_write_info, read_dquot: meta_read_dquot, commit_dquot: meta_commit_dquot, +scan_dquots: meta_scan_dquots, }; diff --git a/quotaio_xfs.c b/quotaio_xfs.c index 62075b5..2e879e6 100644 --- a/quotaio_xfs.c +++ b/quotaio_xfs.c @@ -10,8 +10,6 @@ #include <stdlib.h> #include <string.h> #include <errno.h> -#include <pwd.h> -#include <grp.h> #include "pot.h" #include "common.h" @@ -19,6 +17,7 @@ #include "quotaio.h" #include "quotasys.h" #include "dqblk_xfs.h" +#include "quotaio_generic.h" #define XFS_USRQUOTA(h) ((h)->qh_type == USRQUOTA && \ (h)->qh_info.u.xfs_mdqi.qs_flags & XFS_QUOTA_UDQ_ACCT) @@ -175,24 +174,21 @@ static int xfs_commit_dquot(struct dquot *dquot, int flags) /* * xfs_scan_dquots helper - processes a single dquot */ -static int xfs_scan_dquot(struct quota_handle *h, - struct xfs_kern_dqblk *d, - char *name, struct dquot *dq, - int (*process_dquot) (struct dquot *dquot, char *dqname)) +static int xfs_get_dquot(struct dquot *dq) { - int qcmd = QCMD(Q_XFS_GETQUOTA, h->qh_type); - - memset(d, 0, sizeof(struct xfs_kern_dqblk)); - - if (quotactl(qcmd, h->qh_quotadev, dq->dq_id, (void *)d) < 0) { - return 0; + struct xfs_kern_dqblk d; + int qcmd = QCMD(Q_XFS_GETQUOTA, dq->dq_h->qh_type); + int ret; + + memset(&d, 0, sizeof(d)); + ret = quotactl(qcmd, dq->dq_h->qh_quotadev, dq->dq_id, (void *)&d); + if (ret < 0) { + if (ret == -ENOENT) + return 0; + return ret; } - if (d->d_blk_hardlimit == 0 && - d->d_blk_softlimit == 0 && - d->d_ino_hardlimit == 0 && - d->d_ino_softlimit == 0 && d->d_bcount == 0 && d->d_icount == 0) return 0; - xfs_kern2utildqblk(&dq->dq_dqb, d); - return process_dquot(dq, name); + xfs_kern2utildqblk(&dq->dq_dqb, &d); + return 0; } /* @@ -200,42 +196,10 @@ static int xfs_scan_dquot(struct quota_handle *h, */ static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot *dquot, char *dqname)) { - struct dquot *dq; - struct xfs_kern_dqblk d; - int rd = 0; - if (!XFS_USRQUOTA(h) && !XFS_GRPQUOTA(h)) - return rd; - - dq = get_empty_dquot(); - dq->dq_h = h; - if (h->qh_type == USRQUOTA) { - struct passwd *usr; - - setpwent(); - while ((usr = getpwent()) != NULL) { - dq->dq_id = usr->pw_uid; - rd = xfs_scan_dquot(h, &d, usr->pw_name, dq, process_dquot); - if (rd < 0) - break; - } - endpwent(); - } - else { /* GRPQUOTA */ - struct group *grp; - - setgrent(); - while ((grp = getgrent()) != NULL) { - dq->dq_id = grp->gr_gid; - rd = xfs_scan_dquot(h, &d, grp->gr_name, dq, process_dquot); - if (rd < 0) - break; - } - endgrent(); - } + return 0; - free(dq); - return rd; + return generic_scan_dquots(h, process_dquot, xfs_get_dquot); } /* @@ -20,7 +20,7 @@ /* Flags for IO initialization */ #define IOI_READONLY 0x1 /* Only readonly access */ -#define IOI_OPENFILE 0x2 /* Open file even if kernel has quotas turned on */ +#define IOI_INITSCAN 0x2 /* Prepare handle for scanning dquots */ #define IOI_NFS_MIXED_PATHS 0x4 /* Trim leading / from NFSv4 mountpoints */ #define KERN_KNOWN_QUOTA_VERSION (6*10000 + 5*100 + 1) @@ -317,9 +317,9 @@ static void report(int type) int i; if (flags & FL_ALL) - handles = create_handle_list(0, NULL, type, fmt, IOI_READONLY | IOI_OPENFILE, MS_LOCALONLY | (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0)); + handles = create_handle_list(0, NULL, type, fmt, IOI_READONLY | IOI_INITSCAN, MS_LOCALONLY | (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0)); else - handles = create_handle_list(mntcnt, mnt, type, fmt, IOI_READONLY | IOI_OPENFILE, MS_LOCALONLY | (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0)); + handles = create_handle_list(mntcnt, mnt, type, fmt, IOI_READONLY | IOI_INITSCAN, MS_LOCALONLY | (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0)); for (i = 0; handles[i]; i++) report_it(handles[i], type); dispose_handle_list(handles); diff --git a/warnquota.c b/warnquota.c index 9f09fcd..2ca286f 100644 --- a/warnquota.c +++ b/warnquota.c @@ -951,7 +951,7 @@ static void warn_quota(void) wc_exit(1); if (flags & FL_USER) { - handles = create_handle_list(0, NULL, USRQUOTA, -1, IOI_READONLY | IOI_OPENFILE, MS_LOCALONLY | (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0)); + handles = create_handle_list(0, NULL, USRQUOTA, -1, IOI_READONLY | IOI_INITSCAN, MS_LOCALONLY | (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0)); if (!maildev[0] || !strcasecmp(maildev, "any")) maildev_handle = NULL; else @@ -963,7 +963,7 @@ static void warn_quota(void) if (flags & FL_GROUP) { if (get_groupadmins() < 0) wc_exit(1); - handles = create_handle_list(0, NULL, GRPQUOTA, -1, IOI_READONLY | IOI_OPENFILE, MS_LOCALONLY | (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0)); + handles = create_handle_list(0, NULL, GRPQUOTA, -1, IOI_READONLY | IOI_INITSCAN, MS_LOCALONLY | (flags & FL_NOAUTOFS ? MS_NO_AUTOFS : 0)); if (!maildev[0] || !strcasecmp(maildev, "any")) maildev_handle = NULL; else |