diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 0ab83bb7bbdf..164ccc824820 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -591,7 +591,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data, /* uppercase search key for c-i directory */ - UniStrcpy(ciKey.name, key->name); + UniStrncpy_le(ciKey.name, key->name, JFS_NAME_MAX); ciKey.namlen = key->namlen; /* only uppercase if case-insensitive support is on */ @@ -1483,6 +1483,9 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split, tlck, ip, mp); dtlck = (struct dt_lock *) & tlck->lock; + if (dtlck->index >= dtlck->maxcnt) + dtlck = txLinelock(dtlck); + /* linelock header of previous right sibling page */ lv = & dtlck->lv[dtlck->index]; lv->offset = 0; @@ -1553,6 +1556,8 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split, * new/right page moved in entries are linelocked; */ /* linelock header + stbl of new right page */ + if (rdtlck->index >= rdtlck->maxcnt) + rdtlck = txLinelock(rdtlck); rlv = & rdtlck->lv[rdtlck->index]; rlv->offset = 0; rlv->length = 5; @@ -1834,6 +1839,8 @@ static int dtExtendPage(tid_t tid, */ tlck = txLock(tid, ip, pmp, tlckDTREE | tlckENTRY); dtlck = (struct dt_lock *) & tlck->lock; + if (dtlck->index >= dtlck->maxcnt) + dtlck = txLinelock(dtlck); lv = & dtlck->lv[dtlck->index]; /* linelock parent entry - 1st slot */ @@ -3809,10 +3816,14 @@ static void dtMoveEntry(dtpage_t * sp, int si, dtpage_t * dp, sfsi = sp->header.freelist; /* linelock destination entry slot */ + if (ddtlck->index >= ddtlck->maxcnt) + ddtlck = txLinelock(ddtlck); dlv = & ddtlck->lv[ddtlck->index]; dlv->offset = dsi; /* linelock source entry slot */ + if (sdtlck->index >= sdtlck->maxcnt) + sdtlck = txLinelock(sdtlck); slv = & sdtlck->lv[sdtlck->index]; slv->offset = sstbl[si]; xssi = slv->offset - 1; diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index ecb8e05b8b84..4affea8be5f1 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -762,6 +762,8 @@ int diWrite(tid_t tid, struct inode *ip) * copy inline symlink from in-memory inode to on-disk inode */ if (S_ISLNK(ip->i_mode) && ip->i_size < IDATASIZE) { + if (unlikely(dilinelock->index >= dilinelock->maxcnt)) + dilinelock = txLinelock(dilinelock); lv = & dilinelock->lv[dilinelock->index]; lv->offset = (dioffset + 2 * 128) >> L2INODESLOTSIZE; lv->length = 2; @@ -773,6 +775,8 @@ int diWrite(tid_t tid, struct inode *ip) * 128 byte slot granularity */ if (test_cflag(COMMIT_Inlineea, ip)) { + if (unlikely(dilinelock->index >= dilinelock->maxcnt)) + dilinelock = txLinelock(dilinelock); lv = & dilinelock->lv[dilinelock->index]; lv->offset = (dioffset + 3 * 128) >> L2INODESLOTSIZE; lv->length = 1; @@ -785,6 +789,8 @@ int diWrite(tid_t tid, struct inode *ip) /* * lock/copy inode base: 128 byte slot granularity */ + if (unlikely(dilinelock->index >= dilinelock->maxcnt)) + dilinelock = txLinelock(dilinelock); lv = & dilinelock->lv[dilinelock->index]; lv->offset = dioffset >> L2INODESLOTSIZE; copy_to_dinode(dp, ip); @@ -3022,6 +3028,25 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno, diFreeSpecial(ip); } +static int dinode_check_dtroot(dtroot_t *p) +{ + int fsi, fcnt; + + fcnt = p->header.freecnt; + if (fcnt > DTROOTMAXSLOT - 1) + return -EIO; + + fsi = p->header.freelist; + while (fcnt--) { + if (fsi >= DTROOTMAXSLOT || fsi < 1) + return -EIO; + + fsi = p->slot[fsi].next; + } + + return 0; +} + /* * NAME: copy_from_dinode() * @@ -3116,7 +3141,7 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip) jfs_ip->atlhead = 0; jfs_ip->atltail = 0; jfs_ip->xtlid = 0; - return (0); + return dinode_check_dtroot(&jfs_ip->i_dtroot); } /* diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 871cf4fb3636..0d6c40e7e551 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -270,6 +270,7 @@ static inline struct metapage *alloc_metapage(gfp_t gfp_mask) mp->clsn = 0; mp->log = NULL; init_waitqueue_head(&mp->wait); + INIT_LIST_HEAD(&mp->synclist); } return mp; } @@ -379,7 +380,7 @@ static void remove_from_logsync(struct metapage *mp) mp->lsn = 0; mp->clsn = 0; log->count--; - list_del(&mp->synclist); + list_del_init(&mp->synclist); } LOGSYNC_UNLOCK(log, flags); } diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 7840a03e5bcb..a5a5bc0a266d 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -275,6 +275,7 @@ int txInit(void) for (k = 0; k < nTxBlock; k++) { init_waitqueue_head(&TxBlock[k].gcwait); init_waitqueue_head(&TxBlock[k].waitor); + INIT_LIST_HEAD(&TxBlock[k].synclist); } for (k = 1; k < nTxBlock - 1; k++) { @@ -974,7 +975,7 @@ static void txUnlock(struct tblock * tblk) if (tblk->lsn) { LOGSYNC_LOCK(log, flags); log->count--; - list_del(&tblk->synclist); + list_del_init(&tblk->synclist); LOGSYNC_UNLOCK(log, flags); } }