Commit 3aa8e204 authored by Dave Kleikamp's avatar Dave Kleikamp

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

into kleikamp.austin.ibm.com:/home/shaggy/bk/jfs-2.5
parents 14fc589b b275001f
......@@ -2830,6 +2830,86 @@ void dtInitRoot(tid_t tid, struct inode *ip, u32 idotdot)
return;
}
/*
* add_missing_indices()
*
* function: Fix dtree page in which one or more entries has an invalid index.
* fsck.jfs should really fix this, but it currently does not.
* Called from jfs_readdir when bad index is detected.
*/
static void add_missing_indices(struct inode *inode, s64 bn)
{
struct ldtentry *d;
struct dt_lock *dtlck;
int i;
uint index;
struct lv *lv;
struct metapage *mp;
dtpage_t *p;
int rc;
s8 *stbl;
tid_t tid;
struct tlock *tlck;
tid = txBegin(inode->i_sb, 0);
DT_GETPAGE(inode, bn, mp, PSIZE, p, rc);
if (rc) {
printk(KERN_ERR "DT_GETPAGE failed!\n");
goto end;
}
BT_MARK_DIRTY(mp, inode);
ASSERT(p->header.flag & BT_LEAF);
tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY);
dtlck = (struct dt_lock *) &tlck->lock;
stbl = DT_GETSTBL(p);
for (i = 0; i < p->header.nextindex; i++) {
d = (struct ldtentry *) &p->slot[stbl[i]];
index = le32_to_cpu(d->index);
if ((index < 2) || (index >= JFS_IP(inode)->next_index)) {
d->index = cpu_to_le32(add_index(tid, inode, bn, i));
if (dtlck->index >= dtlck->maxcnt)
dtlck = (struct dt_lock *) txLinelock(dtlck);
lv = dtlck->lv;
lv->offset = stbl[i];
lv->length = 1;
dtlck->index++;
}
}
DT_PUTPAGE(mp);
(void) txCommit(tid, 1, &inode, 0);
end:
txEnd(tid);
}
/*
* Buffer to hold directory entry info while traversing a dtree page
* before being fed to the filldir function
*/
struct jfs_dirent {
loff_t position;
int ino;
u16 name_len;
char name[0];
};
/*
* function to determine next variable-sized jfs_dirent in buffer
*/
inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent)
{
return (struct jfs_dirent *)
((char *)dirent +
((sizeof (struct jfs_dirent) + dirent->name_len + 1 +
sizeof (loff_t) - 1) &
~(sizeof (loff_t) - 1)));
}
/*
* jfs_readdir()
*
......@@ -2846,11 +2926,12 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
struct inode *ip = filp->f_dentry->d_inode;
struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab;
int rc = 0;
loff_t dtpos; /* legacy OS/2 style position */
struct dtoffset {
s16 pn;
s16 index;
s32 unused;
} *dtoffset = (struct dtoffset *) &filp->f_pos;
} *dtoffset = (struct dtoffset *) &dtpos;
s64 bn;
struct metapage *mp;
dtpage_t *p;
......@@ -2860,12 +2941,17 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
int i, next;
struct ldtentry *d;
struct dtslot *t;
int d_namleft, d_namlen, len, outlen;
char *d_name, *name_ptr;
int d_namleft, len, outlen;
unsigned long dirent_buf;
char *name_ptr;
int dtlhdrdatalen;
u32 dir_index;
int do_index = 0;
uint loop_count = 0;
struct jfs_dirent *jfs_dirent;
int jfs_dirents;
int overflow, fix_page, page_fixed = 0;
static int unique_pos = 2; /* If we can't fix broken index */
if (filp->f_pos == DIREND)
return 0;
......@@ -2885,7 +2971,9 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (dir_index > 1) {
struct dir_table_slot dirtab_slot;
if (dtEmpty(ip)) {
if (dtEmpty(ip) ||
(dir_index >= JFS_IP(ip)->next_index)) {
/* Stale position. Directory has shrunk */
filp->f_pos = DIREND;
return 0;
}
......@@ -2963,13 +3051,15 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
*/
dtlhdrdatalen = DTLHDRDATALEN_LEGACY;
if (filp->f_pos == 0) {
dtpos = filp->f_pos;
if (dtpos == 0) {
/* build "." entry */
if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino,
DT_DIR))
return 0;
dtoffset->index = 1;
filp->f_pos = dtpos;
}
if (dtoffset->pn == 0) {
......@@ -2985,6 +3075,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
dtoffset->pn = 1;
dtoffset->index = 0;
filp->f_pos = dtpos;
}
if (dtEmpty(ip)) {
......@@ -3009,32 +3100,72 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
}
d_name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t), GFP_NOFS);
if (d_name == NULL) {
dirent_buf = __get_free_page(GFP_KERNEL);
if (dirent_buf == 0) {
DT_PUTPAGE(mp);
jERROR(1, ("jfs_readdir: kmalloc failed!\n"));
jERROR(1, ("jfs_readdir: __get_free_page failed!\n"));
filp->f_pos = DIREND;
return 0;
return -ENOMEM;
}
while (1) {
jfs_dirent = (struct jfs_dirent *) dirent_buf;
jfs_dirents = 0;
overflow = fix_page = 0;
stbl = DT_GETSTBL(p);
for (i = index; i < p->header.nextindex; i++) {
d = (struct ldtentry *) & p->slot[stbl[i]];
if (((long) jfs_dirent + d->namlen + 1) >
(dirent_buf + PSIZE)) {
/* DBCS codepages could overrun dirent_buf */
index = i;
overflow = 1;
break;
}
d_namleft = d->namlen;
name_ptr = d_name;
name_ptr = jfs_dirent->name;
jfs_dirent->ino = le32_to_cpu(d->inumber);
if (do_index) {
filp->f_pos = le32_to_cpu(d->index);
len = min(d_namleft, DTLHDRDATALEN);
} else
jfs_dirent->position = le32_to_cpu(d->index);
/*
* d->index should always be valid, but it
* isn't. fsck.jfs doesn't create the
* directory index for the lost+found
* directory. Rather than let it go,
* we can try to fix it.
*/
if ((jfs_dirent->position < 2) ||
(jfs_dirent->position >=
JFS_IP(ip)->next_index)) {
if (!page_fixed && !isReadOnly(ip)) {
fix_page = 1;
/*
* setting overflow and setting
* index to i will cause the
* same page to be processed
* again starting here
*/
overflow = 1;
index = i;
break;
}
jfs_dirent->position = unique_pos++;
}
} else {
jfs_dirent->position = dtpos;
len = min(d_namleft, DTLHDRDATALEN_LEGACY);
}
/* copy the name of head/only segment */
outlen = jfs_strfromUCS_le(name_ptr, d->name, len,
codepage);
d_namlen = outlen;
jfs_dirent->name_len = outlen;
/* copy name in the additional segment(s) */
next = d->next;
......@@ -3053,56 +3184,66 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
len = min(d_namleft, DTSLOTDATALEN);
outlen = jfs_strfromUCS_le(name_ptr, t->name,
len, codepage);
d_namlen+= outlen;
jfs_dirent->name_len += outlen;
next = t->next;
}
if (filldir(dirent, d_name, d_namlen, filp->f_pos,
le32_to_cpu(d->inumber), DT_UNKNOWN))
goto out;
jfs_dirents++;
jfs_dirent = next_jfs_dirent(jfs_dirent);
skip_one:
if (!do_index)
dtoffset->index++;
}
/*
* get next leaf page
*/
if (!overflow) {
/* Point to next leaf page */
if (p->header.flag & BT_ROOT)
bn = 0;
else {
bn = le64_to_cpu(p->header.next);
index = 0;
/* update offset (pn:index) for new page */
if (!do_index) {
dtoffset->pn++;
dtoffset->index = 0;
}
}
page_fixed = 0;
}
if (p->header.flag & BT_ROOT) {
filp->f_pos = DIREND;
break;
/* unpin previous leaf page */
DT_PUTPAGE(mp);
jfs_dirent = (struct jfs_dirent *) dirent_buf;
while (jfs_dirents--) {
filp->f_pos = jfs_dirent->position;
if (filldir(dirent, jfs_dirent->name,
jfs_dirent->name_len, filp->f_pos,
jfs_dirent->ino, DT_UNKNOWN))
goto out;
jfs_dirent = next_jfs_dirent(jfs_dirent);
}
bn = le64_to_cpu(p->header.next);
if (bn == 0) {
if (fix_page) {
add_missing_indices(ip, bn);
page_fixed = 1;
}
if (!overflow && (bn == 0)) {
filp->f_pos = DIREND;
break;
}
/* unpin previous leaf page */
DT_PUTPAGE(mp);
/* get next leaf page */
DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc) {
kfree(d_name);
free_page(dirent_buf);
return -rc;
}
/* update offset (pn:index) for new page */
index = 0;
if (!do_index) {
dtoffset->pn++;
dtoffset->index = 0;
}
}
out:
kfree(d_name);
DT_PUTPAGE(mp);
free_page(dirent_buf);
return rc;
}
......
......@@ -365,11 +365,7 @@ int diRead(struct inode *ip)
if ((lengthPXD(&iagp->inoext[extno]) != imap->im_nbperiext) ||
(addressPXD(&iagp->inoext[extno]) == 0)) {
jERROR(1, ("diRead: Bad inoext: 0x%lx, 0x%lx\n",
(ulong) addressPXD(&iagp->inoext[extno]),
(ulong) lengthPXD(&iagp->inoext[extno])));
release_metapage(mp);
updateSuper(ip->i_sb, FM_DIRTY);
return ESTALE;
}
......@@ -416,12 +412,9 @@ int diRead(struct inode *ip)
jERROR(1, ("diRead: i_ino != di_number\n"));
updateSuper(ip->i_sb, FM_DIRTY);
rc = EIO;
} else if (le32_to_cpu(dp->di_nlink) == 0) {
jERROR(1,
("diRead: di_nlink is zero. ino=%ld\n", ip->i_ino));
updateSuper(ip->i_sb, FM_DIRTY);
} else if (le32_to_cpu(dp->di_nlink) == 0)
rc = ESTALE;
} else
else
/* copy the disk inode to the in-memory inode */
rc = copy_from_dinode(dp, ip);
......
......@@ -1552,7 +1552,12 @@ static int lmLogFileSystem(struct jfs_log * log, char *uuid, int activate)
memcpy(logsuper->active[i].uuid, NULL_UUID, 16);
break;
}
assert(i < MAX_ACTIVE);
if (i == MAX_ACTIVE) {
jERROR(1,("Somebody stomped on the journal!\n"));
lbmFree(bpsuper);
return EIO;
}
}
/*
......
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