xfs
[Top] [All Lists]

Re: repquota bug?

To: Andrey Nekrasov <andy@xxxxxxxxxx>, linux-xfs@xxxxxxxxxxx
Subject: Re: repquota bug?
From: "Nathan Scott" <nathans@xxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 4 May 2001 17:16:32 -0500
In-reply-to: Andrey Nekrasov <andy@spylog.com> "Re: repquota bug?" (May 4, 10:42am)
References: <20010503231735.A1917@an.local> <andy@spylog.com> <10105040845.ZM55988@wobbly.melbourne.sgi.com> <20010504104245.A3512@an.local>
Sender: owner-linux-xfs@xxxxxxxxxxx
hi Andrey,

Could you try the attached patch to the quota-3.01-pre5
user tools & ensure it fixes the problem?  I've forwarded
it onto the other quota maintainers to get their feedback
too (bug explanation follows if you're interested).

thanks.


--- Forwarded mail from <nathans@xxxxxxxxxxxxxxxxxxxxxxxx> ("Nathan Scott")

From: "Nathan Scott" <nathans@xxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 4 May 2001 17:04:15 -0500
To: Jan Kara <jack@xxxxxx>, Marco van Wieringen <mvw@xxxxxxxxxxxxxxx>
Subject: repquota bug

...[snip]...
The problem was basically that repquota can get into an
infinite loop on Redhat 7.1.  After some soul searching, it
turned out that the problem is to do with the implementation
of getpwent and getpwuid in the version of libc which ships
with that version of Redhat (which was why I had not seen it
before now myself).

I use getpwent in the xfs_scan_dquots, to find the users who
have quota information.  The problem is the "process_dquot"
callback routine makes a call to getpwuid, which resets (!)
the password entry state for subsequent getpwent calls, in
this particular libc version only it seems.  This reset
causes repquota to continually refetch the first passwd file
entry, instead of moving onto the next.

So, I've changed the code to pass the name associated with
the dquot id into the callback, so this reentrancy problem
no longer occurs.  For the other two quota formats, this
just means moving the id2name call out of repquota's "print"
callback and into the quotaio_v?.c files, and for XFS it
means there is no additional getpwuid() call since it has
already got the user/group name via getpwent/getgrent.
...[snip]...

---End of forwarded mail from <nathans@xxxxxxxxxxxxxxxxxxxxxxxx> ("Nathan 
Scott")


-- 
Nathan
diff -Naur -xpo -xdoc -xCVS pre5/quota-tools/convertquota.c 
cvs/quota-tools/convertquota.c
--- pre5/quota-tools/convertquota.c     Wed May  2 02:35:34 2001
+++ cvs/quota-tools/convertquota.c      Fri May  4 16:51:09 2001
@@ -72,7 +72,7 @@
        mntpoint = argstr[optind];
 }
 
-int convert_dquot(struct dquot *dquot)
+int convert_dquot(struct dquot *dquot, char *name)
 {
        struct dquot newdquot;
 
@@ -88,8 +88,8 @@
        newdquot.dq_dqb.dqb_btime = dquot->dq_dqb.dqb_btime;
        newdquot.dq_dqb.dqb_itime = dquot->dq_dqb.dqb_itime;
        if (qn->qh_ops->commit_dquot(&newdquot) < 0) {
-               errstr(_("Can't commit dquot for id %u: %s\n"),
-                       (uint)dquot->dq_id, strerror(errno));
+               errstr(_("Can't commit dquot for id %u (%s): %s\n"),
+                       (uint)dquot->dq_id, name, strerror(errno));
                return -1;
        }
        return 0;
diff -Naur -xpo -xdoc -xCVS pre5/quota-tools/quotaio.h cvs/quota-tools/quotaio.h
--- pre5/quota-tools/quotaio.h  Wed May  2 03:19:18 2001
+++ cvs/quota-tools/quotaio.h   Fri May  4 15:57:40 2001
@@ -122,7 +122,7 @@
        int (*write_info) (struct quota_handle * h);    /* Write info about 
quotafile */
        struct dquot *(*read_dquot) (struct quota_handle * h, qid_t id);        
/* Read dquot into memory */
        int (*commit_dquot) (struct dquot * dquot);     /* Write given dquot to 
disk */
-       int (*scan_dquots) (struct quota_handle * h, int (*process_dquot) 
(struct dquot * dquot));      /* Scan quotafile and call callback on every 
structure */
+       int (*scan_dquots) (struct quota_handle * h, int (*process_dquot) 
(struct dquot * dquot, char * dqname));       /* Scan quotafile and call 
callback on every structure */
        int (*report) (struct quota_handle * h, int verbose);   /* Function 
called after 'repquota' to print format specific file information */
 };
 
diff -Naur -xpo -xdoc -xCVS pre5/quota-tools/quotaio_v1.c 
cvs/quota-tools/quotaio_v1.c
--- pre5/quota-tools/quotaio_v1.c       Wed May  2 19:32:22 2001
+++ cvs/quota-tools/quotaio_v1.c        Fri May  4 15:59:43 2001
@@ -46,13 +46,14 @@
 #include "quotaio_v1.h"
 #include "dqblk_v1.h"
 #include "quotaio.h"
+#include "quotasys.h"
 
 static int v1_init_io(struct quota_handle *h);
 static int v1_new_io(struct quota_handle *h);
 static int v1_write_info(struct quota_handle *h);
 static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id);
 static int v1_commit_dquot(struct dquot *dquot);
