diff options
author | Jan Kara <jack@suse.cz> | 2011-05-05 16:14:07 +0200 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2011-05-05 16:14:07 +0200 |
commit | c3a392437a2ec4793f2b1112058de0c3b459b6fe (patch) | |
tree | 0af9cc6eb7c7e9155716142d33cd937aefe89648 /quotaio_generic.c | |
parent | e482f256411dba6a9d647e6df7f24eef8af3d59b (diff) |
Implement repquota for filesystems without quota files
Some filesystem do not have quota files accessible from userspace. For these
implementing ->scan_dquots() used by repquota is problematic. What we do is
that we iterate over all users and ask for quota information for each of them.
XFS already does this so make its code generic and use it for all filesystems
using quotaio_meta.c - only OCFS2 these days.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'quotaio_generic.c')
-rw-r--r-- | quotaio_generic.c | 63 |
1 files changed, 63 insertions, 0 deletions
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; +} |