GFS2: use kmalloc for lvb bitmap

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 <teigland@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
David Teigland 2013-03-05 16:01:47 -05:00 committed by Steven Whitehouse
parent 66ade47423
commit 57c7310b8e
2 changed files with 19 additions and 13 deletions

View File

@ -588,6 +588,7 @@ struct lm_lockstruct {
struct dlm_lksb ls_control_lksb; /* control_lock */ struct dlm_lksb ls_control_lksb; /* control_lock */
char ls_control_lvb[GDLM_LVB_SIZE]; /* control_lock lvb */ char ls_control_lvb[GDLM_LVB_SIZE]; /* control_lock lvb */
struct completion ls_sync_wait; /* {control,mounted}_{lock,unlock} */ struct completion ls_sync_wait; /* {control,mounted}_{lock,unlock} */
char *ls_lvb_bits;
spinlock_t ls_recover_spin; /* protects following fields */ spinlock_t ls_recover_spin; /* protects following fields */
unsigned long ls_recover_flags; /* DFL_ */ unsigned long ls_recover_flags; /* DFL_ */

View File

@ -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 gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_control_work.work);
struct lm_lockstruct *ls = &sdp->sd_lockstruct; struct lm_lockstruct *ls = &sdp->sd_lockstruct;
char lvb_bits[GDLM_LVB_SIZE];
uint32_t block_gen, start_gen, lvb_gen, flags; uint32_t block_gen, start_gen, lvb_gen, flags;
int recover_set = 0; int recover_set = 0;
int write_lvb = 0; int write_lvb = 0;
@ -634,7 +633,7 @@ static void gfs2_control_func(struct work_struct *work)
return; 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); spin_lock(&ls->ls_recover_spin);
if (block_gen != ls->ls_recover_block || 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; 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; continue;
__clear_bit_le(i, lvb_bits + JID_BITMAP_OFFSET); __clear_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET);
write_lvb = 1; write_lvb = 1;
} }
} }
@ -691,7 +690,7 @@ static void gfs2_control_func(struct work_struct *work)
continue; continue;
if (ls->ls_recover_submit[i] < start_gen) { if (ls->ls_recover_submit[i] < start_gen) {
ls->ls_recover_submit[i] = 0; 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 /* 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); spin_unlock(&ls->ls_recover_spin);
if (write_lvb) { 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; flags = DLM_LKF_CONVERT | DLM_LKF_VALBLK;
} else { } else {
flags = DLM_LKF_CONVERT; flags = DLM_LKF_CONVERT;
@ -725,7 +724,7 @@ static void gfs2_control_func(struct work_struct *work)
*/ */
for (i = 0; i < recover_size; i++) { 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", fs_info(sdp, "recover generation %u jid %d\n",
start_gen, i); start_gen, i);
gfs2_recover_set(sdp, 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) static int control_mount(struct gfs2_sbd *sdp)
{ {
struct lm_lockstruct *ls = &sdp->sd_lockstruct; struct lm_lockstruct *ls = &sdp->sd_lockstruct;
char lvb_bits[GDLM_LVB_SIZE];
uint32_t start_gen, block_gen, mount_gen, lvb_gen; uint32_t start_gen, block_gen, mount_gen, lvb_gen;
int mounted_mode; int mounted_mode;
int retries = 0; int retries = 0;
@ -857,7 +855,7 @@ locks_done:
* lvb_gen will be non-zero. * 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 == 0xFFFFFFFF) { if (lvb_gen == 0xFFFFFFFF) {
/* special value to force mount attempts to fail */ /* 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.) * 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 */ /* journals need recovery, wait until all are clear */
fs_info(sdp, "control_mount wait for journal recovery\n"); fs_info(sdp, "control_mount wait for journal recovery\n");
goto restart; goto restart;
@ -949,7 +947,6 @@ static int dlm_recovery_wait(void *word)
static int control_first_done(struct gfs2_sbd *sdp) static int control_first_done(struct gfs2_sbd *sdp)
{ {
struct lm_lockstruct *ls = &sdp->sd_lockstruct; struct lm_lockstruct *ls = &sdp->sd_lockstruct;
char lvb_bits[GDLM_LVB_SIZE];
uint32_t start_gen, block_gen; uint32_t start_gen, block_gen;
int error; int error;
@ -991,8 +988,8 @@ restart:
memset(ls->ls_recover_result, 0, ls->ls_recover_size*sizeof(uint32_t)); memset(ls->ls_recover_result, 0, ls->ls_recover_size*sizeof(uint32_t));
spin_unlock(&ls->ls_recover_spin); spin_unlock(&ls->ls_recover_spin);
memset(lvb_bits, 0, sizeof(lvb_bits)); memset(ls->ls_lvb_bits, 0, GDLM_LVB_SIZE);
control_lvb_write(ls, start_gen, lvb_bits); control_lvb_write(ls, start_gen, ls->ls_lvb_bits);
error = mounted_lock(sdp, DLM_LOCK_PR, DLM_LKF_CONVERT); error = mounted_lock(sdp, DLM_LOCK_PR, DLM_LKF_CONVERT);
if (error) if (error)
@ -1022,6 +1019,12 @@ static int set_recover_size(struct gfs2_sbd *sdp, struct dlm_slot *slots,
uint32_t old_size, new_size; uint32_t old_size, new_size;
int i, max_jid; int i, max_jid;
if (!ls->ls_lvb_bits) {
ls->ls_lvb_bits = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
if (!ls->ls_lvb_bits)
return -ENOMEM;
}
max_jid = 0; max_jid = 0;
for (i = 0; i < num_slots; i++) { for (i = 0; i < num_slots; i++) {
if (max_jid < slots[i].slot - 1) if (max_jid < slots[i].slot - 1)
@ -1057,6 +1060,7 @@ static int set_recover_size(struct gfs2_sbd *sdp, struct dlm_slot *slots,
static void free_recover_size(struct lm_lockstruct *ls) static void free_recover_size(struct lm_lockstruct *ls)
{ {
kfree(ls->ls_lvb_bits);
kfree(ls->ls_recover_submit); kfree(ls->ls_recover_submit);
kfree(ls->ls_recover_result); kfree(ls->ls_recover_result);
ls->ls_recover_submit = NULL; ls->ls_recover_submit = NULL;
@ -1205,6 +1209,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
ls->ls_recover_size = 0; ls->ls_recover_size = 0;
ls->ls_recover_submit = NULL; ls->ls_recover_submit = NULL;
ls->ls_recover_result = NULL; ls->ls_recover_result = NULL;
ls->ls_lvb_bits = NULL;
error = set_recover_size(sdp, NULL, 0); error = set_recover_size(sdp, NULL, 0);
if (error) if (error)