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 | ||