Commit 27d0e5bc authored by Jeff Mahoney's avatar Jeff Mahoney Committed by Jan Kara

reiserfs: fix corruption introduced by balance_leaf refactor

Commits f1f007c3 (reiserfs: balance_leaf refactor, pull out
balance_leaf_insert_left) and cf22df18 (reiserfs: balance_leaf
refactor, pull out balance_leaf_paste_left) missed that the `body'
pointer was getting repositioned. Subsequent users of the pointer
would expect it to be repositioned, and as a result, parts of the
tree would get overwritten. The most common observed corruption
is indirect block pointers being overwritten.

Since the body value isn't actually used anymore in the called routines,
we can pass back the offset it should be shifted. We constify the body
and ih pointers in the balance_leaf as a mostly-free preventative measure.

Cc: <stable@vger.kernel.org> # 3.16
Reported-and-tested-by: default avatarJeff Chua <jeff.chua.linux@gmail.com>
Signed-off-by: default avatarJeff Mahoney <jeffm@suse.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 3f1be4f9
...@@ -286,12 +286,14 @@ static int balance_leaf_when_delete(struct tree_balance *tb, int flag) ...@@ -286,12 +286,14 @@ static int balance_leaf_when_delete(struct tree_balance *tb, int flag)
return 0; return 0;
} }
static void balance_leaf_insert_left(struct tree_balance *tb, static unsigned int balance_leaf_insert_left(struct tree_balance *tb,
struct item_head *ih, const char *body) struct item_head *const ih,
const char * const body)
{ {
int ret; int ret;
struct buffer_info bi; struct buffer_info bi;
int n = B_NR_ITEMS(tb->L[0]); int n = B_NR_ITEMS(tb->L[0]);
unsigned body_shift_bytes = 0;
if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
/* part of new item falls into L[0] */ /* part of new item falls into L[0] */
...@@ -329,7 +331,7 @@ static void balance_leaf_insert_left(struct tree_balance *tb, ...@@ -329,7 +331,7 @@ static void balance_leaf_insert_left(struct tree_balance *tb,
put_ih_item_len(ih, new_item_len); put_ih_item_len(ih, new_item_len);
if (tb->lbytes > tb->zeroes_num) { if (tb->lbytes > tb->zeroes_num) {
body += (tb->lbytes - tb->zeroes_num); body_shift_bytes = tb->lbytes - tb->zeroes_num;
tb->zeroes_num = 0; tb->zeroes_num = 0;
} else } else
tb->zeroes_num -= tb->lbytes; tb->zeroes_num -= tb->lbytes;
...@@ -349,11 +351,12 @@ static void balance_leaf_insert_left(struct tree_balance *tb, ...@@ -349,11 +351,12 @@ static void balance_leaf_insert_left(struct tree_balance *tb,
tb->insert_size[0] = 0; tb->insert_size[0] = 0;
tb->zeroes_num = 0; tb->zeroes_num = 0;
} }
return body_shift_bytes;
} }
static void balance_leaf_paste_left_shift_dirent(struct tree_balance *tb, static void balance_leaf_paste_left_shift_dirent(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body) const char * const body)
{ {
int n = B_NR_ITEMS(tb->L[0]); int n = B_NR_ITEMS(tb->L[0]);
struct buffer_info bi; struct buffer_info bi;
...@@ -413,17 +416,18 @@ static void balance_leaf_paste_left_shift_dirent(struct tree_balance *tb, ...@@ -413,17 +416,18 @@ static void balance_leaf_paste_left_shift_dirent(struct tree_balance *tb,
tb->pos_in_item -= tb->lbytes; tb->pos_in_item -= tb->lbytes;
} }
static void balance_leaf_paste_left_shift(struct tree_balance *tb, static unsigned int balance_leaf_paste_left_shift(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body) const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
int n = B_NR_ITEMS(tb->L[0]); int n = B_NR_ITEMS(tb->L[0]);
struct buffer_info bi; struct buffer_info bi;
int body_shift_bytes = 0;
if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) { if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) {
balance_leaf_paste_left_shift_dirent(tb, ih, body); balance_leaf_paste_left_shift_dirent(tb, ih, body);
return; return 0;
} }
RFALSE(tb->lbytes <= 0, RFALSE(tb->lbytes <= 0,
...@@ -497,7 +501,7 @@ static void balance_leaf_paste_left_shift(struct tree_balance *tb, ...@@ -497,7 +501,7 @@ static void balance_leaf_paste_left_shift(struct tree_balance *tb,
* insert_size[0] * insert_size[0]
*/ */
if (l_n > tb->zeroes_num) { if (l_n > tb->zeroes_num) {
body += (l_n - tb->zeroes_num); body_shift_bytes = l_n - tb->zeroes_num;
tb->zeroes_num = 0; tb->zeroes_num = 0;
} else } else
tb->zeroes_num -= l_n; tb->zeroes_num -= l_n;
...@@ -526,13 +530,14 @@ static void balance_leaf_paste_left_shift(struct tree_balance *tb, ...@@ -526,13 +530,14 @@ static void balance_leaf_paste_left_shift(struct tree_balance *tb,
*/ */
leaf_shift_left(tb, tb->lnum[0], tb->lbytes); leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
} }
return body_shift_bytes;
} }
/* appended item will be in L[0] in whole */ /* appended item will be in L[0] in whole */
static void balance_leaf_paste_left_whole(struct tree_balance *tb, static void balance_leaf_paste_left_whole(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body) const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
int n = B_NR_ITEMS(tb->L[0]); int n = B_NR_ITEMS(tb->L[0]);
...@@ -584,39 +589,44 @@ static void balance_leaf_paste_left_whole(struct tree_balance *tb, ...@@ -584,39 +589,44 @@ static void balance_leaf_paste_left_whole(struct tree_balance *tb,
tb->zeroes_num = 0; tb->zeroes_num = 0;
} }
static void balance_leaf_paste_left(struct tree_balance *tb, static unsigned int balance_leaf_paste_left(struct tree_balance *tb,
struct item_head *ih, const char *body) struct item_head * const ih,
const char * const body)
{ {
/* we must shift the part of the appended item */ /* we must shift the part of the appended item */
if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1)
balance_leaf_paste_left_shift(tb, ih, body); return balance_leaf_paste_left_shift(tb, ih, body);
else else
balance_leaf_paste_left_whole(tb, ih, body); balance_leaf_paste_left_whole(tb, ih, body);
return 0;
} }
/* Shift lnum[0] items from S[0] to the left neighbor L[0] */ /* Shift lnum[0] items from S[0] to the left neighbor L[0] */
static void balance_leaf_left(struct tree_balance *tb, struct item_head *ih, static unsigned int balance_leaf_left(struct tree_balance *tb,
const char *body, int flag) struct item_head * const ih,
const char * const body, int flag)
{ {
if (tb->lnum[0] <= 0) if (tb->lnum[0] <= 0)
return; return 0;
/* new item or it part falls to L[0], shift it too */ /* new item or it part falls to L[0], shift it too */
if (tb->item_pos < tb->lnum[0]) { if (tb->item_pos < tb->lnum[0]) {
BUG_ON(flag != M_INSERT && flag != M_PASTE); BUG_ON(flag != M_INSERT && flag != M_PASTE);
if (flag == M_INSERT) if (flag == M_INSERT)
balance_leaf_insert_left(tb, ih, body); return balance_leaf_insert_left(tb, ih, body);
else /* M_PASTE */ else /* M_PASTE */
balance_leaf_paste_left(tb, ih, body); return balance_leaf_paste_left(tb, ih, body);
} else } else
/* new item doesn't fall into L[0] */ /* new item doesn't fall into L[0] */
leaf_shift_left(tb, tb->lnum[0], tb->lbytes); leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
return 0;
} }
static void balance_leaf_insert_right(struct tree_balance *tb, static void balance_leaf_insert_right(struct tree_balance *tb,
struct item_head *ih, const char *body) struct item_head * const ih,
const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
...@@ -704,7 +714,8 @@ static void balance_leaf_insert_right(struct tree_balance *tb, ...@@ -704,7 +714,8 @@ static void balance_leaf_insert_right(struct tree_balance *tb,
static void balance_leaf_paste_right_shift_dirent(struct tree_balance *tb, static void balance_leaf_paste_right_shift_dirent(struct tree_balance *tb,
struct item_head *ih, const char *body) struct item_head * const ih,
const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
struct buffer_info bi; struct buffer_info bi;
...@@ -754,7 +765,8 @@ static void balance_leaf_paste_right_shift_dirent(struct tree_balance *tb, ...@@ -754,7 +765,8 @@ static void balance_leaf_paste_right_shift_dirent(struct tree_balance *tb,
} }
static void balance_leaf_paste_right_shift(struct tree_balance *tb, static void balance_leaf_paste_right_shift(struct tree_balance *tb,
struct item_head *ih, const char *body) struct item_head * const ih,
const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
int n_shift, n_rem, r_zeroes_number, version; int n_shift, n_rem, r_zeroes_number, version;
...@@ -831,7 +843,8 @@ static void balance_leaf_paste_right_shift(struct tree_balance *tb, ...@@ -831,7 +843,8 @@ static void balance_leaf_paste_right_shift(struct tree_balance *tb,
} }
static void balance_leaf_paste_right_whole(struct tree_balance *tb, static void balance_leaf_paste_right_whole(struct tree_balance *tb,
struct item_head *ih, const char *body) struct item_head * const ih,
const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
int n = B_NR_ITEMS(tbS0); int n = B_NR_ITEMS(tbS0);
...@@ -874,7 +887,8 @@ static void balance_leaf_paste_right_whole(struct tree_balance *tb, ...@@ -874,7 +887,8 @@ static void balance_leaf_paste_right_whole(struct tree_balance *tb,
} }
static void balance_leaf_paste_right(struct tree_balance *tb, static void balance_leaf_paste_right(struct tree_balance *tb,
struct item_head *ih, const char *body) struct item_head * const ih,
const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
int n = B_NR_ITEMS(tbS0); int n = B_NR_ITEMS(tbS0);
...@@ -896,8 +910,9 @@ static void balance_leaf_paste_right(struct tree_balance *tb, ...@@ -896,8 +910,9 @@ static void balance_leaf_paste_right(struct tree_balance *tb,
} }
/* shift rnum[0] items from S[0] to the right neighbor R[0] */ /* shift rnum[0] items from S[0] to the right neighbor R[0] */
static void balance_leaf_right(struct tree_balance *tb, struct item_head *ih, static void balance_leaf_right(struct tree_balance *tb,
const char *body, int flag) struct item_head * const ih,
const char * const body, int flag)
{ {
if (tb->rnum[0] <= 0) if (tb->rnum[0] <= 0)
return; return;
...@@ -911,8 +926,8 @@ static void balance_leaf_right(struct tree_balance *tb, struct item_head *ih, ...@@ -911,8 +926,8 @@ static void balance_leaf_right(struct tree_balance *tb, struct item_head *ih,
} }
static void balance_leaf_new_nodes_insert(struct tree_balance *tb, static void balance_leaf_new_nodes_insert(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body, const char * const body,
struct item_head *insert_key, struct item_head *insert_key,
struct buffer_head **insert_ptr, struct buffer_head **insert_ptr,
int i) int i)
...@@ -1003,8 +1018,8 @@ static void balance_leaf_new_nodes_insert(struct tree_balance *tb, ...@@ -1003,8 +1018,8 @@ static void balance_leaf_new_nodes_insert(struct tree_balance *tb,
/* we append to directory item */ /* we append to directory item */
static void balance_leaf_new_nodes_paste_dirent(struct tree_balance *tb, static void balance_leaf_new_nodes_paste_dirent(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body, const char * const body,
struct item_head *insert_key, struct item_head *insert_key,
struct buffer_head **insert_ptr, struct buffer_head **insert_ptr,
int i) int i)
...@@ -1058,8 +1073,8 @@ static void balance_leaf_new_nodes_paste_dirent(struct tree_balance *tb, ...@@ -1058,8 +1073,8 @@ static void balance_leaf_new_nodes_paste_dirent(struct tree_balance *tb,
} }
static void balance_leaf_new_nodes_paste_shift(struct tree_balance *tb, static void balance_leaf_new_nodes_paste_shift(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body, const char * const body,
struct item_head *insert_key, struct item_head *insert_key,
struct buffer_head **insert_ptr, struct buffer_head **insert_ptr,
int i) int i)
...@@ -1131,8 +1146,8 @@ static void balance_leaf_new_nodes_paste_shift(struct tree_balance *tb, ...@@ -1131,8 +1146,8 @@ static void balance_leaf_new_nodes_paste_shift(struct tree_balance *tb,
} }
static void balance_leaf_new_nodes_paste_whole(struct tree_balance *tb, static void balance_leaf_new_nodes_paste_whole(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body, const char * const body,
struct item_head *insert_key, struct item_head *insert_key,
struct buffer_head **insert_ptr, struct buffer_head **insert_ptr,
int i) int i)
...@@ -1184,8 +1199,8 @@ static void balance_leaf_new_nodes_paste_whole(struct tree_balance *tb, ...@@ -1184,8 +1199,8 @@ static void balance_leaf_new_nodes_paste_whole(struct tree_balance *tb,
} }
static void balance_leaf_new_nodes_paste(struct tree_balance *tb, static void balance_leaf_new_nodes_paste(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body, const char * const body,
struct item_head *insert_key, struct item_head *insert_key,
struct buffer_head **insert_ptr, struct buffer_head **insert_ptr,
int i) int i)
...@@ -1214,8 +1229,8 @@ static void balance_leaf_new_nodes_paste(struct tree_balance *tb, ...@@ -1214,8 +1229,8 @@ static void balance_leaf_new_nodes_paste(struct tree_balance *tb,
/* Fill new nodes that appear in place of S[0] */ /* Fill new nodes that appear in place of S[0] */
static void balance_leaf_new_nodes(struct tree_balance *tb, static void balance_leaf_new_nodes(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body, const char * const body,
struct item_head *insert_key, struct item_head *insert_key,
struct buffer_head **insert_ptr, struct buffer_head **insert_ptr,
int flag) int flag)
...@@ -1254,8 +1269,8 @@ static void balance_leaf_new_nodes(struct tree_balance *tb, ...@@ -1254,8 +1269,8 @@ static void balance_leaf_new_nodes(struct tree_balance *tb,
} }
static void balance_leaf_finish_node_insert(struct tree_balance *tb, static void balance_leaf_finish_node_insert(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body) const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
struct buffer_info bi; struct buffer_info bi;
...@@ -1271,8 +1286,8 @@ static void balance_leaf_finish_node_insert(struct tree_balance *tb, ...@@ -1271,8 +1286,8 @@ static void balance_leaf_finish_node_insert(struct tree_balance *tb,
} }
static void balance_leaf_finish_node_paste_dirent(struct tree_balance *tb, static void balance_leaf_finish_node_paste_dirent(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body) const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
struct item_head *pasted = item_head(tbS0, tb->item_pos); struct item_head *pasted = item_head(tbS0, tb->item_pos);
...@@ -1305,8 +1320,8 @@ static void balance_leaf_finish_node_paste_dirent(struct tree_balance *tb, ...@@ -1305,8 +1320,8 @@ static void balance_leaf_finish_node_paste_dirent(struct tree_balance *tb,
} }
static void balance_leaf_finish_node_paste(struct tree_balance *tb, static void balance_leaf_finish_node_paste(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body) const char * const body)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
struct buffer_info bi; struct buffer_info bi;
...@@ -1349,8 +1364,8 @@ static void balance_leaf_finish_node_paste(struct tree_balance *tb, ...@@ -1349,8 +1364,8 @@ static void balance_leaf_finish_node_paste(struct tree_balance *tb,
* of the affected item which remains in S * of the affected item which remains in S
*/ */
static void balance_leaf_finish_node(struct tree_balance *tb, static void balance_leaf_finish_node(struct tree_balance *tb,
struct item_head *ih, struct item_head * const ih,
const char *body, int flag) const char * const body, int flag)
{ {
/* if we must insert or append into buffer S[0] */ /* if we must insert or append into buffer S[0] */
if (0 <= tb->item_pos && tb->item_pos < tb->s0num) { if (0 <= tb->item_pos && tb->item_pos < tb->s0num) {
...@@ -1402,7 +1417,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, ...@@ -1402,7 +1417,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,
&& is_indirect_le_ih(item_head(tbS0, tb->item_pos))) && is_indirect_le_ih(item_head(tbS0, tb->item_pos)))
tb->pos_in_item *= UNFM_P_SIZE; tb->pos_in_item *= UNFM_P_SIZE;
balance_leaf_left(tb, ih, body, flag); body += balance_leaf_left(tb, ih, body, flag);
/* tb->lnum[0] > 0 */ /* tb->lnum[0] > 0 */
/* Calculate new item position */ /* Calculate new item position */
......
...@@ -899,8 +899,9 @@ void leaf_delete_items(struct buffer_info *cur_bi, int last_first, ...@@ -899,8 +899,9 @@ void leaf_delete_items(struct buffer_info *cur_bi, int last_first,
/* insert item into the leaf node in position before */ /* insert item into the leaf node in position before */
void leaf_insert_into_buf(struct buffer_info *bi, int before, void leaf_insert_into_buf(struct buffer_info *bi, int before,
struct item_head *inserted_item_ih, struct item_head * const inserted_item_ih,
const char *inserted_item_body, int zeros_number) const char * const inserted_item_body,
int zeros_number)
{ {
struct buffer_head *bh = bi->bi_bh; struct buffer_head *bh = bi->bi_bh;
int nr, free_space; int nr, free_space;
......
...@@ -3216,11 +3216,12 @@ int leaf_shift_right(struct tree_balance *tb, int shift_num, int shift_bytes); ...@@ -3216,11 +3216,12 @@ int leaf_shift_right(struct tree_balance *tb, int shift_num, int shift_bytes);
void leaf_delete_items(struct buffer_info *cur_bi, int last_first, int first, void leaf_delete_items(struct buffer_info *cur_bi, int last_first, int first,
int del_num, int del_bytes); int del_num, int del_bytes);
void leaf_insert_into_buf(struct buffer_info *bi, int before, void leaf_insert_into_buf(struct buffer_info *bi, int before,
struct item_head *inserted_item_ih, struct item_head * const inserted_item_ih,
const char *inserted_item_body, int zeros_number); const char * const inserted_item_body,
void leaf_paste_in_buffer(struct buffer_info *bi, int pasted_item_num,
int pos_in_item, int paste_size, const char *body,
int zeros_number); int zeros_number);
void leaf_paste_in_buffer(struct buffer_info *bi, int pasted_item_num,
int pos_in_item, int paste_size,
const char * const body, int zeros_number);
void leaf_cut_from_buffer(struct buffer_info *bi, int cut_item_num, void leaf_cut_from_buffer(struct buffer_info *bi, int cut_item_num,
int pos_in_item, int cut_size); int pos_in_item, int cut_size);
void leaf_paste_entries(struct buffer_info *bi, int item_num, int before, void leaf_paste_entries(struct buffer_info *bi, int item_num, int before,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment