From 82c0376c407c3e1c03d19fad1cf8e0f07b3b9e89 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 2 Oct 2010 11:46:04 +1000 Subject: [PATCH] use little-endian bit operations for inode usage map. Must not use hos-endian here, so use generic 'le' operations. Also protect all operations with i_mutex. Even if the bitops were atomic, we need the locking when punching a hole in the file, or adding a new block. Signed-off-by: NeilBrown --- inode.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/inode.c b/inode.c index c70a934..1a11743 100644 --- a/inode.c +++ b/inode.c @@ -1409,13 +1409,13 @@ retry: buf = map_dblock(b); while (bnum == 0 && bit < 16) { /* Never return an inum below 16 - they are special */ - if (!test_bit(bit, (unsigned long *)buf)) - set_bit(bit, (unsigned long *)buf); + if (!generic_test_le_bit(bit, (unsigned long *)buf)) + generic___clear_le_bit(bit, (unsigned long *)buf); bit++; } - bit = find_next_bit((unsigned long *)buf, - fs->blocksize<<3, bit); + bit = generic_find_next_le_bit((unsigned long *)buf, + fs->blocksize<<3, bit); unmap_dblock(b, buf); LAFSI(im)->md.inodemap.nextbit = bit+1; if (bit >= fs->blocksize<<3) { @@ -1500,12 +1500,13 @@ inode_map_new_commit(struct inode_map_new_info *imni) int blksize = imni->ib->b.inode->i_sb->s_blocksize; int bit = imni->ib->b.fileaddr & (blksize*8 - 1); int hole = 0; - struct inode *ino; + struct inode *ino = imni->mb->b.inode; + mutex_lock_nested(&ino->i_mutex, I_MUTEX_QUOTA); buf = map_dblock(imni->mb); - clear_bit(bit, buf); + generic___clear_le_bit(bit, buf); if (buf[blksize/sizeof(*buf)-1] == 0 && - find_first_bit(buf, blksize*8) == blksize*8) + generic_find_next_le_bit(buf, blksize*8, 0) == blksize*8) /* block is empty, punch a hole */ hole = 1; @@ -1515,8 +1516,8 @@ inode_map_new_commit(struct inode_map_new_info *imni) else lafs_dirty_dblock(imni->mb); - ino = imni->mb->b.inode; putdref(imni->mb, MKREF(cfi_map)); + mutex_unlock(&ino->i_mutex); iput(ino); } putdref(imni->ib, MKREF(cfi_ino)); @@ -1622,17 +1623,21 @@ static int inode_map_free(struct fs *fs, struct super_block *sb, u32 inum) u32 bnum; int err; + mutex_lock_nested(&im->i_mutex, I_MUTEX_QUOTA); + bnum = inum >> (3 + sb->s_blocksize_bits); bit = inum - (bnum << (3 + sb->s_blocksize_bits)); b = lafs_get_block(im, bnum, NULL, GFP_KERNEL, MKREF(inode_map_free)); if (!b) { + mutex_unlock(&im->i_mutex); iput(im); return -ENOMEM; } err = lafs_read_block(b); if (err) { - iput(im); putdref(b, MKREF(inode_map_free)); + mutex_unlock(&im->i_mutex); + iput(im); return err; } lafs_iolock_written(&b->b); @@ -1647,11 +1652,12 @@ retry: } BUG_ON(err < 0); buf = map_dblock(b); - set_bit(bit, buf); // FIXME this is host-endian !! + generic___set_le_bit(bit, buf); unmap_dblock(b, buf); lafs_dirty_dblock(b); putdref(b, MKREF(inode_map_free)); lafs_checkpoint_unlock(fs); + mutex_unlock(&im->i_mutex); iput(im); return 0; } -- 2.39.5