Commit fff4f98f authored by Dave Kleikamp's avatar Dave Kleikamp

Merge jfs@jfs.bkbits.net:linux-2.5

into austin.ibm.com:/shaggy/bk/jfs-2.5
parents 929ad084 fa2c79c3
/* /*
* Copyright (c) International Business Machines Corp., 2000-2001 * Copyright (C) International Business Machines Corp., 2000-2004
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -108,13 +108,12 @@ struct btpage { ...@@ -108,13 +108,12 @@ struct btpage {
* record the path traversed during the search; * record the path traversed during the search;
* top frame record the leaf page/entry selected. * top frame record the leaf page/entry selected.
*/ */
#define MAXTREEHEIGHT 8
struct btframe { /* stack frame */ struct btframe { /* stack frame */
s64 bn; /* 8: */ s64 bn; /* 8: */
s16 index; /* 2: */ s16 index; /* 2: */
s16 lastindex; /* 2: */ s16 lastindex; /* 2: unused */
struct metapage *mp; /* 4: */ struct metapage *mp; /* 4/8: */
}; /* (16) */ }; /* (16/24) */
struct btstack { struct btstack {
struct btframe *top; struct btframe *top;
...@@ -125,12 +124,15 @@ struct btstack { ...@@ -125,12 +124,15 @@ struct btstack {
#define BT_CLR(btstack)\ #define BT_CLR(btstack)\
(btstack)->top = (btstack)->stack (btstack)->top = (btstack)->stack
#define BT_STACK_FULL(btstack)\
( (btstack)->top == &((btstack)->stack[MAXTREEHEIGHT-1]))
#define BT_PUSH(BTSTACK, BN, INDEX)\ #define BT_PUSH(BTSTACK, BN, INDEX)\
{\ {\
assert(!BT_STACK_FULL(BTSTACK));\
(BTSTACK)->top->bn = BN;\ (BTSTACK)->top->bn = BN;\
(BTSTACK)->top->index = INDEX;\ (BTSTACK)->top->index = INDEX;\
++(BTSTACK)->top;\ ++(BTSTACK)->top;\
assert((BTSTACK)->top != &((BTSTACK)->stack[MAXTREEHEIGHT]));\
} }
#define BT_POP(btstack)\ #define BT_POP(btstack)\
...@@ -139,6 +141,16 @@ struct btstack { ...@@ -139,6 +141,16 @@ struct btstack {
#define BT_STACK(btstack)\ #define BT_STACK(btstack)\
( (btstack)->top == (btstack)->stack ? NULL : (btstack)->top ) ( (btstack)->top == (btstack)->stack ? NULL : (btstack)->top )
static inline void BT_STACK_DUMP(struct btstack *btstack)
{
int i;
printk("btstack dump:\n");
for (i = 0; i < MAXTREEHEIGHT; i++)
printk(KERN_ERR "bn = %Lx, index = %d\n",
btstack->stack[i].bn,
btstack->stack[i].index);
}
/* retrieve search results */ /* retrieve search results */
#define BT_GETSEARCH(IP, LEAF, BN, MP, TYPE, P, INDEX, ROOT)\ #define BT_GETSEARCH(IP, LEAF, BN, MP, TYPE, P, INDEX, ROOT)\
{\ {\
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -382,7 +382,7 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks) ...@@ -382,7 +382,7 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
IREAD_LOCK(ipbmap); IREAD_LOCK(ipbmap);
/* block to be freed better be within the mapsize. */ /* block to be freed better be within the mapsize. */
if (blkno + nblocks > bmp->db_mapsize) { if (unlikely((blkno == 0) || (blkno + nblocks > bmp->db_mapsize))) {
IREAD_UNLOCK(ipbmap); IREAD_UNLOCK(ipbmap);
printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n", printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n",
(unsigned long long) blkno, (unsigned long long) blkno,
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -378,6 +378,8 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot) ...@@ -378,6 +378,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 * It's time to move the inline table to an external
* page and begin to build the xtree * page and begin to build the xtree
*/ */
if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr))
goto clean_up; /* No space */
/* /*
* Save the table, we're going to overwrite it with the * Save the table, we're going to overwrite it with the
...@@ -394,8 +396,8 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot) ...@@ -394,8 +396,8 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
/* /*
* Allocate the first block & add it to the xtree * Allocate the first block & add it to the xtree
*/ */
xaddr = 0;
if (xtInsert(tid, ip, 0, 0, sbi->nbperpage, &xaddr, 0)) { if (xtInsert(tid, ip, 0, 0, sbi->nbperpage, &xaddr, 0)) {
/* This really shouldn't fail */
jfs_warn("add_index: xtInsert failed!"); jfs_warn("add_index: xtInsert failed!");
memcpy(&jfs_ip->i_dirtable, temp_table, memcpy(&jfs_ip->i_dirtable, temp_table,
sizeof (temp_table)); sizeof (temp_table));
...@@ -764,11 +766,12 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data, ...@@ -764,11 +766,12 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
*/ */
getChild: getChild:
/* update max. number of pages to split */ /* update max. number of pages to split */
if (btstack->nsplit >= 8) { if (BT_STACK_FULL(btstack)) {
/* Something's corrupted, mark filesytem dirty so /* Something's corrupted, mark filesytem dirty so
* chkdsk will fix it. * chkdsk will fix it.
*/ */
jfs_error(sb, "stack overrun in dtSearch!"); jfs_error(sb, "stack overrun in dtSearch!");
BT_STACK_DUMP(btstack);
rc = -EIO; rc = -EIO;
goto out; goto out;
} }
...@@ -975,8 +978,10 @@ static int dtSplitUp(tid_t tid, ...@@ -975,8 +978,10 @@ static int dtSplitUp(tid_t tid,
n -= DTROOTMAXSLOT - sp->header.freecnt; /* header + entries */ n -= DTROOTMAXSLOT - sp->header.freecnt; /* header + entries */
if (n <= split->nslot) if (n <= split->nslot)
xlen++; xlen++;
if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr))) if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr))) {
DT_PUTPAGE(smp);
goto freeKeyName; goto freeKeyName;
}
pxdlist.maxnpxd = 1; pxdlist.maxnpxd = 1;
pxdlist.npxd = 0; pxdlist.npxd = 0;
...@@ -3342,6 +3347,12 @@ static int dtReadFirst(struct inode *ip, struct btstack * btstack) ...@@ -3342,6 +3347,12 @@ static int dtReadFirst(struct inode *ip, struct btstack * btstack)
/* /*
* descend down to leftmost child page * descend down to leftmost child page
*/ */
if (BT_STACK_FULL(btstack)) {
DT_PUTPAGE(mp);
jfs_error(ip->i_sb, "dtReadFirst: btstack overrun");
BT_STACK_DUMP(btstack);
return -EIO;
}
/* push (bn, index) of the parent page/entry */ /* push (bn, index) of the parent page/entry */
BT_PUSH(btstack, bn, 0); BT_PUSH(btstack, bn, 0);
......
...@@ -1747,7 +1747,10 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, ...@@ -1747,7 +1747,10 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
if (lwm == next) if (lwm == next)
goto out; goto out;
assert(lwm < next); if (lwm > next) {
jfs_err("xtLog: lwm > next\n");
goto out;
}
tlck->flag |= tlckUPDATEMAP; tlck->flag |= tlckUPDATEMAP;
xadlock->flag = mlckALLOCXADLIST; xadlock->flag = mlckALLOCXADLIST;
xadlock->count = next - lwm; xadlock->count = next - lwm;
...@@ -1913,25 +1916,18 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, ...@@ -1913,25 +1916,18 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
/* /*
* write log records * write log records
*/ */
/* /* log after-image for logredo():
* allocate entries XAD[lwm:next]: *
* logredo() will update bmap for alloc of new/extended
* extents (XAD_NEW|XAD_EXTEND) of XAD[lwm:next) from
* after-image of XADlist;
* logredo() resets (XAD_NEW|XAD_EXTEND) flag when
* applying the after-image to the meta-data page.
*/ */
if (lwm < next) { lrd->type = cpu_to_le16(LOG_REDOPAGE);
/* log after-image for logredo(): PXDaddress(pxd, mp->index);
* logredo() will update bmap for alloc of new/extended PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits);
* extents (XAD_NEW|XAD_EXTEND) of XAD[lwm:next) from lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
* after-image of XADlist;
* logredo() resets (XAD_NEW|XAD_EXTEND) flag when
* applying the after-image to the meta-data page.
*/
lrd->type = cpu_to_le16(LOG_REDOPAGE);
PXDaddress(pxd, mp->index);
PXDlength(pxd,
mp->logical_size >> tblk->sb->
s_blocksize_bits);
lrd->backchain =
cpu_to_le32(lmLog(log, tblk, lrd, tlck));
}
/* /*
* truncate entry XAD[twm == next - 1]: * truncate entry XAD[twm == next - 1]:
...@@ -2624,6 +2620,7 @@ void txAbort(tid_t tid, int dirty) ...@@ -2624,6 +2620,7 @@ void txAbort(tid_t tid, int dirty)
lid_t lid, next; lid_t lid, next;
struct metapage *mp; struct metapage *mp;
struct tblock *tblk = tid_to_tblock(tid); struct tblock *tblk = tid_to_tblock(tid);
struct tlock *tlck;
jfs_warn("txAbort: tid:%d dirty:0x%x", tid, dirty); jfs_warn("txAbort: tid:%d dirty:0x%x", tid, dirty);
...@@ -2631,9 +2628,10 @@ void txAbort(tid_t tid, int dirty) ...@@ -2631,9 +2628,10 @@ void txAbort(tid_t tid, int dirty)
* free tlocks of the transaction * free tlocks of the transaction
*/ */
for (lid = tblk->next; lid; lid = next) { for (lid = tblk->next; lid; lid = next) {
next = lid_to_tlock(lid)->next; tlck = lid_to_tlock(lid);
next = tlck->next;
mp = lid_to_tlock(lid)->mp; mp = tlck->mp;
JFS_IP(tlck->ip)->xtlid = 0;
if (mp) { if (mp) {
mp->lid = 0; mp->lid = 0;
......
...@@ -113,11 +113,12 @@ typedef struct { ...@@ -113,11 +113,12 @@ typedef struct {
#define addressPXD(pxd)\ #define addressPXD(pxd)\
( ((s64)((pxd)->addr1)) << 32 | __le32_to_cpu((pxd)->addr2)) ( ((s64)((pxd)->addr1)) << 32 | __le32_to_cpu((pxd)->addr2))
#define MAXTREEHEIGHT 8
/* pxd list */ /* pxd list */
struct pxdlist { struct pxdlist {
s16 maxnpxd; s16 maxnpxd;
s16 npxd; s16 npxd;
pxd_t pxd[8]; pxd_t pxd[MAXTREEHEIGHT];
}; };
......
...@@ -858,7 +858,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, ...@@ -858,7 +858,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
unchar *i_fastsymlink; unchar *i_fastsymlink;
s64 xlen = 0; s64 xlen = 0;
int bmask = 0, xsize; int bmask = 0, xsize;
s64 xaddr; s64 extent = 0, xaddr;
struct metapage *mp; struct metapage *mp;
struct super_block *sb; struct super_block *sb;
struct tblock *tblk; struct tblock *tblk;
...@@ -892,29 +892,11 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, ...@@ -892,29 +892,11 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
down(&JFS_IP(dip)->commit_sem); down(&JFS_IP(dip)->commit_sem);
down(&JFS_IP(ip)->commit_sem); down(&JFS_IP(ip)->commit_sem);
if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE)))
goto out3;
tblk = tid_to_tblock(tid); tblk = tid_to_tblock(tid);
tblk->xflag |= COMMIT_CREATE; tblk->xflag |= COMMIT_CREATE;
tblk->ino = ip->i_ino; tblk->ino = ip->i_ino;
tblk->u.ixpxd = JFS_IP(ip)->ixpxd; tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
/*
* create entry for symbolic link in parent directory
*/
ino = ip->i_ino;
if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
jfs_err("jfs_symlink: dtInsert returned %d", rc);
/* discard ne inode */
goto out3;
}
/* fix symlink access permission /* fix symlink access permission
* (dir_create() ANDs in the u.u_cmask, * (dir_create() ANDs in the u.u_cmask,
* but symlinks really need to be 777 access) * but symlinks really need to be 777 access)
...@@ -922,7 +904,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, ...@@ -922,7 +904,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
ip->i_mode |= 0777; ip->i_mode |= 0777;
/* /*
* write symbolic link target path name * write symbolic link target path name
*/ */
xtInitRoot(tid, ip); xtInitRoot(tid, ip);
...@@ -966,37 +948,48 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, ...@@ -966,37 +948,48 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
xsize = (ssize + bmask) & ~bmask; xsize = (ssize + bmask) & ~bmask;
xaddr = 0; xaddr = 0;
xlen = xsize >> JFS_SBI(sb)->l2bsize; xlen = xsize >> JFS_SBI(sb)->l2bsize;
if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0)) == 0) { if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) {
ip->i_size = ssize - 1; txAbort(tid, 0);
while (ssize) {
int copy_size = min(ssize, PSIZE);
mp = get_metapage(ip, xaddr, PSIZE, 1);
if (mp == NULL) {
dtDelete(tid, dip, &dname, &ino,
JFS_REMOVE);
rc = -EIO;
goto out3;
}
memcpy(mp->data, name, copy_size);
flush_metapage(mp);
#if 0
set_buffer_uptodate(bp);
mark_buffer_dirty(bp, 1);
if (IS_SYNC(dip))
sync_dirty_buffer(bp);
brelse(bp);
#endif /* 0 */
ssize -= copy_size;
xaddr += JFS_SBI(sb)->nbperpage;
}
ip->i_blocks = LBLK2PBLK(sb, xlen);
} else {
dtDelete(tid, dip, &dname, &ino, JFS_REMOVE);
rc = -ENOSPC; rc = -ENOSPC;
goto out3; goto out3;
} }
extent = xaddr;
ip->i_size = ssize - 1;
while (ssize) {
/* This is kind of silly since PATH_MAX == 4K */
int copy_size = min(ssize, PSIZE);
mp = get_metapage(ip, xaddr, PSIZE, 1);
if (mp == NULL) {
dbFree(ip, extent, xlen);
rc = -EIO;
txAbort(tid, 0);
goto out3;
}
memcpy(mp->data, name, copy_size);
flush_metapage(mp);
ssize -= copy_size;
name += copy_size;
xaddr += JFS_SBI(sb)->nbperpage;
}
ip->i_blocks = LBLK2PBLK(sb, xlen);
}
/*
* create entry for symbolic link in parent directory
*/
rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE);
if (rc == 0) {
ino = ip->i_ino;
rc = dtInsert(tid, dip, &dname, &ino, &btstack);
}
if (rc) {
if (xlen)
dbFree(ip, extent, xlen);
txAbort(tid, 0);
/* discard new inode */
goto out3;
} }
insert_inode_hash(ip); insert_inode_hash(ip);
...@@ -1004,23 +997,11 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, ...@@ -1004,23 +997,11 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
/* /*
* commit update of parent directory and link object * commit update of parent directory and link object
*
* if extent allocation failed (ENOSPC),
* the parent inode is committed regardless to avoid
* backing out parent directory update (by dtInsert())
* and subsequent dtDelete() which is harmless wrt
* integrity concern.
* the symlink inode will be freed by iput() at exit
* as it has a zero link count (by dtDelete()) and
* no permanant resources.
*/ */
iplist[0] = dip; iplist[0] = dip;
if (rc == 0) { iplist[1] = ip;
iplist[1] = ip; rc = txCommit(tid, 2, &iplist[0], 0);
rc = txCommit(tid, 2, &iplist[0], 0);
} else
rc = txCommit(tid, 1, &iplist[0], 0);
out3: out3:
txEnd(tid); txEnd(tid);
...@@ -1223,7 +1204,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1223,7 +1204,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/* Linelock header of dtree */ /* Linelock header of dtree */
tlck = txLock(tid, old_ip, tlck = txLock(tid, old_ip,
(struct metapage *) &JFS_IP(old_ip)->bxflag, (struct metapage *) &JFS_IP(old_ip)->bxflag,
tlckDTREE | tlckBTROOT); tlckDTREE | tlckBTROOT | tlckRELINK);
dtlck = (struct dt_lock *) & tlck->lock; dtlck = (struct dt_lock *) & tlck->lock;
ASSERT(dtlck->index == 0); ASSERT(dtlck->index == 0);
lv = & dtlck->lv[0]; lv = & dtlck->lv[0];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment