http://jfs.bkbits.net/linux-2.5
jfs.adm@hostme.bitkeeper.com|ChangeSet|20040824201615|15869 jfs.adm

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/08/24 17:57:22-07:00 akpm@bix.(none) 
#   Merge http://jfs.bkbits.net/linux-2.5 into bix.(none):/usr/src/bk-jfs
# 
# fs/jfs/jfs_txnmgr.c
#   2004/08/24 17:57:18-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/24 17:56:17-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-jfs
# 
# fs/jfs/super.c
#   2004/08/24 17:56:13-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/24 13:16:15-07:00 jfs.adm@hostme.bitkeeper.com 
#   Merge bk://linux.bkbits.net/linux-2.5
#   into hostme.bitkeeper.com:/repos/j/jfs/linux-2.5
# 
# fs/jfs/jfs_txnmgr.c
#   2004/08/24 13:16:08-07:00 jfs.adm@hostme.bitkeeper.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/23 14:17:07-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-jfs
# 
# fs/jfs/jfs_txnmgr.c
#   2004/08/23 14:17:03-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/18 14:21:31-07:00 akpm@bix.(none) 
#   Merge http://jfs.bkbits.net/linux-2.5 into bix.(none):/usr/src/bk-jfs
# 
# fs/jfs/jfs_xtree.c
#   2004/08/18 14:21:27-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# fs/jfs/jfs_imap.c
#   2004/08/18 14:21:27-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/18 14:32:52-05:00 shaggy@austin.ibm.com 
#   JFS: disk quota support
#   
#   This patch adds disk quota support to jfs.
#   
#   A patch is required for quota-tools to work with jfs.  It can be
#   found at http://oss.software.ibm.com/jfs/project/pub/quota-tools.patch
#   Quota tools source can be downloaded from
#   https://sourceforge.net/projects/linuxquota/
#   
#   Written by: Karl Rister & Dave Kleikamp
#   Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
# 
# fs/jfs/xattr.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +42 -9
#   Disk Quota Support
# 
# fs/jfs/resize.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +3 -2
#   Disk Quota Support
# 
# fs/jfs/namei.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +25 -14
#   Disk Quota Support
# 
# fs/jfs/jfs_xtree.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +44 -17
#   Disk Quota Support
# 
# fs/jfs/jfs_txnmgr.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +0 -2
#   Disk Quota Support
# 
# fs/jfs/jfs_inode.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +13 -1
#   Disk Quota Support
# 
# fs/jfs/jfs_imap.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +7 -20
#   Disk Quota Support
# 
# fs/jfs/jfs_extent.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +19 -7
#   Disk Quota Support
# 
# fs/jfs/jfs_dtree.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +37 -28
#   Disk Quota Support
# 
# fs/jfs/inode.c
#   2004/08/18 14:32:20-05:00 shaggy@austin.ibm.com +10 -2
#   Disk Quota Support
# 
# fs/jfs/acl.c
#   2004/08/18 14:32:19-05:00 shaggy@austin.ibm.com +10 -3
#   Disk Quota Support
# 
# ChangeSet
#   2004/07/12 21:11:35-07:00 akpm@bix.(none) 
#   Merge http://jfs.bkbits.net/linux-2.5 into bix.(none):/usr/src/bk-jfs
# 
# fs/jfs/super.c
#   2004/07/12 21:11:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# fs/jfs/jfs_xtree.c
#   2004/07/12 21:11:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# fs/jfs/jfs_metapage.c
#   2004/07/12 21:11:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# fs/jfs/jfs_imap.c
#   2004/07/12 21:11:32-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/07/11 13:34:53-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-jfs
# 
# fs/jfs/super.c
#   2004/07/11 13:34:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# fs/jfs/jfs_xtree.c
#   2004/07/11 13:34:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# fs/jfs/jfs_metapage.c
#   2004/07/11 13:34:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# fs/jfs/jfs_imap.c
#   2004/07/11 13:34:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
diff -Nru a/fs/jfs/acl.c b/fs/jfs/acl.c
--- a/fs/jfs/acl.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/acl.c	2004-08-25 19:48:33 -07:00
@@ -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"
@@ -280,6 +281,12 @@
 	rc = inode_change_ok(inode, 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);
 
diff -Nru a/fs/jfs/inode.c b/fs/jfs/inode.c
--- a/fs/jfs/inode.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/inode.c	2004-08-25 19:48:33 -07:00
@@ -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"
@@ -133,6 +134,13 @@
 		freeZeroLink(inode);
 
 	diFree(inode);
