Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 846826 Details for
Bug 1027451
GFS2: [RFE] remove freeze lock from transaction code path
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
yet another not quite working fsfreeze patch
ya_fsfreeze.patch (text/plain), 30.08 KB, created by
Ben Marzinski
on 2014-01-07 20:19:22 UTC
(
hide
)
Description:
yet another not quite working fsfreeze patch
Filename:
MIME Type:
Creator:
Ben Marzinski
Created:
2014-01-07 20:19:22 UTC
Size:
30.08 KB
patch
obsolete
>--- > fs/gfs2/aops.c | 2 > fs/gfs2/file.c | 2 > fs/gfs2/glops.c | 68 +++++++++++++++--------- > fs/gfs2/glops.h | 5 + > fs/gfs2/incore.h | 14 +++-- > fs/gfs2/log.c | 68 ++++++++++++++---------- > fs/gfs2/log.h | 10 ++- > fs/gfs2/main.c | 11 +++ > fs/gfs2/ops_fstype.c | 12 ++-- > fs/gfs2/quota.c | 2 > fs/gfs2/recovery.c | 19 +----- > fs/gfs2/rgrp.c | 2 > fs/gfs2/super.c | 108 +++++++++++++++++++++++++++++---------- > fs/gfs2/super.h | 1 > fs/gfs2/sys.c | 4 - > fs/gfs2/trans.c | 33 ++++------- > include/uapi/linux/gfs2_ondisk.h | 2 > 17 files changed, 230 insertions(+), 133 deletions(-) > >Index: gfs2-131111/fs/gfs2/glops.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/glops.c >+++ gfs2-131111/fs/gfs2/glops.c >@@ -28,6 +28,8 @@ > #include "trans.h" > #include "dir.h" > >+struct workqueue_struct *gfs2_freeze_wq; >+ > static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) > { > fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n", >@@ -87,7 +89,9 @@ static void gfs2_ail_empty_gl(struct gfs > if (!tr.tr_revokes) > return; > >- /* A shortened, inline version of gfs2_trans_begin() */ >+ /* A shortened, inline version of gfs2_trans_begin() >+ * tr->alloced is not set since the transaction structure is >+ * on the stack */ > tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); > tr.tr_ip = (unsigned long)__builtin_return_address(0); > sb_start_intwrite(sdp->sd_vfs); >@@ -98,7 +102,7 @@ static void gfs2_ail_empty_gl(struct gfs > __gfs2_ail_flush(gl, 0, tr.tr_revokes); > > gfs2_trans_end(sdp); >- gfs2_log_flush(sdp, NULL); >+ gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); > } > > void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) >@@ -119,7 +123,7 @@ void gfs2_ail_flush(struct gfs2_glock *g > return; > __gfs2_ail_flush(gl, fsync, max_revokes); > gfs2_trans_end(sdp); >- gfs2_log_flush(sdp, NULL); >+ gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); > } > > /** >@@ -141,7 +145,7 @@ static void rgrp_go_sync(struct gfs2_glo > return; > GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE); > >- gfs2_log_flush(gl->gl_sbd, gl); >+ gfs2_log_flush(gl->gl_sbd, gl, NORMAL_FLUSH); > filemap_fdatawrite(metamapping); > error = filemap_fdatawait(metamapping); > mapping_set_error(metamapping, error); >@@ -199,7 +203,7 @@ static void inode_go_sync(struct gfs2_gl > > GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE); > >- gfs2_log_flush(gl->gl_sbd, gl); >+ gfs2_log_flush(gl->gl_sbd, gl, NORMAL_FLUSH); > filemap_fdatawrite(metamapping); > if (ip) { > struct address_space *mapping = ip->i_inode.i_mapping; >@@ -246,7 +250,7 @@ static void inode_go_inval(struct gfs2_g > } > > if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) { >- gfs2_log_flush(gl->gl_sbd, NULL); >+ gfs2_log_flush(gl->gl_sbd, NULL, NORMAL_FLUSH); > gl->gl_sbd->sd_rindex_uptodate = 0; > } > if (ip && S_ISREG(ip->i_inode.i_mode)) >@@ -447,33 +451,35 @@ static int inode_go_dump(struct seq_file > } > > /** >- * trans_go_sync - promote/demote the transaction glock >+ * freeze_go_sync - promote/demote the freeze glock > * @gl: the glock > * @state: the requested state > * @flags: > * > */ > >-static void trans_go_sync(struct gfs2_glock *gl) >+static void freeze_go_sync(struct gfs2_glock *gl) > { >+ int error = 0; > struct gfs2_sbd *sdp = gl->gl_sbd; > >- if (gl->gl_state != LM_ST_UNLOCKED && >+ if (gl->gl_state == LM_ST_SHARED && > test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { >- gfs2_meta_syncfs(sdp); >- gfs2_log_shutdown(sdp); >+ atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE); >+ if (!atomic_read(&sdp->sd_started_freeze)) { >+ error = freeze_super(sdp->sd_vfs); >+ if (error) { >+ printk(KERN_INFO "GFS2: couldn't freeze filesystem: %d\n", error); >+ gfs2_assert_withdraw(sdp, 0); >+ } >+ queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work); >+ } >+ gfs2_log_flush(sdp, NULL, FREEZE_FLUSH); > } > } > >-/** >- * trans_go_xmote_bh - After promoting/demoting the transaction glock >- * @gl: the glock >- * >- */ >- >-static int trans_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh) >+void check_frozen_log(struct gfs2_sbd *sdp) > { >- struct gfs2_sbd *sdp = gl->gl_sbd; > struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); > struct gfs2_glock *j_gl = ip->i_gl; > struct gfs2_log_header_host head; >@@ -494,6 +500,20 @@ static int trans_go_xmote_bh(struct gfs2 > gfs2_log_pointers_init(sdp, head.lh_blkno); > } > } >+} >+ >+/** >+ * freeze_go_xmote_bh - After promoting/demoting the freeze glock >+ * @gl: the glock >+ * >+ */ >+ >+static int freeze_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh) >+{ >+ struct gfs2_sbd *sdp = gl->gl_sbd; >+ >+ if (!atomic_read(&sdp->sd_started_freeze)) >+ check_frozen_log(sdp); > return 0; > } > >@@ -504,7 +524,7 @@ static int trans_go_xmote_bh(struct gfs2 > * Always returns 0 > */ > >-static int trans_go_demote_ok(const struct gfs2_glock *gl) >+static int freeze_go_demote_ok(const struct gfs2_glock *gl) > { > return 0; > } >@@ -555,10 +575,10 @@ const struct gfs2_glock_operations gfs2_ > .go_flags = GLOF_ASPACE | GLOF_LVB, > }; > >-const struct gfs2_glock_operations gfs2_trans_glops = { >- .go_sync = trans_go_sync, >- .go_xmote_bh = trans_go_xmote_bh, >- .go_demote_ok = trans_go_demote_ok, >+const struct gfs2_glock_operations gfs2_freeze_glops = { >+ .go_sync = freeze_go_sync, >+ .go_xmote_bh = freeze_go_xmote_bh, >+ .go_demote_ok = freeze_go_demote_ok, > .go_type = LM_TYPE_NONDISK, > }; > >Index: gfs2-131111/fs/gfs2/glops.h >=================================================================== >--- gfs2-131111.orig/fs/gfs2/glops.h >+++ gfs2-131111/fs/gfs2/glops.h >@@ -12,10 +12,12 @@ > > #include "incore.h" > >+extern struct workqueue_struct *gfs2_freeze_wq; >+ > extern const struct gfs2_glock_operations gfs2_meta_glops; > extern const struct gfs2_glock_operations gfs2_inode_glops; > extern const struct gfs2_glock_operations gfs2_rgrp_glops; >-extern const struct gfs2_glock_operations gfs2_trans_glops; >+extern const struct gfs2_glock_operations gfs2_freeze_glops; > extern const struct gfs2_glock_operations gfs2_iopen_glops; > extern const struct gfs2_glock_operations gfs2_flock_glops; > extern const struct gfs2_glock_operations gfs2_nondisk_glops; >@@ -23,6 +25,7 @@ extern const struct gfs2_glock_operation > extern const struct gfs2_glock_operations gfs2_journal_glops; > extern const struct gfs2_glock_operations *gfs2_glops_list[]; > >+extern void check_frozen_log(struct gfs2_sbd *sdp); > extern void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync); > > #endif /* __GLOPS_DOT_H__ */ >Index: gfs2-131111/fs/gfs2/incore.h >=================================================================== >--- gfs2-131111.orig/fs/gfs2/incore.h >+++ gfs2-131111/fs/gfs2/incore.h >@@ -450,8 +450,7 @@ struct gfs2_trans { > unsigned int tr_revokes; > unsigned int tr_reserved; > >- struct gfs2_holder tr_t_gh; >- >+ int tr_alloced; > int tr_touched; > int tr_attached; > >@@ -560,6 +559,12 @@ enum { > SDF_SKIP_DLM_UNLOCK = 8, > }; > >+enum gfs2_freeze_state { >+ SFS_UNFROZEN = 0, >+ SFS_STARTING_FREEZE = 1, >+ SFS_FROZEN = 2, >+}; >+ > #define GFS2_FSNAME_LEN 256 > > struct gfs2_inum_host { >@@ -656,7 +661,8 @@ struct gfs2_sbd { > struct lm_lockstruct sd_lockstruct; > struct gfs2_holder sd_live_gh; > struct gfs2_glock *sd_rename_gl; >- struct gfs2_glock *sd_trans_gl; >+ struct gfs2_glock *sd_freeze_gl; >+ struct work_struct sd_freeze_work; > wait_queue_head_t sd_glock_wait; > atomic_t sd_glock_disposal; > struct completion sd_locking_init; >@@ -782,6 +788,8 @@ struct gfs2_sbd { > > /* For quiescing the filesystem */ > struct gfs2_holder sd_freeze_gh; >+ atomic_t sd_freeze_state; >+ atomic_t sd_started_freeze; > > char sd_fsname[GFS2_FSNAME_LEN]; > char sd_table_name[GFS2_FSNAME_LEN]; >Index: gfs2-131111/fs/gfs2/log.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/log.c >+++ gfs2-131111/fs/gfs2/log.c >@@ -630,9 +630,13 @@ static void log_write_header(struct gfs2 > u32 hash; > int rw = WRITE_FLUSH_FUA | REQ_META; > 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); >@@ -669,9 +673,11 @@ static void log_write_header(struct gfs2 > * > */ > >-void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl) >+void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, >+ enum gfs2_flush_type type) > { > struct gfs2_trans *tr; >+ enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); > > down_write(&sdp->sd_log_flush_lock); > >@@ -681,7 +687,8 @@ void gfs2_log_flush(struct gfs2_sbd *sdp > return; > } > trace_gfs2_log_flush(sdp, 1); >- >+ printk("%s:%d In gfs2_log_flush. type %d\n", current->comm, >+ current->pid, type); > tr = sdp->sd_log_tr; > if (tr) { > sdp->sd_log_tr = NULL; >@@ -702,6 +709,13 @@ void gfs2_log_flush(struct gfs2_sbd *sdp > gfs2_assert_withdraw(sdp, > sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); > >+ if (unlikely(state == SFS_FROZEN && (sdp->sd_log_num_buf || sdp->sd_log_num_databuf || sdp->sd_log_num_revoke))) { >+ printk("GFS2: %s:%d buf=%u databuf=%u revoke=%u\n", >+ current->comm, current->pid, sdp->sd_log_num_buf, >+ sdp->sd_log_num_databuf, sdp->sd_log_num_revoke); >+ gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf && !sdp->sd_log_num_databuf && !sdp->sd_log_num_revoke); >+ } >+ > sdp->sd_log_flush_head = sdp->sd_log_head; > sdp->sd_log_flush_wrapped = 0; > if (tr) >@@ -734,6 +748,26 @@ void gfs2_log_flush(struct gfs2_sbd *sdp > } > spin_unlock(&sdp->sd_ail_lock); > gfs2_log_unlock(sdp); >+ >+ if (type != NORMAL_FLUSH) { >+ if (!sdp->sd_log_idle) { >+ for (;;) { >+ gfs2_ail1_start(sdp); >+ gfs2_ail1_wait(sdp); >+ if (gfs2_ail1_empty(sdp)) >+ break; >+ } >+ atomic_dec(&sdp->sd_log_blks_free); /* Adjust for unreserved buffer */ >+ trace_gfs2_log_blocks(sdp, -1); >+ sdp->sd_log_flush_wrapped = 0; >+ log_write_header(sdp, 0); >+ sdp->sd_log_head = sdp->sd_log_flush_head; >+ } >+ if (type == SHUTDOWN_FLUSH || type == FREEZE_FLUSH) >+ gfs2_log_shutdown(sdp); >+ if (type == FREEZE_FLUSH) >+ atomic_set(&sdp->sd_freeze_state, SFS_FROZEN); >+ } > trace_gfs2_log_flush(sdp, 0); > up_write(&sdp->sd_log_flush_lock); > >@@ -764,7 +798,7 @@ static void log_refund(struct gfs2_sbd * > > if (sdp->sd_log_tr == NULL && > (tr->tr_num_buf_new || tr->tr_num_databuf_new)) { >- gfs2_assert_withdraw(sdp, tr->tr_t_gh.gh_gl); >+ gfs2_assert_withdraw(sdp, tr->tr_alloced); > sdp->sd_log_tr = tr; > tr->tr_attached = 1; > } >@@ -804,8 +838,6 @@ void gfs2_log_commit(struct gfs2_sbd *sd > > void gfs2_log_shutdown(struct gfs2_sbd *sdp) > { >- down_write(&sdp->sd_log_flush_lock); >- > gfs2_assert_withdraw(sdp, !sdp->sd_log_blks_reserved); > gfs2_assert_withdraw(sdp, !sdp->sd_log_num_buf); > gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); >@@ -818,33 +850,11 @@ void gfs2_log_shutdown(struct gfs2_sbd * > > log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT); > >- gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks); > gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail); > gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list)); > > sdp->sd_log_head = sdp->sd_log_flush_head; > sdp->sd_log_tail = sdp->sd_log_head; >- >- up_write(&sdp->sd_log_flush_lock); >-} >- >- >-/** >- * gfs2_meta_syncfs - sync all the buffers in a filesystem >- * @sdp: the filesystem >- * >- */ >- >-void gfs2_meta_syncfs(struct gfs2_sbd *sdp) >-{ >- gfs2_log_flush(sdp, NULL); >- for (;;) { >- gfs2_ail1_start(sdp); >- gfs2_ail1_wait(sdp); >- if (gfs2_ail1_empty(sdp)) >- break; >- } >- gfs2_log_flush(sdp, NULL); > } > > static inline int gfs2_jrnl_flush_reqd(struct gfs2_sbd *sdp) >@@ -876,14 +886,14 @@ int gfs2_logd(void *data) > > if (gfs2_jrnl_flush_reqd(sdp) || t == 0) { > gfs2_ail1_empty(sdp); >- gfs2_log_flush(sdp, NULL); >+ gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); > } > > if (gfs2_ail_flush_reqd(sdp)) { > gfs2_ail1_start(sdp); > gfs2_ail1_wait(sdp); > gfs2_ail1_empty(sdp); >- gfs2_log_flush(sdp, NULL); >+ gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); > } > > if (!gfs2_ail_flush_reqd(sdp)) >Index: gfs2-131111/fs/gfs2/ops_fstype.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/ops_fstype.c >+++ gfs2-131111/fs/gfs2/ops_fstype.c >@@ -115,6 +115,8 @@ static struct gfs2_sbd *init_sbd(struct > init_rwsem(&sdp->sd_log_flush_lock); > atomic_set(&sdp->sd_log_in_flight, 0); > init_waitqueue_head(&sdp->sd_log_flush_wait); >+ atomic_set(&sdp->sd_freeze_state, SFS_UNFROZEN); >+ atomic_set(&sdp->sd_started_freeze, 0); > > INIT_LIST_HEAD(&sdp->sd_revoke_list); > >@@ -407,8 +409,8 @@ static int init_locking(struct gfs2_sbd > goto fail_live; > } > >- error = gfs2_glock_get(sdp, GFS2_TRANS_LOCK, &gfs2_trans_glops, >- CREATE, &sdp->sd_trans_gl); >+ error = gfs2_glock_get(sdp, GFS2_FREEZE_LOCK, &gfs2_freeze_glops, >+ CREATE, &sdp->sd_freeze_gl); > if (error) { > fs_err(sdp, "can't create transaction glock: %d\n", error); > goto fail_rename; >@@ -417,7 +419,7 @@ static int init_locking(struct gfs2_sbd > return 0; > > fail_trans: >- gfs2_glock_put(sdp->sd_trans_gl); >+ gfs2_glock_put(sdp->sd_freeze_gl); > fail_rename: > gfs2_glock_put(sdp->sd_rename_gl); > fail_live: >@@ -802,7 +804,7 @@ static int init_journal(struct gfs2_sbd > set_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags); > gfs2_glock_dq_uninit(&ji_gh); > jindex = 0; >- >+ INIT_WORK(&sdp->sd_freeze_work, gfs2_freeze_func); > return 0; > > fail_jinode_gh: >@@ -1457,7 +1459,7 @@ static void gfs2_kill_sb(struct super_bl > return; > } > >- gfs2_meta_syncfs(sdp); >+ gfs2_log_flush(sdp, NULL, SYNC_FLUSH); > dput(sdp->sd_root_dir); > dput(sdp->sd_master_dir); > sdp->sd_root_dir = NULL; >Index: gfs2-131111/fs/gfs2/recovery.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/recovery.c >+++ gfs2-131111/fs/gfs2/recovery.c >@@ -454,7 +454,7 @@ void gfs2_recover_func(struct work_struc > struct gfs2_inode *ip = GFS2_I(jd->jd_inode); > struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); > struct gfs2_log_header_host head; >- struct gfs2_holder j_gh, ji_gh, t_gh; >+ struct gfs2_holder j_gh, ji_gh; > unsigned long t; > int ro = 0; > unsigned int pass; >@@ -508,14 +508,6 @@ void gfs2_recover_func(struct work_struc > > t = jiffies; > >- /* Acquire a shared hold on the transaction lock */ >- >- error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, >- LM_FLAG_NOEXP | LM_FLAG_PRIORITY | >- GL_NOCACHE, &t_gh); >- if (error) >- goto fail_gunlock_ji; >- > if (test_bit(SDF_RORECOVERY, &sdp->sd_flags)) { > ro = 1; > } else if (test_bit(SDF_JOURNAL_CHECKED, &sdp->sd_flags)) { >@@ -538,7 +530,7 @@ void gfs2_recover_func(struct work_struc > fs_warn(sdp, "jid=%u: Can't replay: read-only block " > "device\n", jd->jd_jid); > error = -EROFS; >- goto fail_gunlock_tr; >+ goto fail_gunlock_ji; > } > > fs_info(sdp, "jid=%u: Replaying journal...\n", jd->jd_jid); >@@ -549,14 +541,13 @@ void gfs2_recover_func(struct work_struc > head.lh_blkno, pass); > lops_after_scan(jd, error, pass); > if (error) >- goto fail_gunlock_tr; >+ goto fail_gunlock_ji; > } > > error = clean_journal(jd, &head); > if (error) >- goto fail_gunlock_tr; >+ goto fail_gunlock_ji; > >- gfs2_glock_dq_uninit(&t_gh); > t = DIV_ROUND_UP(jiffies - t, HZ); > fs_info(sdp, "jid=%u: Journal replayed in %lus\n", > jd->jd_jid, t); >@@ -572,8 +563,6 @@ void gfs2_recover_func(struct work_struc > fs_info(sdp, "jid=%u: Done\n", jd->jd_jid); > goto done; > >-fail_gunlock_tr: >- gfs2_glock_dq_uninit(&t_gh); > fail_gunlock_ji: > if (jlocked) { > gfs2_glock_dq_uninit(&ji_gh); >Index: gfs2-131111/fs/gfs2/super.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/super.c >+++ gfs2-131111/fs/gfs2/super.c >@@ -24,6 +24,7 @@ > #include <linux/wait.h> > #include <linux/writeback.h> > #include <linux/backing-dev.h> >+#include <linux/kernel.h> > > #include "gfs2.h" > #include "incore.h" >@@ -380,11 +381,12 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp > { > struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); > struct gfs2_glock *j_gl = ip->i_gl; >- struct gfs2_holder t_gh; >+ struct gfs2_holder freeze_gh; > struct gfs2_log_header_host head; > int error; > >- error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &t_gh); >+ error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, >+ &freeze_gh); > if (error) > return error; > >@@ -410,13 +412,13 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp > > set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); > >- gfs2_glock_dq_uninit(&t_gh); >+ gfs2_glock_dq_uninit(&freeze_gh); > > return 0; > > fail: >- t_gh.gh_flags |= GL_NOCACHE; >- gfs2_glock_dq_uninit(&t_gh); >+ freeze_gh.gh_flags |= GL_NOCACHE; >+ gfs2_glock_dq_uninit(&freeze_gh); > > return error; > } >@@ -554,14 +556,15 @@ int gfs2_statfs_sync(struct super_block > struct buffer_head *m_bh, *l_bh; > int error; > >+ sb_start_write(sb); > error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, > &gh); > if (error) >- return error; >+ goto out; > > error = gfs2_meta_inode_buffer(m_ip, &m_bh); > if (error) >- goto out; >+ goto out_unlock; > > spin_lock(&sdp->sd_statfs_spin); > gfs2_statfs_change_in(m_sc, m_bh->b_data + >@@ -589,8 +592,10 @@ out_bh2: > brelse(l_bh); > out_bh: > brelse(m_bh); >-out: >+out_unlock: > gfs2_glock_dq_uninit(&gh); >+out: >+ sb_end_write(sb); > return error; > } > >@@ -610,7 +615,7 @@ struct lfcc { > */ > > static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp, >- struct gfs2_holder *t_gh) >+ struct gfs2_holder *freeze_gh) > { > struct gfs2_inode *ip; > struct gfs2_jdesc *jd; >@@ -633,10 +638,9 @@ static int gfs2_lock_fs_check_clean(stru > } > list_add(&lfcc->list, &list); > } >- >- error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_DEFERRED, >- GL_NOCACHE, t_gh); >- >+ atomic_inc(&sdp->sd_started_freeze); >+ error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_EXCLUSIVE, >+ GL_NOCACHE, freeze_gh); > list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { > error = gfs2_jdesc_check(jd); > if (error) >@@ -651,7 +655,7 @@ static int gfs2_lock_fs_check_clean(stru > } > > if (error) >- gfs2_glock_dq_uninit(t_gh); >+ gfs2_glock_dq_uninit(freeze_gh); > > out: > while (!list_empty(&list)) { >@@ -717,7 +721,7 @@ static int gfs2_write_inode(struct inode > int ret = 0; > > if (wbc->sync_mode == WB_SYNC_ALL) >- gfs2_log_flush(GFS2_SB(inode), ip->i_gl); >+ gfs2_log_flush(GFS2_SB(inode), ip->i_gl, NORMAL_FLUSH); > if (bdi->dirty_exceeded) > gfs2_ail1_flush(sdp, wbc); > else >@@ -797,25 +801,25 @@ out: > > static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) > { >- struct gfs2_holder t_gh; >+ struct gfs2_holder freeze_gh; > int error; > > flush_workqueue(gfs2_delete_workqueue); > gfs2_quota_sync(sdp->sd_vfs, 0); > gfs2_statfs_sync(sdp->sd_vfs, 0); > >- error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, >- &t_gh); >+ error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, GL_NOCACHE, >+ &freeze_gh); > if (error && !test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) > return error; > >- gfs2_meta_syncfs(sdp); >- gfs2_log_shutdown(sdp); >+ gfs2_log_flush(sdp, NULL, SHUTDOWN_FLUSH); >+ gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks); > > clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); > >- if (t_gh.gh_gl) >- gfs2_glock_dq_uninit(&t_gh); >+ if (freeze_gh.gh_gl) >+ gfs2_glock_dq_uninit(&freeze_gh); > > gfs2_quota_cleanup(sdp); > >@@ -875,7 +879,7 @@ restart: > iput(sdp->sd_quota_inode); > > gfs2_glock_put(sdp->sd_rename_gl); >- gfs2_glock_put(sdp->sd_trans_gl); >+ gfs2_glock_put(sdp->sd_freeze_gl); > > if (!sdp->sd_args.ar_spectator) { > gfs2_glock_dq_uninit(&sdp->sd_journal_gh); >@@ -911,10 +915,39 @@ static int gfs2_sync_fs(struct super_blo > > gfs2_quota_sync(sb, -1); > if (wait && sdp) >- gfs2_log_flush(sdp, NULL); >+ gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); > return 0; > } > >+void gfs2_freeze_func(struct work_struct *work) >+{ >+ int error; >+ struct gfs2_holder freeze_gh; >+ struct gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_freeze_work); >+ struct super_block *sb = sdp->sd_vfs; >+ >+ atomic_inc(&sb->s_active); >+ error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, >+ &freeze_gh); >+ if (error) { >+ printk(KERN_INFO "GFS2: couln't get freeze lock : %d\n", error); >+ gfs2_assert_withdraw(sdp, 0); >+ } >+ else { >+ printk("%s:%d got freeze lock\n", current->comm, current->pid); >+ atomic_set(&sdp->sd_freeze_state, SFS_UNFROZEN); >+ error = thaw_super(sb); >+ if (error) { >+ printk(KERN_INFO "GFS2: couldn't thaw filesystem: %d\n", >+ error); >+ gfs2_assert_withdraw(sdp, 0); >+ } >+ gfs2_glock_dq_uninit(&freeze_gh); >+ } >+ deactivate_super(sb); >+ return; >+} >+ > /** > * gfs2_freeze - prevent further writes to the filesystem > * @sb: the VFS structure for the filesystem >@@ -926,6 +959,12 @@ static int gfs2_freeze(struct super_bloc > struct gfs2_sbd *sdp = sb->s_fs_info; > int error; > >+ /* Just return if this is triggered by a freeze on another node >+ * in the cluster */ >+ if (atomic_read(&sdp->sd_freeze_state) != SFS_UNFROZEN) >+ return 0; >+ printk("GFS2: actually doing gfs2_freeze\n"); >+ > if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) > return -EINVAL; > >@@ -959,8 +998,27 @@ static int gfs2_freeze(struct super_bloc > static int gfs2_unfreeze(struct super_block *sb) > { > struct gfs2_sbd *sdp = sb->s_fs_info; >+ struct gfs2_holder freeze_gh; >+ int error; > >+ /* Just return if the freeze was started by another node in the >+ * cluster */ >+ if (!atomic_read(&sdp->sd_started_freeze)) >+ return 0; >+ printk("%s:%d unfreezing filesystem\n", current->comm, current->pid); >+ atomic_set(&sdp->sd_freeze_state, SFS_UNFROZEN); > gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); >+ check_frozen_log(sdp); >+ error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, 0, >+ &freeze_gh); >+ if (error) { >+ printk(KERN_INFO "GFS2: couln't get freeze lock : %d\n", error); >+ gfs2_assert_withdraw(sdp, 0); >+ } >+ else { >+ atomic_dec(&sdp->sd_started_freeze); >+ gfs2_glock_dq_uninit(&freeze_gh); >+ } > return 0; > } > >@@ -1493,7 +1551,7 @@ static void gfs2_evict_inode(struct inod > goto out_unlock; > > out_truncate: >- gfs2_log_flush(sdp, ip->i_gl); >+ gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH); > if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) { > struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); > filemap_fdatawrite(metamapping); >Index: gfs2-131111/fs/gfs2/sys.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/sys.c >+++ gfs2-131111/fs/gfs2/sys.c >@@ -239,8 +239,8 @@ static ssize_t demote_rq_store(struct gf > > if (gltype > LM_TYPE_JOURNAL) > return -EINVAL; >- if (gltype == LM_TYPE_NONDISK && glnum == GFS2_TRANS_LOCK) >- glops = &gfs2_trans_glops; >+ if (gltype == LM_TYPE_NONDISK && glnum == GFS2_FREEZE_LOCK) >+ glops = &gfs2_freeze_glops; > else > glops = gfs2_glops_list[gltype]; > if (glops == NULL) >Index: gfs2-131111/fs/gfs2/trans.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/trans.c >+++ gfs2-131111/fs/gfs2/trans.c >@@ -46,32 +46,24 @@ int gfs2_trans_begin(struct gfs2_sbd *sd > tr->tr_blocks = blocks; > tr->tr_revokes = revokes; > tr->tr_reserved = 1; >+ tr->tr_alloced = 1; > if (blocks) > tr->tr_reserved += 6 + blocks; > if (revokes) > tr->tr_reserved += gfs2_struct2blk(sdp, revokes, > sizeof(u64)); > sb_start_intwrite(sdp->sd_vfs); >- gfs2_holder_init(sdp->sd_trans_gl, LM_ST_SHARED, 0, &tr->tr_t_gh); >- >- error = gfs2_glock_nq(&tr->tr_t_gh); >- if (error) >- goto fail_holder_uninit; > > error = gfs2_log_reserve(sdp, tr->tr_reserved); > if (error) >- goto fail_gunlock; >+ goto fail; > > current->journal_info = tr; > > return 0; > >-fail_gunlock: >- gfs2_glock_dq(&tr->tr_t_gh); >- >-fail_holder_uninit: >+fail: > sb_end_intwrite(sdp->sd_vfs); >- gfs2_holder_uninit(&tr->tr_t_gh); > kfree(tr); > > return error; >@@ -115,11 +107,8 @@ void gfs2_trans_end(struct gfs2_sbd *sdp > > if (!tr->tr_touched) { > gfs2_log_release(sdp, tr->tr_reserved); >- if (tr->tr_t_gh.gh_gl) { >- gfs2_glock_dq(&tr->tr_t_gh); >- gfs2_holder_uninit(&tr->tr_t_gh); >+ if (tr->tr_alloced) > kfree(tr); >- } > sb_end_intwrite(sdp->sd_vfs); > return; > } >@@ -133,16 +122,12 @@ void gfs2_trans_end(struct gfs2_sbd *sdp > gfs2_print_trans(tr); > > gfs2_log_commit(sdp, tr); >- if (tr->tr_t_gh.gh_gl) { >- gfs2_glock_dq(&tr->tr_t_gh); >- gfs2_holder_uninit(&tr->tr_t_gh); >- if (!tr->tr_attached) >+ if (tr->tr_alloced && !tr->tr_attached) > kfree(tr); >- } > up_read(&sdp->sd_log_flush_lock); > > if (sdp->sd_vfs->s_flags & MS_SYNCHRONOUS) >- gfs2_log_flush(sdp, NULL); >+ gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); > sb_end_intwrite(sdp->sd_vfs); > } > >@@ -221,6 +206,7 @@ static void meta_lo_add(struct gfs2_sbd > { > struct gfs2_meta_header *mh; > struct gfs2_trans *tr; >+ enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); > > tr = current->journal_info; > tr->tr_touched = 1; >@@ -235,6 +221,11 @@ static void meta_lo_add(struct gfs2_sbd > (unsigned long long)bd->bd_bh->b_blocknr); > BUG(); > } >+ if (unlikely(state == SFS_FROZEN)) { >+ printk("GFS2: %s:%d adding buf while frozen\n", >+ current->comm, current->pid); >+ gfs2_assert_withdraw(sdp, 0); >+ } > gfs2_pin(sdp, bd->bd_bh); > mh->__pad0 = cpu_to_be64(0); > mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid); >Index: gfs2-131111/include/uapi/linux/gfs2_ondisk.h >=================================================================== >--- gfs2-131111.orig/include/uapi/linux/gfs2_ondisk.h >+++ gfs2-131111/include/uapi/linux/gfs2_ondisk.h >@@ -20,7 +20,7 @@ > > #define GFS2_MOUNT_LOCK 0 > #define GFS2_LIVE_LOCK 1 >-#define GFS2_TRANS_LOCK 2 >+#define GFS2_FREEZE_LOCK 2 > #define GFS2_RENAME_LOCK 3 > #define GFS2_CONTROL_LOCK 4 > #define GFS2_MOUNTED_LOCK 5 >Index: gfs2-131111/fs/gfs2/aops.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/aops.c >+++ gfs2-131111/fs/gfs2/aops.c >@@ -371,7 +371,7 @@ static int gfs2_jdata_writepages(struct > > ret = gfs2_write_cache_jdata(mapping, wbc); > if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) { >- gfs2_log_flush(sdp, ip->i_gl); >+ gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH); > ret = gfs2_write_cache_jdata(mapping, wbc); > } > return ret; >Index: gfs2-131111/fs/gfs2/file.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/file.c >+++ gfs2-131111/fs/gfs2/file.c >@@ -256,7 +256,7 @@ static int do_gfs2_set_flags(struct file > } > if ((flags ^ new_flags) & GFS2_DIF_JDATA) { > if (flags & GFS2_DIF_JDATA) >- gfs2_log_flush(sdp, ip->i_gl); >+ gfs2_log_flush(sdp, ip->i_gl, NORMAL_FLUSH); > error = filemap_fdatawrite(inode->i_mapping); > if (error) > goto out; >Index: gfs2-131111/fs/gfs2/log.h >=================================================================== >--- gfs2-131111.orig/fs/gfs2/log.h >+++ gfs2-131111/fs/gfs2/log.h >@@ -64,13 +64,19 @@ extern unsigned int gfs2_struct2blk(stru > unsigned int ssize); > > extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks); >-extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl); >+enum gfs2_flush_type { >+ NORMAL_FLUSH = 0, >+ SYNC_FLUSH, >+ SHUTDOWN_FLUSH, >+ FREEZE_FLUSH >+}; >+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); > extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd); > extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc); > > extern void gfs2_log_shutdown(struct gfs2_sbd *sdp); >-extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp); > extern int gfs2_logd(void *data); > extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); > extern void gfs2_write_revokes(struct gfs2_sbd *sdp); >Index: gfs2-131111/fs/gfs2/quota.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/quota.c >+++ gfs2-131111/fs/gfs2/quota.c >@@ -871,7 +871,7 @@ out: > gfs2_glock_dq_uninit(&ghs[qx]); > mutex_unlock(&ip->i_inode.i_mutex); > kfree(ghs); >- gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl); >+ gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl, NORMAL_FLUSH); > return error; > } > >Index: gfs2-131111/fs/gfs2/rgrp.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/rgrp.c >+++ gfs2-131111/fs/gfs2/rgrp.c >@@ -1943,7 +1943,7 @@ next_rgrp: > } > /* Flushing the log may release space */ > if (loops == 2) >- gfs2_log_flush(sdp, NULL); >+ gfs2_log_flush(sdp, NULL, NORMAL_FLUSH); > } > > return -ENOSPC; >Index: gfs2-131111/fs/gfs2/main.c >=================================================================== >--- gfs2-131111.orig/fs/gfs2/main.c >+++ gfs2-131111/fs/gfs2/main.c >@@ -28,6 +28,7 @@ > #include "quota.h" > #include "recovery.h" > #include "dir.h" >+#include "glops.h" > > struct workqueue_struct *gfs2_control_wq; > >@@ -158,9 +159,14 @@ static int __init init_gfs2_fs(void) > if (!gfs2_control_wq) > goto fail_recovery; > >+ gfs2_freeze_wq = alloc_workqueue("freeze_workqueue", 0, 0); >+ >+ if (!gfs2_freeze_wq) >+ goto fail_control; >+ > gfs2_page_pool = mempool_create_page_pool(64, 0); > if (!gfs2_page_pool) >- goto fail_control; >+ goto fail_freeze; > > gfs2_register_debugfs(); > >@@ -168,6 +174,8 @@ static int __init init_gfs2_fs(void) > > return 0; > >+fail_freeze: >+ destroy_workqueue(gfs2_freeze_wq); > fail_control: > destroy_workqueue(gfs2_control_wq); > fail_recovery: >@@ -221,6 +229,7 @@ static void __exit exit_gfs2_fs(void) > unregister_filesystem(&gfs2meta_fs_type); > destroy_workqueue(gfs_recovery_wq); > destroy_workqueue(gfs2_control_wq); >+ destroy_workqueue(gfs2_freeze_wq); > list_lru_destroy(&gfs2_qd_lru); > > rcu_barrier(); >Index: gfs2-131111/fs/gfs2/super.h >=================================================================== >--- gfs2-131111.orig/fs/gfs2/super.h >+++ gfs2-131111/fs/gfs2/super.h >@@ -45,6 +45,7 @@ extern void gfs2_statfs_change_in(struct > extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, > struct buffer_head *l_bh); > extern int gfs2_statfs_sync(struct super_block *sb, int type); >+extern void gfs2_freeze_func(struct work_struct *work); > > extern struct file_system_type gfs2_fs_type; > extern struct file_system_type gfs2meta_fs_type;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1027451
:
820790
|
824779
|
833334
|
846826
|
888221
|
888975
|
891000