diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/incore.h | 11 | ||||
-rw-r--r-- | fs/gfs2/log.c | 22 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 68 | ||||
-rw-r--r-- | fs/gfs2/super.c | 13 |
4 files changed, 97 insertions, 17 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 330f4c73d0e7..51166c12c5d7 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
@@ -360,8 +360,17 @@ struct gfs2_ail { | |||
360 | u64 ai_sync_gen; | 360 | u64 ai_sync_gen; |
361 | }; | 361 | }; |
362 | 362 | ||
363 | struct gfs2_journal_extent { | ||
364 | struct list_head extent_list; | ||
365 | |||
366 | unsigned int lblock; /* First logical block */ | ||
367 | u64 dblock; /* First disk block */ | ||
368 | u64 blocks; | ||
369 | }; | ||
370 | |||
363 | struct gfs2_jdesc { | 371 | struct gfs2_jdesc { |
364 | struct list_head jd_list; | 372 | struct list_head jd_list; |
373 | struct list_head extent_list; | ||
365 | 374 | ||
366 | struct inode *jd_inode; | 375 | struct inode *jd_inode; |
367 | unsigned int jd_jid; | 376 | unsigned int jd_jid; |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 14333d81cf7d..69a583ec43c7 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
@@ -339,18 +339,14 @@ void gfs2_log_release(struct gfs2_sbd *sdp, unsigned int blks) | |||
339 | 339 | ||
340 | static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn) | 340 | static u64 log_bmap(struct gfs2_sbd *sdp, unsigned int lbn) |
341 | { | 341 | { |
342 | struct inode *inode = sdp->sd_jdesc->jd_inode; | 342 | struct gfs2_journal_extent *je; |
343 | int error; | 343 | |
344 | struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; | 344 | list_for_each_entry(je, &sdp->sd_jdesc->extent_list, extent_list) { |
345 | 345 | if (lbn >= je->lblock && lbn < je->lblock + je->blocks) | |
346 | bh_map.b_size = 1 << inode->i_blkbits; | 346 | return je->dblock + lbn; |
347 | error = gfs2_block_map(inode, lbn, &bh_map, 0); | 347 | } |
348 | if (error || !bh_map.b_blocknr) | 348 | |
349 | printk(KERN_INFO "error=%d, dbn=%llu lbn=%u", error, | 349 | return -1; |
350 | (unsigned long long)bh_map.b_blocknr, lbn); | ||
351 | gfs2_assert_withdraw(sdp, !error && bh_map.b_blocknr); | ||
352 | |||
353 | return bh_map.b_blocknr; | ||
354 | } | 350 | } |
355 | 351 | ||
356 | /** | 352 | /** |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 1bba6ac0bcac..0921f17a164c 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include "gfs2.h" | 22 | #include "gfs2.h" |
23 | #include "incore.h" | 23 | #include "incore.h" |
24 | #include "bmap.h" | ||
24 | #include "daemon.h" | 25 | #include "daemon.h" |
25 | #include "glock.h" | 26 | #include "glock.h" |
26 | #include "glops.h" | 27 | #include "glops.h" |
@@ -302,6 +303,68 @@ out: | |||
302 | return error; | 303 | return error; |
303 | } | 304 | } |
304 | 305 | ||
306 | /** | ||
307 | * map_journal_extents - create a reusable "extent" mapping from all logical | ||
308 | * blocks to all physical blocks for the given journal. This will save | ||
309 | * us time when writing journal blocks. Most journals will have only one | ||
310 | * extent that maps all their logical blocks. That's because gfs2.mkfs | ||
311 | * arranges the journal blocks sequentially to maximize performance. | ||
312 | * So the extent would map the first block for the entire file length. | ||
313 | * However, gfs2_jadd can happen while file activity is happening, so | ||
314 | * those journals may not be sequential. Less likely is the case where | ||
315 | * the users created their own journals by mounting the metafs and | ||
316 | * laying it out. But it's still possible. These journals might have | ||
317 | * several extents. | ||
318 | * | ||
319 | * TODO: This should be done in bigger chunks rather than one block at a time, | ||
320 | * but since it's only done at mount time, I'm not worried about the | ||
321 | * time it takes. | ||
322 | */ | ||
323 | static int map_journal_extents(struct gfs2_sbd *sdp) | ||
324 | { | ||
325 | struct gfs2_jdesc *jd = sdp->sd_jdesc; | ||
326 | unsigned int lb; | ||
327 | u64 db, prev_db; /* logical block, disk block, prev disk block */ | ||
328 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); | ||
329 | struct gfs2_journal_extent *jext = NULL; | ||
330 | struct buffer_head bh; | ||
331 | int rc = 0; | ||
332 | |||
333 | INIT_LIST_HEAD(&jd->extent_list); | ||
334 | prev_db = 0; | ||
335 | |||
336 | for (lb = 0; lb < ip->i_di.di_size / sdp->sd_sb.sb_bsize; lb++) { | ||
337 | bh.b_state = 0; | ||
338 | bh.b_blocknr = 0; | ||
339 | bh.b_size = 1 << ip->i_inode.i_blkbits; | ||
340 | rc = gfs2_block_map(jd->jd_inode, lb, &bh, 0); | ||
341 | db = bh.b_blocknr; | ||
342 | if (rc || !db) { | ||
343 | printk(KERN_INFO "GFS2 journal mapping error %d: lb=" | ||
344 | "%u db=%llu\n", rc, lb, (unsigned long long)db); | ||
345 | break; | ||
346 | } | ||
347 | if (!prev_db || db != prev_db + 1) { | ||
348 | jext = kzalloc(sizeof(struct gfs2_journal_extent), | ||
349 | GFP_KERNEL); | ||
350 | if (!jext) { | ||
351 | printk(KERN_INFO "GFS2 error: out of memory " | ||
352 | "mapping journal extents.\n"); | ||
353 | rc = -ENOMEM; | ||
354 | break; | ||
355 | } | ||
356 | jext->dblock = db; | ||
357 | jext->lblock = lb; | ||
358 | jext->blocks = 1; | ||
359 | list_add_tail(&jext->extent_list, &jd->extent_list); | ||
360 | } else { | ||
361 | jext->blocks++; | ||
362 | } | ||
363 | prev_db = db; | ||
364 | } | ||
365 | return rc; | ||
366 | } | ||
367 | |||
305 | static int init_journal(struct gfs2_sbd *sdp, int undo) | 368 | static int init_journal(struct gfs2_sbd *sdp, int undo) |
306 | { | 369 | { |
307 | struct gfs2_holder ji_gh; | 370 | struct gfs2_holder ji_gh; |
@@ -377,6 +440,9 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) | |||
377 | goto fail_jinode_gh; | 440 | goto fail_jinode_gh; |
378 | } | 441 | } |
379 | atomic_set(&sdp->sd_log_blks_free, sdp->sd_jdesc->jd_blocks); | 442 | atomic_set(&sdp->sd_log_blks_free, sdp->sd_jdesc->jd_blocks); |
443 | |||
444 | /* Map the extents for this journal's blocks */ | ||
445 | map_journal_extents(sdp); | ||
380 | } | 446 | } |
381 | 447 | ||
382 | if (sdp->sd_lockstruct.ls_first) { | 448 | if (sdp->sd_lockstruct.ls_first) { |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 2e74792ee487..22e09660d648 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
@@ -416,8 +416,9 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) | |||
416 | 416 | ||
417 | void gfs2_jindex_free(struct gfs2_sbd *sdp) | 417 | void gfs2_jindex_free(struct gfs2_sbd *sdp) |
418 | { | 418 | { |
419 | struct list_head list; | 419 | struct list_head list, *head; |
420 | struct gfs2_jdesc *jd; | 420 | struct gfs2_jdesc *jd; |
421 | struct gfs2_journal_extent *jext; | ||
421 | 422 | ||
422 | spin_lock(&sdp->sd_jindex_spin); | 423 | spin_lock(&sdp->sd_jindex_spin); |
423 | list_add(&list, &sdp->sd_jindex_list); | 424 | list_add(&list, &sdp->sd_jindex_list); |
@@ -427,6 +428,14 @@ void gfs2_jindex_free(struct gfs2_sbd *sdp) | |||
427 | 428 | ||
428 | while (!list_empty(&list)) { | 429 | while (!list_empty(&list)) { |
429 | jd = list_entry(list.next, struct gfs2_jdesc, jd_list); | 430 | jd = list_entry(list.next, struct gfs2_jdesc, jd_list); |
431 | head = &jd->extent_list; | ||
432 | while (!list_empty(head)) { | ||
433 | jext = list_entry(head->next, | ||
434 | struct gfs2_journal_extent, | ||
435 | extent_list); | ||
436 | list_del(&jext->extent_list); | ||
437 | kfree(jext); | ||
438 | } | ||
430 | list_del(&jd->jd_list); | 439 | list_del(&jd->jd_list); |
431 | iput(jd->jd_inode); | 440 | iput(jd->jd_inode); |
432 | kfree(jd); | 441 | kfree(jd); |