[Cluster-devel] GFS2: Pre-pull patch posting
Hi, Here are a few GFS2 fixes which are pending. There are two patches which fix up a couple of minor issues in the DLM interface code, a missing error path in gfs2_rs_alloc(), two patches which fix problems during withdraw and a fix for discards/FITRIM when using 4k sector sized devices, Steve.
[Cluster-devel] [PATCH 1/6] GFS2: use kmalloc for lvb bitmap
From: David Teigland teigl...@redhat.com The temp lvb bitmap was on the stack, which could be an alignment problem for __set_bit_le. Use kmalloc for it instead. Signed-off-by: David Teigland teigl...@redhat.com Signed-off-by: Steven Whitehouse swhit...@redhat.com diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 156e42e..5c29216 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -588,6 +588,7 @@ struct lm_lockstruct { struct dlm_lksb ls_control_lksb; /* control_lock */ char ls_control_lvb[GDLM_LVB_SIZE]; /* control_lock lvb */ struct completion ls_sync_wait; /* {control,mounted}_{lock,unlock} */ + char *ls_lvb_bits; spinlock_t ls_recover_spin; /* protects following fields */ unsigned long ls_recover_flags; /* DFL_ */ diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index 9802de0..b15bb45 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -580,7 +580,6 @@ static void gfs2_control_func(struct work_struct *work) { struct gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_control_work.work); struct lm_lockstruct *ls = sdp-sd_lockstruct; - char lvb_bits[GDLM_LVB_SIZE]; uint32_t block_gen, start_gen, lvb_gen, flags; int recover_set = 0; int write_lvb = 0; @@ -634,7 +633,7 @@ static void gfs2_control_func(struct work_struct *work) return; } - control_lvb_read(ls, lvb_gen, lvb_bits); + control_lvb_read(ls, lvb_gen, ls-ls_lvb_bits); spin_lock(ls-ls_recover_spin); if (block_gen != ls-ls_recover_block || @@ -664,10 +663,10 @@ static void gfs2_control_func(struct work_struct *work) ls-ls_recover_result[i] = 0; - if (!test_bit_le(i, lvb_bits + JID_BITMAP_OFFSET)) + if (!test_bit_le(i, ls-ls_lvb_bits + JID_BITMAP_OFFSET)) continue; - __clear_bit_le(i, lvb_bits + JID_BITMAP_OFFSET); + __clear_bit_le(i, ls-ls_lvb_bits + JID_BITMAP_OFFSET); write_lvb = 1; } } @@ -691,7 +690,7 @@ static void gfs2_control_func(struct work_struct *work) continue; if (ls-ls_recover_submit[i] start_gen) { ls-ls_recover_submit[i] = 0; - __set_bit_le(i, lvb_bits + JID_BITMAP_OFFSET); + __set_bit_le(i, ls-ls_lvb_bits + JID_BITMAP_OFFSET); } } /* even if there are no bits to set, we need to write the @@ -705,7 +704,7 @@ static void gfs2_control_func(struct work_struct *work) spin_unlock(ls-ls_recover_spin); if (write_lvb) { - control_lvb_write(ls, start_gen, lvb_bits); + control_lvb_write(ls, start_gen, ls-ls_lvb_bits); flags = DLM_LKF_CONVERT | DLM_LKF_VALBLK; } else { flags = DLM_LKF_CONVERT; @@ -725,7 +724,7 @@ static void gfs2_control_func(struct work_struct *work) */ for (i = 0; i recover_size; i++) { - if (test_bit_le(i, lvb_bits + JID_BITMAP_OFFSET)) { + if (test_bit_le(i, ls-ls_lvb_bits + JID_BITMAP_OFFSET)) { fs_info(sdp, recover generation %u jid %d\n, start_gen, i); gfs2_recover_set(sdp, i); @@ -758,7 +757,6 @@ static void gfs2_control_func(struct work_struct *work) static int control_mount(struct gfs2_sbd *sdp) { struct lm_lockstruct *ls = sdp-sd_lockstruct; - char lvb_bits[GDLM_LVB_SIZE]; uint32_t start_gen, block_gen, mount_gen, lvb_gen; int mounted_mode; int retries = 0; @@ -857,7 +855,7 @@ locks_done: * lvb_gen will be non-zero. */ - control_lvb_read(ls, lvb_gen, lvb_bits); + control_lvb_read(ls, lvb_gen, ls-ls_lvb_bits); if (lvb_gen == 0x) { /* special value to force mount attempts to fail */ @@ -887,7 +885,7 @@ locks_done: * and all lvb bits to be clear (no pending journal recoveries.) */ - if (!all_jid_bits_clear(lvb_bits)) { + if (!all_jid_bits_clear(ls-ls_lvb_bits)) { /* journals need recovery, wait until all are clear */ fs_info(sdp, control_mount wait for journal recovery\n); goto restart; @@ -949,7 +947,6 @@ static int dlm_recovery_wait(void *word) static int control_first_done(struct gfs2_sbd *sdp) { struct lm_lockstruct *ls = sdp-sd_lockstruct; - char lvb_bits[GDLM_LVB_SIZE]; uint32_t start_gen, block_gen; int error; @@ -991,8 +988,8 @@ restart: memset(ls-ls_recover_result, 0, ls-ls_recover_size*sizeof(uint32_t)); spin_unlock(ls-ls_recover_spin); - memset(lvb_bits, 0, sizeof(lvb_bits)); -
[Cluster-devel] [PATCH 5/6] GFS2: Fix unlock of fcntl locks during withdrawn state
From: David Teigland teigl...@redhat.com This reminded me of another old patch I had sitting around which I never had a chance to test. I copied this idea from the nfs code. The problem is that when the kernel clears flocks/plocks during close, it calls posix unlock even if there are no posix locks on the file. Without this patch, that extraneous unlock propagates up to controld, across the cluster, and back down to the kernel. That can amount to a lot of plock activity on a fs that may have never used a single plock (only flocks). With this patch, we should detect that the unlock is extraneous (since it doesn't exist in the vfs), and skip all the userland traffic. Signed-off-by: David Teigland teigl...@redhat.com Signed-off-by: Steven Whitehouse swhit...@redhat.com diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c index 01fd5c1..f704458 100644 --- a/fs/dlm/plock.c +++ b/fs/dlm/plock.c @@ -247,6 +247,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file, struct dlm_ls *ls; struct plock_op *op; int rv; + unsigned char fl_flags = fl-fl_flags; ls = dlm_find_lockspace_local(lockspace); if (!ls) @@ -258,9 +259,18 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file, goto out; } - if (posix_lock_file_wait(file, fl) 0) - log_error(ls, dlm_posix_unlock: vfs unlock error %llx, - (unsigned long long)number); + /* cause the vfs unlock to return ENOENT if lock is not found */ + fl-fl_flags |= FL_EXISTS; + + rv = posix_lock_file_wait(file, fl); + if (rv == -ENOENT) { + rv = 0; + goto out_free; + } + if (rv 0) { + log_error(ls, dlm_posix_unlock: vfs unlock error %d %llx, + rv, (unsigned long long)number); + } op-info.optype = DLM_PLOCK_OP_UNLOCK; op-info.pid= fl-fl_pid; @@ -296,9 +306,11 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file, if (rv == -ENOENT) rv = 0; +out_free: kfree(op); out: dlm_put_lockspace(ls); + fl-fl_flags = fl_flags; return rv; } EXPORT_SYMBOL_GPL(dlm_posix_unlock); -- 1.7.4
[Cluster-devel] [PATCH 2/6] GFS2: use memchr_inv
From: Akinobu Mita akinobu.m...@gmail.com Use memchr_inv to verify that the specified memory range is cleared. Signed-off-by: Akinobu Mita akinobu.m...@gmail.com Cc: Steven Whitehouse swhit...@redhat.com Cc: cluster-devel@redhat.com Cc: Christine Caulfield ccaul...@redhat.com Cc: David Teigland teigl...@redhat.com diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index b15bb45..c8423d6 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -483,12 +483,8 @@ static void control_lvb_write(struct lm_lockstruct *ls, uint32_t lvb_gen, static int all_jid_bits_clear(char *lvb) { - int i; - for (i = JID_BITMAP_OFFSET; i GDLM_LVB_SIZE; i++) { - if (lvb[i]) - return 0; - } - return 1; + return !memchr_inv(lvb + JID_BITMAP_OFFSET, 0, + GDLM_LVB_SIZE - JID_BITMAP_OFFSET); } static void sync_wait_cb(void *arg) -- 1.7.4
[Cluster-devel] [PATCH 3/6] GFS2: return error if malloc failed in gfs2_rs_alloc()
From: Wei Yongjun yongjun_...@trendmicro.com.cn The error code in gfs2_rs_alloc() is set to ENOMEM when error but never be used, instead, gfs2_rs_alloc() always return 0. Fix to return 'error'. Signed-off-by: Wei Yongjun yongjun_...@trendmicro.com.cn Signed-off-by: Steven Whitehouse swhit...@redhat.com diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index d1f51fd..70d1cd0 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -576,7 +576,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip) RB_CLEAR_NODE(ip-i_res-rs_node); out: up_write(ip-i_rw_mutex); - return 0; + return error; } static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs) -- 1.7.4
[Cluster-devel] [PATCH 6/6] GFS2: Issue discards in 512b sectors
From: Bob Peterson rpete...@redhat.com This patch changes GFS2's discard issuing code so that it calls function sb_issue_discard rather than blkdev_issue_discard. The code was calling blkdev_issue_discard and specifying the correct sector offset and sector size, but blkdev_issue_discard expects these values to be in terms of 512 byte sectors, even if the native sector size for the device is different. Calling sb_issue_discard with the BLOCK size instead ensures the correct block-to-512b-sector translation. I verified that minlen is specified in blocks, so comparing it to a number of blocks is correct. Signed-off-by: Bob Peterson rpete...@redhat.com Signed-off-by: Steven Whitehouse swhit...@redhat.com diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 70d1cd0..5a51265 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1181,12 +1181,9 @@ int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed) { struct super_block *sb = sdp-sd_vfs; - struct block_device *bdev = sb-s_bdev; - const unsigned int sects_per_blk = sdp-sd_sb.sb_bsize / - bdev_logical_block_size(sb-s_bdev); u64 blk; sector_t start = 0; - sector_t nr_sects = 0; + sector_t nr_blks = 0; int rv; unsigned int x; u32 trimmed = 0; @@ -1206,35 +1203,34 @@ int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, if (diff == 0) continue; blk = offset + ((bi-bi_start + x) * GFS2_NBBY); - blk *= sects_per_blk; /* convert to sectors */ while(diff) { if (diff 1) { - if (nr_sects == 0) + if (nr_blks == 0) goto start_new_extent; - if ((start + nr_sects) != blk) { - if (nr_sects = minlen) { - rv = blkdev_issue_discard(bdev, - start, nr_sects, + if ((start + nr_blks) != blk) { + if (nr_blks = minlen) { + rv = sb_issue_discard(sb, + start, nr_blks, GFP_NOFS, 0); if (rv) goto fail; - trimmed += nr_sects; + trimmed += nr_blks; } - nr_sects = 0; + nr_blks = 0; start_new_extent: start = blk; } - nr_sects += sects_per_blk; + nr_blks++; } diff = 2; - blk += sects_per_blk; + blk++; } } - if (nr_sects = minlen) { - rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, 0); + if (nr_blks = minlen) { + rv = sb_issue_discard(sb, start, nr_blks, GFP_NOFS, 0); if (rv) goto fail; - trimmed += nr_sects; + trimmed += nr_blks; } if (ptrimmed) *ptrimmed = trimmed; -- 1.7.4
[Cluster-devel] [PATCH 4/6] GFS2: Fix unlock of fcntl locks during withdrawn state
When withdraw occurs, we need to continue to allow unlocks of fcntl locks to occur, however these will only be local, since the node has withdrawn from the cluster. This prevents triggering a VFS level bug trap due to locks remaining when a file is closed. Signed-off-by: Steven Whitehouse swhit...@redhat.com diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 019f45e..d79c2da 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -923,8 +923,11 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) cmd = F_SETLK; fl-fl_type = F_UNLCK; } - if (unlikely(test_bit(SDF_SHUTDOWN, sdp-sd_flags))) + if (unlikely(test_bit(SDF_SHUTDOWN, sdp-sd_flags))) { + if (fl-fl_type == F_UNLCK) + posix_lock_file_wait(file, fl); return -EIO; + } if (IS_GETLK(cmd)) return dlm_posix_get(ls-ls_dlm, ip-i_no_addr, file, fl); else if (fl-fl_type == F_UNLCK) -- 1.7.4
[Cluster-devel] GFS2: Pull request (fixes)
Hi, Please consider pulling the following changes, Steve. There are two patches which fix up a couple of minor issues in the DLM interface code, a missing error path in gfs2_rs_alloc(), two patches which fix problems during withdraw and a fix for discards/FITRIM when using 4k sector sized devices. The following changes since commit 66ade474237745a57b7e87da9a93c7ec69fd52bb: Merge branch 'fixes' of git://git.linaro.org/people/rmk/linux-arm (2013-04-03 16:15:17 -0700) are available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes.git master Akinobu Mita (1): GFS2: use memchr_inv Bob Peterson (1): GFS2: Issue discards in 512b sectors David Teigland (2): GFS2: use kmalloc for lvb bitmap GFS2: Fix unlock of fcntl locks during withdrawn state Steven Whitehouse (1): GFS2: Fix unlock of fcntl locks during withdrawn state Wei Yongjun (1): GFS2: return error if malloc failed in gfs2_rs_alloc() fs/dlm/plock.c | 18 +++--- fs/gfs2/file.c |5 - fs/gfs2/incore.h |1 + fs/gfs2/lock_dlm.c | 39 --- fs/gfs2/rgrp.c | 32 ++-- 5 files changed, 54 insertions(+), 41 deletions(-)
Re: [Cluster-devel] GFS2: Pull request (fixes)
On Fri, Apr 05, 2013 at 11:34:45AM +0100, Steven Whitehouse wrote: Please consider pulling the following changes, There's some mixup here that should be cleared up first. David Teigland (2): GFS2: Fix unlock of fcntl locks during withdrawn state Steven Whitehouse (1): GFS2: Fix unlock of fcntl locks during withdrawn state
Re: [Cluster-devel] GFS2: Pull request (fixes)
Hi, On Fri, 2013-04-05 at 12:27 -0400, David Teigland wrote: On Fri, Apr 05, 2013 at 11:34:45AM +0100, Steven Whitehouse wrote: Please consider pulling the following changes, There's some mixup here that should be cleared up first. David Teigland (2): GFS2: Fix unlock of fcntl locks during withdrawn state Steven Whitehouse (1): GFS2: Fix unlock of fcntl locks during withdrawn state Yes, sorry about that. I'll fix that up and resend the pull request in due course, Steve.
Re: [Cluster-devel] GFS2: Pull request (fixes)
Hi, I've dropped out the patch which shouldn't have made it into the previous pull request, so this set should be ok now. Apologies for not spotting that issue sooner, Steve. - There are two patches which fix up a couple of minor issues in the DLM interface code, a missing error path in gfs2_rs_alloc(), one patch which fixes a problem during withdraw and a fix for discards/FITRIM when using 4k sector sized devices. - The following changes since commit 66ade474237745a57b7e87da9a93c7ec69fd52bb: Merge branch 'fixes' of git://git.linaro.org/people/rmk/linux-arm (2013-04-03 16:15:17 -0700) are available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes.git master Akinobu Mita (1): GFS2: use memchr_inv Bob Peterson (1): GFS2: Issue discards in 512b sectors David Teigland (1): GFS2: use kmalloc for lvb bitmap Steven Whitehouse (1): GFS2: Fix unlock of fcntl locks during withdrawn state Wei Yongjun (1): GFS2: return error if malloc failed in gfs2_rs_alloc() fs/gfs2/file.c |5 - fs/gfs2/incore.h |1 + fs/gfs2/lock_dlm.c | 39 --- fs/gfs2/rgrp.c | 32 ++-- 4 files changed, 39 insertions(+), 38 deletions(-) signature.asc Description: This is a digitally signed message part
[Cluster-devel] [PATCH] GFS2: replace gfs2_ail structure with gfs2_trans
In order to allow transactions and log flushes to happen at the same time, gfs2 needs to move the transaction accounting and active items list code into the gfs2_trans structure. As a first step toward this, this patch removes the gfs2_ail structure, and handles the active items list in the gfs_trans structure. This keeps gfs2 from allocating an ail structure on log flushes, and gives us a struture that can later be used to store the transaction accounting outside of the gfs2 superblock structure. With this patch, at the end of a transaction, gfs2 will add the gfs2_trans structure to the superblock if there is not one already. This structure now has the active items fields that were previously in gfs2_ail. This is not necessary in the case where the transaction was simply used to add revokes, since these are never written outside of the journal, and thus, don't need an active items list. Also, in order to make sure that the transaction structure is not removed while it's still in use by gfs2_trans_end, unlocking the sd_log_flush_lock has to happen slightly later in ending the transaction. Signed-off-by: Benjamin Marzinski bmarz...@redhat.com --- fs/gfs2/aops.c|2 - fs/gfs2/incore.h | 17 fs/gfs2/log.c | 104 +- fs/gfs2/lops.c| 32 ++-- fs/gfs2/lops.h|5 +- fs/gfs2/meta_io.c |2 - fs/gfs2/trans.c |4 +- 7 files changed, 94 insertions(+), 72 deletions(-) Index: gfs2-3.0-nmw-130405/fs/gfs2/aops.c === --- gfs2-3.0-nmw-130405.orig/fs/gfs2/aops.c +++ gfs2-3.0-nmw-130405/fs/gfs2/aops.c @@ -1055,7 +1055,7 @@ int gfs2_releasepage(struct page *page, if (atomic_read(bh-b_count)) goto cannot_release; bd = bh-b_private; - if (bd bd-bd_ail) + if (bd bd-bd_tr) goto cannot_release; if (buffer_pinned(bh) || buffer_dirty(bh)) goto not_possible; Index: gfs2-3.0-nmw-130405/fs/gfs2/incore.h === --- gfs2-3.0-nmw-130405.orig/fs/gfs2/incore.h +++ gfs2-3.0-nmw-130405/fs/gfs2/incore.h @@ -31,7 +31,6 @@ struct gfs2_holder; struct gfs2_glock; struct gfs2_quota_data; struct gfs2_trans; -struct gfs2_ail; struct gfs2_jdesc; struct gfs2_sbd; struct lm_lockops; @@ -53,7 +52,7 @@ struct gfs2_log_header_host { struct gfs2_log_operations { void (*lo_before_commit) (struct gfs2_sbd *sdp); - void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai); + void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr); void (*lo_before_scan) (struct gfs2_jdesc *jd, struct gfs2_log_header_host *head, int pass); int (*lo_scan_elements) (struct gfs2_jdesc *jd, unsigned int start, @@ -139,7 +138,7 @@ struct gfs2_bufdata { struct list_head bd_list; const struct gfs2_log_operations *bd_ops; - struct gfs2_ail *bd_ail; + struct gfs2_trans *bd_tr; struct list_head bd_ail_st_list; struct list_head bd_ail_gl_list; }; @@ -433,6 +432,7 @@ struct gfs2_trans { struct gfs2_holder tr_t_gh; int tr_touched; + int tr_attached; unsigned int tr_num_buf_new; unsigned int tr_num_databuf_new; @@ -440,14 +440,12 @@ struct gfs2_trans { unsigned int tr_num_databuf_rm; unsigned int tr_num_revoke; unsigned int tr_num_revoke_rm; -}; -struct gfs2_ail { - struct list_head ai_list; + struct list_head tr_list; - unsigned int ai_first; - struct list_head ai_ail1_list; - struct list_head ai_ail2_list; + unsigned int tr_first; + struct list_head tr_ail1_list; + struct list_head tr_ail2_list; }; struct gfs2_journal_extent { @@ -710,6 +708,7 @@ struct gfs2_sbd { spinlock_t sd_log_lock; + struct gfs2_trans *sd_log_tr; unsigned int sd_log_blks_reserved; unsigned int sd_log_commited_buf; unsigned int sd_log_commited_databuf; Index: gfs2-3.0-nmw-130405/fs/gfs2/log.c === --- gfs2-3.0-nmw-130405.orig/fs/gfs2/log.c +++ gfs2-3.0-nmw-130405/fs/gfs2/log.c @@ -73,7 +73,7 @@ unsigned int gfs2_struct2blk(struct gfs2 void gfs2_remove_from_ail(struct gfs2_bufdata *bd) { - bd-bd_ail = NULL; + bd-bd_tr = NULL; list_del_init(bd-bd_ail_st_list); list_del_init(bd-bd_ail_gl_list); atomic_dec(bd-bd_gl-gl_ail_count); @@ -90,7 +90,7 @@ void gfs2_remove_from_ail(struct gfs2_bu static int gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct writeback_control *wbc, - struct gfs2_ail *ai) + struct gfs2_trans *tr)