aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Kleikamp <jfs.adm@hostme.bitkeeper.com>2004-08-25 19:09:12 -0700
committerDave Kleikamp <jfs.adm@hostme.bitkeeper.com>2004-08-25 19:09:12 -0700
commit639f284f946518e567ad79cde723bee6e77a5755 (patch)
tree59426aef9e0067a7fd305e021c4478dcdef4d211
parent0bfcccd100f56721a08d065f57764bc09b54429e (diff)
parent91ed0f3c16e80db7299bd34e88f59cec1d85c87a (diff)
downloadhistory-639f284f946518e567ad79cde723bee6e77a5755.tar.gz
Merge bk://linux.bkbits.net/linux-2.5
into hostme.bitkeeper.com:/repos/j/jfs/linux-2.5
-rw-r--r--fs/jfs/acl.c13
-rw-r--r--fs/jfs/inode.c12
-rw-r--r--fs/jfs/jfs_dtree.c65
-rw-r--r--fs/jfs/jfs_extent.c26
-rw-r--r--fs/jfs/jfs_imap.c27
-rw-r--r--fs/jfs/jfs_inode.c14
-rw-r--r--fs/jfs/jfs_txnmgr.c2
-rw-r--r--fs/jfs/jfs_xtree.c61
-rw-r--r--fs/jfs/namei.c39
-rw-r--r--fs/jfs/resize.c5
-rw-r--r--fs/jfs/xattr.c51
11 files changed, 210 insertions, 105 deletions
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 8353f48f72393..fc584f2194f4f 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -1,7 +1,7 @@
/*
- * Copyright (c) International Business Machines Corp., 2002
- * Copyright (c) Andreas Gruenbacher, 2001
- * Copyright (c) Linus Torvalds, 1991, 1992
+ * Copyright (C) International Business Machines Corp., 2002-2004
+ * Copyright (C) Andreas Gruenbacher, 2001
+ * Copyright (C) Linus Torvalds, 1991, 1992
*
* 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/sched.h>
#include <linux/fs.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_xattr.h"
#include "jfs_acl.h"
@@ -281,6 +282,12 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
if (rc)
return rc;
+ if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
+ (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {
+ if (DQUOT_TRANSFER(inode, iattr))
+ return -EDQUOT;
+ }
+
rc = inode_setattr(inode, iattr);
if (!rc && (iattr->ia_valid & ATTR_MODE))
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 2b70f813e76ec..c5e219ef6ac36 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2002
- * Portions Copyright (c) Christoph Hellwig, 2001-2002
+ * Copyright (C) International Business Machines Corp., 2000-2004
+ * Portions Copyright (C) Christoph Hellwig, 2001-2002
*
* 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
@@ -21,6 +21,7 @@
#include <linux/mpage.h>
#include <linux/buffer_head.h>
#include <linux/pagemap.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
#include "jfs_imap.h"
@@ -134,6 +135,13 @@ void jfs_delete_inode(struct inode *inode)
diFree(inode);
+ /*
+ * Free the inode from the quota allocation.
+ */
+ DQUOT_INIT(inode);
+ DQUOT_FREE_INODE(inode);
+ DQUOT_DROP(inode);
+
clear_inode(inode);
}
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 71e797774c088..29930b6ccf43e 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -101,6 +101,7 @@
*/
#include <linux/fs.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_filsys.h"
@@ -380,7 +381,8 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
* It's time to move the inline table to an external
* page and begin to build the xtree
*/
- if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr))
+ if (DQUOT_ALLOC_BLOCK(ip, sbi->nbperpage) ||
+ dbAlloc(ip, 0, sbi->nbperpage, &xaddr))
goto clean_up; /* No space */
/*
@@ -405,7 +407,6 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
goto clean_up;
}
ip->i_size = PSIZE;
- ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
if ((mp = get_index_page(ip, 0)) == 0) {
jfs_err("add_index: get_metapage failed!");
@@ -447,7 +448,6 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
goto clean_up;
}
ip->i_size += PSIZE;
- ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
if ((mp = get_index_page(ip, blkno)))
memset(mp->data, 0, PSIZE); /* Just looks better */
@@ -946,6 +946,7 @@ static int dtSplitUp(tid_t tid,
struct dt_lock *dtlck;
struct tlock *tlck;
struct lv *lv;
+ int quota_allocation = 0;
/* get split page */
smp = split->mp;
@@ -992,7 +993,9 @@ static int dtSplitUp(tid_t tid,
split->pxdlist = &pxdlist;
rc = dtSplitRoot(tid, ip, split, &rmp);
- if (!rc)
+ if (rc)
+ dbFree(ip, xaddr, xlen);
+ else
DT_PUTPAGE(rmp);
DT_PUTPAGE(smp);
@@ -1017,6 +1020,14 @@ static int dtSplitUp(tid_t tid,
n = xlen + (xlen << 1);
else
n = xlen;
+
+ /* Allocate blocks to quota. */
+ if (DQUOT_ALLOC_BLOCK(ip, n)) {
+ rc = -EDQUOT;
+ goto extendOut;
+ }
+ quota_allocation += n;
+
if ((rc = dbReAlloc(sbi->ipbmap, xaddr, (s64) xlen,
(s64) n, &nxaddr)))
goto extendOut;
@@ -1285,6 +1296,10 @@ static int dtSplitUp(tid_t tid,
freeKeyName:
kfree(key.name);
+ /* Rollback quota allocation */
+ if (rc && quota_allocation)
+ DQUOT_FREE_BLOCK(ip, quota_allocation);
+
dtSplitUp_Exit:
return rc;
@@ -1305,7 +1320,6 @@ static int dtSplitUp(tid_t tid,
static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
struct metapage ** rmpp, dtpage_t ** rpp, pxd_t * rpxdp)
{
- struct super_block *sb = ip->i_sb;
int rc = 0;
struct metapage *smp;
dtpage_t *sp;
@@ -1344,6 +1358,12 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
if (rmp == NULL)
return -EIO;
+ /* Allocate blocks to quota. */
+ if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+ release_metapage(rmp);
+ return -EDQUOT;
+ }
+
jfs_info("dtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
BT_MARK_DIRTY(rmp, ip);
@@ -1593,8 +1613,6 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
*rmpp = rmp;
*rpxdp = *pxd;
- ip->i_blocks += LBLK2PBLK(sb, lengthPXD(pxd));
-
return rc;
}
@@ -1823,16 +1841,6 @@ static int dtExtendPage(tid_t tid,
tpxd = (pxd_t *) & pp->slot[1];
*tpxd = *pxd;
- /* Since the directory might have an EA and/or ACL associated with it
- * we need to make sure we take that into account when setting the
- * i_nblocks
- */
- ip->i_blocks = LBLK2PBLK(ip->i_sb, xlen +
- ((JFS_IP(ip)->ea.flag & DXD_EXTENT) ?
- lengthDXD(&JFS_IP(ip)->ea) : 0) +
- ((JFS_IP(ip)->acl.flag & DXD_EXTENT) ?
- lengthDXD(&JFS_IP(ip)->acl) : 0));
-
DT_PUTPAGE(pmp);
return 0;
}
@@ -1900,6 +1908,12 @@ static int dtSplitRoot(tid_t tid,
rp = rmp->data;
+ /* Allocate blocks to quota. */
+ if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+ release_metapage(rmp);
+ return -EDQUOT;
+ }
+
BT_MARK_DIRTY(rmp, ip);
/*
* acquire a transaction lock on the new right page
@@ -2042,7 +2056,6 @@ static int dtSplitRoot(tid_t tid,
*rmpp = rmp;
- ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
return 0;
}
@@ -2265,7 +2278,9 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
}
xlen = lengthPXD(&fp->header.self);
- ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
+
+ /* Free quota allocation. */
+ DQUOT_FREE_BLOCK(ip, xlen);
/* free/invalidate its buffer page */
discard_metapage(fmp);
@@ -2339,7 +2354,9 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
}
xlen = lengthPXD(&p->header.self);
- ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
+
+ /* Free quota allocation */
+ DQUOT_FREE_BLOCK(ip, xlen);
/* free/invalidate its buffer page */
discard_metapage(mp);
@@ -2877,14 +2894,6 @@ void dtInitRoot(tid_t tid, struct inode *ip, u32 idotdot)
/* init '..' entry */
p->header.idotdot = cpu_to_le32(idotdot);
-#if 0
- ip->i_blocks = LBLK2PBLK(ip->i_sb,
- ((jfs_ip->ea.flag & DXD_EXTENT) ?
- lengthDXD(&jfs_ip->ea) : 0) +
- ((jfs_ip->acl.flag & DXD_EXTENT) ?
- lengthDXD(&jfs_ip->acl) : 0));
-#endif
-
return;
}
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 2b411bc32eb83..1953acb792663 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -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
@@ -17,6 +17,7 @@
*/
#include <linux/fs.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h"
@@ -144,6 +145,13 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
return (rc);
}
+ /* Allocate blocks to quota. */
+ if (DQUOT_ALLOC_BLOCK(ip, nxlen)) {
+ dbFree(ip, nxaddr, (s64) nxlen);
+ up(&JFS_IP(ip)->commit_sem);
+ return -EDQUOT;
+ }
+
/* determine the value of the extent flag */
xflag = (abnr == TRUE) ? XAD_NOTRECORDED : 0;
@@ -161,13 +169,11 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
*/
if (rc) {
dbFree(ip, nxaddr, nxlen);
+ DQUOT_FREE_BLOCK(ip, nxlen);
up(&JFS_IP(ip)->commit_sem);
return (rc);
}
- /* update the number of blocks allocated to the file */
- ip->i_blocks += LBLK2PBLK(ip->i_sb, nxlen);
-
/* set the results of the extent allocation */
XADaddress(xp, nxaddr);
XADlength(xp, nxlen);
@@ -254,6 +260,13 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
if ((rc = extBrealloc(ip, xaddr, xlen, &nxlen, &nxaddr)))
goto exit;
+ /* Allocat blocks to quota. */
+ if (DQUOT_ALLOC_BLOCK(ip, nxlen)) {
+ dbFree(ip, nxaddr, (s64) nxlen);
+ up(&JFS_IP(ip)->commit_sem);
+ return -EDQUOT;
+ }
+
delta = nxlen - xlen;
/* check if the extend page is not abnr but the request is abnr
@@ -289,6 +302,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
/* extend the extent */
if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) {
dbFree(ip, xaddr + xlen, delta);
+ DQUOT_FREE_BLOCK(ip, nxlen);
goto exit;
}
} else {
@@ -299,6 +313,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
*/
if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) {
dbFree(ip, nxaddr, nxlen);
+ DQUOT_FREE_BLOCK(ip, nxlen);
goto exit;
}
}
@@ -320,9 +335,6 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
}
}
- /* update the inode with the number of blocks allocated */
- ip->i_blocks += LBLK2PBLK(sb, delta);
-
/* set the return results */
XADaddress(xp, nxaddr);
XADlength(xp, nxlen);
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index cfb582d282174..fbac5be13283e 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -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
@@ -44,6 +44,7 @@
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/pagemap.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
@@ -504,6 +505,9 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
ip->i_mapping->a_ops = &jfs_aops;
mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
+ /* Allocations to metadata inodes should not affect quotas */
+ ip->i_flags |= S_NOQUOTA;
+
if ((inum == FILESYSTEM_I) && (JFS_IP(ip)->ipimap == sbi->ipaimap)) {
sbi->gengen = le32_to_cpu(dp->di_gengen);
sbi->inostamp = le32_to_cpu(dp->di_inostamp);
@@ -2601,28 +2605,11 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
iagp->inosmap[i] = ONES;
flush_metapage(mp);
-#ifdef _STILL_TO_PORT
- /* synchronously write the iag page */
- if (bmWrite(bp)) {
- /* Free the blocks allocated for the iag since it was
- * not successfully added to the inode map
- */
- dbFree(ipimap, xaddr, (s64) xlen);
-
- /* release the inode map lock */
- IWRITE_UNLOCK(ipimap);
-
- rc = -EIO;
- goto out;
- }
-
- /* Now the iag is on disk */
/*
* start tyransaction of update of the inode map
* addressing structure pointing to the new iag page;
*/
-#endif /* _STILL_TO_PORT */
tid = txBegin(sb, COMMIT_FORCE);
down(&JFS_IP(ipimap)->commit_sem);
@@ -2644,7 +2631,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
/* update the inode map's inode to reflect the extension */
ipimap->i_size += PSIZE;
- ipimap->i_blocks += LBLK2PBLK(sb, xlen);
+ inode_add_bytes(ipimap, PSIZE);
/*
* txCommit(COMMIT_FORCE) will synchronously write address
@@ -3085,7 +3072,7 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
}
/* update the inode map's inode to reflect the extension */
ip->i_size += PSIZE;
- ip->i_blocks += LBLK2PBLK(sb, xlen);
+ inode_add_bytes(ip, PSIZE);
txCommit(tid, 1, &ip, COMMIT_FORCE);
cleanup:
txEnd(tid);
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 3e8592b9b0fcb..84f2459b2191d 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2002
+ * 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
@@ -17,6 +17,7 @@
*/
#include <linux/fs.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
#include "jfs_imap.h"
@@ -60,6 +61,17 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
} else
inode->i_gid = current->fsgid;
+ /*
+ * Allocate inode to quota.
+ */
+ if (DQUOT_ALLOC_INODE(inode)) {
+ DQUOT_DROP(inode);
+ inode->i_flags |= S_NOQUOTA;
+ inode->i_nlink = 0;
+ iput(inode);
+ return NULL;
+ }
+
inode->i_mode = mode;
if (S_ISDIR(mode))
jfs_inode->mode2 = IDIRECTORY | mode;
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index db99cf6f974dd..12e9ccffb49bf 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -2621,8 +2621,6 @@ void txAbort(tid_t tid, int dirty)
struct tblock *tblk = tid_to_tblock(tid);
struct tlock *tlck;
- jfs_warn("txAbort: tid:%d dirty:0x%x", tid, dirty);
-
/*
* free tlocks of the transaction
*/
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index 19913fcd4c332..b4dc15924f636 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -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;
}
@@ -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;
}
@@ -3909,8 +3936,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
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 8c3a8e78d0f8c..e089615adb6b1 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/ctype.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_inode.h"
@@ -123,10 +124,10 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
*/
ino = ip->i_ino;
if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
- jfs_err("jfs_create: dtInsert returned %d", rc);
- if (rc == -EIO)
+ if (rc == -EIO) {
+ jfs_err("jfs_create: dtInsert returned -EIO");
txAbort(tid, 1); /* Marks Filesystem dirty */
- else
+ } else
txAbort(tid, 0); /* Filesystem full */
goto out3;
}
@@ -250,11 +251,10 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
*/
ino = ip->i_ino;
if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
- jfs_err("jfs_mkdir: dtInsert returned %d", rc);
-
- if (rc == -EIO)
+ if (rc == -EIO) {
+ jfs_err("jfs_mkdir: dtInsert returned -EIO");
txAbort(tid, 1); /* Marks Filesystem dirty */
- else
+ } else
txAbort(tid, 0); /* Filesystem full */
goto out3;
}
@@ -330,6 +330,9 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);
+ /* Init inode for quota operations. */
+ DQUOT_INIT(ip);
+
/* directory must be empty to be removed */
if (!dtEmpty(ip)) {
rc = -ENOTEMPTY;
@@ -455,6 +458,9 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);
+ /* Init inode for quota operations. */
+ DQUOT_INIT(ip);
+
if ((rc = get_UCSname(&dname, dentry)))
goto out;
@@ -813,7 +819,10 @@ static int jfs_link(struct dentry *old_dentry,
iplist[1] = dir;
rc = txCommit(tid, 2, &iplist[0], 0);
- if (!rc)
+ if (rc) {
+ ip->i_nlink--;
+ iput(ip);
+ } else
d_instantiate(dentry, ip);
free_dname:
@@ -964,7 +973,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
mp = get_metapage(ip, xaddr, PSIZE, 1);
if (mp == NULL) {
- dbFree(ip, extent, xlen);
+ xtTruncate(tid, ip, 0, COMMIT_PWMAP);
rc = -EIO;
txAbort(tid, 0);
goto out3;
@@ -975,7 +984,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
name += copy_size;
xaddr += JFS_SBI(sb)->nbperpage;
}
- ip->i_blocks = LBLK2PBLK(sb, xlen);
}
/*
@@ -988,7 +996,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
}
if (rc) {
if (xlen)
- dbFree(ip, extent, xlen);
+ xtTruncate(tid, ip, 0, COMMIT_PWMAP);
txAbort(tid, 0);
/* discard new inode */
goto out3;
@@ -1104,8 +1112,11 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
rc = -EMLINK;
goto out3;
}
- } else if (new_ip)
+ } else if (new_ip) {
IWRITE_LOCK(new_ip);
+ /* Init inode for quota operations. */
+ DQUOT_INIT(new_ip);
+ }
/*
* The real work starts here
@@ -1174,8 +1185,8 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
ino = old_ip->i_ino;
rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack);
if (rc) {
- jfs_err("jfs_rename: dtInsert failed w/rc = %d",
- rc);
+ if (rc == -EIO)
+ jfs_err("jfs_rename: dtInsert returned -EIO");
goto out4;
}
if (S_ISDIR(old_ip->i_mode))
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 71f675356758f..2eb6869b6e723 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -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
@@ -18,6 +18,7 @@
#include <linux/fs.h>
#include <linux/buffer_head.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
#include "jfs_metapage.h"
@@ -390,7 +391,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
}
/* update bmap file size */
ipbmap->i_size += xlen << sbi->l2bsize;
- ipbmap->i_blocks += LBLK2PBLK(sb, xlen);
+ inode_add_bytes(ipbmap, xlen << sbi->l2bsize);
iplist[0] = ipbmap;
rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index cf3fba6e5d781..9c0e3a524e9be 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) International Business Machines Corp., 2000-2003
+ * Copyright (C) International Business Machines Corp., 2000-2004
* Copyright (C) Christoph Hellwig, 2002
*
* This program is free software; you can redistribute it and/or modify
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/xattr.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h"
@@ -251,9 +252,17 @@ static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size,
/* figure out how many blocks we need */
nblocks = (size + (sb->s_blocksize - 1)) >> sb->s_blocksize_bits;
+ /* Allocate new blocks to quota. */
+ if (DQUOT_ALLOC_BLOCK(ip, nblocks)) {
+ return -EDQUOT;
+ }
+
rc = dbAlloc(ip, INOHINT(ip), nblocks, &blkno);
- if (rc)
+ if (rc) {
+ /*Rollback quota allocation. */
+ DQUOT_FREE_BLOCK(ip, nblocks);
return rc;
+ }
/*
* Now have nblocks worth of storage to stuff into the FEALIST.
@@ -315,6 +324,9 @@ static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size,
return 0;
failed:
+ /* Rollback quota allocation. */
+ DQUOT_FREE_BLOCK(ip, nblocks);
+
dbFree(ip, blkno, nblocks);
return rc;
}
@@ -448,6 +460,7 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
int blocks_needed, current_blocks;
s64 blkno;
int rc;
+ int quota_allocation = 0;
/* When fsck.jfs clears a bad ea, it doesn't clear the size */
if (ji->ea.flag == 0)
@@ -517,10 +530,16 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
sb->s_blocksize_bits;
if (blocks_needed > current_blocks) {
+ /* Allocate new blocks to quota. */
+ if (DQUOT_ALLOC_BLOCK(inode, blocks_needed))
+ return -EDQUOT;
+
+ quota_allocation = blocks_needed;
+
rc = dbAlloc(inode, INOHINT(inode), (s64) blocks_needed,
&blkno);
if (rc)
- return rc;
+ goto clean_up;
DXDlength(&ea_buf->new_ea, blocks_needed);
DXDaddress(&ea_buf->new_ea, blkno);
@@ -534,7 +553,8 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
1);
if (ea_buf->mp == NULL) {
dbFree(inode, blkno, (s64) blocks_needed);
- return -EIO;
+ rc = -EIO;
+ goto clean_up;
}
ea_buf->xattr = ea_buf->mp->data;
ea_buf->max_size = (min_size + sb->s_blocksize - 1) &
@@ -544,7 +564,7 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
if ((rc = ea_read(inode, ea_buf->xattr))) {
discard_metapage(ea_buf->mp);
dbFree(inode, blkno, (s64) blocks_needed);
- return rc;
+ goto clean_up;
}
goto size_check;
}
@@ -552,8 +572,10 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
ea_buf->mp = read_metapage(inode, addressDXD(&ji->ea),
lengthDXD(&ji->ea) << sb->s_blocksize_bits,
1);
- if (ea_buf->mp == NULL)
- return -EIO;
+ if (ea_buf->mp == NULL) {
+ rc = -EIO;
+ goto clean_up;
+ }
ea_buf->xattr = ea_buf->mp->data;
ea_buf->max_size = (ea_size + sb->s_blocksize - 1) &
~(sb->s_blocksize - 1);
@@ -563,10 +585,18 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
printk(KERN_ERR "ea_get: invalid extended attribute\n");
dump_mem("xattr", ea_buf->xattr, ea_size);
ea_release(inode, ea_buf);
- return -EIO;
+ rc = -EIO;
+ goto clean_up;
}
return ea_size;
+
+ clean_up:
+ /* Rollback quota allocation */
+ if (quota_allocation)
+ DQUOT_FREE_BLOCK(inode, quota_allocation);
+
+ return (rc);
}
static void ea_release(struct inode *inode, struct ea_buffer *ea_buf)
@@ -640,7 +670,10 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
ji->ea.size = 0;
}
- inode->i_blocks += LBLK2PBLK(inode->i_sb, new_blocks - old_blocks);
+ /* If old blocks exist, they must be removed from quota allocation. */
+ if (old_blocks)
+ DQUOT_FREE_BLOCK(inode, old_blocks);
+
inode->i_ctime = CURRENT_TIME;
rc = txCommit(tid, 1, &inode, 0);
txEnd(tid);