Hello.

  Following patch fixes bug in dquot_transfer() - while we were sleeping
i_blocks might change and so number quota was miscounted. Patches are
against 2.2.16 and 2.4.0-test6 (but should apply well on newer versions).

                                                        Honza

--- linux/fs/dquot.c    Tue Aug 29 11:01:00 2000
+++ linux/fs/dquot.c    Sat Sep  2 23:01:04 2000
@@ -1260,14 +1260,6 @@
        if (!inode)
                return -ENOENT;
        /*
-        * Find out if this filesystem uses i_blocks.
-        */
-       if (inode->i_blksize == 0)
-               blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE);
-       else
-               blocks = (inode->i_blocks / 2);
-
-       /*
         * Build the transfer_from and transfer_to lists and check quotas to see
         * if operation is permitted.
         */
@@ -1326,13 +1318,25 @@
                 * dqget() could block and so the first structure might got
                 * invalidated or locked...
                 */
-               if (!transfer_to[cnt]->dq_mnt || !transfer_from[cnt]->dq_mnt ||
-                   check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA ||
-                   check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == 
NO_QUOTA) {
+               if (!transfer_to[cnt]->dq_mnt || !transfer_from[cnt]->dq_mnt) {
                        cnt++;
                        goto put_all;
                }
        }
+
+       /*
+        * Find out if this filesystem uses i_blocks.
+        */
+       if (inode->i_blksize == 0)
+               blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE);
+       else
+               blocks = (inode->i_blocks / 2);
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               if (check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA ||
+                   check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == 
+NO_QUOTA) {
+                       cnt = MAXQUOTAS;
+                       goto put_all;
+               }
 
        if ((error = notify_change(dentry, iattr)))
                goto put_all; 
--- linux/fs/dquot.c    Mon Aug 28 20:12:25 2000
+++ linux/fs/dquot.c    Sat Sep  2 23:10:29 2000
@@ -1214,14 +1214,6 @@
 
        lock_kernel();
        /*
-        * Find out if this filesystem uses i_blocks.
-        */
-       if (!inode->i_sb->s_blocksize)
-               blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE_BITS);
-       else
-               blocks = (inode->i_blocks >> 1);
-
-       /*
         * Build the transfer_from and transfer_to lists and check quotas to see
         * if operation is permitted.
         */
@@ -1280,13 +1272,25 @@
                 * dqget() could block and so the first structure might got
                 * invalidated or locked...
                 */
-               if (!transfer_to[cnt]->dq_sb || !transfer_from[cnt]->dq_sb ||
-                   check_idq(transfer_to[cnt], 1) == NO_QUOTA ||
-                   check_bdq(transfer_to[cnt], blocks, 0) == NO_QUOTA) {
+               if (!transfer_to[cnt]->dq_sb || !transfer_from[cnt]->dq_sb) {
                        cnt++;
                        goto put_all;
                }
        }
+
+       /*
+        * Find out if this filesystem uses i_blocks.
+        */
+       if (!inode->i_sb->s_blocksize)
+               blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE_BITS);
+       else
+               blocks = (inode->i_blocks >> 1);
+       for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+               if (check_idq(transfer_to[cnt], 1) == NO_QUOTA ||
+                   check_bdq(transfer_to[cnt], blocks, 0) == NO_QUOTA) {
+                       cnt = MAXQUOTAS;
+                       goto put_all;
+               }
 
        if ((error = notify_change(dentry, iattr)))
                goto put_all; 

Reply via email to