[PATCH] Handle out of space errors more gracefully (1 of 2)
[email protected] Thu, 10 Jun 2004 12:41:53 -0500
| Newsgroups | gmane.comp.file-systems.jfs.patches |
|---|---|
| Message-ID | <[email protected]> |
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/02 16:28:51-05:00 [email protected] # JFS: Handle out of space errors more gracefully # # Signed-off-by: Dave Kleikamp <[email protected]> # diff -Nru a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c --- a/fs/jfs/jfs_dtree.c 2004-06-10 12:37:17 -05:00 +++ b/fs/jfs/jfs_dtree.c 2004-06-10 12:37:17 -05:00 @@ -378,6 +378,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)) + goto clean_up; /* No space */ /* * Save the table, we're going to overwrite it with the @@ -394,8 +396,8 @@ /* * Allocate the first block & add it to the xtree */ - xaddr = 0; if (xtInsert(tid, ip, 0, 0, sbi->nbperpage, &xaddr, 0)) { + /* This really shouldn't fail */ jfs_warn("add_index: xtInsert failed!"); memcpy(&jfs_ip->i_dirtable, temp_table, sizeof (temp_table)); @@ -975,8 +977,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; diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c --- a/fs/jfs/jfs_txnmgr.c 2004-06-10 12:37:17 -05:00 +++ b/fs/jfs/jfs_txnmgr.c 2004-06-10 12:37:17 -05:00 @@ -1747,7 +1747,10 @@ if (lwm == next) goto out; - assert(lwm < next); + if (lwm > next) { + jfs_err("xtLog: lwm > next\n"); + goto out; + } tlck->flag |= tlckUPDATEMAP; xadlock->flag = mlckALLOCXADLIST; xadlock->count = next - lwm; @@ -1913,25 +1916,18 @@ /* * write log records */ - /* - * allocate entries XAD[lwm:next]: - */ - if (lwm < next) { - /* log after-image for logredo(): - * 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. - */ - 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)); - } + /* log after-image for logredo(): + * + * 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. + */ + 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]: @@ -2624,6 +2620,7 @@ lid_t lid, next; struct metapage *mp; struct tblock *tblk = tid_to_tblock(tid); + struct tlock *tlck; jfs_warn("txAbort: tid:%d dirty:0x%x", tid, dirty); @@ -2631,9 +2628,10 @@ * free tlocks of the transaction */ for (lid = tblk->next; lid; lid = next) { - next = lid_to_tlock(lid)->next; - - mp = lid_to_tlock(lid)->mp; + tlck = lid_to_tlock(lid); + next = tlck->next; + mp = tlck->mp; + JFS_IP(tlck->ip)->xtlid = 0; if (mp) { mp->lid = 0; diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c --- a/fs/jfs/namei.c 2004-06-10 12:37:17 -05:00 +++ b/fs/jfs/namei.c 2004-06-10 12:37:17 -05:00 @@ -858,7 +858,7 @@ unchar *i_fastsymlink; s64 xlen = 0; int bmask = 0, xsize; - s64 xaddr; + s64 extent = 0, xaddr; struct metapage *mp; struct super_block *sb; struct tblock *tblk; @@ -892,29 +892,11 @@ down(&JFS_IP(dip)->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->xflag |= COMMIT_CREATE; tblk->ino = ip->i_ino; 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 * (dir_create() ANDs in the u.u_cmask, * but symlinks really need to be 777 access) @@ -922,7 +904,7 @@ ip->i_mode |= 0777; /* - * write symbolic link target path name + * write symbolic link target path name */ xtInitRoot(tid, ip); @@ -966,37 +948,48 @@ xsize = (ssize + bmask) & ~bmask; xaddr = 0; xlen = xsize >> JFS_SBI(sb)->l2bsize; - if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0)) == 0) { - ip->i_size = ssize - 1; - 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); + if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) { + txAbort(tid, 0); rc = -ENOSPC; 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); @@ -1004,23 +997,11 @@ /* * 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; - if (rc == 0) { - iplist[1] = ip; - rc = txCommit(tid, 2, &iplist[0], 0); - } else - rc = txCommit(tid, 1, &iplist[0], 0); + iplist[1] = ip; + rc = txCommit(tid, 2, &iplist[0], 0); out3: txEnd(tid); @@ -1223,7 +1204,7 @@ /* Linelock header of dtree */ tlck = txLock(tid, old_ip, (struct metapage *) &JFS_IP(old_ip)->bxflag, - tlckDTREE | tlckBTROOT); + tlckDTREE | tlckBTROOT | tlckRELINK); dtlck = (struct dt_lock *) & tlck->lock; ASSERT(dtlck->index == 0); lv = & dtlck->lv[0];