http://jfs.bkbits.net/linux-2.5 shaggy@austin.ibm.com|ChangeSet|20040818193252|41465 shaggy # This is a BitKeeper generated diff -Nru style patch. # # 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 # # 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-18 23:17:39 -07:00 +++ b/fs/jfs/acl.c 2004-08-18 23:17:39 -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 #include +#include #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-18 23:17:39 -07:00 +++ b/fs/jfs/inode.c 2004-08-18 23:17:39 -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 #include #include +#include #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-18 23:17:39 -07:00 +++ b/fs/jfs/jfs_dtree.c 2004-08-18 23:17:39 -07:00 @@ -101,6 +101,7 @@ */ #include +#include #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-18 23:17:39 -07:00 +++ b/fs/jfs/jfs_extent.c 2004-08-18 23:17:39 -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 +#include #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-18 23:17:39 -07:00 +++ b/fs/jfs/jfs_imap.c 2004-08-18 23:17:39 -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 #include #include +#include #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-18 23:17:39 -07:00 +++ b/fs/jfs/jfs_inode.c 2004-08-18 23:17:39 -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 +#include #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-18 23:17:39 -07:00 +++ b/fs/jfs/jfs_txnmgr.c 2004-08-18 23:17:39 -07:00 @@ -2622,8 +2622,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-18 23:17:39 -07:00 +++ b/fs/jfs/jfs_xtree.c 2004-08-18 23:17:39 -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 +#include #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-18 23:17:39 -07:00 +++ b/fs/jfs/namei.c 2004-08-18 23:17:39 -07:00 @@ -19,6 +19,7 @@ #include #include +#include #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-18 23:17:39 -07:00 +++ b/fs/jfs/resize.c 2004-08-18 23:17:39 -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 #include +#include #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-18 23:17:39 -07:00 +++ b/fs/jfs/xattr.c 2004-08-18 23:17:39 -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 #include +#include #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);