diff options
Diffstat (limited to 'fs/ufs')
| -rw-r--r-- | fs/ufs/balloc.c | 46 | ||||
| -rw-r--r-- | fs/ufs/inode.c | 14 | ||||
| -rw-r--r-- | fs/ufs/truncate.c | 4 |
3 files changed, 41 insertions, 23 deletions
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 2e0021e8f366..638f4c585e89 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
| @@ -227,24 +227,27 @@ failed: | |||
| 227 | * We can come here from ufs_writepage or ufs_prepare_write, | 227 | * We can come here from ufs_writepage or ufs_prepare_write, |
| 228 | * locked_page is argument of these functions, so we already lock it. | 228 | * locked_page is argument of these functions, so we already lock it. |
| 229 | */ | 229 | */ |
| 230 | static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, | 230 | static void ufs_change_blocknr(struct inode *inode, unsigned int beg, |
| 231 | unsigned int count, unsigned int oldb, | 231 | unsigned int count, unsigned int oldb, |
| 232 | unsigned int newb, struct page *locked_page) | 232 | unsigned int newb, struct page *locked_page) |
| 233 | { | 233 | { |
| 234 | unsigned int blk_per_page = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 234 | const unsigned mask = (1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1; |
| 235 | struct address_space *mapping = inode->i_mapping; | 235 | struct address_space * const mapping = inode->i_mapping; |
| 236 | pgoff_t index, cur_index = locked_page->index; | 236 | pgoff_t index, cur_index; |
| 237 | unsigned int i, j; | 237 | unsigned end, pos, j; |
| 238 | struct page *page; | 238 | struct page *page; |
| 239 | struct buffer_head *head, *bh; | 239 | struct buffer_head *head, *bh; |
| 240 | 240 | ||
| 241 | UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n", | 241 | UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n", |
| 242 | inode->i_ino, count, oldb, newb); | 242 | inode->i_ino, count, oldb, newb); |
| 243 | 243 | ||
| 244 | BUG_ON(!locked_page); | ||
| 244 | BUG_ON(!PageLocked(locked_page)); | 245 | BUG_ON(!PageLocked(locked_page)); |
| 245 | 246 | ||
| 246 | for (i = 0; i < count; i += blk_per_page) { | 247 | cur_index = locked_page->index; |
| 247 | index = (baseblk+i) >> (PAGE_CACHE_SHIFT - inode->i_blkbits); | 248 | |
| 249 | for (end = count + beg; beg < end; beg = (beg | mask) + 1) { | ||
| 250 | index = beg >> (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
| 248 | 251 | ||
| 249 | if (likely(cur_index != index)) { | 252 | if (likely(cur_index != index)) { |
| 250 | page = ufs_get_locked_page(mapping, index); | 253 | page = ufs_get_locked_page(mapping, index); |
| @@ -253,21 +256,32 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, | |||
| 253 | } else | 256 | } else |
| 254 | page = locked_page; | 257 | page = locked_page; |
| 255 | 258 | ||
| 256 | j = i; | ||
| 257 | head = page_buffers(page); | 259 | head = page_buffers(page); |
| 258 | bh = head; | 260 | bh = head; |
| 261 | pos = beg & mask; | ||
| 262 | for (j = 0; j < pos; ++j) | ||
| 263 | bh = bh->b_this_page; | ||
| 264 | j = 0; | ||
| 259 | do { | 265 | do { |
| 260 | if (likely(bh->b_blocknr == j + oldb && j < count)) { | 266 | if (buffer_mapped(bh)) { |
| 261 | unmap_underlying_metadata(bh->b_bdev, | 267 | pos = bh->b_blocknr - oldb; |
| 262 | bh->b_blocknr); | 268 | if (pos < count) { |
| 263 | bh->b_blocknr = newb + j++; | 269 | UFSD(" change from %llu to %llu\n", |
| 264 | mark_buffer_dirty(bh); | 270 | (unsigned long long)pos + oldb, |
| 271 | (unsigned long long)pos + newb); | ||
| 272 | bh->b_blocknr = newb + pos; | ||
| 273 | unmap_underlying_metadata(bh->b_bdev, | ||
| 274 | bh->b_blocknr); | ||
| 275 | mark_buffer_dirty(bh); | ||
| 276 | ++j; | ||
| 277 | } | ||
| 265 | } | 278 | } |
| 266 | 279 | ||
| 267 | bh = bh->b_this_page; | 280 | bh = bh->b_this_page; |
| 268 | } while (bh != head); | 281 | } while (bh != head); |
| 269 | 282 | ||
| 270 | set_page_dirty(page); | 283 | if (j) |
| 284 | set_page_dirty(page); | ||
| 271 | 285 | ||
| 272 | if (likely(cur_index != index)) | 286 | if (likely(cur_index != index)) |
| 273 | ufs_put_locked_page(page); | 287 | ufs_put_locked_page(page); |
| @@ -415,14 +429,14 @@ unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment, | |||
| 415 | } | 429 | } |
| 416 | result = ufs_alloc_fragments (inode, cgno, goal, request, err); | 430 | result = ufs_alloc_fragments (inode, cgno, goal, request, err); |
| 417 | if (result) { | 431 | if (result) { |
| 432 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, | ||
| 433 | locked_page != NULL); | ||
| 418 | ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp, | 434 | ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp, |
| 419 | result, locked_page); | 435 | result, locked_page); |
| 420 | 436 | ||
| 421 | *p = cpu_to_fs32(sb, result); | 437 | *p = cpu_to_fs32(sb, result); |
| 422 | *err = 0; | 438 | *err = 0; |
| 423 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); | 439 | UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); |
| 424 | ufs_clear_frags(inode, result + oldcount, newcount - oldcount, | ||
| 425 | locked_page != NULL); | ||
| 426 | unlock_super(sb); | 440 | unlock_super(sb); |
| 427 | if (newcount < request) | 441 | if (newcount < request) |
| 428 | ufs_free_fragments (inode, result + newcount, request - newcount); | 442 | ufs_free_fragments (inode, result + newcount, request - newcount); |
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 2fbab0aab688..4295ca91cf85 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c | |||
| @@ -242,7 +242,8 @@ repeat: | |||
| 242 | goal = tmp + uspi->s_fpb; | 242 | goal = tmp + uspi->s_fpb; |
| 243 | tmp = ufs_new_fragments (inode, p, fragment - blockoff, | 243 | tmp = ufs_new_fragments (inode, p, fragment - blockoff, |
| 244 | goal, required + blockoff, | 244 | goal, required + blockoff, |
| 245 | err, locked_page); | 245 | err, |
| 246 | phys != NULL ? locked_page : NULL); | ||
| 246 | } | 247 | } |
| 247 | /* | 248 | /* |
| 248 | * We will extend last allocated block | 249 | * We will extend last allocated block |
| @@ -250,7 +251,7 @@ repeat: | |||
| 250 | else if (lastblock == block) { | 251 | else if (lastblock == block) { |
| 251 | tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff), | 252 | tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff), |
| 252 | fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), | 253 | fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), |
| 253 | err, locked_page); | 254 | err, phys != NULL ? locked_page : NULL); |
| 254 | } else /* (lastblock > block) */ { | 255 | } else /* (lastblock > block) */ { |
| 255 | /* | 256 | /* |
| 256 | * We will allocate new block before last allocated block | 257 | * We will allocate new block before last allocated block |
| @@ -261,7 +262,8 @@ repeat: | |||
| 261 | goal = tmp + uspi->s_fpb; | 262 | goal = tmp + uspi->s_fpb; |
| 262 | } | 263 | } |
| 263 | tmp = ufs_new_fragments(inode, p, fragment - blockoff, | 264 | tmp = ufs_new_fragments(inode, p, fragment - blockoff, |
| 264 | goal, uspi->s_fpb, err, locked_page); | 265 | goal, uspi->s_fpb, err, |
| 266 | phys != NULL ? locked_page : NULL); | ||
| 265 | } | 267 | } |
| 266 | if (!tmp) { | 268 | if (!tmp) { |
| 267 | if ((!blockoff && *p) || | 269 | if ((!blockoff && *p) || |
| @@ -438,9 +440,11 @@ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head | |||
| 438 | * it much more readable: | 440 | * it much more readable: |
| 439 | */ | 441 | */ |
| 440 | #define GET_INODE_DATABLOCK(x) \ | 442 | #define GET_INODE_DATABLOCK(x) \ |
| 441 | ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new, bh_result->b_page) | 443 | ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new,\ |
| 444 | bh_result->b_page) | ||
| 442 | #define GET_INODE_PTR(x) \ | 445 | #define GET_INODE_PTR(x) \ |
| 443 | ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL, NULL) | 446 | ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL,\ |
| 447 | bh_result->b_page) | ||
| 444 | #define GET_INDIRECT_DATABLOCK(x) \ | 448 | #define GET_INDIRECT_DATABLOCK(x) \ |
| 445 | ufs_inode_getblock(inode, bh, x, fragment, \ | 449 | ufs_inode_getblock(inode, bh, x, fragment, \ |
| 446 | &err, &phys, &new, bh_result->b_page) | 450 | &err, &phys, &new, bh_result->b_page) |
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index ea11d04c41a0..0437b0a6fe97 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c | |||
| @@ -109,10 +109,10 @@ static int ufs_trunc_direct (struct inode * inode) | |||
| 109 | tmp = fs32_to_cpu(sb, *p); | 109 | tmp = fs32_to_cpu(sb, *p); |
| 110 | if (!tmp ) | 110 | if (!tmp ) |
| 111 | ufs_panic (sb, "ufs_trunc_direct", "internal error"); | 111 | ufs_panic (sb, "ufs_trunc_direct", "internal error"); |
| 112 | frag2 -= frag1; | ||
| 112 | frag1 = ufs_fragnum (frag1); | 113 | frag1 = ufs_fragnum (frag1); |
| 113 | frag2 = ufs_fragnum (frag2); | ||
| 114 | 114 | ||
| 115 | ufs_free_fragments (inode, tmp + frag1, frag2 - frag1); | 115 | ufs_free_fragments(inode, tmp + frag1, frag2); |
| 116 | mark_inode_dirty(inode); | 116 | mark_inode_dirty(inode); |
| 117 | frag_to_free = tmp + frag1; | 117 | frag_to_free = tmp + frag1; |
| 118 | 118 | ||