-static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct 
dquot * dquot));
+static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct 
dquot *dquot, char *dqname));
 
 struct quotafile_ops quotafile_ops_1 = {
 init_io:       v1_init_io,
@@ -281,9 +282,10 @@
 /*
  *     Scan all dquots in file and call callback on each
  */
-static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct 
dquot * dquot))
+static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct 
dquot *, char *))
 {
        int rd;
+       char name[MAXNAMELEN];
        struct v1_disk_dqblk ddqblk;
        struct dquot *dquot = get_empty_dquot();
        qid_t id = 0;
@@ -303,7 +305,8 @@
                        continue;
                v1_disk2memdqblk(&dquot->dq_dqb, &ddqblk);
                dquot->dq_id = id;
-               if ((rd = process_dquot(dquot)) < 0) {
+               id2name(dquot->dq_id, h->qh_type, name);
+               if ((rd = process_dquot(dquot, name)) < 0) {
                        free(dquot);
                        return rd;
                }
diff -Naur -xpo -xdoc -xCVS pre5/quota-tools/quotaio_v2.c 
cvs/quota-tools/quotaio_v2.c
--- pre5/quota-tools/quotaio_v2.c       Wed May  2 20:00:57 2001
+++ cvs/quota-tools/quotaio_v2.c        Fri May  4 15:59:20 2001
@@ -17,6 +17,7 @@
 #include "quotaio_v2.h"
 #include "dqblk_v2.h"
 #include "quotaio.h"
+#include "quotasys.h"
 
 typedef char *dqbuf_t;
 
@@ -25,7 +26,7 @@
 static int v2_write_info(struct quota_handle *h);
 static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id);
 static int v2_commit_dquot(struct dquot *dquot);
-static int v2_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct 
dquot * dquot));
+static int v2_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct 
dquot *dquot, char *dqname));
 static int v2_report(struct quota_handle *h, int verbose);
 
 struct quotafile_ops quotafile_ops_2 = {
@@ -656,11 +657,12 @@
 #define get_bit(bmp, ind) ((bmp)[(ind) >> 3] & (1 << ((ind) & 7)))
 
 static int report_block(struct dquot *dquot, uint blk, char *bitmap,
-                       int (*process_dquot) (struct dquot *))
+                       int (*process_dquot) (struct dquot *, char *))
 {
        dqbuf_t buf = getdqbuf();
        struct v2_disk_dqdbheader *dh;
        struct v2_disk_dqblk *ddata;
+       char name[MAXNAMELEN];
        int entries, i;
 
        set_bit(bitmap, blk);
@@ -672,7 +674,8 @@
                if (!empty_dquot(ddata + i)) {
                        v2_disk2memdqblk(&dquot->dq_dqb, ddata + i);
                        dquot->dq_id = __le32_to_cpu(ddata[i].dqb_id);
-                       if (process_dquot(dquot) < 0)
+                       id2name(dquot->dq_id, dquot->dq_h->qh_type, name);
+                       if (process_dquot(dquot, name) < 0)
                                break;
                }
        freedqbuf(buf);
@@ -680,7 +683,7 @@
 }
 
 static int report_tree(struct dquot *dquot, uint blk, int depth, char *bitmap,
-                      int (*process_dquot) (struct dquot *))
+                      int (*process_dquot) (struct dquot *, char *))
 {
        int entries = 0, i;
        dqbuf_t buf = getdqbuf();
@@ -714,7 +717,7 @@
        return used;
 }
 
-static int v2_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct 
dquot * dquot))
+static int v2_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct 
dquot *, char *))
 {
        char *bitmap;
        struct v2_mem_dqinfo *info = &h->qh_info.u.v2_mdqi;
diff -Naur -xpo -xdoc -xCVS pre5/quota-tools/quotaio_xfs.c 
cvs/quota-tools/quotaio_xfs.c
--- pre5/quota-tools/quotaio_xfs.c      Wed Apr 11 20:06:06 2001
+++ cvs/quota-tools/quotaio_xfs.c       Fri May  4 15:38:40 2001
@@ -28,7 +28,7 @@
 static int xfs_write_info(struct quota_handle *h);
 static struct dquot *xfs_read_dquot(struct quota_handle *h, qid_t id);
 static int xfs_commit_dquot(struct dquot *dquot);
-static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) 
(struct dquot * dquot));
+static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) 
(struct dquot *dquot, char *dqname));
 static int xfs_report(struct quota_handle *h, int verbose);
 
 struct quotafile_ops quotafile_ops_xfs = {
@@ -166,7 +166,8 @@
  */
 static int xfs_scan_dquot(struct quota_handle *h,
                          struct xfs_kern_dqblk *d,
-                         struct dquot *dq, int (*process_dquot) (struct dquot 
* dquot))
+                         char *name, struct dquot *dq,
+                         int (*process_dquot) (struct dquot *dquot, char 
*dqname))
 {
        int qcmd = QCMD(Q_XFS_GETQUOTA, h->qh_type);
 
@@ -180,13 +181,13 @@
            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);
