From aba344fdfed81b2c03d6114c54cfd73a486aa10b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 5 Jul 1999 23:09:37 +0000 Subject: Merge with Linux 2.3.9. --- fs/ext2/dir.c | 2 +- fs/ext2/file.c | 20 +-- fs/ext2/fsync.c | 2 +- fs/ext2/inode.c | 370 +++++++++++++++++++++++++---------------------------- fs/ext2/namei.c | 2 +- fs/ext2/symlink.c | 2 +- fs/ext2/truncate.c | 33 +---- 7 files changed, 189 insertions(+), 242 deletions(-) (limited to 'fs/ext2') diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 59f068b5e..cf9e615bd 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -67,7 +67,7 @@ struct inode_operations ext2_dir_inode_operations = { ext2_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* bmap */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* flushpage */ diff --git a/fs/ext2/file.c b/fs/ext2/file.c index c90419ce3..e223ce277 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -37,7 +37,6 @@ #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) -static int ext2_writepage (struct file * file, struct page * page); static long long ext2_file_lseek(struct file *, long long, int); #if BITS_PER_LONG < 64 static int ext2_open_file (struct inode *, struct file *); @@ -106,23 +105,16 @@ static inline void remove_suid(struct inode *inode) } } -static int ext2_writepage (struct file * file, struct page * page) -{ - return block_write_full_page(file, page, ext2_getblk_block); -} - -static long ext2_write_one_page (struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf) -{ - return block_write_partial_page(file, page, offset, bytes, buf, ext2_getblk_block); -} - /* * Write to a file (through the page cache). */ static ssize_t ext2_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - ssize_t retval = generic_file_write(file, buf, count, ppos, ext2_write_one_page); + ssize_t retval; + + retval = generic_file_write(file, buf, count, + ppos, block_write_partial_page); if (retval > 0) { struct inode *inode = file->f_dentry->d_inode; remove_suid(inode); @@ -195,9 +187,9 @@ struct inode_operations ext2_file_inode_operations = { NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - ext2_bmap, /* bmap */ + ext2_get_block, /* get_block */ block_read_full_page, /* readpage */ - ext2_writepage, /* writepage */ + block_write_full_page, /* writepage */ block_flushpage, /* flushpage */ ext2_truncate, /* truncate */ ext2_permission, /* permission */ diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c index 8ae361e73..3969e17e9 100644 --- a/fs/ext2/fsync.c +++ b/fs/ext2/fsync.c @@ -56,7 +56,7 @@ static int sync_indirect(struct inode * inode, u32 * block, int wait) return 0; } ll_rw_block(WRITE, 1, &bh); - bh->b_count--; + atomic_dec(&bh->b_count); return 0; } diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 02fb5b7b7..171f34a16 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -129,23 +129,22 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err) return result; } - -int ext2_bmap (struct inode * inode, int block) +static inline long ext2_block_map (struct inode * inode, long block) { int i, ret; - int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); - int addr_per_block_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); + int ptrs = EXT2_ADDR_PER_BLOCK(inode->i_sb); + int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); ret = 0; lock_kernel(); if (block < 0) { - ext2_warning (inode->i_sb, "ext2_bmap", "block < 0"); + ext2_warning (inode->i_sb, "ext2_block_map", "block < 0"); goto out; } - if (block >= EXT2_NDIR_BLOCKS + addr_per_block + - (1 << (addr_per_block_bits * 2)) + - ((1 << (addr_per_block_bits * 2)) << addr_per_block_bits)) { - ext2_warning (inode->i_sb, "ext2_bmap", "block > big"); + if (block >= EXT2_NDIR_BLOCKS + ptrs + + (1 << (ptrs_bits * 2)) + + ((1 << (ptrs_bits * 2)) << ptrs_bits)) { + ext2_warning (inode->i_sb, "ext2_block_map", "block > big"); goto out; } if (block < EXT2_NDIR_BLOCKS) { @@ -153,7 +152,7 @@ int ext2_bmap (struct inode * inode, int block) goto out; } block -= EXT2_NDIR_BLOCKS; - if (block < addr_per_block) { + if (block < ptrs) { i = inode_bmap (inode, EXT2_IND_BLOCK); if (!i) goto out; @@ -161,122 +160,64 @@ int ext2_bmap (struct inode * inode, int block) inode->i_sb->s_blocksize), block); goto out; } - block -= addr_per_block; - if (block < (1 << (addr_per_block_bits * 2))) { + block -= ptrs; + if (block < (1 << (ptrs_bits * 2))) { i = inode_bmap (inode, EXT2_DIND_BLOCK); if (!i) goto out; i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - block >> addr_per_block_bits); + block >> ptrs_bits); if (!i) goto out; ret = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - block & (addr_per_block - 1)); + block & (ptrs - 1)); + goto out; } - block -= (1 << (addr_per_block_bits * 2)); + block -= (1 << (ptrs_bits * 2)); i = inode_bmap (inode, EXT2_TIND_BLOCK); if (!i) goto out; i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - block >> (addr_per_block_bits * 2)); + block >> (ptrs_bits * 2)); if (!i) goto out; i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - (block >> addr_per_block_bits) & (addr_per_block - 1)); + (block >> ptrs_bits) & (ptrs - 1)); if (!i) goto out; ret = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - block & (addr_per_block - 1)); + block & (ptrs - 1)); out: unlock_kernel(); return ret; } -int ext2_bmap_create (struct inode * inode, int block) -{ - int i; - int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); - int addr_per_block_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); - - if (block < 0) { - ext2_warning (inode->i_sb, "ext2_bmap", "block < 0"); - return 0; - } - if (block >= EXT2_NDIR_BLOCKS + addr_per_block + - (1 << (addr_per_block_bits * 2)) + - ((1 << (addr_per_block_bits * 2)) << addr_per_block_bits)) { - ext2_warning (inode->i_sb, "ext2_bmap", "block > big"); - return 0; - } - if (block < EXT2_NDIR_BLOCKS) - return inode_bmap (inode, block); - block -= EXT2_NDIR_BLOCKS; - if (block < addr_per_block) { - i = inode_bmap (inode, EXT2_IND_BLOCK); - if (!i) - return 0; - return block_bmap (bread (inode->i_dev, i, - inode->i_sb->s_blocksize), block); - } - block -= addr_per_block; - if (block < (1 << (addr_per_block_bits * 2))) { - i = inode_bmap (inode, EXT2_DIND_BLOCK); - if (!i) - return 0; - i = block_bmap (bread (inode->i_dev, i, - inode->i_sb->s_blocksize), - block >> addr_per_block_bits); - if (!i) - return 0; - return block_bmap (bread (inode->i_dev, i, - inode->i_sb->s_blocksize), - block & (addr_per_block - 1)); - } - block -= (1 << (addr_per_block_bits * 2)); - i = inode_bmap (inode, EXT2_TIND_BLOCK); - if (!i) - return 0; - i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - block >> (addr_per_block_bits * 2)); - if (!i) - return 0; - i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - (block >> addr_per_block_bits) & (addr_per_block - 1)); - if (!i) - return 0; - return block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - block & (addr_per_block - 1)); -} - static struct buffer_head * inode_getblk (struct inode * inode, int nr, - int create, int new_block, int * err, int metadata, - int *phys_block, int *created) + int new_block, int * err, int metadata, long *phys, int *new) { u32 * p; int tmp, goal = 0; struct buffer_head * result; - int blocks = inode->i_sb->s_blocksize / 512; + int blocksize = inode->i_sb->s_blocksize; p = inode->u.ext2_i.i_data + nr; repeat: tmp = le32_to_cpu(*p); if (tmp) { if (metadata) { - struct buffer_head * result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize); + result = getblk (inode->i_dev, tmp, blocksize); if (tmp == le32_to_cpu(*p)) return result; brelse (result); goto repeat; } else { - *phys_block = tmp; + *phys = tmp; return NULL; } } *err = -EFBIG; - if (!create) - goto dont_create; /* Check file limits.. */ { @@ -285,7 +226,6 @@ repeat: limit >>= EXT2_BLOCK_SIZE_BITS(inode->i_sb); if (new_block >= limit) { send_sig(SIGXFSZ, current, 0); -dont_create: *err = -EFBIG; return NULL; } @@ -313,34 +253,41 @@ dont_create: ext2_debug ("goal = %d.\n", goal); tmp = ext2_alloc_block (inode, goal, err); - if (!tmp) + if (!tmp) { + *err = -ENOSPC; return NULL; + } if (metadata) { - result = getblk (inode->i_dev, tmp, inode->i_sb->s_blocksize); + result = getblk (inode->i_dev, tmp, blocksize); if (*p) { ext2_free_blocks (inode, tmp, 1); brelse (result); goto repeat; } - memset(result->b_data, 0, inode->i_sb->s_blocksize); + memset(result->b_data, 0, blocksize); mark_buffer_uptodate(result, 1); mark_buffer_dirty(result, 1); } else { if (*p) { + /* + * Nobody is allowed to change block allocation + * state from under us: + */ + BUG(); ext2_free_blocks (inode, tmp, 1); goto repeat; } - *phys_block = tmp; + *phys = tmp; result = NULL; *err = 0; - *created = 1; + *new = 1; } *p = cpu_to_le32(tmp); inode->u.ext2_i.i_next_alloc_block = new_block; inode->u.ext2_i.i_next_alloc_goal = tmp; inode->i_ctime = CURRENT_TIME; - inode->i_blocks += blocks; + inode->i_blocks += blocksize/512; if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) ext2_sync_inode (inode); else @@ -357,24 +304,23 @@ dont_create: * NULL return in the data case is mandatory. */ static struct buffer_head * block_getblk (struct inode * inode, - struct buffer_head * bh, int nr, int create, int blocksize, - int new_block, int * err, int metadata, int *phys_block, int *created) + struct buffer_head * bh, int nr, + int new_block, int * err, int metadata, long *phys, int *new) { int tmp, goal = 0; u32 * p; struct buffer_head * result; - int blocks = inode->i_sb->s_blocksize / 512; + int blocksize = inode->i_sb->s_blocksize; unsigned long limit; - + + result = NULL; if (!bh) - return NULL; + goto out; if (!buffer_uptodate(bh)) { ll_rw_block (READ, 1, &bh); wait_on_buffer (bh); - if (!buffer_uptodate(bh)) { - brelse (bh); - return NULL; - } + if (!buffer_uptodate(bh)) + goto out; } p = (u32 *) bh->b_data + nr; repeat: @@ -382,31 +328,24 @@ repeat: if (tmp) { if (metadata) { result = getblk (bh->b_dev, tmp, blocksize); - if (tmp == le32_to_cpu(*p)) { - brelse (bh); - return result; - } + if (tmp == le32_to_cpu(*p)) + goto out; brelse (result); goto repeat; } else { - *phys_block = tmp; - brelse (bh); - return NULL; + *phys = tmp; + /* result == NULL */ + goto out; } } *err = -EFBIG; - if (!create) { - brelse (bh); - return NULL; - } limit = current->rlim[RLIMIT_FSIZE].rlim_cur; if (limit < RLIM_INFINITY) { limit >>= EXT2_BLOCK_SIZE_BITS(inode->i_sb); if (new_block >= limit) { - brelse (bh); send_sig(SIGXFSZ, current, 0); - return NULL; + goto out; } } @@ -423,10 +362,8 @@ repeat: goal = bh->b_blocknr; } tmp = ext2_alloc_block (inode, goal, err); - if (!tmp) { - brelse (bh); - return NULL; - } + if (!tmp) + goto out; if (metadata) { result = getblk (bh->b_dev, tmp, blocksize); if (*p) { @@ -438,12 +375,10 @@ repeat: mark_buffer_uptodate(result, 1); mark_buffer_dirty(result, 1); } else { - *phys_block = tmp; - result = NULL; - *err = 0; - *created = 1; + *phys = tmp; + *new = 1; } - if (le32_to_cpu(*p)) { + if (*p) { ext2_free_blocks (inode, tmp, 1); brelse (result); goto repeat; @@ -455,117 +390,162 @@ repeat: wait_on_buffer (bh); } inode->i_ctime = CURRENT_TIME; - inode->i_blocks += blocks; + inode->i_blocks += blocksize/512; mark_inode_dirty(inode); inode->u.ext2_i.i_next_alloc_block = new_block; inode->u.ext2_i.i_next_alloc_goal = tmp; + *err = 0; +out: brelse (bh); return result; } -int ext2_getblk_block (struct inode * inode, long block, - int create, int * err, int * created) +int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) { - struct buffer_head * bh, *tmp; - unsigned long b; - unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); - int addr_per_block_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); - int phys_block, ret; + int ret, err, new; + struct buffer_head *bh; + unsigned long ptr, phys; + /* + * block pointers per block + */ + unsigned long ptrs = EXT2_ADDR_PER_BLOCK(inode->i_sb); + int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); + const int direct_blocks = EXT2_NDIR_BLOCKS, + indirect_blocks = ptrs, + double_blocks = (1 << (ptrs_bits * 2)), + triple_blocks = (1 << (ptrs_bits * 3)); - lock_kernel(); - ret = 0; - *err = -EIO; - if (block < 0) { - ext2_warning (inode->i_sb, "ext2_getblk", "block < 0"); - goto abort; - } - if (block > EXT2_NDIR_BLOCKS + addr_per_block + - (1 << (addr_per_block_bits * 2)) + - ((1 << (addr_per_block_bits * 2)) << addr_per_block_bits)) { - ext2_warning (inode->i_sb, "ext2_getblk", "block > big"); - goto abort; + if (!create) { + /* + * Will clean this up further, ext2_block_map() should use the + * bh instead of an integer block-number interface. + */ + phys = ext2_block_map(inode, iblock); + if (phys) { + bh_result->b_dev = inode->i_dev; + bh_result->b_blocknr = phys; + bh_result->b_state |= (1UL << BH_Mapped); + } + return 0; } + + err = -EIO; + new = 0; + ret = 0; + bh = NULL; + + lock_kernel(); + + if (iblock < 0) + goto abort_negative; + if (iblock > direct_blocks + indirect_blocks + + double_blocks + triple_blocks) + goto abort_too_big; + /* * If this is a sequential block allocation, set the next_alloc_block * to this block now so that all the indblock and data block * allocations use the same goal zone */ - ext2_debug ("block %lu, next %lu, goal %lu.\n", block, + ext2_debug ("block %lu, next %lu, goal %lu.\n", iblock, inode->u.ext2_i.i_next_alloc_block, inode->u.ext2_i.i_next_alloc_goal); - if (block == inode->u.ext2_i.i_next_alloc_block + 1) { + if (iblock == inode->u.ext2_i.i_next_alloc_block + 1) { inode->u.ext2_i.i_next_alloc_block++; inode->u.ext2_i.i_next_alloc_goal++; } - *err = 0; // -ENOSPC; - b = block; - *created = 0; - if (block < EXT2_NDIR_BLOCKS) { - /* - * data page. - */ - tmp = inode_getblk (inode, block, create, b, - err, 0, &phys_block, created); - goto out; - } - block -= EXT2_NDIR_BLOCKS; - if (block < addr_per_block) { - bh = inode_getblk (inode, EXT2_IND_BLOCK, create, b, err, 1, NULL, NULL); - tmp = block_getblk (inode, bh, block, create, - inode->i_sb->s_blocksize, b, err, 0, &phys_block, created); - goto out; - } - block -= addr_per_block; - if (block < (1 << (addr_per_block_bits * 2))) { - bh = inode_getblk (inode, EXT2_DIND_BLOCK, create, b, err, 1, NULL, NULL); - bh = block_getblk (inode, bh, block >> addr_per_block_bits, - create, inode->i_sb->s_blocksize, b, err, 1, NULL, NULL); - tmp = block_getblk (inode, bh, block & (addr_per_block - 1), - create, inode->i_sb->s_blocksize, b, err, 0, &phys_block, created); + err = 0; + ptr = iblock; + + /* + * ok, these macros clean the logic up a bit and make + * it much more readable: + */ +#define GET_INODE_DATABLOCK(x) \ + inode_getblk(inode, x, iblock, &err, 0, &phys, &new) +#define GET_INODE_PTR(x) \ + inode_getblk(inode, x, iblock, &err, 1, NULL, NULL) +#define GET_INDIRECT_DATABLOCK(x) \ + block_getblk (inode, bh, x, iblock, &err, 0, &phys, &new); +#define GET_INDIRECT_PTR(x) \ + block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL); + + if (ptr < direct_blocks) { + bh = GET_INODE_DATABLOCK(ptr); goto out; } - block -= (1 << (addr_per_block_bits * 2)); - bh = inode_getblk (inode, EXT2_TIND_BLOCK, create, b, err, 1, NULL,NULL); - bh = block_getblk (inode, bh, block >> (addr_per_block_bits * 2), - create, inode->i_sb->s_blocksize, b, err, 1, NULL,NULL); - bh = block_getblk (inode, bh, (block >> addr_per_block_bits) & - (addr_per_block - 1), create, inode->i_sb->s_blocksize, - b, err, 1, NULL,NULL); - tmp = block_getblk (inode, bh, block & (addr_per_block - 1), create, - inode->i_sb->s_blocksize, b, err, 0, &phys_block, created); + ptr -= direct_blocks; + if (ptr < indirect_blocks) { + bh = GET_INODE_PTR(EXT2_IND_BLOCK); + goto get_indirect; + } + ptr -= indirect_blocks; + if (ptr < double_blocks) { + bh = GET_INODE_PTR(EXT2_DIND_BLOCK); + goto get_double; + } + ptr -= double_blocks; + bh = GET_INODE_PTR(EXT2_TIND_BLOCK); + bh = GET_INDIRECT_PTR(ptr >> (ptrs_bits * 2)); +get_double: + bh = GET_INDIRECT_PTR((ptr >> ptrs_bits) & (ptrs - 1)); +get_indirect: + bh = GET_INDIRECT_DATABLOCK(ptr & (ptrs - 1)); + +#undef GET_INODE_DATABLOCK +#undef GET_INODE_PTR +#undef GET_INDIRECT_DATABLOCK +#undef GET_INDIRECT_PTR out: - if (!phys_block) - goto abort; - if (*err) + if (bh) + BUG(); // temporary debugging check + if (err) goto abort; - ret = phys_block; + if (!phys) + BUG(); // must not happen either + + bh_result->b_dev = inode->i_dev; + bh_result->b_blocknr = phys; + bh_result->b_state |= (1UL << BH_Mapped); /* safe */ + if (new) + bh_result->b_state |= (1UL << BH_New); abort: unlock_kernel(); - return ret; + return err; + +abort_negative: + ext2_warning (inode->i_sb, "ext2_get_block", "block < 0"); + goto abort; + +abort_too_big: + ext2_warning (inode->i_sb, "ext2_get_block", "block > big"); + goto abort; } -struct buffer_head * ext2_getblk (struct inode * inode, long block, - int create, int * err) +struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, int * err) { - struct buffer_head *tmp = NULL; - int phys_block; - int created; - - phys_block = ext2_getblk_block (inode, block, create, err, &created); - - if (phys_block) { - tmp = getblk (inode->i_dev, phys_block, inode->i_sb->s_blocksize); - if (created) { - memset(tmp->b_data, 0, inode->i_sb->s_blocksize); - mark_buffer_uptodate(tmp, 1); - mark_buffer_dirty(tmp, 1); + struct buffer_head dummy; + int error; + + dummy.b_state = 0; + dummy.b_blocknr = -1000; + error = ext2_get_block(inode, block, &dummy, create); + *err = error; + if (!error && buffer_mapped(&dummy)) { + struct buffer_head *bh; + bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); + if (buffer_new(&dummy)) { + memset(bh->b_data, 0, inode->i_sb->s_blocksize); + mark_buffer_uptodate(bh, 1); + mark_buffer_dirty(bh, 1); } + return bh; } - return tmp; + return NULL; } struct buffer_head * ext2_bread (struct inode * inode, int block, diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 885929f70..9666118ee 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -555,7 +555,7 @@ static int empty_dir (struct inode * inode) while (offset < inode->i_size ) { if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { brelse (bh); - bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &err); + bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 0, &err); if (!bh) { #if 0 ext2_error (sb, "empty_dir", diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index b0ebcb91b..5f73159c3 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -43,7 +43,7 @@ struct inode_operations ext2_symlink_inode_operations = { NULL, /* rename */ ext2_readlink, /* readlink */ ext2_follow_link, /* follow_link */ - NULL, /* bmap */ + NULL, /* get_block */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* flushpage */ diff --git a/fs/ext2/truncate.c b/fs/ext2/truncate.c index b6f57efb0..d824edb0b 100644 --- a/fs/ext2/truncate.c +++ b/fs/ext2/truncate.c @@ -129,7 +129,7 @@ static int check_block_empty(struct inode *inode, struct buffer_head *bh, if (*(ind++)) goto in_use; - if (bh->b_count == 1) { + if (atomic_read(&bh->b_count) == 1) { int tmp; tmp = le32_to_cpu(*p); *p = 0; @@ -141,7 +141,7 @@ static int check_block_empty(struct inode *inode, struct buffer_head *bh, bforget(bh); if (ind_bh) mark_buffer_dirty(ind_bh, 1); - ext2_free_blocks (inode, tmp, 1); + ext2_free_blocks(inode, tmp, 1); goto out; } retry = 1; @@ -158,11 +158,10 @@ out: } #define DATA_BUFFER_USED(bh) \ - (bh->b_count || buffer_locked(bh)) + (atomic_read(&bh->b_count) || buffer_locked(bh)) static int trunc_direct (struct inode * inode) { - struct buffer_head * bh; int i, retry = 0; unsigned long block_to_free = 0, free_count = 0; int blocks = inode->i_sb->s_blocksize / 512; @@ -175,19 +174,9 @@ static int trunc_direct (struct inode * inode) if (!tmp) continue; - bh = find_buffer(inode->i_dev, tmp, inode->i_sb->s_blocksize); - if (bh) { - if (DATA_BUFFER_USED(bh)) { - retry = 1; - continue; - } - bh->b_count++; - } - *p = 0; inode->i_blocks -= blocks; mark_inode_dirty(inode); - bforget(bh); /* accumulate blocks to free if they're contiguous */ if (free_count == 0) @@ -206,8 +195,7 @@ static int trunc_direct (struct inode * inode) return retry; } -static int trunc_indirect (struct inode * inode, int offset, u32 * p, - struct buffer_head *dind_bh) +static int trunc_indirect (struct inode * inode, int offset, u32 * p, struct buffer_head *dind_bh) { struct buffer_head * ind_bh; int i, tmp, retry = 0; @@ -242,28 +230,15 @@ static int trunc_indirect (struct inode * inode, int offset, u32 * p, indirect_block = 0; for (i = indirect_block ; i < addr_per_block ; i++) { u32 * ind = i + (u32 *) ind_bh->b_data; - struct buffer_head * bh; wait_on_buffer(ind_bh); tmp = le32_to_cpu(*ind); if (!tmp) continue; - /* - * Use find_buffer so we don't block here. - */ - bh = find_buffer(inode->i_dev, tmp, inode->i_sb->s_blocksize); - if (bh) { - if (DATA_BUFFER_USED(bh)) { - retry = 1; - continue; - } - bh->b_count++; - } *ind = 0; inode->i_blocks -= blocks; mark_inode_dirty(inode); - bforget(bh); mark_buffer_dirty(ind_bh, 1); /* accumulate blocks to free if they're contiguous */ -- cgit v1.2.3