vserver 1.9.5.x5
[linux-2.6.git] / fs / jfs / jfs_xtree.c
index 19913fc..11c58c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -829,8 +830,12 @@ int xtInsert(tid_t tid,            /* transaction id */
                        hint = addressXAD(xad) + lengthXAD(xad) - 1;
                } else
                        hint = 0;
-               if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr)))
+               if ((rc = DQUOT_ALLOC_BLOCK(ip, xlen)))
                        goto out;
+               if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr))) {
+                       DQUOT_FREE_BLOCK(ip, xlen);
+                       goto out;
+               }
        }
 
        /*
@@ -855,8 +860,10 @@ int xtInsert(tid_t tid,            /* transaction id */
                split.pxdlist = NULL;
                if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {
                        /* undo data extent allocation */
-                       if (*xaddrp == 0)
+                       if (*xaddrp == 0) {
                                dbFree(ip, xaddr, (s64) xlen);
+                               DQUOT_FREE_BLOCK(ip, xlen);
+                       }
                        return rc;
                }
 
@@ -951,7 +958,7 @@ xtSplitUp(tid_t tid,
 
        /* is inode xtree root extension/inline EA area free ? */
        if ((sp->header.flag & BT_ROOT) && (!S_ISDIR(ip->i_mode)) &&
-           (sp->header.maxentry < cpu_to_le16(XTROOTMAXSLOT)) &&
+           (le16_to_cpu(sp->header.maxentry) < XTROOTMAXSLOT) &&
            (JFS_IP(ip)->mode2 & INLINEEA)) {
                sp->header.maxentry = cpu_to_le16(XTROOTMAXSLOT);
                JFS_IP(ip)->mode2 &= ~INLINEEA;
@@ -1214,22 +1221,34 @@ xtSplitPage(tid_t tid, struct inode *ip,
        pxd_t *pxd;
        struct tlock *tlck;
        struct xtlock *sxtlck = NULL, *rxtlck = NULL;
+       int quota_allocation = 0;
 
        smp = split->mp;
        sp = XT_PAGE(ip, smp);
 
        INCREMENT(xtStat.split);
 
-       /*
-        * allocate the new right page for the split
-        */
        pxdlist = split->pxdlist;
        pxd = &pxdlist->pxd[pxdlist->npxd];
        pxdlist->npxd++;
        rbn = addressPXD(pxd);
+
+       /* Allocate blocks to quota. */
+       if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+              rc = -EDQUOT;
+              goto clean_up;
+       }
+
+       quota_allocation += lengthPXD(pxd);
+
+       /*
+        * allocate the new right page for the split
+        */
        rmp = get_metapage(ip, rbn, PSIZE, 1);
-       if (rmp == NULL)
-               return -EIO;
+       if (rmp == NULL) {
+               rc = -EIO;
+               goto clean_up;
+       }
 
        jfs_info("xtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
 
@@ -1304,8 +1323,6 @@ xtSplitPage(tid_t tid, struct inode *ip,
                *rmpp = rmp;
                *rbnp = rbn;
 
-               ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
                jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
                return 0;
        }
@@ -1321,7 +1338,7 @@ xtSplitPage(tid_t tid, struct inode *ip,
                XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
                if (rc) {
                        XT_PUTPAGE(rmp);
-                       return rc;
+                       goto clean_up;
                }
 
                BT_MARK_DIRTY(mp, ip);
@@ -1420,10 +1437,16 @@ xtSplitPage(tid_t tid, struct inode *ip,
        *rmpp = rmp;
        *rbnp = rbn;
 
-       ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
        jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
        return rc;
+
+      clean_up:
+
+       /* Rollback quota allocation. */
+       if (quota_allocation)
+               DQUOT_FREE_BLOCK(ip, quota_allocation);
+
+       return (rc);
 }
 
 
@@ -1478,6 +1501,12 @@ xtSplitRoot(tid_t tid,
        if (rmp == NULL)
                return -EIO;
 
+       /* Allocate blocks to quota. */
+       if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+               release_metapage(rmp);
+               return -EDQUOT;
+       }
+
        jfs_info("xtSplitRoot: ip:0x%p rmp:0x%p", ip, rmp);
 
        /*
@@ -1561,8 +1590,6 @@ xtSplitRoot(tid_t tid,
 
        *rmpp = rmp;
 
-       ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
        jfs_info("xtSplitRoot: sp:0x%p rp:0x%p", sp, rp);
        return 0;
 }
@@ -1595,7 +1622,6 @@ int xtExtend(tid_t tid,           /* transaction id */
        s64 xaddr;
        struct tlock *tlck;
        struct xtlock *xtlck = NULL;
-       int rootsplit = 0;
 
        jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
 
@@ -1651,8 +1677,6 @@ int xtExtend(tid_t tid,           /* transaction id */
         * The xtSplitUp() will insert the entry and unpin the leaf page.
         */
        if (nextindex == le16_to_cpu(p->header.maxentry)) {
-               rootsplit = p->header.flag & BT_ROOT;
-
                /* xtSpliUp() unpins leaf pages */
                split.mp = mp;
                split.index = index + 1;
@@ -1664,16 +1688,21 @@ int xtExtend(tid_t tid,         /* transaction id */
                if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
                        return rc;
 
+               /* get back old page */
+               XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
+               if (rc)
+                       return rc;
                /*
                 * if leaf root has been split, original root has been
                 * copied to new child page, i.e., original entry now
                 * resides on the new child page;
                 */
-               if (rootsplit) {
+               if (p->header.flag & BT_INTERNAL) {
                        ASSERT(p->header.nextindex ==
                               cpu_to_le16(XTENTRYSTART + 1));
                        xad = &p->xad[XTENTRYSTART];
                        bn = addressXAD(xad);
+                       XT_PUTPAGE(mp);
 
                        /* get new child page */
                        XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
@@ -1685,11 +1714,6 @@ int xtExtend(tid_t tid,          /* transaction id */
                                tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
                                xtlck = (struct xtlock *) & tlck->lock;
                        }
-               } else {
-                       /* get back old page */
-                       XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
-                       if (rc)
-                               return rc;
                }
        }
        /*
@@ -1763,7 +1787,6 @@ int xtTailgate(tid_t tid,         /* transaction id */
        struct xtlock *xtlck = 0;
        struct tlock *mtlck;
        struct maplock *pxdlock;
-       int rootsplit = 0;
 
 /*
 printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
@@ -1821,8 +1844,6 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
         * The xtSplitUp() will insert the entry and unpin the leaf page.
         */
        if (nextindex == le16_to_cpu(p->header.maxentry)) {
-               rootsplit = p->header.flag & BT_ROOT;
-
                /* xtSpliUp() unpins leaf pages */
                split.mp = mp;
                split.index = index + 1;
@@ -1834,16 +1855,21 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
                if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
                        return rc;
 
+               /* get back old page */
+               XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
+               if (rc)
+                       return rc;
                /*
                 * if leaf root has been split, original root has been
                 * copied to new child page, i.e., original entry now
                 * resides on the new child page;
                 */
-               if (rootsplit) {
+               if (p->header.flag & BT_INTERNAL) {
                        ASSERT(p->header.nextindex ==
                               cpu_to_le16(XTENTRYSTART + 1));
                        xad = &p->xad[XTENTRYSTART];
                        bn = addressXAD(xad);
+                       XT_PUTPAGE(mp);
 
                        /* get new child page */
                        XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
@@ -1855,11 +1881,6 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
                                tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
                                xtlck = (struct xtlock *) & tlck->lock;
                        }
-               } else {
-                       /* get back old page */
-                       XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
-                       if (rc)
-                               return rc;
                }
        }
        /*
@@ -1949,7 +1970,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
        s64 nxaddr, xaddr;
        struct tlock *tlck;
        struct xtlock *xtlck = NULL;
-       int rootsplit = 0, newpage = 0;
+       int newpage = 0;
 
        /* there must exist extent to be tailgated */
        nxoff = offsetXAD(nxad);
@@ -2156,7 +2177,6 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
 
        /* insert nXAD:recorded */
        if (nextindex == le16_to_cpu(p->header.maxentry)) {
-               rootsplit = p->header.flag & BT_ROOT;
 
                /* xtSpliUp() unpins leaf pages */
                split.mp = mp;
@@ -2169,16 +2189,21 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
                if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
                        return rc;
 
+               /* get back old page */
+               XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
+               if (rc)
+                       return rc;
                /*
                 * if leaf root has been split, original root has been
                 * copied to new child page, i.e., original entry now
                 * resides on the new child page;
                 */
-               if (rootsplit) {
+               if (p->header.flag & BT_INTERNAL) {
                        ASSERT(p->header.nextindex ==
                               cpu_to_le16(XTENTRYSTART + 1));
                        xad = &p->xad[XTENTRYSTART];
                        bn = addressXAD(xad);
+                       XT_PUTPAGE(mp);
 
                        /* get new child page */
                        XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
@@ -2191,11 +2216,6 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
                                xtlck = (struct xtlock *) & tlck->lock;
                        }
                } else {
-                       /* get back old page */
-                       XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
-                       if (rc)
-                               return rc;
-
                        /* is nXAD on new page ? */
                        if (newindex >
                            (le16_to_cpu(p->header.maxentry) >> 1)) {
@@ -2309,8 +2329,6 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
        xlen = xlen - nxlen;
        xaddr = xaddr + nxlen;
        if (nextindex == le16_to_cpu(p->header.maxentry)) {
-               rootsplit = p->header.flag & BT_ROOT;
-
 /*
 printf("xtUpdate.updateLeft.split p:0x%p\n", p);
 */
@@ -2325,16 +2343,22 @@ printf("xtUpdate.updateLeft.split p:0x%p\n", p);
                if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
                        return rc;
 
+               /* get back old page */
+               XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
+               if (rc)
+                       return rc;
+
                /*
                 * if leaf root has been split, original root has been
                 * copied to new child page, i.e., original entry now
                 * resides on the new child page;
                 */
-               if (rootsplit) {
+               if (p->header.flag & BT_INTERNAL) {
                        ASSERT(p->header.nextindex ==
                               cpu_to_le16(XTENTRYSTART + 1));
                        xad = &p->xad[XTENTRYSTART];
                        bn = addressXAD(xad);
+                       XT_PUTPAGE(mp);
 
                        /* get new child page */
                        XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
@@ -2346,11 +2370,6 @@ printf("xtUpdate.updateLeft.split p:0x%p\n", p);
                                tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
                                xtlck = (struct xtlock *) & tlck->lock;
                        }
-               } else {
-                       /* get back old page */
-                       XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
-                       if (rc)
-                               return rc;
                }
        } else {
                /* if insert into middle, shift right remaining entries */
@@ -3909,8 +3928,8 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
        else
                ip->i_size = newsize;
 
-       /* update nblocks to reflect freed blocks */
-       ip->i_blocks -= LBLK2PBLK(ip->i_sb, nfreed);
+       /* update quota allocation to reflect freed blocks */
+       DQUOT_FREE_BLOCK(ip, nfreed);
 
        /*
         * free tlock of invalidated pages