patch-2.4.27 linux-2.4.27/fs/jfs/jfs_dtree.c
Next file: linux-2.4.27/fs/jfs/jfs_extent.c
Previous file: linux-2.4.27/fs/jfs/jfs_dmap.c
Back to the patch index
Back to the overall index
- Lines: 250
- Date:
2004-08-07 16:26:05.993401797 -0700
- Orig file:
linux-2.4.26/fs/jfs/jfs_dtree.c
- Orig date:
2004-04-14 06:05:40.000000000 -0700
diff -urN linux-2.4.26/fs/jfs/jfs_dtree.c linux-2.4.27/fs/jfs/jfs_dtree.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
@@ -177,8 +177,8 @@
static void dtGetKey(dtpage_t * p, int i, struct component_name * key,
int flag);
-static void ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
- int ri, struct component_name * key, int flag);
+static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
+ int ri, struct component_name * key, int flag);
static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key,
ddata_t * data, struct dt_lock **);
@@ -342,7 +342,6 @@
struct metapage *mp;
s64 offset;
uint page_offset;
- int rc;
struct tlock *tlck;
s64 xaddr;
@@ -375,16 +374,19 @@
return index;
}
if (index == (MAX_INLINE_DIRTABLE_ENTRY + 1)) {
+ struct dir_table_slot temp_table[12];
+
/*
* 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))
+ goto clean_up; /* No space */
/*
* Save the table, we're going to overwrite it with the
* xtree root
*/
- struct dir_table_slot temp_table[12];
memcpy(temp_table, &jfs_ip->i_dirtable, sizeof(temp_table));
/*
@@ -395,12 +397,12 @@
/*
* Allocate the first block & add it to the xtree
*/
- xaddr = 0;
- if ((rc =
- 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!");
- return -EPERM;
+ memcpy(&jfs_ip->i_dirtable, temp_table,
+ sizeof (temp_table));
+ goto clean_up;
}
ip->i_size = PSIZE;
ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
@@ -408,7 +410,9 @@
if ((mp = get_index_page(ip, 0)) == 0) {
jfs_err("add_index: get_metapage failed!");
xtTruncate(tid, ip, 0, COMMIT_PWMAP);
- return -EPERM;
+ memcpy(&jfs_ip->i_dirtable, temp_table,
+ sizeof (temp_table));
+ goto clean_up;
}
tlck = txLock(tid, ip, mp, tlckDATA);
llck = (struct linelock *) & tlck->lock;
@@ -438,12 +442,9 @@
* This will be the beginning of a new page
*/
xaddr = 0;
- if ((rc =
- xtInsert(tid, ip, 0, blkno, sbi->nbperpage,
- &xaddr, 0))) {
+ if (xtInsert(tid, ip, 0, blkno, sbi->nbperpage, &xaddr, 0)) {
jfs_warn("add_index: xtInsert failed!");
- jfs_ip->next_index--;
- return -EPERM;
+ goto clean_up;
}
ip->i_size += PSIZE;
ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
@@ -457,7 +458,7 @@
if (mp == 0) {
jfs_err("add_index: get/read_metapage failed!");
- return -EPERM;
+ goto clean_up;
}
lock_index(tid, ip, mp, index);
@@ -472,6 +473,12 @@
release_metapage(mp);
return index;
+
+ clean_up:
+
+ jfs_ip->next_index--;
+
+ return 0;
}
/*
@@ -760,11 +767,12 @@
*/
getChild:
/* update max. number of pages to split */
- if (btstack->nsplit >= 8) {
+ if (BT_STACK_FULL(btstack)) {
/* Something's corrupted, mark filesytem dirty so
* chkdsk will fix it.
*/
jfs_error(sb, "stack overrun in dtSearch!");
+ BT_STACK_DUMP(btstack);
rc = -EIO;
goto out;
}
@@ -971,8 +979,10 @@
n -= DTROOTMAXSLOT - sp->header.freecnt; /* header + entries */
if (n <= split->nslot)
xlen++;
- if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr)))
+ if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr))) {
+ DT_PUTPAGE(smp);
goto freeKeyName;
+ }
pxdlist.maxnpxd = 1;
pxdlist.npxd = 0;
@@ -982,7 +992,9 @@
split->pxdlist = &pxdlist;
rc = dtSplitRoot(tid, ip, split, &rmp);
- DT_PUTPAGE(rmp);
+ if (!rc)
+ DT_PUTPAGE(rmp);
+
DT_PUTPAGE(smp);
goto freeKeyName;
@@ -1150,9 +1162,16 @@
if ((sp->header.flag & BT_ROOT && skip > 1) ||
sp->header.prev != 0 || skip > 1) {
/* compute uppercase router prefix key */
- ciGetLeafPrefixKey(lp,
- lp->header.nextindex - 1,
- rp, 0, &key, sbi->mntflag);
+ rc = ciGetLeafPrefixKey(lp,
+ lp->header.nextindex-1,
+ rp, 0, &key,
+ sbi->mntflag);
+ if (rc) {
+ DT_PUTPAGE(lmp);
+ DT_PUTPAGE(rmp);
+ DT_PUTPAGE(smp);
+ goto splitOut;
+ }
} else {
/* next to leftmost entry of
lowest internal level */
@@ -1876,6 +1895,9 @@
xlen = lengthPXD(pxd);
xsize = xlen << JFS_SBI(sb)->l2bsize;
rmp = get_metapage(ip, rbn, xsize, 1);
+ if (!rmp)
+ return -EIO;
+
rp = rmp->data;
BT_MARK_DIRTY(rmp, ip);
@@ -3326,6 +3348,12 @@
/*
* 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 */
BT_PUSH(btstack, bn, 0);
@@ -3708,18 +3736,28 @@
* from two adjacent leaf entries
* across page boundary
*
- * return:
- * Number of prefix bytes needed to distinguish b from a.
+ * return: non-zero on error
+ *
*/
-static void ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
+static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
int ri, struct component_name * key, int flag)
{
int klen, namlen;
wchar_t *pl, *pr, *kname;
- wchar_t lname[JFS_NAME_MAX + 1];
- struct component_name lkey = { 0, lname };
- wchar_t rname[JFS_NAME_MAX + 1];
- struct component_name rkey = { 0, rname };
+ struct component_name lkey;
+ struct component_name rkey;
+
+ lkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ GFP_KERNEL);
+ if (lkey.name == NULL)
+ return -ENOSPC;
+
+ rkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ GFP_KERNEL);
+ if (rkey.name == NULL) {
+ kfree(lkey.name);
+ return -ENOSPC;
+ }
/* get left and right key */
dtGetKey(lp, li, &lkey, flag);
@@ -3744,7 +3782,7 @@
*kname = *pr;
if (*pl != *pr) {
key->namlen = klen + 1;
- return;
+ goto free_names;
}
}
@@ -3755,7 +3793,10 @@
} else /* l->namelen == r->namelen */
key->namlen = klen;
- return;
+free_names:
+ kfree(lkey.name);
+ kfree(rkey.name);
+ return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)