/*
- * 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
*/
#include <linux/fs.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
#include "jfs_metapage.h"
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;
+ }
}
/*
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;
}
/* 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;
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);
*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;
}
XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
if (rc) {
XT_PUTPAGE(rmp);
- return rc;
+ goto clean_up;
}
BT_MARK_DIRTY(mp, 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);
}
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);
/*
*rmpp = rmp;
- ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
jfs_info("xtSplitRoot: sp:0x%p rp:0x%p", sp, rp);
return 0;
}
s64 xaddr;
struct tlock *tlck;
struct xtlock *xtlck = NULL;
- int rootsplit = 0;
jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
* 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;
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);
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;
}
}
/*
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",
* 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;
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);
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;
}
}
/*
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);
/* insert nXAD:recorded */
if (nextindex == le16_to_cpu(p->header.maxentry)) {
- rootsplit = p->header.flag & BT_ROOT;
/* xtSpliUp() unpins leaf pages */
split.mp = mp;
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);
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)) {
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);
*/
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);
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 */
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