aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ufs/balloc.c137
-rw-r--r--fs/ufs/inode.c44
-rw-r--r--include/linux/ufs_fs.h3
3 files changed, 140 insertions, 44 deletions
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index cc0c8f15d8fd..06f970d02e3d 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -39,7 +39,8 @@ static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *,
39/* 39/*
40 * Free 'count' fragments from fragment number 'fragment' 40 * Free 'count' fragments from fragment number 'fragment'
41 */ 41 */
42void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count) { 42void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
43{
43 struct super_block * sb; 44 struct super_block * sb;
44 struct ufs_sb_private_info * uspi; 45 struct ufs_sb_private_info * uspi;
45 struct ufs_super_block_first * usb1; 46 struct ufs_super_block_first * usb1;
@@ -134,7 +135,8 @@ failed:
134/* 135/*
135 * Free 'count' fragments from fragment number 'fragment' (free whole blocks) 136 * Free 'count' fragments from fragment number 'fragment' (free whole blocks)
136 */ 137 */
137void ufs_free_blocks (struct inode * inode, unsigned fragment, unsigned count) { 138void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
139{
138 struct super_block * sb; 140 struct super_block * sb;
139 struct ufs_sb_private_info * uspi; 141 struct ufs_sb_private_info * uspi;
140 struct ufs_super_block_first * usb1; 142 struct ufs_super_block_first * usb1;
@@ -222,15 +224,118 @@ failed:
222 return; 224 return;
223} 225}
224 226
227static struct page *ufs_get_locked_page(struct address_space *mapping,
228 unsigned long index)
229{
230 struct page *page;
231
232try_again:
233 page = find_lock_page(mapping, index);
234 if (!page) {
235 page = read_cache_page(mapping, index,
236 (filler_t*)mapping->a_ops->readpage,
237 NULL);
238 if (IS_ERR(page)) {
239 printk(KERN_ERR "ufs_change_blocknr: "
240 "read_cache_page error: ino %lu, index: %lu\n",
241 mapping->host->i_ino, index);
242 goto out;
243 }
244
245 lock_page(page);
246
247 if (!PageUptodate(page) || PageError(page)) {
248 unlock_page(page);
249 page_cache_release(page);
250
251 printk(KERN_ERR "ufs_change_blocknr: "
252 "can not read page: ino %lu, index: %lu\n",
253 mapping->host->i_ino, index);
254
255 page = ERR_PTR(-EIO);
256 goto out;
257 }
258 }
259
260 if (unlikely(!page->mapping || !page_has_buffers(page))) {
261 unlock_page(page);
262 page_cache_release(page);
263 goto try_again;/*we really need these buffers*/
264 }
265out:
266 return page;
267}
268
269/*
270 * Modify inode page cache in such way:
271 * have - blocks with b_blocknr equal to oldb...oldb+count-1
272 * get - blocks with b_blocknr equal to newb...newb+count-1
273 * also we suppose that oldb...oldb+count-1 blocks
274 * situated at the end of file.
275 *
276 * We can come here from ufs_writepage or ufs_prepare_write,
277 * locked_page is argument of these functions, so we already lock it.
278 */
279static void ufs_change_blocknr(struct inode *inode, unsigned int count,
280 unsigned int oldb, unsigned int newb,
281 struct page *locked_page)
282{
283 unsigned int blk_per_page = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
284 sector_t baseblk;
285 struct address_space *mapping = inode->i_mapping;
286 pgoff_t index, cur_index = locked_page->index;
287 unsigned int i, j;
288 struct page *page;
289 struct buffer_head *head, *bh;
290
291 baseblk = ((i_size_read(inode) - 1) >> inode->i_blkbits) + 1 - count;
292
293 UFSD(("ENTER, ino %lu, count %u, oldb %u, newb %u\n",
294 inode->i_ino, count, oldb, newb));
295
296 BUG_ON(!PageLocked(locked_page));
297
298 for (i = 0; i < count; i += blk_per_page) {
299 index = (baseblk+i) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
300
301 if (likely(cur_index != index)) {
302 page = ufs_get_locked_page(mapping, index);
303 if (IS_ERR(page))
304 continue;
305 } else
306 page = locked_page;
307
308 j = i;
309 head = page_buffers(page);
310 bh = head;
311 do {
312 if (likely(bh->b_blocknr == j + oldb && j < count)) {
313 unmap_underlying_metadata(bh->b_bdev,
314 bh->b_blocknr);
315 bh->b_blocknr = newb + j++;
316 mark_buffer_dirty(bh);
317 }
318
319 bh = bh->b_this_page;
320 } while (bh != head);
321
322 set_page_dirty(page);
225 323
226unsigned ufs_new_fragments (struct inode * inode, __fs32 * p, unsigned fragment, 324 if (likely(cur_index != index)) {
227 unsigned goal, unsigned count, int * err ) 325 unlock_page(page);
326 page_cache_release(page);
327 }
328 }
329 UFSD(("EXIT\n"));
330}
331
332unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
333 unsigned goal, unsigned count, int * err, struct page *locked_page)
228{ 334{
229 struct super_block * sb; 335 struct super_block * sb;
230 struct ufs_sb_private_info * uspi; 336 struct ufs_sb_private_info * uspi;
231 struct ufs_super_block_first * usb1; 337 struct ufs_super_block_first * usb1;
232 struct buffer_head * bh; 338 unsigned cgno, oldcount, newcount, tmp, request, result;
233 unsigned cgno, oldcount, newcount, tmp, request, i, result;
234 339
235 UFSD(("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count)) 340 UFSD(("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count))
236 341
@@ -343,24 +448,8 @@ unsigned ufs_new_fragments (struct inode * inode, __fs32 * p, unsigned fragment,
343 } 448 }
344 result = ufs_alloc_fragments (inode, cgno, goal, request, err); 449 result = ufs_alloc_fragments (inode, cgno, goal, request, err);
345 if (result) { 450 if (result) {
346 for (i = 0; i < oldcount; i++) { 451 ufs_change_blocknr(inode, oldcount, tmp, result, locked_page);
347 bh = sb_bread(sb, tmp + i); 452
348 if(bh)
349 {
350 clear_buffer_dirty(bh);
351 bh->b_blocknr = result + i;
352 mark_buffer_dirty (bh);
353 if (IS_SYNC(inode))
354 sync_dirty_buffer(bh);
355 brelse (bh);
356 }
357 else
358 {
359 printk(KERN_ERR "ufs_new_fragments: bread fail\n");
360 unlock_super(sb);
361 return 0;
362 }
363 }
364 *p = cpu_to_fs32(sb, result); 453 *p = cpu_to_fs32(sb, result);
365 *err = 0; 454 *err = 0;
366 inode->i_blocks += count << uspi->s_nspfshift; 455 inode->i_blocks += count << uspi->s_nspfshift;
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 2b2366360e5a..ea2267316a72 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -172,9 +172,10 @@ static void ufs_clear_block(struct inode *inode, struct buffer_head *bh)
172 sync_dirty_buffer(bh); 172 sync_dirty_buffer(bh);
173} 173}
174 174
175static struct buffer_head * ufs_inode_getfrag (struct inode *inode, 175static struct buffer_head *ufs_inode_getfrag(struct inode *inode,
176 unsigned int fragment, unsigned int new_fragment, 176 unsigned int fragment, unsigned int new_fragment,
177 unsigned int required, int *err, int metadata, long *phys, int *new) 177 unsigned int required, int *err, int metadata,
178 long *phys, int *new, struct page *locked_page)
178{ 179{
179 struct ufs_inode_info *ufsi = UFS_I(inode); 180 struct ufs_inode_info *ufsi = UFS_I(inode);
180 struct super_block * sb; 181 struct super_block * sb;
@@ -232,7 +233,8 @@ repeat:
232 if (lastblockoff) { 233 if (lastblockoff) {
233 p2 = ufsi->i_u1.i_data + lastblock; 234 p2 = ufsi->i_u1.i_data + lastblock;
234 tmp = ufs_new_fragments (inode, p2, lastfrag, 235 tmp = ufs_new_fragments (inode, p2, lastfrag,
235 fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff, err); 236 fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff,
237 err, locked_page);
236 if (!tmp) { 238 if (!tmp) {
237 if (lastfrag != ufsi->i_lastfrag) 239 if (lastfrag != ufsi->i_lastfrag)
238 goto repeat; 240 goto repeat;
@@ -244,14 +246,16 @@ repeat:
244 } 246 }
245 goal = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]) + uspi->s_fpb; 247 goal = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]) + uspi->s_fpb;
246 tmp = ufs_new_fragments (inode, p, fragment - blockoff, 248 tmp = ufs_new_fragments (inode, p, fragment - blockoff,
247 goal, required + blockoff, err); 249 goal, required + blockoff,
250 err, locked_page);
248 } 251 }
249 /* 252 /*
250 * We will extend last allocated block 253 * We will extend last allocated block
251 */ 254 */
252 else if (lastblock == block) { 255 else if (lastblock == block) {
253 tmp = ufs_new_fragments (inode, p, fragment - (blockoff - lastblockoff), 256 tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
254 fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), err); 257 fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff),
258 err, locked_page);
255 } 259 }
256 /* 260 /*
257 * We will allocate new block before last allocated block 261 * We will allocate new block before last allocated block
@@ -259,8 +263,8 @@ repeat:
259 else /* (lastblock > block) */ { 263 else /* (lastblock > block) */ {
260 if (lastblock && (tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock-1]))) 264 if (lastblock && (tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock-1])))
261 goal = tmp + uspi->s_fpb; 265 goal = tmp + uspi->s_fpb;
262 tmp = ufs_new_fragments (inode, p, fragment - blockoff, 266 tmp = ufs_new_fragments(inode, p, fragment - blockoff,
263 goal, uspi->s_fpb, err); 267 goal, uspi->s_fpb, err, locked_page);
264 } 268 }
265 if (!tmp) { 269 if (!tmp) {
266 if ((!blockoff && *p) || 270 if ((!blockoff && *p) ||
@@ -303,9 +307,10 @@ repeat2:
303 */ 307 */
304} 308}
305 309
306static struct buffer_head * ufs_block_getfrag (struct inode *inode, 310static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_head *bh,
307 struct buffer_head *bh, unsigned int fragment, unsigned int new_fragment, 311 unsigned int fragment, unsigned int new_fragment,
308 unsigned int blocksize, int * err, int metadata, long *phys, int *new) 312 unsigned int blocksize, int * err, int metadata,
313 long *phys, int *new, struct page *locked_page)
309{ 314{
310 struct super_block * sb; 315 struct super_block * sb;
311 struct ufs_sb_private_info * uspi; 316 struct ufs_sb_private_info * uspi;
@@ -350,7 +355,8 @@ repeat:
350 goal = tmp + uspi->s_fpb; 355 goal = tmp + uspi->s_fpb;
351 else 356 else
352 goal = bh->b_blocknr + uspi->s_fpb; 357 goal = bh->b_blocknr + uspi->s_fpb;
353 tmp = ufs_new_fragments (inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err); 358 tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal,
359 uspi->s_fpb, err, locked_page);
354 if (!tmp) { 360 if (!tmp) {
355 if (fs32_to_cpu(sb, *p)) 361 if (fs32_to_cpu(sb, *p))
356 goto repeat; 362 goto repeat;
@@ -424,15 +430,15 @@ int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_hea
424 * it much more readable: 430 * it much more readable:
425 */ 431 */
426#define GET_INODE_DATABLOCK(x) \ 432#define GET_INODE_DATABLOCK(x) \
427 ufs_inode_getfrag(inode, x, fragment, 1, &err, 0, &phys, &new) 433 ufs_inode_getfrag(inode, x, fragment, 1, &err, 0, &phys, &new, bh_result->b_page)
428#define GET_INODE_PTR(x) \ 434#define GET_INODE_PTR(x) \
429 ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, 1, NULL, NULL) 435 ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, 1, NULL, NULL, bh_result->b_page)
430#define GET_INDIRECT_DATABLOCK(x) \ 436#define GET_INDIRECT_DATABLOCK(x) \
431 ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ 437 ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
432 &err, 0, &phys, &new); 438 &err, 0, &phys, &new, bh_result->b_page);
433#define GET_INDIRECT_PTR(x) \ 439#define GET_INDIRECT_PTR(x) \
434 ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ 440 ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
435 &err, 1, NULL, NULL); 441 &err, 1, NULL, NULL, bh_result->b_page);
436 442
437 if (ptr < UFS_NDIR_FRAGMENT) { 443 if (ptr < UFS_NDIR_FRAGMENT) {
438 bh = GET_INODE_DATABLOCK(ptr); 444 bh = GET_INODE_DATABLOCK(ptr);
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index 86b5b4271b5a..ed5053f5cd71 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -875,7 +875,8 @@ struct ufs_super_block_third {
875/* balloc.c */ 875/* balloc.c */
876extern void ufs_free_fragments (struct inode *, unsigned, unsigned); 876extern void ufs_free_fragments (struct inode *, unsigned, unsigned);
877extern void ufs_free_blocks (struct inode *, unsigned, unsigned); 877extern void ufs_free_blocks (struct inode *, unsigned, unsigned);
878extern unsigned ufs_new_fragments (struct inode *, __fs32 *, unsigned, unsigned, unsigned, int *); 878extern unsigned ufs_new_fragments(struct inode *, __fs32 *, unsigned, unsigned,
879 unsigned, int *, struct page *);
879 880
880/* cylinder.c */ 881/* cylinder.c */
881extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned); 882extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);