+       return process_dquot(dq, name);
 }
 
 /*
  *     Scan all known dquots and call callback on each
  */
-static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) 
(struct dquot * dquot))
+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;
@@ -203,7 +204,8 @@
                setpwent();
                while ((usr = getpwent()) != NULL) {
                        dq->dq_id = usr->pw_uid;
-                       if ((rd = xfs_scan_dquot(h, &d, dq, process_dquot)) < 0)
+                       rd = xfs_scan_dquot(h, &d, usr->pw_name, dq, 
process_dquot);
+                       if (rd < 0)
                                break;
                }
                endpwent();
@@ -214,7 +216,8 @@
                setgrent();
                while ((grp = getgrent()) != NULL) {
                        dq->dq_id = grp->gr_gid;
-                       if ((rd = xfs_scan_dquot(h, &d, dq, process_dquot)) < 0)
+                       rd = xfs_scan_dquot(h, &d, grp->gr_name, dq, 
process_dquot);
+                       if (rd < 0)
                                break;
                }
                endgrent();
diff -Naur -xpo -xdoc -xCVS pre5/quota-tools/repquota.c 
cvs/quota-tools/repquota.c
--- pre5/quota-tools/repquota.c Wed May  2 03:16:07 2001
+++ cvs/quota-tools/repquota.c  Fri May  4 15:48:50 2001
@@ -97,15 +97,13 @@
        return '-';
 }
 
-static int print(struct dquot *dquot)
+static int print(struct dquot *dquot, char *name)
 {
-       char name[MAXNAMELEN];
        char time[MAXTIMELEN];
        struct util_dqblk *entry = &dquot->dq_dqb;
 
        if (!entry->dqb_curspace && !entry->dqb_curinodes && !(flags & 
FL_VERBOSE))
                return 0;
-       id2name(dquot->dq_id, dquot->dq_h->qh_type, name);
        difftime2str(entry->dqb_btime, time);
        printf("%-10s%c%c%8Lu%8Lu%8Lu%7s", name,
               overlim(qb2kb(toqb(entry->dqb_curspace)), 
qb2kb(entry->dqb_bsoftlimit),
diff -Naur -xpo -xdoc -xCVS pre5/quota-tools/warnquota.c 
cvs/quota-tools/warnquota.c
--- pre5/quota-tools/warnquota.c        Wed May  2 19:32:22 2001
+++ cvs/quota-tools/warnquota.c Fri May  4 16:56:14 2001
@@ -25,7 +25,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <pwd.h>
 
 #include "mntopt.h"
 #include "pot.h"
@@ -92,26 +91,22 @@
  */
 static struct offenderlist *offenders = (struct offenderlist *)0;
 
-struct offenderlist *add_offender(int id)
+struct offenderlist *add_offender(int id, char *name)
 {
-       struct passwd *pwd;
        struct offenderlist *offender;
 
-       if ((pwd = getpwuid(id)) == (struct passwd *)0)
-               return ((struct offenderlist *)0);
-
        offender = (struct offenderlist *)smalloc(sizeof(struct offenderlist));
 
        offender->offender_id = id;
-       offender->offender_name = (char *)smalloc(strlen(pwd->pw_name) + 1);
+       offender->offender_name = (char *)smalloc(strlen(name) + 1);
        offender->usage = (struct usage *)NULL;
-       strcpy(offender->offender_name, pwd->pw_name);
+       strcpy(offender->offender_name, name);
        offender->next = offenders;
        offenders = offender;
        return offender;
 }
 
-void add_offence(struct dquot *dquot)
+void add_offence(struct dquot *dquot, char *name)
 {
        struct offenderlist *lptr;
        struct usage *usage;
@@ -121,7 +116,7 @@
                        break;
 
        if (!lptr)
-               if (!(lptr = add_offender(dquot->dq_id)))
+               if (!(lptr = add_offender(dquot->dq_id, name)))
                        return;
 
        usage = (struct usage *)smalloc(sizeof(struct usage));
@@ -135,13 +130,13 @@
        lptr->usage = usage;
 }
 
-int check_offence(struct dquot *dquot)
+int check_offence(struct dquot *dquot, char *name)
 {
        if (
            (dquot->dq_dqb.dqb_bsoftlimit
             && toqb(dquot->dq_dqb.dqb_curspace) >= 
dquot->dq_dqb.dqb_bsoftlimit)
            || (dquot->dq_dqb.dqb_isoftlimit
-               && dquot->dq_dqb.dqb_curinodes >= 
dquot->dq_dqb.dqb_isoftlimit)) add_offence(dquot);
+               && dquot->dq_dqb.dqb_curinodes >= 
dquot->dq_dqb.dqb_isoftlimit)) add_offence(dquot, name);
        return 0;
 }
 
<Prev in Thread] Current Thread [Next in Thread>