dlm: keep cached master rsbs during recovery
To prevent the master of an rsb from changing rapidly, an unused rsb is kept on the "toss list" for a period of time to be reused. The toss list was being cleared completely for each recovery, which is unnecessary. Much of the benefit of the toss list can be maintained if nodes keep rsb's in their toss list that they are the master of. These rsb's need to be included when the resource directory is rebuilt during recovery. Signed-off-by: David Teigland <teigland@redhat.com>
This commit is contained in:
Родитель
594199ebaa
Коммит
85f0379aa0
66
fs/dlm/dir.c
66
fs/dlm/dir.c
|
@ -329,49 +329,47 @@ int dlm_dir_lookup(struct dlm_ls *ls, int nodeid, char *name, int namelen,
|
|||
return get_entry(ls, nodeid, name, namelen, r_nodeid);
|
||||
}
|
||||
|
||||
/* Copy the names of master rsb's into the buffer provided.
|
||||
Only select names whose dir node is the given nodeid. */
|
||||
static struct dlm_rsb *find_rsb_root(struct dlm_ls *ls, char *name, int len)
|
||||
{
|
||||
struct dlm_rsb *r;
|
||||
|
||||
down_read(&ls->ls_root_sem);
|
||||
list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
|
||||
if (len == r->res_length && !memcmp(name, r->res_name, len)) {
|
||||
up_read(&ls->ls_root_sem);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
up_read(&ls->ls_root_sem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find the rsb where we left off (or start again), then send rsb names
|
||||
for rsb's we're master of and whose directory node matches the requesting
|
||||
node. inbuf is the rsb name last sent, inlen is the name's length */
|
||||
|
||||
void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen,
|
||||
char *outbuf, int outlen, int nodeid)
|
||||
{
|
||||
struct list_head *list;
|
||||
struct dlm_rsb *start_r = NULL, *r = NULL;
|
||||
int offset = 0, start_namelen, error, dir_nodeid;
|
||||
char *start_name;
|
||||
struct dlm_rsb *r;
|
||||
int offset = 0, dir_nodeid;
|
||||
uint16_t be_namelen;
|
||||
|
||||
/*
|
||||
* Find the rsb where we left off (or start again)
|
||||
*/
|
||||
|
||||
start_namelen = inlen;
|
||||
start_name = inbuf;
|
||||
|
||||
if (start_namelen > 1) {
|
||||
/*
|
||||
* We could also use a find_rsb_root() function here that
|
||||
* searched the ls_root_list.
|
||||
*/
|
||||
error = dlm_find_rsb(ls, start_name, start_namelen, R_MASTER,
|
||||
&start_r);
|
||||
DLM_ASSERT(!error && start_r,
|
||||
printk("error %d\n", error););
|
||||
DLM_ASSERT(!list_empty(&start_r->res_root_list),
|
||||
dlm_print_rsb(start_r););
|
||||
dlm_put_rsb(start_r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send rsb names for rsb's we're master of and whose directory node
|
||||
* matches the requesting node.
|
||||
*/
|
||||
|
||||
down_read(&ls->ls_root_sem);
|
||||
if (start_r)
|
||||
list = start_r->res_root_list.next;
|
||||
else
|
||||
|
||||
if (inlen > 1) {
|
||||
r = find_rsb_root(ls, inbuf, inlen);
|
||||
if (!r) {
|
||||
inbuf[inlen - 1] = '\0';
|
||||
log_error(ls, "copy_master_names from %d start %d %s",
|
||||
nodeid, inlen, inbuf);
|
||||
goto out;
|
||||
}
|
||||
list = r->res_root_list.next;
|
||||
} else {
|
||||
list = ls->ls_root_list.next;
|
||||
}
|
||||
|
||||
for (offset = 0; list != &ls->ls_root_list; list = list->next) {
|
||||
r = list_entry(list, struct dlm_rsb, res_root_list);
|
||||
|
|
|
@ -489,12 +489,6 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
|
|||
return error;
|
||||
}
|
||||
|
||||
int dlm_find_rsb(struct dlm_ls *ls, char *name, int namelen,
|
||||
unsigned int flags, struct dlm_rsb **r_ret)
|
||||
{
|
||||
return find_rsb(ls, name, namelen, flags, r_ret);
|
||||
}
|
||||
|
||||
/* This is only called to add a reference when the code already holds
|
||||
a valid reference to the rsb, so there's no need for locking. */
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ void dlm_print_lkb(struct dlm_lkb *lkb);
|
|||
void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms);
|
||||
void dlm_receive_buffer(struct dlm_header *hd, int nodeid);
|
||||
int dlm_modes_compat(int mode1, int mode2);
|
||||
int dlm_find_rsb(struct dlm_ls *ls, char *name, int namelen,
|
||||
unsigned int flags, struct dlm_rsb **r_ret);
|
||||
void dlm_put_rsb(struct dlm_rsb *r);
|
||||
void dlm_hold_rsb(struct dlm_rsb *r);
|
||||
int dlm_put_lkb(struct dlm_lkb *lkb);
|
||||
|
|
|
@ -731,6 +731,20 @@ int dlm_create_root_list(struct dlm_ls *ls)
|
|||
list_add(&r->res_root_list, &ls->ls_root_list);
|
||||
dlm_hold_rsb(r);
|
||||
}
|
||||
|
||||
/* If we're using a directory, add tossed rsbs to the root
|
||||
list; they'll have entries created in the new directory,
|
||||
but no other recovery steps should do anything with them. */
|
||||
|
||||
if (dlm_no_directory(ls)) {
|
||||
read_unlock(&ls->ls_rsbtbl[i].lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
list_for_each_entry(r, &ls->ls_rsbtbl[i].toss, res_hashchain) {
|
||||
list_add(&r->res_root_list, &ls->ls_root_list);
|
||||
dlm_hold_rsb(r);
|
||||
}
|
||||
read_unlock(&ls->ls_rsbtbl[i].lock);
|
||||
}
|
||||
out:
|
||||
|
@ -750,6 +764,11 @@ void dlm_release_root_list(struct dlm_ls *ls)
|
|||
up_write(&ls->ls_root_sem);
|
||||
}
|
||||
|
||||
/* If not using a directory, clear the entire toss list, there's no benefit to
|
||||
caching the master value since it's fixed. If we are using a dir, keep the
|
||||
rsb's we're the master of. Recovery will add them to the root list and from
|
||||
there they'll be entered in the rebuilt directory. */
|
||||
|
||||
void dlm_clear_toss_list(struct dlm_ls *ls)
|
||||
{
|
||||
struct dlm_rsb *r, *safe;
|
||||
|
@ -759,8 +778,10 @@ void dlm_clear_toss_list(struct dlm_ls *ls)
|
|||
write_lock(&ls->ls_rsbtbl[i].lock);
|
||||
list_for_each_entry_safe(r, safe, &ls->ls_rsbtbl[i].toss,
|
||||
res_hashchain) {
|
||||
list_del(&r->res_hashchain);
|
||||
dlm_free_rsb(r);
|
||||
if (dlm_no_directory(ls) || !is_master(r)) {
|
||||
list_del(&r->res_hashchain);
|
||||
dlm_free_rsb(r);
|
||||
}
|
||||
}
|
||||
write_unlock(&ls->ls_rsbtbl[i].lock);
|
||||
}
|
||||
|
|
|
@ -66,6 +66,13 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
|
|||
dlm_astd_suspend();
|
||||
dlm_astd_resume();
|
||||
|
||||
/*
|
||||
* Free non-master tossed rsb's. Master rsb's are kept on toss
|
||||
* list and put on root list to be included in resdir recovery.
|
||||
*/
|
||||
|
||||
dlm_clear_toss_list(ls);
|
||||
|
||||
/*
|
||||
* This list of root rsb's will be the basis of most of the recovery
|
||||
* routines.
|
||||
|
@ -73,12 +80,6 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
|
|||
|
||||
dlm_create_root_list(ls);
|
||||
|
||||
/*
|
||||
* Free all the tossed rsb's so we don't have to recover them.
|
||||
*/
|
||||
|
||||
dlm_clear_toss_list(ls);
|
||||
|
||||
/*
|
||||
* Add or remove nodes from the lockspace's ls_nodes list.
|
||||
* Also waits for all nodes to complete dlm_recover_members.
|
||||
|
|
Загрузка…
Ссылка в новой задаче