summaryrefslogtreecommitdiff
path: root/quotaio_generic.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2011-05-05 16:14:07 +0200
committerJan Kara <jack@suse.cz>2011-05-05 16:14:07 +0200
commitc3a392437a2ec4793f2b1112058de0c3b459b6fe (patch)
tree0af9cc6eb7c7e9155716142d33cd937aefe89648 /quotaio_generic.c
parente482f256411dba6a9d647e6df7f24eef8af3d59b (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.c63
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;
+}