+
+	/*
+	 * Free the inode from the quota allocation.
+	 */
+	DQUOT_INIT(inode);
+	DQUOT_FREE_INODE(inode);
+	DQUOT_DROP(inode);
 
 	clear_inode(inode);
 }
diff -Nru a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
--- a/fs/jfs/jfs_dtree.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/jfs_dtree.c	2004-08-25 19:48:33 -07:00
@@ -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 @@
 		 * 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 @@
 			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 @@
 			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 @@
 	struct dt_lock *dtlck;
 	struct tlock *tlck;
 	struct lv *lv;
+	int quota_allocation = 0;
 
 	/* get split page */
 	smp = split->mp;
@@ -992,7 +993,9 @@
 		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 @@
 			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 @@
       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 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 @@
 	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 @@
 	*rmpp = rmp;
 	*rpxdp = *pxd;
 
-	ip->i_blocks += LBLK2PBLK(sb, lengthPXD(pxd));
-
 	return rc;
 }
 
@@ -1823,16 +1841,6 @@
 	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 @@
 
 	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 @@
 
 	*rmpp = rmp;
 
-	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
 	return 0;
 }
 
@@ -2265,7 +2278,9 @@
 	}
 
 	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 @@
 				}
 
 				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);
@@ -2876,14 +2893,6 @@
 
 	/* 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 -Nru a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
--- a/fs/jfs/jfs_extent.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/jfs_extent.c	2004-08-25 19:48:33 -07:00
@@ -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 @@
 		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 @@
 	 */
 	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 @@
 	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 @@
 		/* 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 @@
 		 */
 		if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) {
 			dbFree(ip, nxaddr, nxlen);
+			DQUOT_FREE_BLOCK(ip, nxlen);
 			goto exit;
 		}
 	}
@@ -319,9 +334,6 @@
 			xflag = 0;
 		}
 	}
-
-	/* update the inode with the number of blocks allocated */
-	ip->i_blocks += LBLK2PBLK(sb, delta);
 
 	/* set the return results */
 	XADaddress(xp, nxaddr);
diff -Nru a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
--- a/fs/jfs/jfs_imap.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/jfs_imap.c	2004-08-25 19:48:33 -07:00
@@ -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 @@
 	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 @@
 			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 @@
 
 		/* 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 @@
 	}
 	/* 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 -Nru a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
--- a/fs/jfs/jfs_inode.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/jfs_inode.c	2004-08-25 19:48:33 -07:00
@@ -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"
@@ -59,6 +60,17 @@
 			mode |= S_ISGID;
 	} 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))
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/jfs_txnmgr.c	2004-08-25 19:48:33 -07:00
@@ -2621,8 +2621,6 @@
 	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 -Nru a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
--- a/fs/jfs/jfs_xtree.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/jfs_xtree.c	2004-08-25 19:48:33 -07:00
@@ -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 @@
 			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 @@
 		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 @@
 	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 @@
 		*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 @@
 		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 @@
 	*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 @@
 	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 @@
 
 	*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 @@
 	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 -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c
--- a/fs/jfs/namei.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/namei.c	2004-08-25 19:48:33 -07:00
@@ -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 @@
 	 */
 	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 @@
 	 */
 	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 @@
 
 	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 @@
 
 	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 @@
 	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 @@
 			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 @@
 			name += copy_size;
 			xaddr += JFS_SBI(sb)->nbperpage;
 		}
-		ip->i_blocks = LBLK2PBLK(sb, xlen);
 	}
 
 	/*
@@ -988,7 +996,7 @@
 	}
 	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 @@
 			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 @@
 		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 -Nru a/fs/jfs/resize.c b/fs/jfs/resize.c
--- a/fs/jfs/resize.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/resize.c	2004-08-25 19:48:33 -07:00
@@ -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 @@
 	}
 	/* 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 -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c
--- a/fs/jfs/xattr.c	2004-08-25 19:48:33 -07:00
+++ b/fs/jfs/xattr.c	2004-08-25 19:48:33 -07:00
@@ -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 @@
 	/* 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 @@
 	return 0;
 
       failed:
+	/* Rollback quota allocation. */
+	DQUOT_FREE_BLOCK(ip, nblocks);
+
 	dbFree(ip, blkno, nblocks);
 	return rc;
 }
@@ -448,6 +460,7 @@
 	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 @@
 	    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 @@
 					  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 @@
 		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 @@
 	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 @@
 		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 @@
 		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);