aboutsummaryrefslogtreecommitdiff
path: root/fs/dlm/dir.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-31 09:29:31 +1100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-31 09:29:31 +1100
commitf389e9fcecdec4c4cb890ad28ea30a87a579ec3e (patch)
treea26a94886ca384da320bb972fed56fcaf7722512 /fs/dlm/dir.c
parent2419505acc479d2f1feed94d195b0554a64269a4 (diff)
parent0fe410d3f3b1496190f37ef74cd089229cef97fa (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm: (21 commits) dlm: static initialization improvements dlm: clean ups dlm: Sanity check namelen before copying it dlm: keep cached master rsbs during recovery dlm: change error message to debug dlm: fix possible use-after-free dlm: limit dir lookup loop dlm: reject normal unlock when lock is waiting for lookup dlm: validate messages before processing dlm: reject messages from non-members dlm: another call to confirm_master in receive_request_reply dlm: recover locks waiting for overlap replies dlm: clear ast_type when removing from astqueue dlm: use fixed errno values in messages dlm: swap bytes for rcom lock reply dlm: align midcomms message buffer dlm: close othercons dlm: use dlm prefix on alloc and free functions dlm: don't print common non-errors dlm: proper prototypes ...
Diffstat (limited to 'fs/dlm/dir.c')
-rw-r--r--fs/dlm/dir.c76
1 files changed, 37 insertions, 39 deletions
diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c
index 46754553fdc..ff97ba92433 100644
--- a/fs/dlm/dir.c
+++ b/fs/dlm/dir.c
@@ -49,7 +49,7 @@ static struct dlm_direntry *get_free_de(struct dlm_ls *ls, int len)
spin_unlock(&ls->ls_recover_list_lock);
if (!found)
- de = allocate_direntry(ls, len);
+ de = kzalloc(sizeof(struct dlm_direntry) + len, GFP_KERNEL);
return de;
}
@@ -62,7 +62,7 @@ void dlm_clear_free_entries(struct dlm_ls *ls)
de = list_entry(ls->ls_recover_list.next, struct dlm_direntry,
list);
list_del(&de->list);
- free_direntry(de);
+ kfree(de);
}
spin_unlock(&ls->ls_recover_list_lock);
}
@@ -171,7 +171,7 @@ void dlm_dir_remove_entry(struct dlm_ls *ls, int nodeid, char *name, int namelen
}
list_del(&de->list);
- free_direntry(de);
+ kfree(de);
out:
write_unlock(&ls->ls_dirtbl[bucket].lock);
}
@@ -302,7 +302,7 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name,
write_unlock(&ls->ls_dirtbl[bucket].lock);
- de = allocate_direntry(ls, namelen);
+ de = kzalloc(sizeof(struct dlm_direntry) + namelen, GFP_KERNEL);
if (!de)
return -ENOMEM;
@@ -313,7 +313,7 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name,
write_lock(&ls->ls_dirtbl[bucket].lock);
tmp = search_bucket(ls, name, namelen, bucket);
if (tmp) {
- free_direntry(de);
+ kfree(de);
de = tmp;
} else {
list_add_tail(&de->list, &ls->ls_dirtbl[bucket].list);
@@ -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);