📄 lockspace.c
字号:
/***************************************************************************************************************************************************************** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.**** This copyrighted material is made available to anyone wishing to use,** modify, copy, or redistribute it subject to the terms and conditions** of the GNU General Public License v.2.***************************************************************************************************************************************************************/#include "dlm_internal.h"#include "lockspace.h"#include "member.h"#include "recoverd.h"#include "ast.h"#include "dir.h"#include "lowcomms.h"#include "config.h"#include "memory.h"#include "lock.h"#include "recover.h"#include "requestqueue.h"#ifdef CONFIG_DLM_DEBUGint dlm_create_debug_file(struct dlm_ls *ls);void dlm_delete_debug_file(struct dlm_ls *ls);#elsestatic inline int dlm_create_debug_file(struct dlm_ls *ls) { return 0; }static inline void dlm_delete_debug_file(struct dlm_ls *ls) { }#endifstatic int ls_count;static struct mutex ls_lock;static struct list_head lslist;static spinlock_t lslist_lock;static struct task_struct * scand_task;static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len){ ssize_t ret = len; int n = simple_strtol(buf, NULL, 0); ls = dlm_find_lockspace_local(ls->ls_local_handle); if (!ls) return -EINVAL; switch (n) { case 0: dlm_ls_stop(ls); break; case 1: dlm_ls_start(ls); break; default: ret = -EINVAL; } dlm_put_lockspace(ls); return ret;}static ssize_t dlm_event_store(struct dlm_ls *ls, const char *buf, size_t len){ ls->ls_uevent_result = simple_strtol(buf, NULL, 0); set_bit(LSFL_UEVENT_WAIT, &ls->ls_flags); wake_up(&ls->ls_uevent_wait); return len;}static ssize_t dlm_id_show(struct dlm_ls *ls, char *buf){ return snprintf(buf, PAGE_SIZE, "%u\n", ls->ls_global_id);}static ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len){ ls->ls_global_id = simple_strtoul(buf, NULL, 0); return len;}static ssize_t dlm_recover_status_show(struct dlm_ls *ls, char *buf){ uint32_t status = dlm_recover_status(ls); return snprintf(buf, PAGE_SIZE, "%x\n", status);}static ssize_t dlm_recover_nodeid_show(struct dlm_ls *ls, char *buf){ return snprintf(buf, PAGE_SIZE, "%d\n", ls->ls_recover_nodeid);}struct dlm_attr { struct attribute attr; ssize_t (*show)(struct dlm_ls *, char *); ssize_t (*store)(struct dlm_ls *, const char *, size_t);};static struct dlm_attr dlm_attr_control = { .attr = {.name = "control", .mode = S_IWUSR}, .store = dlm_control_store};static struct dlm_attr dlm_attr_event = { .attr = {.name = "event_done", .mode = S_IWUSR}, .store = dlm_event_store};static struct dlm_attr dlm_attr_id = { .attr = {.name = "id", .mode = S_IRUGO | S_IWUSR}, .show = dlm_id_show, .store = dlm_id_store};static struct dlm_attr dlm_attr_recover_status = { .attr = {.name = "recover_status", .mode = S_IRUGO}, .show = dlm_recover_status_show};static struct dlm_attr dlm_attr_recover_nodeid = { .attr = {.name = "recover_nodeid", .mode = S_IRUGO}, .show = dlm_recover_nodeid_show};static struct attribute *dlm_attrs[] = { &dlm_attr_control.attr, &dlm_attr_event.attr, &dlm_attr_id.attr, &dlm_attr_recover_status.attr, &dlm_attr_recover_nodeid.attr, NULL,};static ssize_t dlm_attr_show(struct kobject *kobj, struct attribute *attr, char *buf){ struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj); struct dlm_attr *a = container_of(attr, struct dlm_attr, attr); return a->show ? a->show(ls, buf) : 0;}static ssize_t dlm_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len){ struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj); struct dlm_attr *a = container_of(attr, struct dlm_attr, attr); return a->store ? a->store(ls, buf, len) : len;}static void lockspace_kobj_release(struct kobject *k){ struct dlm_ls *ls = container_of(k, struct dlm_ls, ls_kobj); kfree(ls);}static struct sysfs_ops dlm_attr_ops = { .show = dlm_attr_show, .store = dlm_attr_store,};static struct kobj_type dlm_ktype = { .default_attrs = dlm_attrs, .sysfs_ops = &dlm_attr_ops, .release = lockspace_kobj_release,};static struct kset dlm_kset = { .ktype = &dlm_ktype,};static int kobject_setup(struct dlm_ls *ls){ char lsname[DLM_LOCKSPACE_LEN]; int error; memset(lsname, 0, DLM_LOCKSPACE_LEN); snprintf(lsname, DLM_LOCKSPACE_LEN, "%s", ls->ls_name); error = kobject_set_name(&ls->ls_kobj, "%s", lsname); if (error) return error; ls->ls_kobj.kset = &dlm_kset; ls->ls_kobj.ktype = &dlm_ktype; return 0;}static int do_uevent(struct dlm_ls *ls, int in){ int error; if (in) kobject_uevent(&ls->ls_kobj, KOBJ_ONLINE); else kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE); log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving"); /* dlm_controld will see the uevent, do the necessary group management and then write to sysfs to wake us */ error = wait_event_interruptible(ls->ls_uevent_wait, test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags)); log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result); if (error) goto out; error = ls->ls_uevent_result; out: if (error) log_error(ls, "group %s failed %d %d", in ? "join" : "leave", error, ls->ls_uevent_result); return error;}int dlm_lockspace_init(void){ int error; ls_count = 0; mutex_init(&ls_lock); INIT_LIST_HEAD(&lslist); spin_lock_init(&lslist_lock); kobject_set_name(&dlm_kset.kobj, "dlm"); kobj_set_kset_s(&dlm_kset, kernel_subsys); error = kset_register(&dlm_kset); if (error) printk("dlm_lockspace_init: cannot register kset %d\n", error); return error;}void dlm_lockspace_exit(void){ kset_unregister(&dlm_kset);}static int dlm_scand(void *data){ struct dlm_ls *ls; while (!kthread_should_stop()) { list_for_each_entry(ls, &lslist, ls_list) { if (dlm_lock_recovery_try(ls)) { dlm_scan_rsbs(ls); dlm_scan_timeout(ls); dlm_unlock_recovery(ls); } } schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ); } return 0;}static int dlm_scand_start(void){ struct task_struct *p; int error = 0; p = kthread_run(dlm_scand, NULL, "dlm_scand"); if (IS_ERR(p)) error = PTR_ERR(p); else scand_task = p; return error;}static void dlm_scand_stop(void){ kthread_stop(scand_task);}static struct dlm_ls *dlm_find_lockspace_name(char *name, int namelen){ struct dlm_ls *ls; spin_lock(&lslist_lock); list_for_each_entry(ls, &lslist, ls_list) { if (ls->ls_namelen == namelen && memcmp(ls->ls_name, name, namelen) == 0) goto out; } ls = NULL; out: spin_unlock(&lslist_lock); return ls;}struct dlm_ls *dlm_find_lockspace_global(uint32_t id){ struct dlm_ls *ls; spin_lock(&lslist_lock); list_for_each_entry(ls, &lslist, ls_list) { if (ls->ls_global_id == id) { ls->ls_count++; goto out; } } ls = NULL; out: spin_unlock(&lslist_lock); return ls;}struct dlm_ls *dlm_find_lockspace_local(dlm_lockspace_t *lockspace){ struct dlm_ls *ls; spin_lock(&lslist_lock); list_for_each_entry(ls, &lslist, ls_list) { if (ls->ls_local_handle == lockspace) { ls->ls_count++; goto out; } } ls = NULL; out: spin_unlock(&lslist_lock); return ls;}struct dlm_ls *dlm_find_lockspace_device(int minor){ struct dlm_ls *ls; spin_lock(&lslist_lock); list_for_each_entry(ls, &lslist, ls_list) { if (ls->ls_device.minor == minor) { ls->ls_count++; goto out; } } ls = NULL; out: spin_unlock(&lslist_lock); return ls;}void dlm_put_lockspace(struct dlm_ls *ls){ spin_lock(&lslist_lock); ls->ls_count--; spin_unlock(&lslist_lock);}static void remove_lockspace(struct dlm_ls *ls){ for (;;) { spin_lock(&lslist_lock); if (ls->ls_count == 0) { list_del(&ls->ls_list); spin_unlock(&lslist_lock); return; } spin_unlock(&lslist_lock); ssleep(1); }}static int threads_start(void){ int error; /* Thread which process lock requests for all lockspace's */ error = dlm_astd_start(); if (error) { log_print("cannot start dlm_astd thread %d", error); goto fail; } error = dlm_scand_start(); if (error) { log_print("cannot start dlm_scand thread %d", error); goto astd_fail; } /* Thread for sending/receiving messages for all lockspace's */ error = dlm_lowcomms_start(); if (error) { log_print("cannot start dlm lowcomms %d", error); goto scand_fail; } return 0; scand_fail: dlm_scand_stop(); astd_fail:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -