diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/aops.c | 5 | ||||
-rw-r--r-- | fs/gfs2/log.c | 53 | ||||
-rw-r--r-- | fs/gfs2/log.h | 2 | ||||
-rw-r--r-- | fs/gfs2/main.c | 90 | ||||
-rw-r--r-- | fs/gfs2/recovery.c | 59 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 26 |
6 files changed, 111 insertions, 124 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 1daf15a1f00c..658ca027cab9 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -255,7 +255,6 @@ static int gfs2_writepages(struct address_space *mapping, * @wbc: The writeback control * @pvec: The vector of pages * @nr_pages: The number of pages to write - * @end: End position * @done_index: Page index * * Returns: non-zero if loop should terminate, zero otherwise @@ -264,7 +263,7 @@ static int gfs2_writepages(struct address_space *mapping, static int gfs2_write_jdata_pagevec(struct address_space *mapping, struct writeback_control *wbc, struct pagevec *pvec, - int nr_pages, pgoff_t end, + int nr_pages, pgoff_t *done_index) { struct inode *inode = mapping->host; @@ -402,7 +401,7 @@ retry: if (nr_pages == 0) break; - ret = gfs2_write_jdata_pagevec(mapping, wbc, &pvec, nr_pages, end, &done_index); + ret = gfs2_write_jdata_pagevec(mapping, wbc, &pvec, nr_pages, &done_index); if (ret) done = 1; if (ret > 0) diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index f72c44231406..b9889ae5fd7c 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -538,9 +538,12 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp) list_sort(NULL, &sdp->sd_log_le_ordered, &ip_cmp); while (!list_empty(&sdp->sd_log_le_ordered)) { ip = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_inode, i_ordered); - list_move(&ip->i_ordered, &written); - if (ip->i_inode.i_mapping->nrpages == 0) + if (ip->i_inode.i_mapping->nrpages == 0) { + test_and_clear_bit(GIF_ORDERED, &ip->i_flags); + list_del(&ip->i_ordered); continue; + } + list_move(&ip->i_ordered, &written); spin_unlock(&sdp->sd_ordered_lock); filemap_fdatawrite(ip->i_inode.i_mapping); spin_lock(&sdp->sd_ordered_lock); @@ -648,49 +651,67 @@ out_of_blocks: } /** - * log_write_header - Get and initialize a journal header buffer + * write_log_header - Write a journal log header buffer at sd_log_flush_head * @sdp: The GFS2 superblock + * @seq: sequence number + * @tail: tail of the log + * @flags: log header flags + * @op_flags: flags to pass to the bio * * Returns: the initialized log buffer descriptor */ -static void log_write_header(struct gfs2_sbd *sdp, u32 flags) +void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail, + u32 flags, int op_flags) { struct gfs2_log_header *lh; - unsigned int tail; u32 hash; - int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC; struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO); - enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); + lh = page_address(page); clear_page(lh); - gfs2_assert_withdraw(sdp, (state != SFS_FROZEN)); - - tail = current_tail(sdp); - lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); lh->lh_header.__pad0 = cpu_to_be64(0); lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); - lh->lh_sequence = cpu_to_be64(sdp->sd_log_sequence++); + lh->lh_sequence = cpu_to_be64(seq); lh->lh_flags = cpu_to_be32(flags); lh->lh_tail = cpu_to_be32(tail); lh->lh_blkno = cpu_to_be32(sdp->sd_log_flush_head); hash = gfs2_disk_hash(page_address(page), sizeof(struct gfs2_log_header)); lh->lh_hash = cpu_to_be32(hash); + gfs2_log_write_page(sdp, page); + gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags); + log_flush_wait(sdp); +} + +/** + * log_write_header - Get and initialize a journal header buffer + * @sdp: The GFS2 superblock + * + * Returns: the initialized log buffer descriptor + */ + +static void log_write_header(struct gfs2_sbd *sdp, u32 flags) +{ + unsigned int tail; + int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC; + enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); + + gfs2_assert_withdraw(sdp, (state != SFS_FROZEN)); + tail = current_tail(sdp); + if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) { gfs2_ordered_wait(sdp); log_flush_wait(sdp); op_flags = REQ_SYNC | REQ_META | REQ_PRIO; } - sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); - gfs2_log_write_page(sdp, page); - gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags); - log_flush_wait(sdp); + gfs2_write_log_header(sdp, sdp->sd_log_sequence++, tail, flags, + op_flags); if (sdp->sd_log_tail != tail) log_pull_tail(sdp, tail); diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h index 9499a6049212..619de9a1ff4f 100644 --- a/fs/gfs2/log.h +++ b/fs/gfs2/log.h @@ -71,6 +71,8 @@ enum gfs2_flush_type { SHUTDOWN_FLUSH, FREEZE_FLUSH }; +extern void gfs2_write_log_header(struct gfs2_sbd *sdp, u64 seq, u32 tail, + u32 flags, int op_flags); extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, enum gfs2_flush_type type); extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 0a89e6f7a314..2d55e2c3333c 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c @@ -93,7 +93,7 @@ static int __init init_gfs2_fs(void) error = gfs2_glock_init(); if (error) - goto fail; + goto fail_glock; error = -ENOMEM; gfs2_glock_cachep = kmem_cache_create("gfs2_glock", @@ -101,7 +101,7 @@ static int __init init_gfs2_fs(void) 0, 0, gfs2_init_glock_once); if (!gfs2_glock_cachep) - goto fail; + goto fail_cachep1; gfs2_glock_aspace_cachep = kmem_cache_create("gfs2_glock(aspace)", sizeof(struct gfs2_glock) + @@ -109,7 +109,7 @@ static int __init init_gfs2_fs(void) 0, 0, gfs2_init_gl_aspace_once); if (!gfs2_glock_aspace_cachep) - goto fail; + goto fail_cachep2; gfs2_inode_cachep = kmem_cache_create("gfs2_inode", sizeof(struct gfs2_inode), @@ -118,107 +118,105 @@ static int __init init_gfs2_fs(void) SLAB_ACCOUNT, gfs2_init_inode_once); if (!gfs2_inode_cachep) - goto fail; + goto fail_cachep3; gfs2_bufdata_cachep = kmem_cache_create("gfs2_bufdata", sizeof(struct gfs2_bufdata), 0, 0, NULL); if (!gfs2_bufdata_cachep) - goto fail; + goto fail_cachep4; gfs2_rgrpd_cachep = kmem_cache_create("gfs2_rgrpd", sizeof(struct gfs2_rgrpd), 0, 0, NULL); if (!gfs2_rgrpd_cachep) - goto fail; + goto fail_cachep5; gfs2_quotad_cachep = kmem_cache_create("gfs2_quotad", sizeof(struct gfs2_quota_data), 0, 0, NULL); if (!gfs2_quotad_cachep) - goto fail; + goto fail_cachep6; gfs2_qadata_cachep = kmem_cache_create("gfs2_qadata", sizeof(struct gfs2_qadata), 0, 0, NULL); if (!gfs2_qadata_cachep) - goto fail; + goto fail_cachep7; error = register_shrinker(&gfs2_qd_shrinker); if (error) - goto fail; + goto fail_shrinker; error = register_filesystem(&gfs2_fs_type); if (error) - goto fail; + goto fail_fs1; error = register_filesystem(&gfs2meta_fs_type); if (error) - goto fail_unregister; + goto fail_fs2; error = -ENOMEM; gfs_recovery_wq = alloc_workqueue("gfs_recovery", WQ_MEM_RECLAIM | WQ_FREEZABLE, 0); if (!gfs_recovery_wq) - goto fail_wq; + goto fail_wq1; gfs2_control_wq = alloc_workqueue("gfs2_control", WQ_UNBOUND | WQ_FREEZABLE, 0); if (!gfs2_control_wq) - goto fail_recovery; + goto fail_wq2; gfs2_freeze_wq = alloc_workqueue("freeze_workqueue", 0, 0); if (!gfs2_freeze_wq) - goto fail_control; + goto fail_wq3; gfs2_page_pool = mempool_create_page_pool(64, 0); if (!gfs2_page_pool) - goto fail_freeze; + goto fail_mempool; - gfs2_register_debugfs(); + error = gfs2_register_debugfs(); + if (error) + goto fail_debugfs; pr_info("GFS2 installed\n"); return 0; -fail_freeze: +fail_debugfs: + mempool_destroy(gfs2_page_pool); +fail_mempool: destroy_workqueue(gfs2_freeze_wq); -fail_control: +fail_wq3: destroy_workqueue(gfs2_control_wq); -fail_recovery: +fail_wq2: destroy_workqueue(gfs_recovery_wq); -fail_wq: +fail_wq1: unregister_filesystem(&gfs2meta_fs_type); -fail_unregister: +fail_fs2: unregister_filesystem(&gfs2_fs_type); -fail: - list_lru_destroy(&gfs2_qd_lru); -fail_lru: +fail_fs1: unregister_shrinker(&gfs2_qd_shrinker); +fail_shrinker: + kmem_cache_destroy(gfs2_qadata_cachep); +fail_cachep7: + kmem_cache_destroy(gfs2_quotad_cachep); +fail_cachep6: + kmem_cache_destroy(gfs2_rgrpd_cachep); +fail_cachep5: + kmem_cache_destroy(gfs2_bufdata_cachep); +fail_cachep4: + kmem_cache_destroy(gfs2_inode_cachep); +fail_cachep3: + kmem_cache_destroy(gfs2_glock_aspace_cachep); +fail_cachep2: + kmem_cache_destroy(gfs2_glock_cachep); +fail_cachep1: gfs2_glock_exit(); - - if (gfs2_qadata_cachep) - kmem_cache_destroy(gfs2_qadata_cachep); - - if (gfs2_quotad_cachep) - kmem_cache_destroy(gfs2_quotad_cachep); - - if (gfs2_rgrpd_cachep) - kmem_cache_destroy(gfs2_rgrpd_cachep); - - if (gfs2_bufdata_cachep) - kmem_cache_destroy(gfs2_bufdata_cachep); - - if (gfs2_inode_cachep) - kmem_cache_destroy(gfs2_inode_cachep); - - if (gfs2_glock_aspace_cachep) - kmem_cache_destroy(gfs2_glock_aspace_cachep); - - if (gfs2_glock_cachep) - kmem_cache_destroy(gfs2_glock_cachep); - +fail_glock: + list_lru_destroy(&gfs2_qd_lru); +fail_lru: gfs2_sys_uninit(); return error; } diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 9395a3db1a60..5d3431219425 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -20,6 +20,7 @@ #include "bmap.h" #include "glock.h" #include "glops.h" +#include "log.h" #include "lops.h" #include "meta_io.h" #include "recovery.h" @@ -370,62 +371,22 @@ static int foreach_descriptor(struct gfs2_jdesc *jd, unsigned int start, /** * clean_journal - mark a dirty journal as being clean - * @sdp: the filesystem * @jd: the journal - * @gl: the journal's glock * @head: the head journal to start from * * Returns: errno */ -static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head) +static void clean_journal(struct gfs2_jdesc *jd, + struct gfs2_log_header_host *head) { - struct gfs2_inode *ip = GFS2_I(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); - unsigned int lblock; - struct gfs2_log_header *lh; - u32 hash; - struct buffer_head *bh; - int error; - struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; - - lblock = head->lh_blkno; - gfs2_replay_incr_blk(jd, &lblock); - bh_map.b_size = 1 << ip->i_inode.i_blkbits; - error = gfs2_block_map(&ip->i_inode, lblock, &bh_map, 0); - if (error) - return error; - if (!bh_map.b_blocknr) { - gfs2_consist_inode(ip); - return -EIO; - } - - bh = sb_getblk(sdp->sd_vfs, bh_map.b_blocknr); - lock_buffer(bh); - memset(bh->b_data, 0, bh->b_size); - set_buffer_uptodate(bh); - clear_buffer_dirty(bh); - unlock_buffer(bh); - - lh = (struct gfs2_log_header *)bh->b_data; - memset(lh, 0, sizeof(struct gfs2_log_header)); - lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC); - lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); - lh->lh_header.__pad0 = cpu_to_be64(0); - lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); - lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); - lh->lh_sequence = cpu_to_be64(head->lh_sequence + 1); - lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT); - lh->lh_blkno = cpu_to_be32(lblock); - hash = gfs2_disk_hash((const char *)lh, sizeof(struct gfs2_log_header)); - lh->lh_hash = cpu_to_be32(hash); - - set_buffer_dirty(bh); - if (sync_dirty_buffer(bh)) - gfs2_io_error_bh(sdp, bh); - brelse(bh); - return error; + sdp->sd_log_flush_head = head->lh_blkno; + gfs2_replay_incr_blk(jd, &sdp->sd_log_flush_head); + gfs2_write_log_header(sdp, head->lh_sequence + 1, 0, + GFS2_LOG_HEAD_UNMOUNT, REQ_PREFLUSH | + REQ_FUA | REQ_META | REQ_SYNC); } @@ -552,9 +513,7 @@ void gfs2_recover_func(struct work_struct *work) goto fail_gunlock_thaw; } - error = clean_journal(jd, &head); - if (error) - goto fail_gunlock_thaw; + clean_journal(jd, &head); gfs2_glock_dq_uninit(&thaw_gh); t = DIV_ROUND_UP(jiffies - t, HZ); diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 211d7a5fa10f..6dea72f49316 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -34,6 +34,7 @@ #include "log.h" #include "inode.h" #include "trace_gfs2.h" +#include "dir.h" #define BFITNOENT ((u32)~0) #define NO_BLOCK ((u64)~0) @@ -1047,17 +1048,30 @@ static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf) rgd->rd_free = be32_to_cpu(str->rg_free); rgd->rd_dinodes = be32_to_cpu(str->rg_dinodes); rgd->rd_igeneration = be64_to_cpu(str->rg_igeneration); + /* rd_data0, rd_data and rd_bitbytes already set from rindex */ } static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf) { + struct gfs2_rgrpd *next = gfs2_rgrpd_get_next(rgd); struct gfs2_rgrp *str = buf; + u32 crc; str->rg_flags = cpu_to_be32(rgd->rd_flags & ~GFS2_RDF_MASK); str->rg_free = cpu_to_be32(rgd->rd_free); str->rg_dinodes = cpu_to_be32(rgd->rd_dinodes); - str->__pad = cpu_to_be32(0); + if (next == NULL) + str->rg_skip = 0; + else if (next->rd_addr > rgd->rd_addr) + str->rg_skip = cpu_to_be32(next->rd_addr - rgd->rd_addr); str->rg_igeneration = cpu_to_be64(rgd->rd_igeneration); + str->rg_data0 = cpu_to_be64(rgd->rd_data0); + str->rg_data = cpu_to_be32(rgd->rd_data); + str->rg_bitbytes = cpu_to_be32(rgd->rd_bitbytes); + str->rg_crc = 0; + crc = gfs2_disk_hash(buf, sizeof(struct gfs2_rgrp)); + str->rg_crc = cpu_to_be32(crc); + memset(&str->rg_reserved, 0, sizeof(str->rg_reserved)); } @@ -2460,12 +2474,12 @@ void gfs2_unlink_di(struct inode *inode) update_rgrp_lvb_unlinked(rgd, 1); } -static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) +void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) { struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_rgrpd *tmp_rgd; - tmp_rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_FREE); + tmp_rgd = rgblk_free(sdp, ip->i_no_addr, 1, GFS2_BLKST_FREE); if (!tmp_rgd) return; gfs2_assert_withdraw(sdp, rgd == tmp_rgd); @@ -2481,12 +2495,6 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) update_rgrp_lvb_unlinked(rgd, -1); gfs2_statfs_change(sdp, 0, +1, -1); -} - - -void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) -{ - gfs2_free_uninit_di(rgd, ip->i_no_addr); trace_gfs2_block_alloc(ip, rgd, ip->i_no_addr, 1, GFS2_BLKST_FREE); gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid); gfs2_meta_wipe(ip, ip->i_no_addr, 1); |