Re: Quota speedup in 2.2.12 and bugfix

Jan Kara (jack@atrey.karlin.mff.cuni.cz)
Sat, 11 Sep 1999 20:28:17 +0200


--OKacYhQ+x31HxR33
Content-Type: text/plain; charset=us-ascii

> Hello.
>
> I'm sending you a small patch to quota code in 2.2.12. It does two things:
>
> 1) Fixes possible race in sync_dquots() where we could end up writing invalidated quota.
> 2) Speeds up quotaoff - currently when inode cache was full of inodes with quota pointers
> set, which is likely when quota enabled on root, quotaoff could take a few seconds
> which is unpleasant. So I made a bit more finegrained detection of blocking when we
> remove references from inodes and so we don't have to restart so often.
>
> The patch is attached.
>
> Bye
> Honza.
Oops. The patch was NOT attached... So I'll retry ;-).

--OKacYhQ+x31HxR33
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="quota-fix-2.2.12-2a.diff"

--- linux/fs/dquot.c Fri Aug 20 12:38:58 1999
+++ linux/fs/dquot.c Sat Sep 11 16:52:38 1999
@@ -97,6 +97,9 @@
static struct wait_queue *dquot_wait = (struct wait_queue *)NULL,
*update_wait = (struct wait_queue *)NULL;

+void dqput(struct dquot *);
+static struct dquot *dqduplicate(struct dquot *);
+
static inline char is_enabled(struct vfsmount *vfsmnt, short type)
{
switch (type) {
@@ -390,7 +393,7 @@

int sync_dquots(kdev_t dev, short type)
{
- struct dquot *dquot, *next;
+ struct dquot *dquot, *next, *ddquot;
int need_restart;

restart:
@@ -407,9 +410,11 @@
if (!(dquot->dq_flags & (DQ_LOCKED | DQ_MOD)))
continue;

- wait_on_dquot(dquot);
- if (dquot->dq_flags & DQ_MOD)
- write_dquot(dquot);
+ if ((ddquot = dqduplicate(dquot)) == NODQUOT)
+ continue;
+ if (ddquot->dq_flags & DQ_MOD)
+ write_dquot(ddquot);
+ dqput(ddquot);
/* Set the flag for another pass. */
need_restart = 1;
}
@@ -424,6 +429,7 @@
return(0);
}

+/* NOTE: If you change this function please check whether dqput_blocks() works right... */
void dqput(struct dquot *dquot)
{
if (!dquot)
@@ -688,6 +694,16 @@
}
}

+/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
+static inline int dqput_blocks(struct dquot *dquot)
+{
+ if (dquot->dq_flags & DQ_LOCKED)
+ return 1;
+ if (dquot->dq_count == 1)
+ return 1;
+ return 0;
+}
+
static int reset_inode_dquot_ptrs(struct inode *inode, short type)
{
struct dquot *dquot = inode->i_dquot[type];
@@ -701,13 +717,16 @@
}
inode->i_flags &= ~S_QUOTA;
put_it:
- if (dquot != NODQUOT) {
- spin_unlock(&inode_lock); /* We may block so drop the lock... */
- dqput(dquot);
- spin_lock(&inode_lock); /* And capture lock again */
- /* we may have blocked ... */
- return 1;
- }
+ if (dquot != NODQUOT)
+ if (dqput_blocks(dquot)) {
+ spin_unlock(&inode_lock); /* We may block so drop the lock... */
+ dqput(dquot);
+ spin_lock(&inode_lock); /* And capture lock again */
+ /* we may have blocked ... */
+ return 1;
+ }
+ else
+ dqput(dquot); /* dqput() won't block so we can hold locks... */
return 0;
}

--OKacYhQ+x31HxR33--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/