int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data, void **ret_data) { int ret; unsigned int locklen; struct dlm_ctxt *dlm = data; struct dlm_lock_resource *res = NULL; struct dlm_lock *lock = NULL; struct dlm_proxy_ast *past = (struct dlm_proxy_ast *) msg->buf; char *name; struct list_head *head = NULL; __be64 cookie; u32 flags; u8 node; if (!dlm_grab(dlm)) { dlm_error(DLM_REJECTED); return DLM_REJECTED; } mlog_bug_on_msg(!dlm_domain_fully_joined(dlm), "Domain %s not fully joined!\n", dlm->name); name = past->name; locklen = past->namelen; cookie = past->cookie; flags = be32_to_cpu(past->flags); node = past->node_idx; if (locklen > DLM_LOCKID_NAME_MAX) { ret = DLM_IVBUFLEN; mlog(ML_ERROR, "Invalid name length (%d) in proxy ast " "handler!\n", locklen); goto leave; } if ((flags & (LKM_PUT_LVB|LKM_GET_LVB)) == (LKM_PUT_LVB|LKM_GET_LVB)) { mlog(ML_ERROR, "Both PUT and GET lvb specified, (0x%x)\n", flags); ret = DLM_BADARGS; goto leave; } mlog(0, "lvb: %s\n", flags & LKM_PUT_LVB ? "put lvb" : (flags & LKM_GET_LVB ? "get lvb" : "none")); mlog(0, "type=%d, blocked_type=%d\n", past->type, past->blocked_type); if (past->type != DLM_AST && past->type != DLM_BAST) { mlog(ML_ERROR, "Unknown ast type! %d, cookie=%u:%llu" "name=%.*s, node=%u\n", past->type, dlm_get_lock_cookie_node(be64_to_cpu(cookie)), dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), locklen, name, node); ret = DLM_IVLOCKID; goto leave; } res = dlm_lookup_lockres(dlm, name, locklen); if (!res) { mlog(0, "Got %sast for unknown lockres! cookie=%u:%llu, " "name=%.*s, node=%u\n", (past->type == DLM_AST ? "" : "b"), dlm_get_lock_cookie_node(be64_to_cpu(cookie)), dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), locklen, name, node); ret = DLM_IVLOCKID; goto leave; } /* cannot get a proxy ast message if this node owns it */ BUG_ON(res->owner == dlm->node_num); mlog(0, "%s: res %.*s\n", dlm->name, res->lockname.len, res->lockname.name); spin_lock(&res->spinlock); if (res->state & DLM_LOCK_RES_RECOVERING) { mlog(0, "Responding with DLM_RECOVERING!\n"); ret = DLM_RECOVERING; goto unlock_out; } if (res->state & DLM_LOCK_RES_MIGRATING) { mlog(0, "Responding with DLM_MIGRATING!\n"); ret = DLM_MIGRATING; goto unlock_out; } /* try convert queue for both ast/bast */ head = &res->converting; lock = NULL; list_for_each_entry(lock, head, list) { if (lock->ml.cookie == cookie) goto do_ast; } /* if not on convert, try blocked for ast, granted for bast */ if (past->type == DLM_AST) head = &res->blocked; else head = &res->granted; list_for_each_entry(lock, head, list) { if (lock->ml.cookie == cookie) goto do_ast; } mlog(0, "Got %sast for unknown lock! cookie=%u:%llu, name=%.*s, " "node=%u\n", past->type == DLM_AST ? "" : "b", dlm_get_lock_cookie_node(be64_to_cpu(cookie)), dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), locklen, name, node); ret = DLM_NORMAL; unlock_out: spin_unlock(&res->spinlock); goto leave; do_ast: ret = DLM_NORMAL; if (past->type == DLM_AST) { /* do not alter lock refcount. switching lists. */ list_move_tail(&lock->list, &res->granted); mlog(0, "%s: res %.*s, lock %u:%llu, Granted type %d => %d\n", dlm->name, res->lockname.len, res->lockname.name, dlm_get_lock_cookie_node(be64_to_cpu(cookie)), dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), lock->ml.type, lock->ml.convert_type); if (lock->ml.convert_type != LKM_IVMODE) { lock->ml.type = lock->ml.convert_type; lock->ml.convert_type = LKM_IVMODE; } else { // should already be there.... } lock->lksb->status = DLM_NORMAL; /* if we requested the lvb, fetch it into our lksb now */ if (flags & LKM_GET_LVB) { BUG_ON(!(lock->lksb->flags & DLM_LKSB_GET_LVB)); memcpy(lock->lksb->lvb, past->lvb, DLM_LVB_LEN); } } spin_unlock(&res->spinlock); if (past->type == DLM_AST) dlm_do_local_ast(dlm, res, lock); else dlm_do_local_bast(dlm, res, lock, past->blocked_type); leave: if (res) dlm_lockres_put(res); dlm_put(dlm); return ret; }
int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data, void **ret_data) { int ret; unsigned int locklen; struct dlm_ctxt *dlm = data; struct dlm_lock_resource *res = NULL; struct dlm_lock *lock = NULL; struct dlm_proxy_ast *past = (struct dlm_proxy_ast *) msg->buf; char *name; struct list_head *iter, *head=NULL; u64 cookie; u32 flags; u8 node; if (!dlm_grab(dlm)) { dlm_error(DLM_REJECTED); return DLM_REJECTED; } mlog_bug_on_msg(!dlm_domain_fully_joined(dlm), "Domain %s not fully joined!\n", dlm->name); name = past->name; locklen = past->namelen; cookie = past->cookie; flags = be32_to_cpu(past->flags); node = past->node_idx; if (locklen > DLM_LOCKID_NAME_MAX) { ret = DLM_IVBUFLEN; mlog(ML_ERROR, "Invalid name length (%d) in proxy ast " "handler!\n", locklen); goto leave; } if ((flags & (LKM_PUT_LVB|LKM_GET_LVB)) == (LKM_PUT_LVB|LKM_GET_LVB)) { mlog(ML_ERROR, "Both PUT and GET lvb specified, (0x%x)\n", flags); ret = DLM_BADARGS; goto leave; } mlog(0, "lvb: %s\n", flags & LKM_PUT_LVB ? "put lvb" : (flags & LKM_GET_LVB ? "get lvb" : "none")); mlog(0, "type=%d, blocked_type=%d\n", past->type, past->blocked_type); if (past->type != DLM_AST && past->type != DLM_BAST) { mlog(ML_ERROR, "Unknown ast type! %d, cookie=%u:%llu" "name=%.*s, node=%u\n", past->type, dlm_get_lock_cookie_node(be64_to_cpu(cookie)), dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), locklen, name, node); ret = DLM_IVLOCKID; goto leave; } res = dlm_lookup_lockres(dlm, name, locklen); if (!res) { mlog(0, "Got %sast for unknown lockres! cookie=%u:%llu, " "name=%.*s, node=%u\n", (past->type == DLM_AST ? "" : "b"), dlm_get_lock_cookie_node(be64_to_cpu(cookie)), dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), locklen, name, node); ret = DLM_IVLOCKID; goto leave; } /* cannot get a proxy ast message if this node owns it */ BUG_ON(res->owner == dlm->node_num); mlog(0, "lockres %.*s\n", res->lockname.len, res->lockname.name); spin_lock(&res->spinlock); if (res->state & DLM_LOCK_RES_RECOVERING) { mlog(0, "Responding with DLM_RECOVERING!\n"); ret = DLM_RECOVERING; goto unlock_out; } if (res->state & DLM_LOCK_RES_MIGRATING) { mlog(0, "Responding with DLM_MIGRATING!\n"); ret = DLM_MIGRATING; goto unlock_out; } /* try convert queue for both ast/bast */ head = &res->converting; lock = NULL; list_for_each(iter, head) { lock = list_entry (iter, struct dlm_lock, list); if (lock->ml.cookie == cookie) goto do_ast; }
/* * locking: * caller needs: none * taken: takes and drops res->spinlock * held on exit: none * returns: DLM_NORMAL, DLM_BADARGS, DLM_IVLOCKID, * return value from dlmunlock_master */ int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data, void **ret_data) { struct dlm_ctxt *dlm = data; struct dlm_unlock_lock *unlock = (struct dlm_unlock_lock *)msg->buf; struct dlm_lock_resource *res = NULL; struct list_head *iter; struct dlm_lock *lock = NULL; enum dlm_status status = DLM_NORMAL; int found = 0, i; struct dlm_lockstatus *lksb = NULL; int ignore; u32 flags; struct list_head *queue; flags = be32_to_cpu(unlock->flags); if (flags & LKM_GET_LVB) { mlog(ML_ERROR, "bad args! GET_LVB specified on unlock!\n"); return DLM_BADARGS; } if ((flags & (LKM_PUT_LVB|LKM_CANCEL)) == (LKM_PUT_LVB|LKM_CANCEL)) { mlog(ML_ERROR, "bad args! cannot modify lvb on a CANCEL " "request!\n"); return DLM_BADARGS; } if (unlock->namelen > DLM_LOCKID_NAME_MAX) { mlog(ML_ERROR, "Invalid name length in unlock handler!\n"); return DLM_IVBUFLEN; } if (!dlm_grab(dlm)) return DLM_REJECTED; mlog_bug_on_msg(!dlm_domain_fully_joined(dlm), "Domain %s not fully joined!\n", dlm->name); mlog(0, "lvb: %s\n", flags & LKM_PUT_LVB ? "put lvb" : "none"); res = dlm_lookup_lockres(dlm, unlock->name, unlock->namelen); if (!res) { /* We assume here that a no lock resource simply means * it was migrated away and destroyed before the other * node could detect it. */ mlog(0, "returning DLM_FORWARD -- res no longer exists\n"); status = DLM_FORWARD; goto not_found; } queue=&res->granted; found = 0; spin_lock(&res->spinlock); if (res->state & DLM_LOCK_RES_RECOVERING) { spin_unlock(&res->spinlock); mlog(0, "returning DLM_RECOVERING\n"); status = DLM_RECOVERING; goto leave; } if (res->state & DLM_LOCK_RES_MIGRATING) { spin_unlock(&res->spinlock); mlog(0, "returning DLM_MIGRATING\n"); status = DLM_MIGRATING; goto leave; } if (res->owner != dlm->node_num) { spin_unlock(&res->spinlock); mlog(0, "returning DLM_FORWARD -- not master\n"); status = DLM_FORWARD; goto leave; } for (i=0; i<3; i++) { list_for_each(iter, queue) { lock = list_entry(iter, struct dlm_lock, list); if (lock->ml.cookie == unlock->cookie && lock->ml.node == unlock->node_idx) { dlm_lock_get(lock); found = 1; break; } } if (found) break; /* scan granted -> converting -> blocked queues */ queue++; }