trans_logger: disallow KEEP_UNIQUE data buffer modification after IO has started

This commit is contained in:
Thomas Schoebel-Theuer 2013-01-01 12:35:33 +01:00
parent 8601114229
commit df950fe505
2 changed files with 29 additions and 6 deletions

View File

@ -244,7 +244,7 @@ int hash_fn(loff_t pos)
}
static inline
struct trans_logger_mref_aspect *_hash_find(struct list_head *start, loff_t pos, int *max_len, struct timespec *elder, bool use_collect_head)
struct trans_logger_mref_aspect *_hash_find(struct list_head *start, loff_t pos, int *max_len, struct timespec *elder, bool use_collect_head, bool find_unstable)
{
struct list_head *tmp;
struct trans_logger_mref_aspect *res = NULL;
@ -289,6 +289,10 @@ struct trans_logger_mref_aspect *_hash_find(struct list_head *start, loff_t pos,
continue; // not relevant
}
// searching for unstable elements (only in special cases)
if (find_unstable && test_a->is_stable)
break;
diff = test->ref_pos - pos;
if (diff <= 0) {
int restlen = test->ref_len + diff;
@ -308,7 +312,7 @@ struct trans_logger_mref_aspect *_hash_find(struct list_head *start, loff_t pos,
}
static noinline
struct trans_logger_mref_aspect *hash_find(struct trans_logger_brick *brick, loff_t pos, int *max_len)
struct trans_logger_mref_aspect *hash_find(struct trans_logger_brick *brick, loff_t pos, int *max_len, bool find_unstable)
{
int hash = hash_fn(pos);
@ -320,7 +324,7 @@ struct trans_logger_mref_aspect *hash_find(struct trans_logger_brick *brick, lof
down_read(&start->hash_mutex);
res = _hash_find(&start->hash_anchor, pos, max_len, NULL, false);
res = _hash_find(&start->hash_anchor, pos, max_len, NULL, false, find_unstable);
/* Ensure the found mref can't go away...
*/
@ -513,6 +517,22 @@ err:
}
}
static inline
void hash_ensure_stableness(struct trans_logger_brick *brick, struct trans_logger_mref_aspect *mref_a)
{
if (!mref_a->is_stable) {
struct mref_object *mref = mref_a->object;
int hash = hash_fn(mref->ref_pos);
struct hash_anchor *start = &brick->hash_table[hash];
down_write(&start->hash_mutex);
mref_a->is_stable = true;
up_write(&start->hash_mutex);
}
}
static
void _inf_callback(struct trans_logger_input *input, bool force)
{
@ -621,7 +641,7 @@ int _read_ref_get(struct trans_logger_output *output, struct trans_logger_mref_a
* the old one.
* When a shadow is found, use it as buffer for the mref.
*/
mshadow_a = hash_find(brick, mref->ref_pos, &mref->ref_len);
mshadow_a = hash_find(brick, mref->ref_pos, &mref->ref_len, false);
if (!mshadow_a) {
return GENERIC_INPUT_CALL(input, mref_get, mref);
}
@ -647,7 +667,7 @@ int _write_ref_get(struct trans_logger_output *output, struct trans_logger_mref_
#endif
#ifdef KEEP_UNIQUE
mshadow_a = hash_find(brick, mref->ref_pos, &mref->ref_len);
mshadow_a = hash_find(brick, mref->ref_pos, &mref->ref_len, true);
if (mshadow_a) {
return _make_sshadow(output, mref_a, mshadow_a);
}
@ -1214,7 +1234,7 @@ struct writeback_info *make_writeback(struct trans_logger_brick *brick, loff_t p
atomic_inc(&brick->total_hash_find_count);
orig_mref_a = _hash_find(&wb->w_collect_list, pos, &this_len, elder, true);
orig_mref_a = _hash_find(&wb->w_collect_list, pos, &this_len, elder, true, false);
if (unlikely(!orig_mref_a)) {
MARS_FAT("could not find data\n");
goto err;
@ -1488,6 +1508,8 @@ bool phase0_startio(struct trans_logger_mref_aspect *orig_mref_a)
goto err;
}
hash_ensure_stableness(brick, orig_mref_a);
memcpy(data, orig_mref_a->shadow_data, orig_mref->ref_len);
ok = log_finalize(logst, orig_mref->ref_len, phase0_preio, phase0_endio, orig_mref_a);

View File

@ -123,6 +123,7 @@ struct trans_logger_mref_aspect {
bool do_dealloc;
bool do_buffered;
bool is_hashed;
bool is_stable;
bool is_dirty;
bool is_collected;
bool is_fired;