summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/fs/dlm
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/fs/dlm')
-rw-r--r--ANDROID_3.4.5/fs/dlm/Kconfig16
-rw-r--r--ANDROID_3.4.5/fs/dlm/Makefile21
-rw-r--r--ANDROID_3.4.5/fs/dlm/ast.c315
-rw-r--r--ANDROID_3.4.5/fs/dlm/ast.h32
-rw-r--r--ANDROID_3.4.5/fs/dlm/config.c1081
-rw-r--r--ANDROID_3.4.5/fs/dlm/config.h56
-rw-r--r--ANDROID_3.4.5/fs/dlm/debug_fs.c726
-rw-r--r--ANDROID_3.4.5/fs/dlm/dir.c457
-rw-r--r--ANDROID_3.4.5/fs/dlm/dir.h30
-rw-r--r--ANDROID_3.4.5/fs/dlm/dlm_internal.h661
-rw-r--r--ANDROID_3.4.5/fs/dlm/lock.c5197
-rw-r--r--ANDROID_3.4.5/fs/dlm/lock.h73
-rw-r--r--ANDROID_3.4.5/fs/dlm/lockspace.c872
-rw-r--r--ANDROID_3.4.5/fs/dlm/lockspace.h26
-rw-r--r--ANDROID_3.4.5/fs/dlm/lowcomms.c1567
-rw-r--r--ANDROID_3.4.5/fs/dlm/lowcomms.h25
-rw-r--r--ANDROID_3.4.5/fs/dlm/lvb_table.h18
-rw-r--r--ANDROID_3.4.5/fs/dlm/main.c95
-rw-r--r--ANDROID_3.4.5/fs/dlm/member.c720
-rw-r--r--ANDROID_3.4.5/fs/dlm/member.h33
-rw-r--r--ANDROID_3.4.5/fs/dlm/memory.c98
-rw-r--r--ANDROID_3.4.5/fs/dlm/memory.h27
-rw-r--r--ANDROID_3.4.5/fs/dlm/midcomms.c137
-rw-r--r--ANDROID_3.4.5/fs/dlm/midcomms.h21
-rw-r--r--ANDROID_3.4.5/fs/dlm/netlink.c139
-rw-r--r--ANDROID_3.4.5/fs/dlm/plock.c503
-rw-r--r--ANDROID_3.4.5/fs/dlm/rcom.c576
-rw-r--r--ANDROID_3.4.5/fs/dlm/rcom.h25
-rw-r--r--ANDROID_3.4.5/fs/dlm/recover.c840
-rw-r--r--ANDROID_3.4.5/fs/dlm/recover.h34
-rw-r--r--ANDROID_3.4.5/fs/dlm/recoverd.c326
-rw-r--r--ANDROID_3.4.5/fs/dlm/recoverd.h24
-rw-r--r--ANDROID_3.4.5/fs/dlm/requestqueue.c188
-rw-r--r--ANDROID_3.4.5/fs/dlm/requestqueue.h22
-rw-r--r--ANDROID_3.4.5/fs/dlm/user.c1012
-rw-r--r--ANDROID_3.4.5/fs/dlm/user.h19
-rw-r--r--ANDROID_3.4.5/fs/dlm/util.c154
-rw-r--r--ANDROID_3.4.5/fs/dlm/util.h22
38 files changed, 0 insertions, 16188 deletions
diff --git a/ANDROID_3.4.5/fs/dlm/Kconfig b/ANDROID_3.4.5/fs/dlm/Kconfig
deleted file mode 100644
index 1897eb1b..00000000
--- a/ANDROID_3.4.5/fs/dlm/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-menuconfig DLM
- tristate "Distributed Lock Manager (DLM)"
- depends on EXPERIMENTAL && INET
- depends on SYSFS && CONFIGFS_FS && (IPV6 || IPV6=n)
- select IP_SCTP
- help
- A general purpose distributed lock manager for kernel or userspace
- applications.
-
-config DLM_DEBUG
- bool "DLM debugging"
- depends on DLM
- help
- Under the debugfs mount point, the name of each lockspace will
- appear as a file in the "dlm" directory. The output is the
- list of resource and locks the local node knows about.
diff --git a/ANDROID_3.4.5/fs/dlm/Makefile b/ANDROID_3.4.5/fs/dlm/Makefile
deleted file mode 100644
index ca1c9124..00000000
--- a/ANDROID_3.4.5/fs/dlm/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-obj-$(CONFIG_DLM) += dlm.o
-dlm-y := ast.o \
- config.o \
- dir.o \
- lock.o \
- lockspace.o \
- main.o \
- member.o \
- memory.o \
- midcomms.o \
- netlink.o \
- lowcomms.o \
- plock.o \
- rcom.o \
- recover.o \
- recoverd.o \
- requestqueue.o \
- user.o \
- util.o
-dlm-$(CONFIG_DLM_DEBUG) += debug_fs.o
-
diff --git a/ANDROID_3.4.5/fs/dlm/ast.c b/ANDROID_3.4.5/fs/dlm/ast.c
deleted file mode 100644
index 90e59972..00000000
--- a/ANDROID_3.4.5/fs/dlm/ast.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2010 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 "lock.h"
-#include "user.h"
-
-static uint64_t dlm_cb_seq;
-static spinlock_t dlm_cb_seq_spin;
-
-static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb)
-{
- int i;
-
- log_print("last_bast %x %llu flags %x mode %d sb %d %x",
- lkb->lkb_id,
- (unsigned long long)lkb->lkb_last_bast.seq,
- lkb->lkb_last_bast.flags,
- lkb->lkb_last_bast.mode,
- lkb->lkb_last_bast.sb_status,
- lkb->lkb_last_bast.sb_flags);
-
- log_print("last_cast %x %llu flags %x mode %d sb %d %x",
- lkb->lkb_id,
- (unsigned long long)lkb->lkb_last_cast.seq,
- lkb->lkb_last_cast.flags,
- lkb->lkb_last_cast.mode,
- lkb->lkb_last_cast.sb_status,
- lkb->lkb_last_cast.sb_flags);
-
- for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
- log_print("cb %x %llu flags %x mode %d sb %d %x",
- lkb->lkb_id,
- (unsigned long long)lkb->lkb_callbacks[i].seq,
- lkb->lkb_callbacks[i].flags,
- lkb->lkb_callbacks[i].mode,
- lkb->lkb_callbacks[i].sb_status,
- lkb->lkb_callbacks[i].sb_flags);
- }
-}
-
-int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
- int status, uint32_t sbflags, uint64_t seq)
-{
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
- uint64_t prev_seq;
- int prev_mode;
- int i, rv;
-
- for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
- if (lkb->lkb_callbacks[i].seq)
- continue;
-
- /*
- * Suppress some redundant basts here, do more on removal.
- * Don't even add a bast if the callback just before it
- * is a bast for the same mode or a more restrictive mode.
- * (the addional > PR check is needed for PR/CW inversion)
- */
-
- if ((i > 0) && (flags & DLM_CB_BAST) &&
- (lkb->lkb_callbacks[i-1].flags & DLM_CB_BAST)) {
-
- prev_seq = lkb->lkb_callbacks[i-1].seq;
- prev_mode = lkb->lkb_callbacks[i-1].mode;
-
- if ((prev_mode == mode) ||
- (prev_mode > mode && prev_mode > DLM_LOCK_PR)) {
-
- log_debug(ls, "skip %x add bast %llu mode %d "
- "for bast %llu mode %d",
- lkb->lkb_id,
- (unsigned long long)seq,
- mode,
- (unsigned long long)prev_seq,
- prev_mode);
- rv = 0;
- goto out;
- }
- }
-
- lkb->lkb_callbacks[i].seq = seq;
- lkb->lkb_callbacks[i].flags = flags;
- lkb->lkb_callbacks[i].mode = mode;
- lkb->lkb_callbacks[i].sb_status = status;
- lkb->lkb_callbacks[i].sb_flags = (sbflags & 0x000000FF);
- rv = 0;
- break;
- }
-
- if (i == DLM_CALLBACKS_SIZE) {
- log_error(ls, "no callbacks %x %llu flags %x mode %d sb %d %x",
- lkb->lkb_id, (unsigned long long)seq,
- flags, mode, status, sbflags);
- dlm_dump_lkb_callbacks(lkb);
- rv = -1;
- goto out;
- }
- out:
- return rv;
-}
-
-int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_callback *cb, int *resid)
-{
- int i, rv;
-
- *resid = 0;
-
- if (!lkb->lkb_callbacks[0].seq) {
- rv = -ENOENT;
- goto out;
- }
-
- /* oldest undelivered cb is callbacks[0] */
-
- memcpy(cb, &lkb->lkb_callbacks[0], sizeof(struct dlm_callback));
- memset(&lkb->lkb_callbacks[0], 0, sizeof(struct dlm_callback));
-
- /* shift others down */
-
- for (i = 1; i < DLM_CALLBACKS_SIZE; i++) {
- if (!lkb->lkb_callbacks[i].seq)
- break;
- memcpy(&lkb->lkb_callbacks[i-1], &lkb->lkb_callbacks[i],
- sizeof(struct dlm_callback));
- memset(&lkb->lkb_callbacks[i], 0, sizeof(struct dlm_callback));
- (*resid)++;
- }
-
- /* if cb is a bast, it should be skipped if the blocking mode is
- compatible with the last granted mode */
-
- if ((cb->flags & DLM_CB_BAST) && lkb->lkb_last_cast.seq) {
- if (dlm_modes_compat(cb->mode, lkb->lkb_last_cast.mode)) {
- cb->flags |= DLM_CB_SKIP;
-
- log_debug(ls, "skip %x bast %llu mode %d "
- "for cast %llu mode %d",
- lkb->lkb_id,
- (unsigned long long)cb->seq,
- cb->mode,
- (unsigned long long)lkb->lkb_last_cast.seq,
- lkb->lkb_last_cast.mode);
- rv = 0;
- goto out;
- }
- }
-
- if (cb->flags & DLM_CB_CAST) {
- memcpy(&lkb->lkb_last_cast, cb, sizeof(struct dlm_callback));
- lkb->lkb_last_cast_time = ktime_get();
- }
-
- if (cb->flags & DLM_CB_BAST) {
- memcpy(&lkb->lkb_last_bast, cb, sizeof(struct dlm_callback));
- lkb->lkb_last_bast_time = ktime_get();
- }
- rv = 0;
- out:
- return rv;
-}
-
-void dlm_add_cb(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
- uint32_t sbflags)
-{
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
- uint64_t new_seq, prev_seq;
- int rv;
-
- spin_lock(&dlm_cb_seq_spin);
- new_seq = ++dlm_cb_seq;
- spin_unlock(&dlm_cb_seq_spin);
-
- if (lkb->lkb_flags & DLM_IFL_USER) {
- dlm_user_add_ast(lkb, flags, mode, status, sbflags, new_seq);
- return;
- }
-
- mutex_lock(&lkb->lkb_cb_mutex);
- prev_seq = lkb->lkb_callbacks[0].seq;
-
- rv = dlm_add_lkb_callback(lkb, flags, mode, status, sbflags, new_seq);
- if (rv < 0)
- goto out;
-
- if (!prev_seq) {
- kref_get(&lkb->lkb_ref);
-
- if (test_bit(LSFL_CB_DELAY, &ls->ls_flags)) {
- mutex_lock(&ls->ls_cb_mutex);
- list_add(&lkb->lkb_cb_list, &ls->ls_cb_delay);
- mutex_unlock(&ls->ls_cb_mutex);
- } else {
- queue_work(ls->ls_callback_wq, &lkb->lkb_cb_work);
- }
- }
- out:
- mutex_unlock(&lkb->lkb_cb_mutex);
-}
-
-void dlm_callback_work(struct work_struct *work)
-{
- struct dlm_lkb *lkb = container_of(work, struct dlm_lkb, lkb_cb_work);
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
- void (*castfn) (void *astparam);
- void (*bastfn) (void *astparam, int mode);
- struct dlm_callback callbacks[DLM_CALLBACKS_SIZE];
- int i, rv, resid;
-
- memset(&callbacks, 0, sizeof(callbacks));
-
- mutex_lock(&lkb->lkb_cb_mutex);
- if (!lkb->lkb_callbacks[0].seq) {
- /* no callback work exists, shouldn't happen */
- log_error(ls, "dlm_callback_work %x no work", lkb->lkb_id);
- dlm_print_lkb(lkb);
- dlm_dump_lkb_callbacks(lkb);
- }
-
- for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
- rv = dlm_rem_lkb_callback(ls, lkb, &callbacks[i], &resid);
- if (rv < 0)
- break;
- }
-
- if (resid) {
- /* cbs remain, loop should have removed all, shouldn't happen */
- log_error(ls, "dlm_callback_work %x resid %d", lkb->lkb_id,
- resid);
- dlm_print_lkb(lkb);
- dlm_dump_lkb_callbacks(lkb);
- }
- mutex_unlock(&lkb->lkb_cb_mutex);
-
- castfn = lkb->lkb_astfn;
- bastfn = lkb->lkb_bastfn;
-
- for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
- if (!callbacks[i].seq)
- break;
- if (callbacks[i].flags & DLM_CB_SKIP) {
- continue;
- } else if (callbacks[i].flags & DLM_CB_BAST) {
- bastfn(lkb->lkb_astparam, callbacks[i].mode);
- } else if (callbacks[i].flags & DLM_CB_CAST) {
- lkb->lkb_lksb->sb_status = callbacks[i].sb_status;
- lkb->lkb_lksb->sb_flags = callbacks[i].sb_flags;
- castfn(lkb->lkb_astparam);
- }
- }
-
- /* undo kref_get from dlm_add_callback, may cause lkb to be freed */
- dlm_put_lkb(lkb);
-}
-
-int dlm_callback_start(struct dlm_ls *ls)
-{
- ls->ls_callback_wq = alloc_workqueue("dlm_callback",
- WQ_UNBOUND |
- WQ_MEM_RECLAIM |
- WQ_NON_REENTRANT,
- 0);
- if (!ls->ls_callback_wq) {
- log_print("can't start dlm_callback workqueue");
- return -ENOMEM;
- }
- return 0;
-}
-
-void dlm_callback_stop(struct dlm_ls *ls)
-{
- if (ls->ls_callback_wq)
- destroy_workqueue(ls->ls_callback_wq);
-}
-
-void dlm_callback_suspend(struct dlm_ls *ls)
-{
- set_bit(LSFL_CB_DELAY, &ls->ls_flags);
-
- if (ls->ls_callback_wq)
- flush_workqueue(ls->ls_callback_wq);
-}
-
-void dlm_callback_resume(struct dlm_ls *ls)
-{
- struct dlm_lkb *lkb, *safe;
- int count = 0;
-
- clear_bit(LSFL_CB_DELAY, &ls->ls_flags);
-
- if (!ls->ls_callback_wq)
- return;
-
- mutex_lock(&ls->ls_cb_mutex);
- list_for_each_entry_safe(lkb, safe, &ls->ls_cb_delay, lkb_cb_list) {
- list_del_init(&lkb->lkb_cb_list);
- queue_work(ls->ls_callback_wq, &lkb->lkb_cb_work);
- count++;
- }
- mutex_unlock(&ls->ls_cb_mutex);
-
- log_debug(ls, "dlm_callback_resume %d", count);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/ast.h b/ANDROID_3.4.5/fs/dlm/ast.h
deleted file mode 100644
index 757b551c..00000000
--- a/ANDROID_3.4.5/fs/dlm/ast.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005-2010 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __ASTD_DOT_H__
-#define __ASTD_DOT_H__
-
-void dlm_del_ast(struct dlm_lkb *lkb);
-int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
- int status, uint32_t sbflags, uint64_t seq);
-int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_callback *cb, int *resid);
-void dlm_add_cb(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
- uint32_t sbflags);
-
-void dlm_callback_work(struct work_struct *work);
-int dlm_callback_start(struct dlm_ls *ls);
-void dlm_callback_stop(struct dlm_ls *ls);
-void dlm_callback_suspend(struct dlm_ls *ls);
-void dlm_callback_resume(struct dlm_ls *ls);
-
-#endif
-
-
diff --git a/ANDROID_3.4.5/fs/dlm/config.c b/ANDROID_3.4.5/fs/dlm/config.c
deleted file mode 100644
index e7e327d4..00000000
--- a/ANDROID_3.4.5/fs/dlm/config.c
+++ /dev/null
@@ -1,1081 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2011 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 <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/configfs.h>
-#include <linux/slab.h>
-#include <linux/in.h>
-#include <linux/in6.h>
-#include <linux/dlmconstants.h>
-#include <net/ipv6.h>
-#include <net/sock.h>
-
-#include "config.h"
-#include "lowcomms.h"
-
-/*
- * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/nodeid
- * /config/dlm/<cluster>/spaces/<space>/nodes/<node>/weight
- * /config/dlm/<cluster>/comms/<comm>/nodeid
- * /config/dlm/<cluster>/comms/<comm>/local
- * /config/dlm/<cluster>/comms/<comm>/addr (write only)
- * /config/dlm/<cluster>/comms/<comm>/addr_list (read only)
- * The <cluster> level is useless, but I haven't figured out how to avoid it.
- */
-
-static struct config_group *space_list;
-static struct config_group *comm_list;
-static struct dlm_comm *local_comm;
-static uint32_t dlm_comm_count;
-
-struct dlm_clusters;
-struct dlm_cluster;
-struct dlm_spaces;
-struct dlm_space;
-struct dlm_comms;
-struct dlm_comm;
-struct dlm_nodes;
-struct dlm_node;
-
-static struct config_group *make_cluster(struct config_group *, const char *);
-static void drop_cluster(struct config_group *, struct config_item *);
-static void release_cluster(struct config_item *);
-static struct config_group *make_space(struct config_group *, const char *);
-static void drop_space(struct config_group *, struct config_item *);
-static void release_space(struct config_item *);
-static struct config_item *make_comm(struct config_group *, const char *);
-static void drop_comm(struct config_group *, struct config_item *);
-static void release_comm(struct config_item *);
-static struct config_item *make_node(struct config_group *, const char *);
-static void drop_node(struct config_group *, struct config_item *);
-static void release_node(struct config_item *);
-
-static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
- char *buf);
-static ssize_t store_cluster(struct config_item *i,
- struct configfs_attribute *a,
- const char *buf, size_t len);
-static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
- char *buf);
-static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
- const char *buf, size_t len);
-static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
- char *buf);
-static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
- const char *buf, size_t len);
-
-static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf);
-static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
- size_t len);
-static ssize_t comm_local_read(struct dlm_comm *cm, char *buf);
-static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
- size_t len);
-static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf,
- size_t len);
-static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf);
-static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf);
-static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
- size_t len);
-static ssize_t node_weight_read(struct dlm_node *nd, char *buf);
-static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
- size_t len);
-
-struct dlm_cluster {
- struct config_group group;
- unsigned int cl_tcp_port;
- unsigned int cl_buffer_size;
- unsigned int cl_rsbtbl_size;
- unsigned int cl_dirtbl_size;
- unsigned int cl_recover_timer;
- unsigned int cl_toss_secs;
- unsigned int cl_scan_secs;
- unsigned int cl_log_debug;
- unsigned int cl_protocol;
- unsigned int cl_timewarn_cs;
- unsigned int cl_waitwarn_us;
- unsigned int cl_new_rsb_count;
- unsigned int cl_recover_callbacks;
- char cl_cluster_name[DLM_LOCKSPACE_LEN];
-};
-
-enum {
- CLUSTER_ATTR_TCP_PORT = 0,
- CLUSTER_ATTR_BUFFER_SIZE,
- CLUSTER_ATTR_RSBTBL_SIZE,
- CLUSTER_ATTR_DIRTBL_SIZE,
- CLUSTER_ATTR_RECOVER_TIMER,
- CLUSTER_ATTR_TOSS_SECS,
- CLUSTER_ATTR_SCAN_SECS,
- CLUSTER_ATTR_LOG_DEBUG,
- CLUSTER_ATTR_PROTOCOL,
- CLUSTER_ATTR_TIMEWARN_CS,
- CLUSTER_ATTR_WAITWARN_US,
- CLUSTER_ATTR_NEW_RSB_COUNT,
- CLUSTER_ATTR_RECOVER_CALLBACKS,
- CLUSTER_ATTR_CLUSTER_NAME,
-};
-
-struct cluster_attribute {
- struct configfs_attribute attr;
- ssize_t (*show)(struct dlm_cluster *, char *);
- ssize_t (*store)(struct dlm_cluster *, const char *, size_t);
-};
-
-static ssize_t cluster_cluster_name_read(struct dlm_cluster *cl, char *buf)
-{
- return sprintf(buf, "%s\n", cl->cl_cluster_name);
-}
-
-static ssize_t cluster_cluster_name_write(struct dlm_cluster *cl,
- const char *buf, size_t len)
-{
- strncpy(dlm_config.ci_cluster_name, buf, DLM_LOCKSPACE_LEN);
- strncpy(cl->cl_cluster_name, buf, DLM_LOCKSPACE_LEN);
- return len;
-}
-
-static struct cluster_attribute cluster_attr_cluster_name = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "cluster_name",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = cluster_cluster_name_read,
- .store = cluster_cluster_name_write,
-};
-
-static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
- int *info_field, int check_zero,
- const char *buf, size_t len)
-{
- unsigned int x;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- x = simple_strtoul(buf, NULL, 0);
-
- if (check_zero && !x)
- return -EINVAL;
-
- *cl_field = x;
- *info_field = x;
-
- return len;
-}
-
-#define CLUSTER_ATTR(name, check_zero) \
-static ssize_t name##_write(struct dlm_cluster *cl, const char *buf, size_t len) \
-{ \
- return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name, \
- check_zero, buf, len); \
-} \
-static ssize_t name##_read(struct dlm_cluster *cl, char *buf) \
-{ \
- return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name); \
-} \
-static struct cluster_attribute cluster_attr_##name = \
-__CONFIGFS_ATTR(name, 0644, name##_read, name##_write)
-
-CLUSTER_ATTR(tcp_port, 1);
-CLUSTER_ATTR(buffer_size, 1);
-CLUSTER_ATTR(rsbtbl_size, 1);
-CLUSTER_ATTR(dirtbl_size, 1);
-CLUSTER_ATTR(recover_timer, 1);
-CLUSTER_ATTR(toss_secs, 1);
-CLUSTER_ATTR(scan_secs, 1);
-CLUSTER_ATTR(log_debug, 0);
-CLUSTER_ATTR(protocol, 0);
-CLUSTER_ATTR(timewarn_cs, 1);
-CLUSTER_ATTR(waitwarn_us, 0);
-CLUSTER_ATTR(new_rsb_count, 0);
-CLUSTER_ATTR(recover_callbacks, 0);
-
-static struct configfs_attribute *cluster_attrs[] = {
- [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
- [CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size.attr,
- [CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size.attr,
- [CLUSTER_ATTR_DIRTBL_SIZE] = &cluster_attr_dirtbl_size.attr,
- [CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer.attr,
- [CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs.attr,
- [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
- [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
- [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
- [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
- [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr,
- [CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr,
- [CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks.attr,
- [CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name.attr,
- NULL,
-};
-
-enum {
- COMM_ATTR_NODEID = 0,
- COMM_ATTR_LOCAL,
- COMM_ATTR_ADDR,
- COMM_ATTR_ADDR_LIST,
-};
-
-struct comm_attribute {
- struct configfs_attribute attr;
- ssize_t (*show)(struct dlm_comm *, char *);
- ssize_t (*store)(struct dlm_comm *, const char *, size_t);
-};
-
-static struct comm_attribute comm_attr_nodeid = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "nodeid",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = comm_nodeid_read,
- .store = comm_nodeid_write,
-};
-
-static struct comm_attribute comm_attr_local = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "local",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = comm_local_read,
- .store = comm_local_write,
-};
-
-static struct comm_attribute comm_attr_addr = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "addr",
- .ca_mode = S_IWUSR },
- .store = comm_addr_write,
-};
-
-static struct comm_attribute comm_attr_addr_list = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "addr_list",
- .ca_mode = S_IRUGO },
- .show = comm_addr_list_read,
-};
-
-static struct configfs_attribute *comm_attrs[] = {
- [COMM_ATTR_NODEID] = &comm_attr_nodeid.attr,
- [COMM_ATTR_LOCAL] = &comm_attr_local.attr,
- [COMM_ATTR_ADDR] = &comm_attr_addr.attr,
- [COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list.attr,
- NULL,
-};
-
-enum {
- NODE_ATTR_NODEID = 0,
- NODE_ATTR_WEIGHT,
-};
-
-struct node_attribute {
- struct configfs_attribute attr;
- ssize_t (*show)(struct dlm_node *, char *);
- ssize_t (*store)(struct dlm_node *, const char *, size_t);
-};
-
-static struct node_attribute node_attr_nodeid = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "nodeid",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = node_nodeid_read,
- .store = node_nodeid_write,
-};
-
-static struct node_attribute node_attr_weight = {
- .attr = { .ca_owner = THIS_MODULE,
- .ca_name = "weight",
- .ca_mode = S_IRUGO | S_IWUSR },
- .show = node_weight_read,
- .store = node_weight_write,
-};
-
-static struct configfs_attribute *node_attrs[] = {
- [NODE_ATTR_NODEID] = &node_attr_nodeid.attr,
- [NODE_ATTR_WEIGHT] = &node_attr_weight.attr,
- NULL,
-};
-
-struct dlm_clusters {
- struct configfs_subsystem subsys;
-};
-
-struct dlm_spaces {
- struct config_group ss_group;
-};
-
-struct dlm_space {
- struct config_group group;
- struct list_head members;
- struct mutex members_lock;
- int members_count;
-};
-
-struct dlm_comms {
- struct config_group cs_group;
-};
-
-struct dlm_comm {
- struct config_item item;
- int seq;
- int nodeid;
- int local;
- int addr_count;
- struct sockaddr_storage *addr[DLM_MAX_ADDR_COUNT];
-};
-
-struct dlm_nodes {
- struct config_group ns_group;
-};
-
-struct dlm_node {
- struct config_item item;
- struct list_head list; /* space->members */
- int nodeid;
- int weight;
- int new;
- int comm_seq; /* copy of cm->seq when nd->nodeid is set */
-};
-
-static struct configfs_group_operations clusters_ops = {
- .make_group = make_cluster,
- .drop_item = drop_cluster,
-};
-
-static struct configfs_item_operations cluster_ops = {
- .release = release_cluster,
- .show_attribute = show_cluster,
- .store_attribute = store_cluster,
-};
-
-static struct configfs_group_operations spaces_ops = {
- .make_group = make_space,
- .drop_item = drop_space,
-};
-
-static struct configfs_item_operations space_ops = {
- .release = release_space,
-};
-
-static struct configfs_group_operations comms_ops = {
- .make_item = make_comm,
- .drop_item = drop_comm,
-};
-
-static struct configfs_item_operations comm_ops = {
- .release = release_comm,
- .show_attribute = show_comm,
- .store_attribute = store_comm,
-};
-
-static struct configfs_group_operations nodes_ops = {
- .make_item = make_node,
- .drop_item = drop_node,
-};
-
-static struct configfs_item_operations node_ops = {
- .release = release_node,
- .show_attribute = show_node,
- .store_attribute = store_node,
-};
-
-static struct config_item_type clusters_type = {
- .ct_group_ops = &clusters_ops,
- .ct_owner = THIS_MODULE,
-};
-
-static struct config_item_type cluster_type = {
- .ct_item_ops = &cluster_ops,
- .ct_attrs = cluster_attrs,
- .ct_owner = THIS_MODULE,
-};
-
-static struct config_item_type spaces_type = {
- .ct_group_ops = &spaces_ops,
- .ct_owner = THIS_MODULE,
-};
-
-static struct config_item_type space_type = {
- .ct_item_ops = &space_ops,
- .ct_owner = THIS_MODULE,
-};
-
-static struct config_item_type comms_type = {
- .ct_group_ops = &comms_ops,
- .ct_owner = THIS_MODULE,
-};
-
-static struct config_item_type comm_type = {
- .ct_item_ops = &comm_ops,
- .ct_attrs = comm_attrs,
- .ct_owner = THIS_MODULE,
-};
-
-static struct config_item_type nodes_type = {
- .ct_group_ops = &nodes_ops,
- .ct_owner = THIS_MODULE,
-};
-
-static struct config_item_type node_type = {
- .ct_item_ops = &node_ops,
- .ct_attrs = node_attrs,
- .ct_owner = THIS_MODULE,
-};
-
-static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
-{
- return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
- NULL;
-}
-
-static struct dlm_space *config_item_to_space(struct config_item *i)
-{
- return i ? container_of(to_config_group(i), struct dlm_space, group) :
- NULL;
-}
-
-static struct dlm_comm *config_item_to_comm(struct config_item *i)
-{
- return i ? container_of(i, struct dlm_comm, item) : NULL;
-}
-
-static struct dlm_node *config_item_to_node(struct config_item *i)
-{
- return i ? container_of(i, struct dlm_node, item) : NULL;
-}
-
-static struct config_group *make_cluster(struct config_group *g,
- const char *name)
-{
- struct dlm_cluster *cl = NULL;
- struct dlm_spaces *sps = NULL;
- struct dlm_comms *cms = NULL;
- void *gps = NULL;
-
- cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS);
- gps = kcalloc(3, sizeof(struct config_group *), GFP_NOFS);
- sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS);
- cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS);
-
- if (!cl || !gps || !sps || !cms)
- goto fail;
-
- config_group_init_type_name(&cl->group, name, &cluster_type);
- config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type);
- config_group_init_type_name(&cms->cs_group, "comms", &comms_type);
-
- cl->group.default_groups = gps;
- cl->group.default_groups[0] = &sps->ss_group;
- cl->group.default_groups[1] = &cms->cs_group;
- cl->group.default_groups[2] = NULL;
-
- cl->cl_tcp_port = dlm_config.ci_tcp_port;
- cl->cl_buffer_size = dlm_config.ci_buffer_size;
- cl->cl_rsbtbl_size = dlm_config.ci_rsbtbl_size;
- cl->cl_dirtbl_size = dlm_config.ci_dirtbl_size;
- cl->cl_recover_timer = dlm_config.ci_recover_timer;
- cl->cl_toss_secs = dlm_config.ci_toss_secs;
- cl->cl_scan_secs = dlm_config.ci_scan_secs;
- cl->cl_log_debug = dlm_config.ci_log_debug;
- cl->cl_protocol = dlm_config.ci_protocol;
- cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
- cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us;
- cl->cl_new_rsb_count = dlm_config.ci_new_rsb_count;
- cl->cl_recover_callbacks = dlm_config.ci_recover_callbacks;
- memcpy(cl->cl_cluster_name, dlm_config.ci_cluster_name,
- DLM_LOCKSPACE_LEN);
-
- space_list = &sps->ss_group;
- comm_list = &cms->cs_group;
- return &cl->group;
-
- fail:
- kfree(cl);
- kfree(gps);
- kfree(sps);
- kfree(cms);
- return ERR_PTR(-ENOMEM);
-}
-
-static void drop_cluster(struct config_group *g, struct config_item *i)
-{
- struct dlm_cluster *cl = config_item_to_cluster(i);
- struct config_item *tmp;
- int j;
-
- for (j = 0; cl->group.default_groups[j]; j++) {
- tmp = &cl->group.default_groups[j]->cg_item;
- cl->group.default_groups[j] = NULL;
- config_item_put(tmp);
- }
-
- space_list = NULL;
- comm_list = NULL;
-
- config_item_put(i);
-}
-
-static void release_cluster(struct config_item *i)
-{
- struct dlm_cluster *cl = config_item_to_cluster(i);
- kfree(cl->group.default_groups);
- kfree(cl);
-}
-
-static struct config_group *make_space(struct config_group *g, const char *name)
-{
- struct dlm_space *sp = NULL;
- struct dlm_nodes *nds = NULL;
- void *gps = NULL;
-
- sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS);
- gps = kcalloc(2, sizeof(struct config_group *), GFP_NOFS);
- nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS);
-
- if (!sp || !gps || !nds)
- goto fail;
-
- config_group_init_type_name(&sp->group, name, &space_type);
- config_group_init_type_name(&nds->ns_group, "nodes", &nodes_type);
-
- sp->group.default_groups = gps;
- sp->group.default_groups[0] = &nds->ns_group;
- sp->group.default_groups[1] = NULL;
-
- INIT_LIST_HEAD(&sp->members);
- mutex_init(&sp->members_lock);
- sp->members_count = 0;
- return &sp->group;
-
- fail:
- kfree(sp);
- kfree(gps);
- kfree(nds);
- return ERR_PTR(-ENOMEM);
-}
-
-static void drop_space(struct config_group *g, struct config_item *i)
-{
- struct dlm_space *sp = config_item_to_space(i);
- struct config_item *tmp;
- int j;
-
- /* assert list_empty(&sp->members) */
-
- for (j = 0; sp->group.default_groups[j]; j++) {
- tmp = &sp->group.default_groups[j]->cg_item;
- sp->group.default_groups[j] = NULL;
- config_item_put(tmp);
- }
-
- config_item_put(i);
-}
-
-static void release_space(struct config_item *i)
-{
- struct dlm_space *sp = config_item_to_space(i);
- kfree(sp->group.default_groups);
- kfree(sp);
-}
-
-static struct config_item *make_comm(struct config_group *g, const char *name)
-{
- struct dlm_comm *cm;
-
- cm = kzalloc(sizeof(struct dlm_comm), GFP_NOFS);
- if (!cm)
- return ERR_PTR(-ENOMEM);
-
- config_item_init_type_name(&cm->item, name, &comm_type);
-
- cm->seq = dlm_comm_count++;
- if (!cm->seq)
- cm->seq = dlm_comm_count++;
-
- cm->nodeid = -1;
- cm->local = 0;
- cm->addr_count = 0;
- return &cm->item;
-}
-
-static void drop_comm(struct config_group *g, struct config_item *i)
-{
- struct dlm_comm *cm = config_item_to_comm(i);
- if (local_comm == cm)
- local_comm = NULL;
- dlm_lowcomms_close(cm->nodeid);
- while (cm->addr_count--)
- kfree(cm->addr[cm->addr_count]);
- config_item_put(i);
-}
-
-static void release_comm(struct config_item *i)
-{
- struct dlm_comm *cm = config_item_to_comm(i);
- kfree(cm);
-}
-
-static struct config_item *make_node(struct config_group *g, const char *name)
-{
- struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
- struct dlm_node *nd;
-
- nd = kzalloc(sizeof(struct dlm_node), GFP_NOFS);
- if (!nd)
- return ERR_PTR(-ENOMEM);
-
- config_item_init_type_name(&nd->item, name, &node_type);
- nd->nodeid = -1;
- nd->weight = 1; /* default weight of 1 if none is set */
- nd->new = 1; /* set to 0 once it's been read by dlm_nodeid_list() */
-
- mutex_lock(&sp->members_lock);
- list_add(&nd->list, &sp->members);
- sp->members_count++;
- mutex_unlock(&sp->members_lock);
-
- return &nd->item;
-}
-
-static void drop_node(struct config_group *g, struct config_item *i)
-{
- struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
- struct dlm_node *nd = config_item_to_node(i);
-
- mutex_lock(&sp->members_lock);
- list_del(&nd->list);
- sp->members_count--;
- mutex_unlock(&sp->members_lock);
-
- config_item_put(i);
-}
-
-static void release_node(struct config_item *i)
-{
- struct dlm_node *nd = config_item_to_node(i);
- kfree(nd);
-}
-
-static struct dlm_clusters clusters_root = {
- .subsys = {
- .su_group = {
- .cg_item = {
- .ci_namebuf = "dlm",
- .ci_type = &clusters_type,
- },
- },
- },
-};
-
-int __init dlm_config_init(void)
-{
- config_group_init(&clusters_root.subsys.su_group);
- mutex_init(&clusters_root.subsys.su_mutex);
- return configfs_register_subsystem(&clusters_root.subsys);
-}
-
-void dlm_config_exit(void)
-{
- configfs_unregister_subsystem(&clusters_root.subsys);
-}
-
-/*
- * Functions for user space to read/write attributes
- */
-
-static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
- char *buf)
-{
- struct dlm_cluster *cl = config_item_to_cluster(i);
- struct cluster_attribute *cla =
- container_of(a, struct cluster_attribute, attr);
- return cla->show ? cla->show(cl, buf) : 0;
-}
-
-static ssize_t store_cluster(struct config_item *i,
- struct configfs_attribute *a,
- const char *buf, size_t len)
-{
- struct dlm_cluster *cl = config_item_to_cluster(i);
- struct cluster_attribute *cla =
- container_of(a, struct cluster_attribute, attr);
- return cla->store ? cla->store(cl, buf, len) : -EINVAL;
-}
-
-static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
- char *buf)
-{
- struct dlm_comm *cm = config_item_to_comm(i);
- struct comm_attribute *cma =
- container_of(a, struct comm_attribute, attr);
- return cma->show ? cma->show(cm, buf) : 0;
-}
-
-static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
- const char *buf, size_t len)
-{
- struct dlm_comm *cm = config_item_to_comm(i);
- struct comm_attribute *cma =
- container_of(a, struct comm_attribute, attr);
- return cma->store ? cma->store(cm, buf, len) : -EINVAL;
-}
-
-static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf)
-{
- return sprintf(buf, "%d\n", cm->nodeid);
-}
-
-static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
- size_t len)
-{
- cm->nodeid = simple_strtol(buf, NULL, 0);
- return len;
-}
-
-static ssize_t comm_local_read(struct dlm_comm *cm, char *buf)
-{
- return sprintf(buf, "%d\n", cm->local);
-}
-
-static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
- size_t len)
-{
- cm->local= simple_strtol(buf, NULL, 0);
- if (cm->local && !local_comm)
- local_comm = cm;
- return len;
-}
-
-static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
-{
- struct sockaddr_storage *addr;
-
- if (len != sizeof(struct sockaddr_storage))
- return -EINVAL;
-
- if (cm->addr_count >= DLM_MAX_ADDR_COUNT)
- return -ENOSPC;
-
- addr = kzalloc(sizeof(*addr), GFP_NOFS);
- if (!addr)
- return -ENOMEM;
-
- memcpy(addr, buf, len);
- cm->addr[cm->addr_count++] = addr;
- return len;
-}
-
-static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf)
-{
- ssize_t s;
- ssize_t allowance;
- int i;
- struct sockaddr_storage *addr;
- struct sockaddr_in *addr_in;
- struct sockaddr_in6 *addr_in6;
-
- /* Taken from ip6_addr_string() defined in lib/vsprintf.c */
- char buf0[sizeof("AF_INET6 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255\n")];
-
-
- /* Derived from SIMPLE_ATTR_SIZE of fs/configfs/file.c */
- allowance = 4096;
- buf[0] = '\0';
-
- for (i = 0; i < cm->addr_count; i++) {
- addr = cm->addr[i];
-
- switch(addr->ss_family) {
- case AF_INET:
- addr_in = (struct sockaddr_in *)addr;
- s = sprintf(buf0, "AF_INET %pI4\n", &addr_in->sin_addr.s_addr);
- break;
- case AF_INET6:
- addr_in6 = (struct sockaddr_in6 *)addr;
- s = sprintf(buf0, "AF_INET6 %pI6\n", &addr_in6->sin6_addr);
- break;
- default:
- s = sprintf(buf0, "%s\n", "<UNKNOWN>");
- break;
- }
- allowance -= s;
- if (allowance >= 0)
- strcat(buf, buf0);
- else {
- allowance += s;
- break;
- }
- }
- return 4096 - allowance;
-}
-
-static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
- char *buf)
-{
- struct dlm_node *nd = config_item_to_node(i);
- struct node_attribute *nda =
- container_of(a, struct node_attribute, attr);
- return nda->show ? nda->show(nd, buf) : 0;
-}
-
-static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
- const char *buf, size_t len)
-{
- struct dlm_node *nd = config_item_to_node(i);
- struct node_attribute *nda =
- container_of(a, struct node_attribute, attr);
- return nda->store ? nda->store(nd, buf, len) : -EINVAL;
-}
-
-static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf)
-{
- return sprintf(buf, "%d\n", nd->nodeid);
-}
-
-static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
- size_t len)
-{
- uint32_t seq = 0;
- nd->nodeid = simple_strtol(buf, NULL, 0);
- dlm_comm_seq(nd->nodeid, &seq);
- nd->comm_seq = seq;
- return len;
-}
-
-static ssize_t node_weight_read(struct dlm_node *nd, char *buf)
-{
- return sprintf(buf, "%d\n", nd->weight);
-}
-
-static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
- size_t len)
-{
- nd->weight = simple_strtol(buf, NULL, 0);
- return len;
-}
-
-/*
- * Functions for the dlm to get the info that's been configured
- */
-
-static struct dlm_space *get_space(char *name)
-{
- struct config_item *i;
-
- if (!space_list)
- return NULL;
-
- mutex_lock(&space_list->cg_subsys->su_mutex);
- i = config_group_find_item(space_list, name);
- mutex_unlock(&space_list->cg_subsys->su_mutex);
-
- return config_item_to_space(i);
-}
-
-static void put_space(struct dlm_space *sp)
-{
- config_item_put(&sp->group.cg_item);
-}
-
-static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y)
-{
- switch (x->ss_family) {
- case AF_INET: {
- struct sockaddr_in *sinx = (struct sockaddr_in *)x;
- struct sockaddr_in *siny = (struct sockaddr_in *)y;
- if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr)
- return 0;
- if (sinx->sin_port != siny->sin_port)
- return 0;
- break;
- }
- case AF_INET6: {
- struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x;
- struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y;
- if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr))
- return 0;
- if (sinx->sin6_port != siny->sin6_port)
- return 0;
- break;
- }
- default:
- return 0;
- }
- return 1;
-}
-
-static struct dlm_comm *get_comm(int nodeid, struct sockaddr_storage *addr)
-{
- struct config_item *i;
- struct dlm_comm *cm = NULL;
- int found = 0;
-
- if (!comm_list)
- return NULL;
-
- mutex_lock(&clusters_root.subsys.su_mutex);
-
- list_for_each_entry(i, &comm_list->cg_children, ci_entry) {
- cm = config_item_to_comm(i);
-
- if (nodeid) {
- if (cm->nodeid != nodeid)
- continue;
- found = 1;
- config_item_get(i);
- break;
- } else {
- if (!cm->addr_count || !addr_compare(cm->addr[0], addr))
- continue;
- found = 1;
- config_item_get(i);
- break;
- }
- }
- mutex_unlock(&clusters_root.subsys.su_mutex);
-
- if (!found)
- cm = NULL;
- return cm;
-}
-
-static void put_comm(struct dlm_comm *cm)
-{
- config_item_put(&cm->item);
-}
-
-/* caller must free mem */
-int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
- int *count_out)
-{
- struct dlm_space *sp;
- struct dlm_node *nd;
- struct dlm_config_node *nodes, *node;
- int rv, count;
-
- sp = get_space(lsname);
- if (!sp)
- return -EEXIST;
-
- mutex_lock(&sp->members_lock);
- if (!sp->members_count) {
- rv = -EINVAL;
- printk(KERN_ERR "dlm: zero members_count\n");
- goto out;
- }
-
- count = sp->members_count;
-
- nodes = kcalloc(count, sizeof(struct dlm_config_node), GFP_NOFS);
- if (!nodes) {
- rv = -ENOMEM;
- goto out;
- }
-
- node = nodes;
- list_for_each_entry(nd, &sp->members, list) {
- node->nodeid = nd->nodeid;
- node->weight = nd->weight;
- node->new = nd->new;
- node->comm_seq = nd->comm_seq;
- node++;
-
- nd->new = 0;
- }
-
- *count_out = count;
- *nodes_out = nodes;
- rv = 0;
- out:
- mutex_unlock(&sp->members_lock);
- put_space(sp);
- return rv;
-}
-
-int dlm_comm_seq(int nodeid, uint32_t *seq)
-{
- struct dlm_comm *cm = get_comm(nodeid, NULL);
- if (!cm)
- return -EEXIST;
- *seq = cm->seq;
- put_comm(cm);
- return 0;
-}
-
-int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr)
-{
- struct dlm_comm *cm = get_comm(nodeid, NULL);
- if (!cm)
- return -EEXIST;
- if (!cm->addr_count)
- return -ENOENT;
- memcpy(addr, cm->addr[0], sizeof(*addr));
- put_comm(cm);
- return 0;
-}
-
-int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid)
-{
- struct dlm_comm *cm = get_comm(0, addr);
- if (!cm)
- return -EEXIST;
- *nodeid = cm->nodeid;
- put_comm(cm);
- return 0;
-}
-
-int dlm_our_nodeid(void)
-{
- return local_comm ? local_comm->nodeid : 0;
-}
-
-/* num 0 is first addr, num 1 is second addr */
-int dlm_our_addr(struct sockaddr_storage *addr, int num)
-{
- if (!local_comm)
- return -1;
- if (num + 1 > local_comm->addr_count)
- return -1;
- memcpy(addr, local_comm->addr[num], sizeof(*addr));
- return 0;
-}
-
-/* Config file defaults */
-#define DEFAULT_TCP_PORT 21064
-#define DEFAULT_BUFFER_SIZE 4096
-#define DEFAULT_RSBTBL_SIZE 1024
-#define DEFAULT_DIRTBL_SIZE 1024
-#define DEFAULT_RECOVER_TIMER 5
-#define DEFAULT_TOSS_SECS 10
-#define DEFAULT_SCAN_SECS 5
-#define DEFAULT_LOG_DEBUG 0
-#define DEFAULT_PROTOCOL 0
-#define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */
-#define DEFAULT_WAITWARN_US 0
-#define DEFAULT_NEW_RSB_COUNT 128
-#define DEFAULT_RECOVER_CALLBACKS 0
-#define DEFAULT_CLUSTER_NAME ""
-
-struct dlm_config_info dlm_config = {
- .ci_tcp_port = DEFAULT_TCP_PORT,
- .ci_buffer_size = DEFAULT_BUFFER_SIZE,
- .ci_rsbtbl_size = DEFAULT_RSBTBL_SIZE,
- .ci_dirtbl_size = DEFAULT_DIRTBL_SIZE,
- .ci_recover_timer = DEFAULT_RECOVER_TIMER,
- .ci_toss_secs = DEFAULT_TOSS_SECS,
- .ci_scan_secs = DEFAULT_SCAN_SECS,
- .ci_log_debug = DEFAULT_LOG_DEBUG,
- .ci_protocol = DEFAULT_PROTOCOL,
- .ci_timewarn_cs = DEFAULT_TIMEWARN_CS,
- .ci_waitwarn_us = DEFAULT_WAITWARN_US,
- .ci_new_rsb_count = DEFAULT_NEW_RSB_COUNT,
- .ci_recover_callbacks = DEFAULT_RECOVER_CALLBACKS,
- .ci_cluster_name = DEFAULT_CLUSTER_NAME
-};
-
diff --git a/ANDROID_3.4.5/fs/dlm/config.h b/ANDROID_3.4.5/fs/dlm/config.h
deleted file mode 100644
index 9f5e3663..00000000
--- a/ANDROID_3.4.5/fs/dlm/config.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2011 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __CONFIG_DOT_H__
-#define __CONFIG_DOT_H__
-
-struct dlm_config_node {
- int nodeid;
- int weight;
- int new;
- uint32_t comm_seq;
-};
-
-#define DLM_MAX_ADDR_COUNT 3
-
-struct dlm_config_info {
- int ci_tcp_port;
- int ci_buffer_size;
- int ci_rsbtbl_size;
- int ci_dirtbl_size;
- int ci_recover_timer;
- int ci_toss_secs;
- int ci_scan_secs;
- int ci_log_debug;
- int ci_protocol;
- int ci_timewarn_cs;
- int ci_waitwarn_us;
- int ci_new_rsb_count;
- int ci_recover_callbacks;
- char ci_cluster_name[DLM_LOCKSPACE_LEN];
-};
-
-extern struct dlm_config_info dlm_config;
-
-int dlm_config_init(void);
-void dlm_config_exit(void);
-int dlm_config_nodes(char *lsname, struct dlm_config_node **nodes_out,
- int *count_out);
-int dlm_comm_seq(int nodeid, uint32_t *seq);
-int dlm_nodeid_to_addr(int nodeid, struct sockaddr_storage *addr);
-int dlm_addr_to_nodeid(struct sockaddr_storage *addr, int *nodeid);
-int dlm_our_nodeid(void);
-int dlm_our_addr(struct sockaddr_storage *addr, int num);
-
-#endif /* __CONFIG_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/debug_fs.c b/ANDROID_3.4.5/fs/dlm/debug_fs.c
deleted file mode 100644
index 1c9b0809..00000000
--- a/ANDROID_3.4.5/fs/dlm/debug_fs.c
+++ /dev/null
@@ -1,726 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005-2009 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 <linux/pagemap.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/ctype.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-
-#include "dlm_internal.h"
-#include "lock.h"
-
-#define DLM_DEBUG_BUF_LEN 4096
-static char debug_buf[DLM_DEBUG_BUF_LEN];
-static struct mutex debug_buf_lock;
-
-static struct dentry *dlm_root;
-
-static char *print_lockmode(int mode)
-{
- switch (mode) {
- case DLM_LOCK_IV:
- return "--";
- case DLM_LOCK_NL:
- return "NL";
- case DLM_LOCK_CR:
- return "CR";
- case DLM_LOCK_CW:
- return "CW";
- case DLM_LOCK_PR:
- return "PR";
- case DLM_LOCK_PW:
- return "PW";
- case DLM_LOCK_EX:
- return "EX";
- default:
- return "??";
- }
-}
-
-static int print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
- struct dlm_rsb *res)
-{
- seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
-
- if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
- lkb->lkb_status == DLM_LKSTS_WAITING)
- seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
-
- if (lkb->lkb_nodeid) {
- if (lkb->lkb_nodeid != res->res_nodeid)
- seq_printf(s, " Remote: %3d %08x", lkb->lkb_nodeid,
- lkb->lkb_remid);
- else
- seq_printf(s, " Master: %08x", lkb->lkb_remid);
- }
-
- if (lkb->lkb_wait_type)
- seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
-
- return seq_printf(s, "\n");
-}
-
-static int print_format1(struct dlm_rsb *res, struct seq_file *s)
-{
- struct dlm_lkb *lkb;
- int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
- int rv;
-
- lock_rsb(res);
-
- rv = seq_printf(s, "\nResource %p Name (len=%d) \"",
- res, res->res_length);
- if (rv)
- goto out;
-
- for (i = 0; i < res->res_length; i++) {
- if (isprint(res->res_name[i]))
- seq_printf(s, "%c", res->res_name[i]);
- else
- seq_printf(s, "%c", '.');
- }
-
- if (res->res_nodeid > 0)
- rv = seq_printf(s, "\" \nLocal Copy, Master is node %d\n",
- res->res_nodeid);
- else if (res->res_nodeid == 0)
- rv = seq_printf(s, "\" \nMaster Copy\n");
- else if (res->res_nodeid == -1)
- rv = seq_printf(s, "\" \nLooking up master (lkid %x)\n",
- res->res_first_lkid);
- else
- rv = seq_printf(s, "\" \nInvalid master %d\n",
- res->res_nodeid);
- if (rv)
- goto out;
-
- /* Print the LVB: */
- if (res->res_lvbptr) {
- seq_printf(s, "LVB: ");
- for (i = 0; i < lvblen; i++) {
- if (i == lvblen / 2)
- seq_printf(s, "\n ");
- seq_printf(s, "%02x ",
- (unsigned char) res->res_lvbptr[i]);
- }
- if (rsb_flag(res, RSB_VALNOTVALID))
- seq_printf(s, " (INVALID)");
- rv = seq_printf(s, "\n");
- if (rv)
- goto out;
- }
-
- root_list = !list_empty(&res->res_root_list);
- recover_list = !list_empty(&res->res_recover_list);
-
- if (root_list || recover_list) {
- rv = seq_printf(s, "Recovery: root %d recover %d flags %lx "
- "count %d\n", root_list, recover_list,
- res->res_flags, res->res_recover_locks_count);
- if (rv)
- goto out;
- }
-
- /* Print the locks attached to this resource */
- seq_printf(s, "Granted Queue\n");
- list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
- rv = print_format1_lock(s, lkb, res);
- if (rv)
- goto out;
- }
-
- seq_printf(s, "Conversion Queue\n");
- list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
- rv = print_format1_lock(s, lkb, res);
- if (rv)
- goto out;
- }
-
- seq_printf(s, "Waiting Queue\n");
- list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
- rv = print_format1_lock(s, lkb, res);
- if (rv)
- goto out;
- }
-
- if (list_empty(&res->res_lookup))
- goto out;
-
- seq_printf(s, "Lookup Queue\n");
- list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
- rv = seq_printf(s, "%08x %s", lkb->lkb_id,
- print_lockmode(lkb->lkb_rqmode));
- if (lkb->lkb_wait_type)
- seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
- rv = seq_printf(s, "\n");
- }
- out:
- unlock_rsb(res);
- return rv;
-}
-
-static int print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
- struct dlm_rsb *r)
-{
- u64 xid = 0;
- u64 us;
- int rv;
-
- if (lkb->lkb_flags & DLM_IFL_USER) {
- if (lkb->lkb_ua)
- xid = lkb->lkb_ua->xid;
- }
-
- /* microseconds since lkb was added to current queue */
- us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
-
- /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
- r_nodeid r_len r_name */
-
- rv = seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
- lkb->lkb_id,
- lkb->lkb_nodeid,
- lkb->lkb_remid,
- lkb->lkb_ownpid,
- (unsigned long long)xid,
- lkb->lkb_exflags,
- lkb->lkb_flags,
- lkb->lkb_status,
- lkb->lkb_grmode,
- lkb->lkb_rqmode,
- (unsigned long long)us,
- r->res_nodeid,
- r->res_length,
- r->res_name);
- return rv;
-}
-
-static int print_format2(struct dlm_rsb *r, struct seq_file *s)
-{
- struct dlm_lkb *lkb;
- int rv = 0;
-
- lock_rsb(r);
-
- list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
- rv = print_format2_lock(s, lkb, r);
- if (rv)
- goto out;
- }
-
- list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
- rv = print_format2_lock(s, lkb, r);
- if (rv)
- goto out;
- }
-
- list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
- rv = print_format2_lock(s, lkb, r);
- if (rv)
- goto out;
- }
- out:
- unlock_rsb(r);
- return rv;
-}
-
-static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
- int rsb_lookup)
-{
- u64 xid = 0;
- int rv;
-
- if (lkb->lkb_flags & DLM_IFL_USER) {
- if (lkb->lkb_ua)
- xid = lkb->lkb_ua->xid;
- }
-
- rv = seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
- lkb->lkb_id,
- lkb->lkb_nodeid,
- lkb->lkb_remid,
- lkb->lkb_ownpid,
- (unsigned long long)xid,
- lkb->lkb_exflags,
- lkb->lkb_flags,
- lkb->lkb_status,
- lkb->lkb_grmode,
- lkb->lkb_rqmode,
- lkb->lkb_last_bast.mode,
- rsb_lookup,
- lkb->lkb_wait_type,
- lkb->lkb_lvbseq,
- (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
- (unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time));
- return rv;
-}
-
-static int print_format3(struct dlm_rsb *r, struct seq_file *s)
-{
- struct dlm_lkb *lkb;
- int i, lvblen = r->res_ls->ls_lvblen;
- int print_name = 1;
- int rv;
-
- lock_rsb(r);
-
- rv = seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
- r,
- r->res_nodeid,
- r->res_first_lkid,
- r->res_flags,
- !list_empty(&r->res_root_list),
- !list_empty(&r->res_recover_list),
- r->res_recover_locks_count,
- r->res_length);
- if (rv)
- goto out;
-
- for (i = 0; i < r->res_length; i++) {
- if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
- print_name = 0;
- }
-
- seq_printf(s, "%s", print_name ? "str " : "hex");
-
- for (i = 0; i < r->res_length; i++) {
- if (print_name)
- seq_printf(s, "%c", r->res_name[i]);
- else
- seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
- }
- rv = seq_printf(s, "\n");
- if (rv)
- goto out;
-
- if (!r->res_lvbptr)
- goto do_locks;
-
- seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);
-
- for (i = 0; i < lvblen; i++)
- seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
- rv = seq_printf(s, "\n");
- if (rv)
- goto out;
-
- do_locks:
- list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
- rv = print_format3_lock(s, lkb, 0);
- if (rv)
- goto out;
- }
-
- list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
- rv = print_format3_lock(s, lkb, 0);
- if (rv)
- goto out;
- }
-
- list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
- rv = print_format3_lock(s, lkb, 0);
- if (rv)
- goto out;
- }
-
- list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
- rv = print_format3_lock(s, lkb, 1);
- if (rv)
- goto out;
- }
- out:
- unlock_rsb(r);
- return rv;
-}
-
-struct rsbtbl_iter {
- struct dlm_rsb *rsb;
- unsigned bucket;
- int format;
- int header;
-};
-
-/* seq_printf returns -1 if the buffer is full, and 0 otherwise.
- If the buffer is full, seq_printf can be called again, but it
- does nothing and just returns -1. So, the these printing routines
- periodically check the return value to avoid wasting too much time
- trying to print to a full buffer. */
-
-static int table_seq_show(struct seq_file *seq, void *iter_ptr)
-{
- struct rsbtbl_iter *ri = iter_ptr;
- int rv = 0;
-
- switch (ri->format) {
- case 1:
- rv = print_format1(ri->rsb, seq);
- break;
- case 2:
- if (ri->header) {
- seq_printf(seq, "id nodeid remid pid xid exflags "
- "flags sts grmode rqmode time_ms "
- "r_nodeid r_len r_name\n");
- ri->header = 0;
- }
- rv = print_format2(ri->rsb, seq);
- break;
- case 3:
- if (ri->header) {
- seq_printf(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
- ri->header = 0;
- }
- rv = print_format3(ri->rsb, seq);
- break;
- }
-
- return rv;
-}
-
-static const struct seq_operations format1_seq_ops;
-static const struct seq_operations format2_seq_ops;
-static const struct seq_operations format3_seq_ops;
-
-static void *table_seq_start(struct seq_file *seq, loff_t *pos)
-{
- struct rb_node *node;
- struct dlm_ls *ls = seq->private;
- struct rsbtbl_iter *ri;
- struct dlm_rsb *r;
- loff_t n = *pos;
- unsigned bucket, entry;
-
- bucket = n >> 32;
- entry = n & ((1LL << 32) - 1);
-
- if (bucket >= ls->ls_rsbtbl_size)
- return NULL;
-
- ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_NOFS);
- if (!ri)
- return NULL;
- if (n == 0)
- ri->header = 1;
- if (seq->op == &format1_seq_ops)
- ri->format = 1;
- if (seq->op == &format2_seq_ops)
- ri->format = 2;
- if (seq->op == &format3_seq_ops)
- ri->format = 3;
-
- spin_lock(&ls->ls_rsbtbl[bucket].lock);
- if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) {
- for (node = rb_first(&ls->ls_rsbtbl[bucket].keep); node;
- node = rb_next(node)) {
- r = rb_entry(node, struct dlm_rsb, res_hashnode);
- if (!entry--) {
- dlm_hold_rsb(r);
- ri->rsb = r;
- ri->bucket = bucket;
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- return ri;
- }
- }
- }
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
-
- /*
- * move to the first rsb in the next non-empty bucket
- */
-
- /* zero the entry */
- n &= ~((1LL << 32) - 1);
-
- while (1) {
- bucket++;
- n += 1LL << 32;
-
- if (bucket >= ls->ls_rsbtbl_size) {
- kfree(ri);
- return NULL;
- }
-
- spin_lock(&ls->ls_rsbtbl[bucket].lock);
- if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) {
- node = rb_first(&ls->ls_rsbtbl[bucket].keep);
- r = rb_entry(node, struct dlm_rsb, res_hashnode);
- dlm_hold_rsb(r);
- ri->rsb = r;
- ri->bucket = bucket;
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- *pos = n;
- return ri;
- }
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- }
-}
-
-static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
-{
- struct dlm_ls *ls = seq->private;
- struct rsbtbl_iter *ri = iter_ptr;
- struct rb_node *next;
- struct dlm_rsb *r, *rp;
- loff_t n = *pos;
- unsigned bucket;
-
- bucket = n >> 32;
-
- /*
- * move to the next rsb in the same bucket
- */
-
- spin_lock(&ls->ls_rsbtbl[bucket].lock);
- rp = ri->rsb;
- next = rb_next(&rp->res_hashnode);
-
- if (next) {
- r = rb_entry(next, struct dlm_rsb, res_hashnode);
- dlm_hold_rsb(r);
- ri->rsb = r;
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- dlm_put_rsb(rp);
- ++*pos;
- return ri;
- }
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- dlm_put_rsb(rp);
-
- /*
- * move to the first rsb in the next non-empty bucket
- */
-
- /* zero the entry */
- n &= ~((1LL << 32) - 1);
-
- while (1) {
- bucket++;
- n += 1LL << 32;
-
- if (bucket >= ls->ls_rsbtbl_size) {
- kfree(ri);
- return NULL;
- }
-
- spin_lock(&ls->ls_rsbtbl[bucket].lock);
- if (!RB_EMPTY_ROOT(&ls->ls_rsbtbl[bucket].keep)) {
- next = rb_first(&ls->ls_rsbtbl[bucket].keep);
- r = rb_entry(next, struct dlm_rsb, res_hashnode);
- dlm_hold_rsb(r);
- ri->rsb = r;
- ri->bucket = bucket;
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- *pos = n;
- return ri;
- }
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- }
-}
-
-static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
-{
- struct rsbtbl_iter *ri = iter_ptr;
-
- if (ri) {
- dlm_put_rsb(ri->rsb);
- kfree(ri);
- }
-}
-
-static const struct seq_operations format1_seq_ops = {
- .start = table_seq_start,
- .next = table_seq_next,
- .stop = table_seq_stop,
- .show = table_seq_show,
-};
-
-static const struct seq_operations format2_seq_ops = {
- .start = table_seq_start,
- .next = table_seq_next,
- .stop = table_seq_stop,
- .show = table_seq_show,
-};
-
-static const struct seq_operations format3_seq_ops = {
- .start = table_seq_start,
- .next = table_seq_next,
- .stop = table_seq_stop,
- .show = table_seq_show,
-};
-
-static const struct file_operations format1_fops;
-static const struct file_operations format2_fops;
-static const struct file_operations format3_fops;
-
-static int table_open(struct inode *inode, struct file *file)
-{
- struct seq_file *seq;
- int ret = -1;
-
- if (file->f_op == &format1_fops)
- ret = seq_open(file, &format1_seq_ops);
- else if (file->f_op == &format2_fops)
- ret = seq_open(file, &format2_seq_ops);
- else if (file->f_op == &format3_fops)
- ret = seq_open(file, &format3_seq_ops);
-
- if (ret)
- return ret;
-
- seq = file->private_data;
- seq->private = inode->i_private; /* the dlm_ls */
- return 0;
-}
-
-static const struct file_operations format1_fops = {
- .owner = THIS_MODULE,
- .open = table_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release
-};
-
-static const struct file_operations format2_fops = {
- .owner = THIS_MODULE,
- .open = table_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release
-};
-
-static const struct file_operations format3_fops = {
- .owner = THIS_MODULE,
- .open = table_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release
-};
-
-/*
- * dump lkb's on the ls_waiters list
- */
-static ssize_t waiters_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- struct dlm_ls *ls = file->private_data;
- struct dlm_lkb *lkb;
- size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
-
- mutex_lock(&debug_buf_lock);
- mutex_lock(&ls->ls_waiters_mutex);
- memset(debug_buf, 0, sizeof(debug_buf));
-
- list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
- ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n",
- lkb->lkb_id, lkb->lkb_wait_type,
- lkb->lkb_nodeid, lkb->lkb_resource->res_name);
- if (ret >= len - pos)
- break;
- pos += ret;
- }
- mutex_unlock(&ls->ls_waiters_mutex);
-
- rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
- mutex_unlock(&debug_buf_lock);
- return rv;
-}
-
-static const struct file_operations waiters_fops = {
- .owner = THIS_MODULE,
- .open = simple_open,
- .read = waiters_read,
- .llseek = default_llseek,
-};
-
-void dlm_delete_debug_file(struct dlm_ls *ls)
-{
- if (ls->ls_debug_rsb_dentry)
- debugfs_remove(ls->ls_debug_rsb_dentry);
- if (ls->ls_debug_waiters_dentry)
- debugfs_remove(ls->ls_debug_waiters_dentry);
- if (ls->ls_debug_locks_dentry)
- debugfs_remove(ls->ls_debug_locks_dentry);
- if (ls->ls_debug_all_dentry)
- debugfs_remove(ls->ls_debug_all_dentry);
-}
-
-int dlm_create_debug_file(struct dlm_ls *ls)
-{
- char name[DLM_LOCKSPACE_LEN+8];
-
- /* format 1 */
-
- ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
- S_IFREG | S_IRUGO,
- dlm_root,
- ls,
- &format1_fops);
- if (!ls->ls_debug_rsb_dentry)
- goto fail;
-
- /* format 2 */
-
- memset(name, 0, sizeof(name));
- snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
-
- ls->ls_debug_locks_dentry = debugfs_create_file(name,
- S_IFREG | S_IRUGO,
- dlm_root,
- ls,
- &format2_fops);
- if (!ls->ls_debug_locks_dentry)
- goto fail;
-
- /* format 3 */
-
- memset(name, 0, sizeof(name));
- snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_all", ls->ls_name);
-
- ls->ls_debug_all_dentry = debugfs_create_file(name,
- S_IFREG | S_IRUGO,
- dlm_root,
- ls,
- &format3_fops);
- if (!ls->ls_debug_all_dentry)
- goto fail;
-
- memset(name, 0, sizeof(name));
- snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);
-
- ls->ls_debug_waiters_dentry = debugfs_create_file(name,
- S_IFREG | S_IRUGO,
- dlm_root,
- ls,
- &waiters_fops);
- if (!ls->ls_debug_waiters_dentry)
- goto fail;
-
- return 0;
-
- fail:
- dlm_delete_debug_file(ls);
- return -ENOMEM;
-}
-
-int __init dlm_register_debugfs(void)
-{
- mutex_init(&debug_buf_lock);
- dlm_root = debugfs_create_dir("dlm", NULL);
- return dlm_root ? 0 : -ENOMEM;
-}
-
-void dlm_unregister_debugfs(void)
-{
- debugfs_remove(dlm_root);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/dir.c b/ANDROID_3.4.5/fs/dlm/dir.c
deleted file mode 100644
index dc5eb598..00000000
--- a/ANDROID_3.4.5/fs/dlm/dir.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 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 "lowcomms.h"
-#include "rcom.h"
-#include "config.h"
-#include "memory.h"
-#include "recover.h"
-#include "util.h"
-#include "lock.h"
-#include "dir.h"
-
-
-static void put_free_de(struct dlm_ls *ls, struct dlm_direntry *de)
-{
- spin_lock(&ls->ls_recover_list_lock);
- list_add(&de->list, &ls->ls_recover_list);
- spin_unlock(&ls->ls_recover_list_lock);
-}
-
-static struct dlm_direntry *get_free_de(struct dlm_ls *ls, int len)
-{
- int found = 0;
- struct dlm_direntry *de;
-
- spin_lock(&ls->ls_recover_list_lock);
- list_for_each_entry(de, &ls->ls_recover_list, list) {
- if (de->length == len) {
- list_del(&de->list);
- de->master_nodeid = 0;
- memset(de->name, 0, len);
- found = 1;
- break;
- }
- }
- spin_unlock(&ls->ls_recover_list_lock);
-
- if (!found)
- de = kzalloc(sizeof(struct dlm_direntry) + len, GFP_NOFS);
- return de;
-}
-
-void dlm_clear_free_entries(struct dlm_ls *ls)
-{
- struct dlm_direntry *de;
-
- spin_lock(&ls->ls_recover_list_lock);
- while (!list_empty(&ls->ls_recover_list)) {
- de = list_entry(ls->ls_recover_list.next, struct dlm_direntry,
- list);
- list_del(&de->list);
- kfree(de);
- }
- spin_unlock(&ls->ls_recover_list_lock);
-}
-
-/*
- * We use the upper 16 bits of the hash value to select the directory node.
- * Low bits are used for distribution of rsb's among hash buckets on each node.
- *
- * To give the exact range wanted (0 to num_nodes-1), we apply a modulus of
- * num_nodes to the hash value. This value in the desired range is used as an
- * offset into the sorted list of nodeid's to give the particular nodeid.
- */
-
-int dlm_hash2nodeid(struct dlm_ls *ls, uint32_t hash)
-{
- struct list_head *tmp;
- struct dlm_member *memb = NULL;
- uint32_t node, n = 0;
- int nodeid;
-
- if (ls->ls_num_nodes == 1) {
- nodeid = dlm_our_nodeid();
- goto out;
- }
-
- if (ls->ls_node_array) {
- node = (hash >> 16) % ls->ls_total_weight;
- nodeid = ls->ls_node_array[node];
- goto out;
- }
-
- /* make_member_array() failed to kmalloc ls_node_array... */
-
- node = (hash >> 16) % ls->ls_num_nodes;
-
- list_for_each(tmp, &ls->ls_nodes) {
- if (n++ != node)
- continue;
- memb = list_entry(tmp, struct dlm_member, list);
- break;
- }
-
- DLM_ASSERT(memb , printk("num_nodes=%u n=%u node=%u\n",
- ls->ls_num_nodes, n, node););
- nodeid = memb->nodeid;
- out:
- return nodeid;
-}
-
-int dlm_dir_nodeid(struct dlm_rsb *r)
-{
- return dlm_hash2nodeid(r->res_ls, r->res_hash);
-}
-
-static inline uint32_t dir_hash(struct dlm_ls *ls, char *name, int len)
-{
- uint32_t val;
-
- val = jhash(name, len, 0);
- val &= (ls->ls_dirtbl_size - 1);
-
- return val;
-}
-
-static void add_entry_to_hash(struct dlm_ls *ls, struct dlm_direntry *de)
-{
- uint32_t bucket;
-
- bucket = dir_hash(ls, de->name, de->length);
- list_add_tail(&de->list, &ls->ls_dirtbl[bucket].list);
-}
-
-static struct dlm_direntry *search_bucket(struct dlm_ls *ls, char *name,
- int namelen, uint32_t bucket)
-{
- struct dlm_direntry *de;
-
- list_for_each_entry(de, &ls->ls_dirtbl[bucket].list, list) {
- if (de->length == namelen && !memcmp(name, de->name, namelen))
- goto out;
- }
- de = NULL;
- out:
- return de;
-}
-
-void dlm_dir_remove_entry(struct dlm_ls *ls, int nodeid, char *name, int namelen)
-{
- struct dlm_direntry *de;
- uint32_t bucket;
-
- bucket = dir_hash(ls, name, namelen);
-
- spin_lock(&ls->ls_dirtbl[bucket].lock);
-
- de = search_bucket(ls, name, namelen, bucket);
-
- if (!de) {
- log_error(ls, "remove fr %u none", nodeid);
- goto out;
- }
-
- if (de->master_nodeid != nodeid) {
- log_error(ls, "remove fr %u ID %u", nodeid, de->master_nodeid);
- goto out;
- }
-
- list_del(&de->list);
- kfree(de);
- out:
- spin_unlock(&ls->ls_dirtbl[bucket].lock);
-}
-
-void dlm_dir_clear(struct dlm_ls *ls)
-{
- struct list_head *head;
- struct dlm_direntry *de;
- int i;
-
- DLM_ASSERT(list_empty(&ls->ls_recover_list), );
-
- for (i = 0; i < ls->ls_dirtbl_size; i++) {
- spin_lock(&ls->ls_dirtbl[i].lock);
- head = &ls->ls_dirtbl[i].list;
- while (!list_empty(head)) {
- de = list_entry(head->next, struct dlm_direntry, list);
- list_del(&de->list);
- put_free_de(ls, de);
- }
- spin_unlock(&ls->ls_dirtbl[i].lock);
- }
-}
-
-int dlm_recover_directory(struct dlm_ls *ls)
-{
- struct dlm_member *memb;
- struct dlm_direntry *de;
- char *b, *last_name = NULL;
- int error = -ENOMEM, last_len, count = 0;
- uint16_t namelen;
-
- log_debug(ls, "dlm_recover_directory");
-
- if (dlm_no_directory(ls))
- goto out_status;
-
- dlm_dir_clear(ls);
-
- last_name = kmalloc(DLM_RESNAME_MAXLEN, GFP_NOFS);
- if (!last_name)
- goto out;
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- memset(last_name, 0, DLM_RESNAME_MAXLEN);
- last_len = 0;
-
- for (;;) {
- int left;
- error = dlm_recovery_stopped(ls);
- if (error)
- goto out_free;
-
- error = dlm_rcom_names(ls, memb->nodeid,
- last_name, last_len);
- if (error)
- goto out_free;
-
- schedule();
-
- /*
- * pick namelen/name pairs out of received buffer
- */
-
- b = ls->ls_recover_buf->rc_buf;
- left = ls->ls_recover_buf->rc_header.h_length;
- left -= sizeof(struct dlm_rcom);
-
- for (;;) {
- __be16 v;
-
- error = -EINVAL;
- if (left < sizeof(__be16))
- goto out_free;
-
- memcpy(&v, b, sizeof(__be16));
- namelen = be16_to_cpu(v);
- b += sizeof(__be16);
- left -= sizeof(__be16);
-
- /* namelen of 0xFFFFF marks end of names for
- this node; namelen of 0 marks end of the
- buffer */
-
- if (namelen == 0xFFFF)
- goto done;
- if (!namelen)
- break;
-
- if (namelen > left)
- goto out_free;
-
- if (namelen > DLM_RESNAME_MAXLEN)
- goto out_free;
-
- error = -ENOMEM;
- de = get_free_de(ls, namelen);
- if (!de)
- goto out_free;
-
- de->master_nodeid = memb->nodeid;
- de->length = namelen;
- last_len = namelen;
- memcpy(de->name, b, namelen);
- memcpy(last_name, b, namelen);
- b += namelen;
- left -= namelen;
-
- add_entry_to_hash(ls, de);
- count++;
- }
- }
- done:
- ;
- }
-
- out_status:
- error = 0;
- log_debug(ls, "dlm_recover_directory %d entries", count);
- out_free:
- kfree(last_name);
- out:
- dlm_clear_free_entries(ls);
- return error;
-}
-
-static int get_entry(struct dlm_ls *ls, int nodeid, char *name,
- int namelen, int *r_nodeid)
-{
- struct dlm_direntry *de, *tmp;
- uint32_t bucket;
-
- bucket = dir_hash(ls, name, namelen);
-
- spin_lock(&ls->ls_dirtbl[bucket].lock);
- de = search_bucket(ls, name, namelen, bucket);
- if (de) {
- *r_nodeid = de->master_nodeid;
- spin_unlock(&ls->ls_dirtbl[bucket].lock);
- if (*r_nodeid == nodeid)
- return -EEXIST;
- return 0;
- }
-
- spin_unlock(&ls->ls_dirtbl[bucket].lock);
-
- if (namelen > DLM_RESNAME_MAXLEN)
- return -EINVAL;
-
- de = kzalloc(sizeof(struct dlm_direntry) + namelen, GFP_NOFS);
- if (!de)
- return -ENOMEM;
-
- de->master_nodeid = nodeid;
- de->length = namelen;
- memcpy(de->name, name, namelen);
-
- spin_lock(&ls->ls_dirtbl[bucket].lock);
- tmp = search_bucket(ls, name, namelen, bucket);
- if (tmp) {
- kfree(de);
- de = tmp;
- } else {
- list_add_tail(&de->list, &ls->ls_dirtbl[bucket].list);
- }
- *r_nodeid = de->master_nodeid;
- spin_unlock(&ls->ls_dirtbl[bucket].lock);
- return 0;
-}
-
-int dlm_dir_lookup(struct dlm_ls *ls, int nodeid, char *name, int namelen,
- int *r_nodeid)
-{
- return get_entry(ls, nodeid, name, namelen, r_nodeid);
-}
-
-static struct dlm_rsb *find_rsb_root(struct dlm_ls *ls, char *name, int len)
-{
- struct dlm_rsb *r;
- uint32_t hash, bucket;
- int rv;
-
- hash = jhash(name, len, 0);
- bucket = hash & (ls->ls_rsbtbl_size - 1);
-
- spin_lock(&ls->ls_rsbtbl[bucket].lock);
- rv = dlm_search_rsb_tree(&ls->ls_rsbtbl[bucket].keep, name, len, 0, &r);
- if (rv)
- rv = dlm_search_rsb_tree(&ls->ls_rsbtbl[bucket].toss,
- name, len, 0, &r);
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
-
- if (!rv)
- return 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);
- log_error(ls, "find_rsb_root revert to root_list %s",
- r->res_name);
- 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 *r;
- int offset = 0, dir_nodeid;
- __be16 be_namelen;
-
- down_read(&ls->ls_root_sem);
-
- 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);
- if (r->res_nodeid)
- continue;
-
- dir_nodeid = dlm_dir_nodeid(r);
- if (dir_nodeid != nodeid)
- continue;
-
- /*
- * The block ends when we can't fit the following in the
- * remaining buffer space:
- * namelen (uint16_t) +
- * name (r->res_length) +
- * end-of-block record 0x0000 (uint16_t)
- */
-
- if (offset + sizeof(uint16_t)*2 + r->res_length > outlen) {
- /* Write end-of-block record */
- be_namelen = cpu_to_be16(0);
- memcpy(outbuf + offset, &be_namelen, sizeof(__be16));
- offset += sizeof(__be16);
- goto out;
- }
-
- be_namelen = cpu_to_be16(r->res_length);
- memcpy(outbuf + offset, &be_namelen, sizeof(__be16));
- offset += sizeof(__be16);
- memcpy(outbuf + offset, r->res_name, r->res_length);
- offset += r->res_length;
- }
-
- /*
- * If we've reached the end of the list (and there's room) write a
- * terminating record.
- */
-
- if ((list == &ls->ls_root_list) &&
- (offset + sizeof(uint16_t) <= outlen)) {
- be_namelen = cpu_to_be16(0xFFFF);
- memcpy(outbuf + offset, &be_namelen, sizeof(__be16));
- offset += sizeof(__be16);
- }
-
- out:
- up_read(&ls->ls_root_sem);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/dir.h b/ANDROID_3.4.5/fs/dlm/dir.h
deleted file mode 100644
index 0b0eb126..00000000
--- a/ANDROID_3.4.5/fs/dlm/dir.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __DIR_DOT_H__
-#define __DIR_DOT_H__
-
-
-int dlm_dir_nodeid(struct dlm_rsb *rsb);
-int dlm_hash2nodeid(struct dlm_ls *ls, uint32_t hash);
-void dlm_dir_remove_entry(struct dlm_ls *ls, int nodeid, char *name, int len);
-void dlm_dir_clear(struct dlm_ls *ls);
-void dlm_clear_free_entries(struct dlm_ls *ls);
-int dlm_recover_directory(struct dlm_ls *ls);
-int dlm_dir_lookup(struct dlm_ls *ls, int nodeid, char *name, int namelen,
- int *r_nodeid);
-void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen,
- char *outbuf, int outlen, int nodeid);
-
-#endif /* __DIR_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/dlm_internal.h b/ANDROID_3.4.5/fs/dlm/dlm_internal.h
deleted file mode 100644
index 3a564d19..00000000
--- a/ANDROID_3.4.5/fs/dlm/dlm_internal.h
+++ /dev/null
@@ -1,661 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2011 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __DLM_INTERNAL_DOT_H__
-#define __DLM_INTERNAL_DOT_H__
-
-/*
- * This is the main header file to be included in each DLM source file.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/ctype.h>
-#include <linux/spinlock.h>
-#include <linux/vmalloc.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <linux/delay.h>
-#include <linux/socket.h>
-#include <linux/kthread.h>
-#include <linux/kobject.h>
-#include <linux/kref.h>
-#include <linux/kernel.h>
-#include <linux/jhash.h>
-#include <linux/miscdevice.h>
-#include <linux/mutex.h>
-#include <linux/idr.h>
-#include <asm/uaccess.h>
-
-#include <linux/dlm.h>
-#include "config.h"
-
-/* Size of the temp buffer midcomms allocates on the stack.
- We try to make this large enough so most messages fit.
- FIXME: should sctp make this unnecessary? */
-
-#define DLM_INBUF_LEN 148
-
-struct dlm_ls;
-struct dlm_lkb;
-struct dlm_rsb;
-struct dlm_member;
-struct dlm_rsbtable;
-struct dlm_dirtable;
-struct dlm_direntry;
-struct dlm_recover;
-struct dlm_header;
-struct dlm_message;
-struct dlm_rcom;
-struct dlm_mhandle;
-
-#define log_print(fmt, args...) \
- printk(KERN_ERR "dlm: "fmt"\n" , ##args)
-#define log_error(ls, fmt, args...) \
- printk(KERN_ERR "dlm: %s: " fmt "\n", (ls)->ls_name , ##args)
-
-#define log_debug(ls, fmt, args...) \
-do { \
- if (dlm_config.ci_log_debug) \
- printk(KERN_DEBUG "dlm: %s: " fmt "\n", \
- (ls)->ls_name , ##args); \
-} while (0)
-
-#define DLM_ASSERT(x, do) \
-{ \
- if (!(x)) \
- { \
- printk(KERN_ERR "\nDLM: Assertion failed on line %d of file %s\n" \
- "DLM: assertion: \"%s\"\n" \
- "DLM: time = %lu\n", \
- __LINE__, __FILE__, #x, jiffies); \
- {do} \
- printk("\n"); \
- BUG(); \
- panic("DLM: Record message above and reboot.\n"); \
- } \
-}
-
-
-struct dlm_direntry {
- struct list_head list;
- uint32_t master_nodeid;
- uint16_t length;
- char name[1];
-};
-
-struct dlm_dirtable {
- struct list_head list;
- spinlock_t lock;
-};
-
-struct dlm_rsbtable {
- struct rb_root keep;
- struct rb_root toss;
- spinlock_t lock;
-};
-
-
-/*
- * Lockspace member (per node in a ls)
- */
-
-struct dlm_member {
- struct list_head list;
- int nodeid;
- int weight;
- int slot;
- int slot_prev;
- int comm_seq;
- uint32_t generation;
-};
-
-/*
- * Save and manage recovery state for a lockspace.
- */
-
-struct dlm_recover {
- struct list_head list;
- struct dlm_config_node *nodes;
- int nodes_count;
- uint64_t seq;
-};
-
-/*
- * Pass input args to second stage locking function.
- */
-
-struct dlm_args {
- uint32_t flags;
- void (*astfn) (void *astparam);
- void *astparam;
- void (*bastfn) (void *astparam, int mode);
- int mode;
- struct dlm_lksb *lksb;
- unsigned long timeout;
-};
-
-
-/*
- * Lock block
- *
- * A lock can be one of three types:
- *
- * local copy lock is mastered locally
- * (lkb_nodeid is zero and DLM_LKF_MSTCPY is not set)
- * process copy lock is mastered on a remote node
- * (lkb_nodeid is non-zero and DLM_LKF_MSTCPY is not set)
- * master copy master node's copy of a lock owned by remote node
- * (lkb_nodeid is non-zero and DLM_LKF_MSTCPY is set)
- *
- * lkb_exflags: a copy of the most recent flags arg provided to dlm_lock or
- * dlm_unlock. The dlm does not modify these or use any private flags in
- * this field; it only contains DLM_LKF_ flags from dlm.h. These flags
- * are sent as-is to the remote master when the lock is remote.
- *
- * lkb_flags: internal dlm flags (DLM_IFL_ prefix) from dlm_internal.h.
- * Some internal flags are shared between the master and process nodes;
- * these shared flags are kept in the lower two bytes. One of these
- * flags set on the master copy will be propagated to the process copy
- * and v.v. Other internal flags are private to the master or process
- * node (e.g. DLM_IFL_MSTCPY). These are kept in the high two bytes.
- *
- * lkb_sbflags: status block flags. These flags are copied directly into
- * the caller's lksb.sb_flags prior to the dlm_lock/dlm_unlock completion
- * ast. All defined in dlm.h with DLM_SBF_ prefix.
- *
- * lkb_status: the lock status indicates which rsb queue the lock is
- * on, grant, convert, or wait. DLM_LKSTS_ WAITING/GRANTED/CONVERT
- *
- * lkb_wait_type: the dlm message type (DLM_MSG_ prefix) for which a
- * reply is needed. Only set when the lkb is on the lockspace waiters
- * list awaiting a reply from a remote node.
- *
- * lkb_nodeid: when the lkb is a local copy, nodeid is 0; when the lkb
- * is a master copy, nodeid specifies the remote lock holder, when the
- * lkb is a process copy, the nodeid specifies the lock master.
- */
-
-/* lkb_status */
-
-#define DLM_LKSTS_WAITING 1
-#define DLM_LKSTS_GRANTED 2
-#define DLM_LKSTS_CONVERT 3
-
-/* lkb_flags */
-
-#define DLM_IFL_MSTCPY 0x00010000
-#define DLM_IFL_RESEND 0x00020000
-#define DLM_IFL_DEAD 0x00040000
-#define DLM_IFL_OVERLAP_UNLOCK 0x00080000
-#define DLM_IFL_OVERLAP_CANCEL 0x00100000
-#define DLM_IFL_ENDOFLIFE 0x00200000
-#define DLM_IFL_WATCH_TIMEWARN 0x00400000
-#define DLM_IFL_TIMEOUT_CANCEL 0x00800000
-#define DLM_IFL_DEADLOCK_CANCEL 0x01000000
-#define DLM_IFL_STUB_MS 0x02000000 /* magic number for m_flags */
-#define DLM_IFL_USER 0x00000001
-#define DLM_IFL_ORPHAN 0x00000002
-
-#define DLM_CALLBACKS_SIZE 6
-
-#define DLM_CB_CAST 0x00000001
-#define DLM_CB_BAST 0x00000002
-#define DLM_CB_SKIP 0x00000004
-
-struct dlm_callback {
- uint64_t seq;
- uint32_t flags; /* DLM_CBF_ */
- int sb_status; /* copy to lksb status */
- uint8_t sb_flags; /* copy to lksb flags */
- int8_t mode; /* rq mode of bast, gr mode of cast */
-};
-
-struct dlm_lkb {
- struct dlm_rsb *lkb_resource; /* the rsb */
- struct kref lkb_ref;
- int lkb_nodeid; /* copied from rsb */
- int lkb_ownpid; /* pid of lock owner */
- uint32_t lkb_id; /* our lock ID */
- uint32_t lkb_remid; /* lock ID on remote partner */
- uint32_t lkb_exflags; /* external flags from caller */
- uint32_t lkb_sbflags; /* lksb flags */
- uint32_t lkb_flags; /* internal flags */
- uint32_t lkb_lvbseq; /* lvb sequence number */
-
- int8_t lkb_status; /* granted, waiting, convert */
- int8_t lkb_rqmode; /* requested lock mode */
- int8_t lkb_grmode; /* granted lock mode */
- int8_t lkb_highbast; /* highest mode bast sent for */
-
- int8_t lkb_wait_type; /* type of reply waiting for */
- int8_t lkb_wait_count;
- int lkb_wait_nodeid; /* for debugging */
-
- struct list_head lkb_statequeue; /* rsb g/c/w list */
- struct list_head lkb_rsb_lookup; /* waiting for rsb lookup */
- struct list_head lkb_wait_reply; /* waiting for remote reply */
- struct list_head lkb_ownqueue; /* list of locks for a process */
- struct list_head lkb_time_list;
- ktime_t lkb_timestamp;
- ktime_t lkb_wait_time;
- unsigned long lkb_timeout_cs;
-
- struct mutex lkb_cb_mutex;
- struct work_struct lkb_cb_work;
- struct list_head lkb_cb_list; /* for ls_cb_delay or proc->asts */
- struct dlm_callback lkb_callbacks[DLM_CALLBACKS_SIZE];
- struct dlm_callback lkb_last_cast;
- struct dlm_callback lkb_last_bast;
- ktime_t lkb_last_cast_time; /* for debugging */
- ktime_t lkb_last_bast_time; /* for debugging */
-
- char *lkb_lvbptr;
- struct dlm_lksb *lkb_lksb; /* caller's status block */
- void (*lkb_astfn) (void *astparam);
- void (*lkb_bastfn) (void *astparam, int mode);
- union {
- void *lkb_astparam; /* caller's ast arg */
- struct dlm_user_args *lkb_ua;
- };
-};
-
-
-struct dlm_rsb {
- struct dlm_ls *res_ls; /* the lockspace */
- struct kref res_ref;
- struct mutex res_mutex;
- unsigned long res_flags;
- int res_length; /* length of rsb name */
- int res_nodeid;
- uint32_t res_lvbseq;
- uint32_t res_hash;
- uint32_t res_bucket; /* rsbtbl */
- unsigned long res_toss_time;
- uint32_t res_first_lkid;
- struct list_head res_lookup; /* lkbs waiting on first */
- union {
- struct list_head res_hashchain;
- struct rb_node res_hashnode; /* rsbtbl */
- };
- struct list_head res_grantqueue;
- struct list_head res_convertqueue;
- struct list_head res_waitqueue;
-
- struct list_head res_root_list; /* used for recovery */
- struct list_head res_recover_list; /* used for recovery */
- int res_recover_locks_count;
-
- char *res_lvbptr;
- char res_name[DLM_RESNAME_MAXLEN+1];
-};
-
-/* find_rsb() flags */
-
-#define R_MASTER 1 /* only return rsb if it's a master */
-#define R_CREATE 2 /* create/add rsb if not found */
-
-/* rsb_flags */
-
-enum rsb_flags {
- RSB_MASTER_UNCERTAIN,
- RSB_VALNOTVALID,
- RSB_VALNOTVALID_PREV,
- RSB_NEW_MASTER,
- RSB_NEW_MASTER2,
- RSB_RECOVER_CONVERT,
- RSB_LOCKS_PURGED,
-};
-
-static inline void rsb_set_flag(struct dlm_rsb *r, enum rsb_flags flag)
-{
- __set_bit(flag, &r->res_flags);
-}
-
-static inline void rsb_clear_flag(struct dlm_rsb *r, enum rsb_flags flag)
-{
- __clear_bit(flag, &r->res_flags);
-}
-
-static inline int rsb_flag(struct dlm_rsb *r, enum rsb_flags flag)
-{
- return test_bit(flag, &r->res_flags);
-}
-
-
-/* dlm_header is first element of all structs sent between nodes */
-
-#define DLM_HEADER_MAJOR 0x00030000
-#define DLM_HEADER_MINOR 0x00000001
-
-#define DLM_HEADER_SLOTS 0x00000001
-
-#define DLM_MSG 1
-#define DLM_RCOM 2
-
-struct dlm_header {
- uint32_t h_version;
- uint32_t h_lockspace;
- uint32_t h_nodeid; /* nodeid of sender */
- uint16_t h_length;
- uint8_t h_cmd; /* DLM_MSG, DLM_RCOM */
- uint8_t h_pad;
-};
-
-
-#define DLM_MSG_REQUEST 1
-#define DLM_MSG_CONVERT 2
-#define DLM_MSG_UNLOCK 3
-#define DLM_MSG_CANCEL 4
-#define DLM_MSG_REQUEST_REPLY 5
-#define DLM_MSG_CONVERT_REPLY 6
-#define DLM_MSG_UNLOCK_REPLY 7
-#define DLM_MSG_CANCEL_REPLY 8
-#define DLM_MSG_GRANT 9
-#define DLM_MSG_BAST 10
-#define DLM_MSG_LOOKUP 11
-#define DLM_MSG_REMOVE 12
-#define DLM_MSG_LOOKUP_REPLY 13
-#define DLM_MSG_PURGE 14
-
-struct dlm_message {
- struct dlm_header m_header;
- uint32_t m_type; /* DLM_MSG_ */
- uint32_t m_nodeid;
- uint32_t m_pid;
- uint32_t m_lkid; /* lkid on sender */
- uint32_t m_remid; /* lkid on receiver */
- uint32_t m_parent_lkid;
- uint32_t m_parent_remid;
- uint32_t m_exflags;
- uint32_t m_sbflags;
- uint32_t m_flags;
- uint32_t m_lvbseq;
- uint32_t m_hash;
- int m_status;
- int m_grmode;
- int m_rqmode;
- int m_bastmode;
- int m_asts;
- int m_result; /* 0 or -EXXX */
- char m_extra[0]; /* name or lvb */
-};
-
-
-#define DLM_RS_NODES 0x00000001
-#define DLM_RS_NODES_ALL 0x00000002
-#define DLM_RS_DIR 0x00000004
-#define DLM_RS_DIR_ALL 0x00000008
-#define DLM_RS_LOCKS 0x00000010
-#define DLM_RS_LOCKS_ALL 0x00000020
-#define DLM_RS_DONE 0x00000040
-#define DLM_RS_DONE_ALL 0x00000080
-
-#define DLM_RCOM_STATUS 1
-#define DLM_RCOM_NAMES 2
-#define DLM_RCOM_LOOKUP 3
-#define DLM_RCOM_LOCK 4
-#define DLM_RCOM_STATUS_REPLY 5
-#define DLM_RCOM_NAMES_REPLY 6
-#define DLM_RCOM_LOOKUP_REPLY 7
-#define DLM_RCOM_LOCK_REPLY 8
-
-struct dlm_rcom {
- struct dlm_header rc_header;
- uint32_t rc_type; /* DLM_RCOM_ */
- int rc_result; /* multi-purpose */
- uint64_t rc_id; /* match reply with request */
- uint64_t rc_seq; /* sender's ls_recover_seq */
- uint64_t rc_seq_reply; /* remote ls_recover_seq */
- char rc_buf[0];
-};
-
-union dlm_packet {
- struct dlm_header header; /* common to other two */
- struct dlm_message message;
- struct dlm_rcom rcom;
-};
-
-#define DLM_RSF_NEED_SLOTS 0x00000001
-
-/* RCOM_STATUS data */
-struct rcom_status {
- __le32 rs_flags;
- __le32 rs_unused1;
- __le64 rs_unused2;
-};
-
-/* RCOM_STATUS_REPLY data */
-struct rcom_config {
- __le32 rf_lvblen;
- __le32 rf_lsflags;
-
- /* DLM_HEADER_SLOTS adds: */
- __le32 rf_flags;
- __le16 rf_our_slot;
- __le16 rf_num_slots;
- __le32 rf_generation;
- __le32 rf_unused1;
- __le64 rf_unused2;
-};
-
-struct rcom_slot {
- __le32 ro_nodeid;
- __le16 ro_slot;
- __le16 ro_unused1;
- __le64 ro_unused2;
-};
-
-struct rcom_lock {
- __le32 rl_ownpid;
- __le32 rl_lkid;
- __le32 rl_remid;
- __le32 rl_parent_lkid;
- __le32 rl_parent_remid;
- __le32 rl_exflags;
- __le32 rl_flags;
- __le32 rl_lvbseq;
- __le32 rl_result;
- int8_t rl_rqmode;
- int8_t rl_grmode;
- int8_t rl_status;
- int8_t rl_asts;
- __le16 rl_wait_type;
- __le16 rl_namelen;
- char rl_name[DLM_RESNAME_MAXLEN];
- char rl_lvb[0];
-};
-
-struct dlm_ls {
- struct list_head ls_list; /* list of lockspaces */
- dlm_lockspace_t *ls_local_handle;
- uint32_t ls_global_id; /* global unique lockspace ID */
- uint32_t ls_generation;
- uint32_t ls_exflags;
- int ls_lvblen;
- int ls_count; /* refcount of processes in
- the dlm using this ls */
- int ls_create_count; /* create/release refcount */
- unsigned long ls_flags; /* LSFL_ */
- unsigned long ls_scan_time;
- struct kobject ls_kobj;
-
- struct idr ls_lkbidr;
- spinlock_t ls_lkbidr_spin;
-
- struct dlm_rsbtable *ls_rsbtbl;
- uint32_t ls_rsbtbl_size;
-
- struct dlm_dirtable *ls_dirtbl;
- uint32_t ls_dirtbl_size;
-
- struct mutex ls_waiters_mutex;
- struct list_head ls_waiters; /* lkbs needing a reply */
-
- struct mutex ls_orphans_mutex;
- struct list_head ls_orphans;
-
- struct mutex ls_timeout_mutex;
- struct list_head ls_timeout;
-
- spinlock_t ls_new_rsb_spin;
- int ls_new_rsb_count;
- struct list_head ls_new_rsb; /* new rsb structs */
-
- struct list_head ls_nodes; /* current nodes in ls */
- struct list_head ls_nodes_gone; /* dead node list, recovery */
- int ls_num_nodes; /* number of nodes in ls */
- int ls_low_nodeid;
- int ls_total_weight;
- int *ls_node_array;
-
- int ls_slot;
- int ls_num_slots;
- int ls_slots_size;
- struct dlm_slot *ls_slots;
-
- struct dlm_rsb ls_stub_rsb; /* for returning errors */
- struct dlm_lkb ls_stub_lkb; /* for returning errors */
- struct dlm_message ls_stub_ms; /* for faking a reply */
-
- struct dentry *ls_debug_rsb_dentry; /* debugfs */
- struct dentry *ls_debug_waiters_dentry; /* debugfs */
- struct dentry *ls_debug_locks_dentry; /* debugfs */
- struct dentry *ls_debug_all_dentry; /* debugfs */
-
- wait_queue_head_t ls_uevent_wait; /* user part of join/leave */
- int ls_uevent_result;
- struct completion ls_members_done;
- int ls_members_result;
-
- struct miscdevice ls_device;
-
- struct workqueue_struct *ls_callback_wq;
-
- /* recovery related */
-
- struct mutex ls_cb_mutex;
- struct list_head ls_cb_delay; /* save for queue_work later */
- struct timer_list ls_timer;
- struct task_struct *ls_recoverd_task;
- struct mutex ls_recoverd_active;
- spinlock_t ls_recover_lock;
- unsigned long ls_recover_begin; /* jiffies timestamp */
- uint32_t ls_recover_status; /* DLM_RS_ */
- uint64_t ls_recover_seq;
- struct dlm_recover *ls_recover_args;
- struct rw_semaphore ls_in_recovery; /* block local requests */
- struct rw_semaphore ls_recv_active; /* block dlm_recv */
- struct list_head ls_requestqueue;/* queue remote requests */
- struct mutex ls_requestqueue_mutex;
- struct dlm_rcom *ls_recover_buf;
- int ls_recover_nodeid; /* for debugging */
- uint64_t ls_rcom_seq;
- spinlock_t ls_rcom_spin;
- struct list_head ls_recover_list;
- spinlock_t ls_recover_list_lock;
- int ls_recover_list_count;
- wait_queue_head_t ls_wait_general;
- struct mutex ls_clear_proc_locks;
-
- struct list_head ls_root_list; /* root resources */
- struct rw_semaphore ls_root_sem; /* protect root_list */
-
- const struct dlm_lockspace_ops *ls_ops;
- void *ls_ops_arg;
-
- int ls_namelen;
- char ls_name[1];
-};
-
-#define LSFL_WORK 0
-#define LSFL_RUNNING 1
-#define LSFL_RECOVERY_STOP 2
-#define LSFL_RCOM_READY 3
-#define LSFL_RCOM_WAIT 4
-#define LSFL_UEVENT_WAIT 5
-#define LSFL_TIMEWARN 6
-#define LSFL_CB_DELAY 7
-
-/* much of this is just saving user space pointers associated with the
- lock that we pass back to the user lib with an ast */
-
-struct dlm_user_args {
- struct dlm_user_proc *proc; /* each process that opens the lockspace
- device has private data
- (dlm_user_proc) on the struct file,
- the process's locks point back to it*/
- struct dlm_lksb lksb;
- struct dlm_lksb __user *user_lksb;
- void __user *castparam;
- void __user *castaddr;
- void __user *bastparam;
- void __user *bastaddr;
- uint64_t xid;
-};
-
-#define DLM_PROC_FLAGS_CLOSING 1
-#define DLM_PROC_FLAGS_COMPAT 2
-
-/* locks list is kept so we can remove all a process's locks when it
- exits (or orphan those that are persistent) */
-
-struct dlm_user_proc {
- dlm_lockspace_t *lockspace;
- unsigned long flags; /* DLM_PROC_FLAGS */
- struct list_head asts;
- spinlock_t asts_spin;
- struct list_head locks;
- spinlock_t locks_spin;
- struct list_head unlocking;
- wait_queue_head_t wait;
-};
-
-static inline int dlm_locking_stopped(struct dlm_ls *ls)
-{
- return !test_bit(LSFL_RUNNING, &ls->ls_flags);
-}
-
-static inline int dlm_recovery_stopped(struct dlm_ls *ls)
-{
- return test_bit(LSFL_RECOVERY_STOP, &ls->ls_flags);
-}
-
-static inline int dlm_no_directory(struct dlm_ls *ls)
-{
- return (ls->ls_exflags & DLM_LSFL_NODIR) ? 1 : 0;
-}
-
-int dlm_netlink_init(void);
-void dlm_netlink_exit(void);
-void dlm_timeout_warn(struct dlm_lkb *lkb);
-int dlm_plock_init(void);
-void dlm_plock_exit(void);
-
-#ifdef CONFIG_DLM_DEBUG
-int dlm_register_debugfs(void);
-void dlm_unregister_debugfs(void);
-int dlm_create_debug_file(struct dlm_ls *ls);
-void dlm_delete_debug_file(struct dlm_ls *ls);
-#else
-static inline int dlm_register_debugfs(void) { return 0; }
-static inline void dlm_unregister_debugfs(void) { }
-static inline int dlm_create_debug_file(struct dlm_ls *ls) { return 0; }
-static inline void dlm_delete_debug_file(struct dlm_ls *ls) { }
-#endif
-
-#endif /* __DLM_INTERNAL_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/lock.c b/ANDROID_3.4.5/fs/dlm/lock.c
deleted file mode 100644
index 4c58d4a3..00000000
--- a/ANDROID_3.4.5/fs/dlm/lock.c
+++ /dev/null
@@ -1,5197 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005-2010 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-/* Central locking logic has four stages:
-
- dlm_lock()
- dlm_unlock()
-
- request_lock(ls, lkb)
- convert_lock(ls, lkb)
- unlock_lock(ls, lkb)
- cancel_lock(ls, lkb)
-
- _request_lock(r, lkb)
- _convert_lock(r, lkb)
- _unlock_lock(r, lkb)
- _cancel_lock(r, lkb)
-
- do_request(r, lkb)
- do_convert(r, lkb)
- do_unlock(r, lkb)
- do_cancel(r, lkb)
-
- Stage 1 (lock, unlock) is mainly about checking input args and
- splitting into one of the four main operations:
-
- dlm_lock = request_lock
- dlm_lock+CONVERT = convert_lock
- dlm_unlock = unlock_lock
- dlm_unlock+CANCEL = cancel_lock
-
- Stage 2, xxxx_lock(), just finds and locks the relevant rsb which is
- provided to the next stage.
-
- Stage 3, _xxxx_lock(), determines if the operation is local or remote.
- When remote, it calls send_xxxx(), when local it calls do_xxxx().
-
- Stage 4, do_xxxx(), is the guts of the operation. It manipulates the
- given rsb and lkb and queues callbacks.
-
- For remote operations, send_xxxx() results in the corresponding do_xxxx()
- function being executed on the remote node. The connecting send/receive
- calls on local (L) and remote (R) nodes:
-
- L: send_xxxx() -> R: receive_xxxx()
- R: do_xxxx()
- L: receive_xxxx_reply() <- R: send_xxxx_reply()
-*/
-#include <linux/types.h>
-#include <linux/rbtree.h>
-#include <linux/slab.h>
-#include "dlm_internal.h"
-#include <linux/dlm_device.h>
-#include "memory.h"
-#include "lowcomms.h"
-#include "requestqueue.h"
-#include "util.h"
-#include "dir.h"
-#include "member.h"
-#include "lockspace.h"
-#include "ast.h"
-#include "lock.h"
-#include "rcom.h"
-#include "recover.h"
-#include "lvb_table.h"
-#include "user.h"
-#include "config.h"
-
-static int send_request(struct dlm_rsb *r, struct dlm_lkb *lkb);
-static int send_convert(struct dlm_rsb *r, struct dlm_lkb *lkb);
-static int send_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb);
-static int send_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb);
-static int send_grant(struct dlm_rsb *r, struct dlm_lkb *lkb);
-static int send_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int mode);
-static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb);
-static int send_remove(struct dlm_rsb *r);
-static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
-static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
-static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
- struct dlm_message *ms);
-static int receive_extralen(struct dlm_message *ms);
-static void do_purge(struct dlm_ls *ls, int nodeid, int pid);
-static void del_timeout(struct dlm_lkb *lkb);
-
-/*
- * Lock compatibilty matrix - thanks Steve
- * UN = Unlocked state. Not really a state, used as a flag
- * PD = Padding. Used to make the matrix a nice power of two in size
- * Other states are the same as the VMS DLM.
- * Usage: matrix[grmode+1][rqmode+1] (although m[rq+1][gr+1] is the same)
- */
-
-static const int __dlm_compat_matrix[8][8] = {
- /* UN NL CR CW PR PW EX PD */
- {1, 1, 1, 1, 1, 1, 1, 0}, /* UN */
- {1, 1, 1, 1, 1, 1, 1, 0}, /* NL */
- {1, 1, 1, 1, 1, 1, 0, 0}, /* CR */
- {1, 1, 1, 1, 0, 0, 0, 0}, /* CW */
- {1, 1, 1, 0, 1, 0, 0, 0}, /* PR */
- {1, 1, 1, 0, 0, 0, 0, 0}, /* PW */
- {1, 1, 0, 0, 0, 0, 0, 0}, /* EX */
- {0, 0, 0, 0, 0, 0, 0, 0} /* PD */
-};
-
-/*
- * This defines the direction of transfer of LVB data.
- * Granted mode is the row; requested mode is the column.
- * Usage: matrix[grmode+1][rqmode+1]
- * 1 = LVB is returned to the caller
- * 0 = LVB is written to the resource
- * -1 = nothing happens to the LVB
- */
-
-const int dlm_lvb_operations[8][8] = {
- /* UN NL CR CW PR PW EX PD*/
- { -1, 1, 1, 1, 1, 1, 1, -1 }, /* UN */
- { -1, 1, 1, 1, 1, 1, 1, 0 }, /* NL */
- { -1, -1, 1, 1, 1, 1, 1, 0 }, /* CR */
- { -1, -1, -1, 1, 1, 1, 1, 0 }, /* CW */
- { -1, -1, -1, -1, 1, 1, 1, 0 }, /* PR */
- { -1, 0, 0, 0, 0, 0, 1, 0 }, /* PW */
- { -1, 0, 0, 0, 0, 0, 0, 0 }, /* EX */
- { -1, 0, 0, 0, 0, 0, 0, 0 } /* PD */
-};
-
-#define modes_compat(gr, rq) \
- __dlm_compat_matrix[(gr)->lkb_grmode + 1][(rq)->lkb_rqmode + 1]
-
-int dlm_modes_compat(int mode1, int mode2)
-{
- return __dlm_compat_matrix[mode1 + 1][mode2 + 1];
-}
-
-/*
- * Compatibility matrix for conversions with QUECVT set.
- * Granted mode is the row; requested mode is the column.
- * Usage: matrix[grmode+1][rqmode+1]
- */
-
-static const int __quecvt_compat_matrix[8][8] = {
- /* UN NL CR CW PR PW EX PD */
- {0, 0, 0, 0, 0, 0, 0, 0}, /* UN */
- {0, 0, 1, 1, 1, 1, 1, 0}, /* NL */
- {0, 0, 0, 1, 1, 1, 1, 0}, /* CR */
- {0, 0, 0, 0, 1, 1, 1, 0}, /* CW */
- {0, 0, 0, 1, 0, 1, 1, 0}, /* PR */
- {0, 0, 0, 0, 0, 0, 1, 0}, /* PW */
- {0, 0, 0, 0, 0, 0, 0, 0}, /* EX */
- {0, 0, 0, 0, 0, 0, 0, 0} /* PD */
-};
-
-void dlm_print_lkb(struct dlm_lkb *lkb)
-{
- printk(KERN_ERR "lkb: nodeid %d id %x remid %x exflags %x flags %x\n"
- " status %d rqmode %d grmode %d wait_type %d\n",
- lkb->lkb_nodeid, lkb->lkb_id, lkb->lkb_remid, lkb->lkb_exflags,
- lkb->lkb_flags, lkb->lkb_status, lkb->lkb_rqmode,
- lkb->lkb_grmode, lkb->lkb_wait_type);
-}
-
-static void dlm_print_rsb(struct dlm_rsb *r)
-{
- printk(KERN_ERR "rsb: nodeid %d flags %lx first %x rlc %d name %s\n",
- r->res_nodeid, r->res_flags, r->res_first_lkid,
- r->res_recover_locks_count, r->res_name);
-}
-
-void dlm_dump_rsb(struct dlm_rsb *r)
-{
- struct dlm_lkb *lkb;
-
- dlm_print_rsb(r);
-
- printk(KERN_ERR "rsb: root_list empty %d recover_list empty %d\n",
- list_empty(&r->res_root_list), list_empty(&r->res_recover_list));
- printk(KERN_ERR "rsb lookup list\n");
- list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup)
- dlm_print_lkb(lkb);
- printk(KERN_ERR "rsb grant queue:\n");
- list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
- dlm_print_lkb(lkb);
- printk(KERN_ERR "rsb convert queue:\n");
- list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
- dlm_print_lkb(lkb);
- printk(KERN_ERR "rsb wait queue:\n");
- list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
- dlm_print_lkb(lkb);
-}
-
-/* Threads cannot use the lockspace while it's being recovered */
-
-static inline void dlm_lock_recovery(struct dlm_ls *ls)
-{
- down_read(&ls->ls_in_recovery);
-}
-
-void dlm_unlock_recovery(struct dlm_ls *ls)
-{
- up_read(&ls->ls_in_recovery);
-}
-
-int dlm_lock_recovery_try(struct dlm_ls *ls)
-{
- return down_read_trylock(&ls->ls_in_recovery);
-}
-
-static inline int can_be_queued(struct dlm_lkb *lkb)
-{
- return !(lkb->lkb_exflags & DLM_LKF_NOQUEUE);
-}
-
-static inline int force_blocking_asts(struct dlm_lkb *lkb)
-{
- return (lkb->lkb_exflags & DLM_LKF_NOQUEUEBAST);
-}
-
-static inline int is_demoted(struct dlm_lkb *lkb)
-{
- return (lkb->lkb_sbflags & DLM_SBF_DEMOTED);
-}
-
-static inline int is_altmode(struct dlm_lkb *lkb)
-{
- return (lkb->lkb_sbflags & DLM_SBF_ALTMODE);
-}
-
-static inline int is_granted(struct dlm_lkb *lkb)
-{
- return (lkb->lkb_status == DLM_LKSTS_GRANTED);
-}
-
-static inline int is_remote(struct dlm_rsb *r)
-{
- DLM_ASSERT(r->res_nodeid >= 0, dlm_print_rsb(r););
- return !!r->res_nodeid;
-}
-
-static inline int is_process_copy(struct dlm_lkb *lkb)
-{
- return (lkb->lkb_nodeid && !(lkb->lkb_flags & DLM_IFL_MSTCPY));
-}
-
-static inline int is_master_copy(struct dlm_lkb *lkb)
-{
- if (lkb->lkb_flags & DLM_IFL_MSTCPY)
- DLM_ASSERT(lkb->lkb_nodeid, dlm_print_lkb(lkb););
- return (lkb->lkb_flags & DLM_IFL_MSTCPY) ? 1 : 0;
-}
-
-static inline int middle_conversion(struct dlm_lkb *lkb)
-{
- if ((lkb->lkb_grmode==DLM_LOCK_PR && lkb->lkb_rqmode==DLM_LOCK_CW) ||
- (lkb->lkb_rqmode==DLM_LOCK_PR && lkb->lkb_grmode==DLM_LOCK_CW))
- return 1;
- return 0;
-}
-
-static inline int down_conversion(struct dlm_lkb *lkb)
-{
- return (!middle_conversion(lkb) && lkb->lkb_rqmode < lkb->lkb_grmode);
-}
-
-static inline int is_overlap_unlock(struct dlm_lkb *lkb)
-{
- return lkb->lkb_flags & DLM_IFL_OVERLAP_UNLOCK;
-}
-
-static inline int is_overlap_cancel(struct dlm_lkb *lkb)
-{
- return lkb->lkb_flags & DLM_IFL_OVERLAP_CANCEL;
-}
-
-static inline int is_overlap(struct dlm_lkb *lkb)
-{
- return (lkb->lkb_flags & (DLM_IFL_OVERLAP_UNLOCK |
- DLM_IFL_OVERLAP_CANCEL));
-}
-
-static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
-{
- if (is_master_copy(lkb))
- return;
-
- del_timeout(lkb);
-
- DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb););
-
- /* if the operation was a cancel, then return -DLM_ECANCEL, if a
- timeout caused the cancel then return -ETIMEDOUT */
- if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_TIMEOUT_CANCEL)) {
- lkb->lkb_flags &= ~DLM_IFL_TIMEOUT_CANCEL;
- rv = -ETIMEDOUT;
- }
-
- if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_DEADLOCK_CANCEL)) {
- lkb->lkb_flags &= ~DLM_IFL_DEADLOCK_CANCEL;
- rv = -EDEADLK;
- }
-
- dlm_add_cb(lkb, DLM_CB_CAST, lkb->lkb_grmode, rv, lkb->lkb_sbflags);
-}
-
-static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- queue_cast(r, lkb,
- is_overlap_unlock(lkb) ? -DLM_EUNLOCK : -DLM_ECANCEL);
-}
-
-static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
-{
- if (is_master_copy(lkb)) {
- send_bast(r, lkb, rqmode);
- } else {
- dlm_add_cb(lkb, DLM_CB_BAST, rqmode, 0, 0);
- }
-}
-
-/*
- * Basic operations on rsb's and lkb's
- */
-
-static int pre_rsb_struct(struct dlm_ls *ls)
-{
- struct dlm_rsb *r1, *r2;
- int count = 0;
-
- spin_lock(&ls->ls_new_rsb_spin);
- if (ls->ls_new_rsb_count > dlm_config.ci_new_rsb_count / 2) {
- spin_unlock(&ls->ls_new_rsb_spin);
- return 0;
- }
- spin_unlock(&ls->ls_new_rsb_spin);
-
- r1 = dlm_allocate_rsb(ls);
- r2 = dlm_allocate_rsb(ls);
-
- spin_lock(&ls->ls_new_rsb_spin);
- if (r1) {
- list_add(&r1->res_hashchain, &ls->ls_new_rsb);
- ls->ls_new_rsb_count++;
- }
- if (r2) {
- list_add(&r2->res_hashchain, &ls->ls_new_rsb);
- ls->ls_new_rsb_count++;
- }
- count = ls->ls_new_rsb_count;
- spin_unlock(&ls->ls_new_rsb_spin);
-
- if (!count)
- return -ENOMEM;
- return 0;
-}
-
-/* If ls->ls_new_rsb is empty, return -EAGAIN, so the caller can
- unlock any spinlocks, go back and call pre_rsb_struct again.
- Otherwise, take an rsb off the list and return it. */
-
-static int get_rsb_struct(struct dlm_ls *ls, char *name, int len,
- struct dlm_rsb **r_ret)
-{
- struct dlm_rsb *r;
- int count;
-
- spin_lock(&ls->ls_new_rsb_spin);
- if (list_empty(&ls->ls_new_rsb)) {
- count = ls->ls_new_rsb_count;
- spin_unlock(&ls->ls_new_rsb_spin);
- log_debug(ls, "find_rsb retry %d %d %s",
- count, dlm_config.ci_new_rsb_count, name);
- return -EAGAIN;
- }
-
- r = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, res_hashchain);
- list_del(&r->res_hashchain);
- /* Convert the empty list_head to a NULL rb_node for tree usage: */
- memset(&r->res_hashnode, 0, sizeof(struct rb_node));
- ls->ls_new_rsb_count--;
- spin_unlock(&ls->ls_new_rsb_spin);
-
- r->res_ls = ls;
- r->res_length = len;
- memcpy(r->res_name, name, len);
- mutex_init(&r->res_mutex);
-
- INIT_LIST_HEAD(&r->res_lookup);
- INIT_LIST_HEAD(&r->res_grantqueue);
- INIT_LIST_HEAD(&r->res_convertqueue);
- INIT_LIST_HEAD(&r->res_waitqueue);
- INIT_LIST_HEAD(&r->res_root_list);
- INIT_LIST_HEAD(&r->res_recover_list);
-
- *r_ret = r;
- return 0;
-}
-
-static int rsb_cmp(struct dlm_rsb *r, const char *name, int nlen)
-{
- char maxname[DLM_RESNAME_MAXLEN];
-
- memset(maxname, 0, DLM_RESNAME_MAXLEN);
- memcpy(maxname, name, nlen);
- return memcmp(r->res_name, maxname, DLM_RESNAME_MAXLEN);
-}
-
-int dlm_search_rsb_tree(struct rb_root *tree, char *name, int len,
- unsigned int flags, struct dlm_rsb **r_ret)
-{
- struct rb_node *node = tree->rb_node;
- struct dlm_rsb *r;
- int error = 0;
- int rc;
-
- while (node) {
- r = rb_entry(node, struct dlm_rsb, res_hashnode);
- rc = rsb_cmp(r, name, len);
- if (rc < 0)
- node = node->rb_left;
- else if (rc > 0)
- node = node->rb_right;
- else
- goto found;
- }
- *r_ret = NULL;
- return -EBADR;
-
- found:
- if (r->res_nodeid && (flags & R_MASTER))
- error = -ENOTBLK;
- *r_ret = r;
- return error;
-}
-
-static int rsb_insert(struct dlm_rsb *rsb, struct rb_root *tree)
-{
- struct rb_node **newn = &tree->rb_node;
- struct rb_node *parent = NULL;
- int rc;
-
- while (*newn) {
- struct dlm_rsb *cur = rb_entry(*newn, struct dlm_rsb,
- res_hashnode);
-
- parent = *newn;
- rc = rsb_cmp(cur, rsb->res_name, rsb->res_length);
- if (rc < 0)
- newn = &parent->rb_left;
- else if (rc > 0)
- newn = &parent->rb_right;
- else {
- log_print("rsb_insert match");
- dlm_dump_rsb(rsb);
- dlm_dump_rsb(cur);
- return -EEXIST;
- }
- }
-
- rb_link_node(&rsb->res_hashnode, parent, newn);
- rb_insert_color(&rsb->res_hashnode, tree);
- return 0;
-}
-
-static int _search_rsb(struct dlm_ls *ls, char *name, int len, int b,
- unsigned int flags, struct dlm_rsb **r_ret)
-{
- struct dlm_rsb *r;
- int error;
-
- error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, flags, &r);
- if (!error) {
- kref_get(&r->res_ref);
- goto out;
- }
- error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, flags, &r);
- if (error)
- goto out;
-
- rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss);
- error = rsb_insert(r, &ls->ls_rsbtbl[b].keep);
- if (error)
- return error;
-
- if (dlm_no_directory(ls))
- goto out;
-
- if (r->res_nodeid == -1) {
- rsb_clear_flag(r, RSB_MASTER_UNCERTAIN);
- r->res_first_lkid = 0;
- } else if (r->res_nodeid > 0) {
- rsb_set_flag(r, RSB_MASTER_UNCERTAIN);
- r->res_first_lkid = 0;
- } else {
- DLM_ASSERT(r->res_nodeid == 0, dlm_print_rsb(r););
- DLM_ASSERT(!rsb_flag(r, RSB_MASTER_UNCERTAIN),);
- }
- out:
- *r_ret = r;
- return error;
-}
-
-/*
- * Find rsb in rsbtbl and potentially create/add one
- *
- * Delaying the release of rsb's has a similar benefit to applications keeping
- * NL locks on an rsb, but without the guarantee that the cached master value
- * will still be valid when the rsb is reused. Apps aren't always smart enough
- * to keep NL locks on an rsb that they may lock again shortly; this can lead
- * to excessive master lookups and removals if we don't delay the release.
- *
- * Searching for an rsb means looking through both the normal list and toss
- * list. When found on the toss list the rsb is moved to the normal list with
- * ref count of 1; when found on normal list the ref count is incremented.
- */
-
-static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
- unsigned int flags, struct dlm_rsb **r_ret)
-{
- struct dlm_rsb *r = NULL;
- uint32_t hash, bucket;
- int error;
-
- if (namelen > DLM_RESNAME_MAXLEN) {
- error = -EINVAL;
- goto out;
- }
-
- if (dlm_no_directory(ls))
- flags |= R_CREATE;
-
- hash = jhash(name, namelen, 0);
- bucket = hash & (ls->ls_rsbtbl_size - 1);
-
- retry:
- if (flags & R_CREATE) {
- error = pre_rsb_struct(ls);
- if (error < 0)
- goto out;
- }
-
- spin_lock(&ls->ls_rsbtbl[bucket].lock);
-
- error = _search_rsb(ls, name, namelen, bucket, flags, &r);
- if (!error)
- goto out_unlock;
-
- if (error == -EBADR && !(flags & R_CREATE))
- goto out_unlock;
-
- /* the rsb was found but wasn't a master copy */
- if (error == -ENOTBLK)
- goto out_unlock;
-
- error = get_rsb_struct(ls, name, namelen, &r);
- if (error == -EAGAIN) {
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- goto retry;
- }
- if (error)
- goto out_unlock;
-
- r->res_hash = hash;
- r->res_bucket = bucket;
- r->res_nodeid = -1;
- kref_init(&r->res_ref);
-
- /* With no directory, the master can be set immediately */
- if (dlm_no_directory(ls)) {
- int nodeid = dlm_dir_nodeid(r);
- if (nodeid == dlm_our_nodeid())
- nodeid = 0;
- r->res_nodeid = nodeid;
- }
- error = rsb_insert(r, &ls->ls_rsbtbl[bucket].keep);
- out_unlock:
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- out:
- *r_ret = r;
- return error;
-}
-
-/* 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. */
-
-static inline void hold_rsb(struct dlm_rsb *r)
-{
- kref_get(&r->res_ref);
-}
-
-void dlm_hold_rsb(struct dlm_rsb *r)
-{
- hold_rsb(r);
-}
-
-static void toss_rsb(struct kref *kref)
-{
- struct dlm_rsb *r = container_of(kref, struct dlm_rsb, res_ref);
- struct dlm_ls *ls = r->res_ls;
-
- DLM_ASSERT(list_empty(&r->res_root_list), dlm_print_rsb(r););
- kref_init(&r->res_ref);
- rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[r->res_bucket].keep);
- rsb_insert(r, &ls->ls_rsbtbl[r->res_bucket].toss);
- r->res_toss_time = jiffies;
- if (r->res_lvbptr) {
- dlm_free_lvb(r->res_lvbptr);
- r->res_lvbptr = NULL;
- }
-}
-
-/* When all references to the rsb are gone it's transferred to
- the tossed list for later disposal. */
-
-static void put_rsb(struct dlm_rsb *r)
-{
- struct dlm_ls *ls = r->res_ls;
- uint32_t bucket = r->res_bucket;
-
- spin_lock(&ls->ls_rsbtbl[bucket].lock);
- kref_put(&r->res_ref, toss_rsb);
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
-}
-
-void dlm_put_rsb(struct dlm_rsb *r)
-{
- put_rsb(r);
-}
-
-/* See comment for unhold_lkb */
-
-static void unhold_rsb(struct dlm_rsb *r)
-{
- int rv;
- rv = kref_put(&r->res_ref, toss_rsb);
- DLM_ASSERT(!rv, dlm_dump_rsb(r););
-}
-
-static void kill_rsb(struct kref *kref)
-{
- struct dlm_rsb *r = container_of(kref, struct dlm_rsb, res_ref);
-
- /* All work is done after the return from kref_put() so we
- can release the write_lock before the remove and free. */
-
- DLM_ASSERT(list_empty(&r->res_lookup), dlm_dump_rsb(r););
- DLM_ASSERT(list_empty(&r->res_grantqueue), dlm_dump_rsb(r););
- DLM_ASSERT(list_empty(&r->res_convertqueue), dlm_dump_rsb(r););
- DLM_ASSERT(list_empty(&r->res_waitqueue), dlm_dump_rsb(r););
- DLM_ASSERT(list_empty(&r->res_root_list), dlm_dump_rsb(r););
- DLM_ASSERT(list_empty(&r->res_recover_list), dlm_dump_rsb(r););
-}
-
-/* Attaching/detaching lkb's from rsb's is for rsb reference counting.
- The rsb must exist as long as any lkb's for it do. */
-
-static void attach_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- hold_rsb(r);
- lkb->lkb_resource = r;
-}
-
-static void detach_lkb(struct dlm_lkb *lkb)
-{
- if (lkb->lkb_resource) {
- put_rsb(lkb->lkb_resource);
- lkb->lkb_resource = NULL;
- }
-}
-
-static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
-{
- struct dlm_lkb *lkb;
- int rv, id;
-
- lkb = dlm_allocate_lkb(ls);
- if (!lkb)
- return -ENOMEM;
-
- lkb->lkb_nodeid = -1;
- lkb->lkb_grmode = DLM_LOCK_IV;
- kref_init(&lkb->lkb_ref);
- INIT_LIST_HEAD(&lkb->lkb_ownqueue);
- INIT_LIST_HEAD(&lkb->lkb_rsb_lookup);
- INIT_LIST_HEAD(&lkb->lkb_time_list);
- INIT_LIST_HEAD(&lkb->lkb_cb_list);
- mutex_init(&lkb->lkb_cb_mutex);
- INIT_WORK(&lkb->lkb_cb_work, dlm_callback_work);
-
- retry:
- rv = idr_pre_get(&ls->ls_lkbidr, GFP_NOFS);
- if (!rv)
- return -ENOMEM;
-
- spin_lock(&ls->ls_lkbidr_spin);
- rv = idr_get_new_above(&ls->ls_lkbidr, lkb, 1, &id);
- if (!rv)
- lkb->lkb_id = id;
- spin_unlock(&ls->ls_lkbidr_spin);
-
- if (rv == -EAGAIN)
- goto retry;
-
- if (rv < 0) {
- log_error(ls, "create_lkb idr error %d", rv);
- return rv;
- }
-
- *lkb_ret = lkb;
- return 0;
-}
-
-static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret)
-{
- struct dlm_lkb *lkb;
-
- spin_lock(&ls->ls_lkbidr_spin);
- lkb = idr_find(&ls->ls_lkbidr, lkid);
- if (lkb)
- kref_get(&lkb->lkb_ref);
- spin_unlock(&ls->ls_lkbidr_spin);
-
- *lkb_ret = lkb;
- return lkb ? 0 : -ENOENT;
-}
-
-static void kill_lkb(struct kref *kref)
-{
- struct dlm_lkb *lkb = container_of(kref, struct dlm_lkb, lkb_ref);
-
- /* All work is done after the return from kref_put() so we
- can release the write_lock before the detach_lkb */
-
- DLM_ASSERT(!lkb->lkb_status, dlm_print_lkb(lkb););
-}
-
-/* __put_lkb() is used when an lkb may not have an rsb attached to
- it so we need to provide the lockspace explicitly */
-
-static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb)
-{
- uint32_t lkid = lkb->lkb_id;
-
- spin_lock(&ls->ls_lkbidr_spin);
- if (kref_put(&lkb->lkb_ref, kill_lkb)) {
- idr_remove(&ls->ls_lkbidr, lkid);
- spin_unlock(&ls->ls_lkbidr_spin);
-
- detach_lkb(lkb);
-
- /* for local/process lkbs, lvbptr points to caller's lksb */
- if (lkb->lkb_lvbptr && is_master_copy(lkb))
- dlm_free_lvb(lkb->lkb_lvbptr);
- dlm_free_lkb(lkb);
- return 1;
- } else {
- spin_unlock(&ls->ls_lkbidr_spin);
- return 0;
- }
-}
-
-int dlm_put_lkb(struct dlm_lkb *lkb)
-{
- struct dlm_ls *ls;
-
- DLM_ASSERT(lkb->lkb_resource, dlm_print_lkb(lkb););
- DLM_ASSERT(lkb->lkb_resource->res_ls, dlm_print_lkb(lkb););
-
- ls = lkb->lkb_resource->res_ls;
- return __put_lkb(ls, lkb);
-}
-
-/* This is only called to add a reference when the code already holds
- a valid reference to the lkb, so there's no need for locking. */
-
-static inline void hold_lkb(struct dlm_lkb *lkb)
-{
- kref_get(&lkb->lkb_ref);
-}
-
-/* This is called when we need to remove a reference and are certain
- it's not the last ref. e.g. del_lkb is always called between a
- find_lkb/put_lkb and is always the inverse of a previous add_lkb.
- put_lkb would work fine, but would involve unnecessary locking */
-
-static inline void unhold_lkb(struct dlm_lkb *lkb)
-{
- int rv;
- rv = kref_put(&lkb->lkb_ref, kill_lkb);
- DLM_ASSERT(!rv, dlm_print_lkb(lkb););
-}
-
-static void lkb_add_ordered(struct list_head *new, struct list_head *head,
- int mode)
-{
- struct dlm_lkb *lkb = NULL;
-
- list_for_each_entry(lkb, head, lkb_statequeue)
- if (lkb->lkb_rqmode < mode)
- break;
-
- __list_add(new, lkb->lkb_statequeue.prev, &lkb->lkb_statequeue);
-}
-
-/* add/remove lkb to rsb's grant/convert/wait queue */
-
-static void add_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb, int status)
-{
- kref_get(&lkb->lkb_ref);
-
- DLM_ASSERT(!lkb->lkb_status, dlm_print_lkb(lkb););
-
- lkb->lkb_timestamp = ktime_get();
-
- lkb->lkb_status = status;
-
- switch (status) {
- case DLM_LKSTS_WAITING:
- if (lkb->lkb_exflags & DLM_LKF_HEADQUE)
- list_add(&lkb->lkb_statequeue, &r->res_waitqueue);
- else
- list_add_tail(&lkb->lkb_statequeue, &r->res_waitqueue);
- break;
- case DLM_LKSTS_GRANTED:
- /* convention says granted locks kept in order of grmode */
- lkb_add_ordered(&lkb->lkb_statequeue, &r->res_grantqueue,
- lkb->lkb_grmode);
- break;
- case DLM_LKSTS_CONVERT:
- if (lkb->lkb_exflags & DLM_LKF_HEADQUE)
- list_add(&lkb->lkb_statequeue, &r->res_convertqueue);
- else
- list_add_tail(&lkb->lkb_statequeue,
- &r->res_convertqueue);
- break;
- default:
- DLM_ASSERT(0, dlm_print_lkb(lkb); printk("sts=%d\n", status););
- }
-}
-
-static void del_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- lkb->lkb_status = 0;
- list_del(&lkb->lkb_statequeue);
- unhold_lkb(lkb);
-}
-
-static void move_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb, int sts)
-{
- hold_lkb(lkb);
- del_lkb(r, lkb);
- add_lkb(r, lkb, sts);
- unhold_lkb(lkb);
-}
-
-static int msg_reply_type(int mstype)
-{
- switch (mstype) {
- case DLM_MSG_REQUEST:
- return DLM_MSG_REQUEST_REPLY;
- case DLM_MSG_CONVERT:
- return DLM_MSG_CONVERT_REPLY;
- case DLM_MSG_UNLOCK:
- return DLM_MSG_UNLOCK_REPLY;
- case DLM_MSG_CANCEL:
- return DLM_MSG_CANCEL_REPLY;
- case DLM_MSG_LOOKUP:
- return DLM_MSG_LOOKUP_REPLY;
- }
- return -1;
-}
-
-static int nodeid_warned(int nodeid, int num_nodes, int *warned)
-{
- int i;
-
- for (i = 0; i < num_nodes; i++) {
- if (!warned[i]) {
- warned[i] = nodeid;
- return 0;
- }
- if (warned[i] == nodeid)
- return 1;
- }
- return 0;
-}
-
-void dlm_scan_waiters(struct dlm_ls *ls)
-{
- struct dlm_lkb *lkb;
- ktime_t zero = ktime_set(0, 0);
- s64 us;
- s64 debug_maxus = 0;
- u32 debug_scanned = 0;
- u32 debug_expired = 0;
- int num_nodes = 0;
- int *warned = NULL;
-
- if (!dlm_config.ci_waitwarn_us)
- return;
-
- mutex_lock(&ls->ls_waiters_mutex);
-
- list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
- if (ktime_equal(lkb->lkb_wait_time, zero))
- continue;
-
- debug_scanned++;
-
- us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_wait_time));
-
- if (us < dlm_config.ci_waitwarn_us)
- continue;
-
- lkb->lkb_wait_time = zero;
-
- debug_expired++;
- if (us > debug_maxus)
- debug_maxus = us;
-
- if (!num_nodes) {
- num_nodes = ls->ls_num_nodes;
- warned = kzalloc(num_nodes * sizeof(int), GFP_KERNEL);
- }
- if (!warned)
- continue;
- if (nodeid_warned(lkb->lkb_wait_nodeid, num_nodes, warned))
- continue;
-
- log_error(ls, "waitwarn %x %lld %d us check connection to "
- "node %d", lkb->lkb_id, (long long)us,
- dlm_config.ci_waitwarn_us, lkb->lkb_wait_nodeid);
- }
- mutex_unlock(&ls->ls_waiters_mutex);
- kfree(warned);
-
- if (debug_expired)
- log_debug(ls, "scan_waiters %u warn %u over %d us max %lld us",
- debug_scanned, debug_expired,
- dlm_config.ci_waitwarn_us, (long long)debug_maxus);
-}
-
-/* add/remove lkb from global waiters list of lkb's waiting for
- a reply from a remote node */
-
-static int add_to_waiters(struct dlm_lkb *lkb, int mstype, int to_nodeid)
-{
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
- int error = 0;
-
- mutex_lock(&ls->ls_waiters_mutex);
-
- if (is_overlap_unlock(lkb) ||
- (is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL))) {
- error = -EINVAL;
- goto out;
- }
-
- if (lkb->lkb_wait_type || is_overlap_cancel(lkb)) {
- switch (mstype) {
- case DLM_MSG_UNLOCK:
- lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
- break;
- case DLM_MSG_CANCEL:
- lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
- break;
- default:
- error = -EBUSY;
- goto out;
- }
- lkb->lkb_wait_count++;
- hold_lkb(lkb);
-
- log_debug(ls, "addwait %x cur %d overlap %d count %d f %x",
- lkb->lkb_id, lkb->lkb_wait_type, mstype,
- lkb->lkb_wait_count, lkb->lkb_flags);
- goto out;
- }
-
- DLM_ASSERT(!lkb->lkb_wait_count,
- dlm_print_lkb(lkb);
- printk("wait_count %d\n", lkb->lkb_wait_count););
-
- lkb->lkb_wait_count++;
- lkb->lkb_wait_type = mstype;
- lkb->lkb_wait_time = ktime_get();
- lkb->lkb_wait_nodeid = to_nodeid; /* for debugging */
- hold_lkb(lkb);
- list_add(&lkb->lkb_wait_reply, &ls->ls_waiters);
- out:
- if (error)
- log_error(ls, "addwait error %x %d flags %x %d %d %s",
- lkb->lkb_id, error, lkb->lkb_flags, mstype,
- lkb->lkb_wait_type, lkb->lkb_resource->res_name);
- mutex_unlock(&ls->ls_waiters_mutex);
- return error;
-}
-
-/* We clear the RESEND flag because we might be taking an lkb off the waiters
- list as part of process_requestqueue (e.g. a lookup that has an optimized
- request reply on the requestqueue) between dlm_recover_waiters_pre() which
- set RESEND and dlm_recover_waiters_post() */
-
-static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype,
- struct dlm_message *ms)
-{
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
- int overlap_done = 0;
-
- if (is_overlap_unlock(lkb) && (mstype == DLM_MSG_UNLOCK_REPLY)) {
- log_debug(ls, "remwait %x unlock_reply overlap", lkb->lkb_id);
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
- overlap_done = 1;
- goto out_del;
- }
-
- if (is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL_REPLY)) {
- log_debug(ls, "remwait %x cancel_reply overlap", lkb->lkb_id);
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
- overlap_done = 1;
- goto out_del;
- }
-
- /* Cancel state was preemptively cleared by a successful convert,
- see next comment, nothing to do. */
-
- if ((mstype == DLM_MSG_CANCEL_REPLY) &&
- (lkb->lkb_wait_type != DLM_MSG_CANCEL)) {
- log_debug(ls, "remwait %x cancel_reply wait_type %d",
- lkb->lkb_id, lkb->lkb_wait_type);
- return -1;
- }
-
- /* Remove for the convert reply, and premptively remove for the
- cancel reply. A convert has been granted while there's still
- an outstanding cancel on it (the cancel is moot and the result
- in the cancel reply should be 0). We preempt the cancel reply
- because the app gets the convert result and then can follow up
- with another op, like convert. This subsequent op would see the
- lingering state of the cancel and fail with -EBUSY. */
-
- if ((mstype == DLM_MSG_CONVERT_REPLY) &&
- (lkb->lkb_wait_type == DLM_MSG_CONVERT) &&
- is_overlap_cancel(lkb) && ms && !ms->m_result) {
- log_debug(ls, "remwait %x convert_reply zap overlap_cancel",
- lkb->lkb_id);
- lkb->lkb_wait_type = 0;
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
- lkb->lkb_wait_count--;
- goto out_del;
- }
-
- /* N.B. type of reply may not always correspond to type of original
- msg due to lookup->request optimization, verify others? */
-
- if (lkb->lkb_wait_type) {
- lkb->lkb_wait_type = 0;
- goto out_del;
- }
-
- log_error(ls, "remwait error %x reply %d flags %x no wait_type",
- lkb->lkb_id, mstype, lkb->lkb_flags);
- return -1;
-
- out_del:
- /* the force-unlock/cancel has completed and we haven't recvd a reply
- to the op that was in progress prior to the unlock/cancel; we
- give up on any reply to the earlier op. FIXME: not sure when/how
- this would happen */
-
- if (overlap_done && lkb->lkb_wait_type) {
- log_error(ls, "remwait error %x reply %d wait_type %d overlap",
- lkb->lkb_id, mstype, lkb->lkb_wait_type);
- lkb->lkb_wait_count--;
- lkb->lkb_wait_type = 0;
- }
-
- DLM_ASSERT(lkb->lkb_wait_count, dlm_print_lkb(lkb););
-
- lkb->lkb_flags &= ~DLM_IFL_RESEND;
- lkb->lkb_wait_count--;
- if (!lkb->lkb_wait_count)
- list_del_init(&lkb->lkb_wait_reply);
- unhold_lkb(lkb);
- return 0;
-}
-
-static int remove_from_waiters(struct dlm_lkb *lkb, int mstype)
-{
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
- int error;
-
- mutex_lock(&ls->ls_waiters_mutex);
- error = _remove_from_waiters(lkb, mstype, NULL);
- mutex_unlock(&ls->ls_waiters_mutex);
- return error;
-}
-
-/* Handles situations where we might be processing a "fake" or "stub" reply in
- which we can't try to take waiters_mutex again. */
-
-static int remove_from_waiters_ms(struct dlm_lkb *lkb, struct dlm_message *ms)
-{
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
- int error;
-
- if (ms->m_flags != DLM_IFL_STUB_MS)
- mutex_lock(&ls->ls_waiters_mutex);
- error = _remove_from_waiters(lkb, ms->m_type, ms);
- if (ms->m_flags != DLM_IFL_STUB_MS)
- mutex_unlock(&ls->ls_waiters_mutex);
- return error;
-}
-
-static void dir_remove(struct dlm_rsb *r)
-{
- int to_nodeid;
-
- if (dlm_no_directory(r->res_ls))
- return;
-
- to_nodeid = dlm_dir_nodeid(r);
- if (to_nodeid != dlm_our_nodeid())
- send_remove(r);
- else
- dlm_dir_remove_entry(r->res_ls, to_nodeid,
- r->res_name, r->res_length);
-}
-
-/* FIXME: make this more efficient */
-
-static int shrink_bucket(struct dlm_ls *ls, int b)
-{
- struct rb_node *n;
- struct dlm_rsb *r;
- int count = 0, found;
-
- for (;;) {
- found = 0;
- spin_lock(&ls->ls_rsbtbl[b].lock);
- for (n = rb_first(&ls->ls_rsbtbl[b].toss); n; n = rb_next(n)) {
- r = rb_entry(n, struct dlm_rsb, res_hashnode);
- if (!time_after_eq(jiffies, r->res_toss_time +
- dlm_config.ci_toss_secs * HZ))
- continue;
- found = 1;
- break;
- }
-
- if (!found) {
- spin_unlock(&ls->ls_rsbtbl[b].lock);
- break;
- }
-
- if (kref_put(&r->res_ref, kill_rsb)) {
- rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss);
- spin_unlock(&ls->ls_rsbtbl[b].lock);
-
- if (is_master(r))
- dir_remove(r);
- dlm_free_rsb(r);
- count++;
- } else {
- spin_unlock(&ls->ls_rsbtbl[b].lock);
- log_error(ls, "tossed rsb in use %s", r->res_name);
- }
- }
-
- return count;
-}
-
-void dlm_scan_rsbs(struct dlm_ls *ls)
-{
- int i;
-
- for (i = 0; i < ls->ls_rsbtbl_size; i++) {
- shrink_bucket(ls, i);
- if (dlm_locking_stopped(ls))
- break;
- cond_resched();
- }
-}
-
-static void add_timeout(struct dlm_lkb *lkb)
-{
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
-
- if (is_master_copy(lkb))
- return;
-
- if (test_bit(LSFL_TIMEWARN, &ls->ls_flags) &&
- !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
- lkb->lkb_flags |= DLM_IFL_WATCH_TIMEWARN;
- goto add_it;
- }
- if (lkb->lkb_exflags & DLM_LKF_TIMEOUT)
- goto add_it;
- return;
-
- add_it:
- DLM_ASSERT(list_empty(&lkb->lkb_time_list), dlm_print_lkb(lkb););
- mutex_lock(&ls->ls_timeout_mutex);
- hold_lkb(lkb);
- list_add_tail(&lkb->lkb_time_list, &ls->ls_timeout);
- mutex_unlock(&ls->ls_timeout_mutex);
-}
-
-static void del_timeout(struct dlm_lkb *lkb)
-{
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
-
- mutex_lock(&ls->ls_timeout_mutex);
- if (!list_empty(&lkb->lkb_time_list)) {
- list_del_init(&lkb->lkb_time_list);
- unhold_lkb(lkb);
- }
- mutex_unlock(&ls->ls_timeout_mutex);
-}
-
-/* FIXME: is it safe to look at lkb_exflags, lkb_flags, lkb_timestamp, and
- lkb_lksb_timeout without lock_rsb? Note: we can't lock timeout_mutex
- and then lock rsb because of lock ordering in add_timeout. We may need
- to specify some special timeout-related bits in the lkb that are just to
- be accessed under the timeout_mutex. */
-
-void dlm_scan_timeout(struct dlm_ls *ls)
-{
- struct dlm_rsb *r;
- struct dlm_lkb *lkb;
- int do_cancel, do_warn;
- s64 wait_us;
-
- for (;;) {
- if (dlm_locking_stopped(ls))
- break;
-
- do_cancel = 0;
- do_warn = 0;
- mutex_lock(&ls->ls_timeout_mutex);
- list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) {
-
- wait_us = ktime_to_us(ktime_sub(ktime_get(),
- lkb->lkb_timestamp));
-
- if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) &&
- wait_us >= (lkb->lkb_timeout_cs * 10000))
- do_cancel = 1;
-
- if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
- wait_us >= dlm_config.ci_timewarn_cs * 10000)
- do_warn = 1;
-
- if (!do_cancel && !do_warn)
- continue;
- hold_lkb(lkb);
- break;
- }
- mutex_unlock(&ls->ls_timeout_mutex);
-
- if (!do_cancel && !do_warn)
- break;
-
- r = lkb->lkb_resource;
- hold_rsb(r);
- lock_rsb(r);
-
- if (do_warn) {
- /* clear flag so we only warn once */
- lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
- if (!(lkb->lkb_exflags & DLM_LKF_TIMEOUT))
- del_timeout(lkb);
- dlm_timeout_warn(lkb);
- }
-
- if (do_cancel) {
- log_debug(ls, "timeout cancel %x node %d %s",
- lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
- lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
- lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL;
- del_timeout(lkb);
- _cancel_lock(r, lkb);
- }
-
- unlock_rsb(r);
- unhold_rsb(r);
- dlm_put_lkb(lkb);
- }
-}
-
-/* This is only called by dlm_recoverd, and we rely on dlm_ls_stop() stopping
- dlm_recoverd before checking/setting ls_recover_begin. */
-
-void dlm_adjust_timeouts(struct dlm_ls *ls)
-{
- struct dlm_lkb *lkb;
- u64 adj_us = jiffies_to_usecs(jiffies - ls->ls_recover_begin);
-
- ls->ls_recover_begin = 0;
- mutex_lock(&ls->ls_timeout_mutex);
- list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list)
- lkb->lkb_timestamp = ktime_add_us(lkb->lkb_timestamp, adj_us);
- mutex_unlock(&ls->ls_timeout_mutex);
-
- if (!dlm_config.ci_waitwarn_us)
- return;
-
- mutex_lock(&ls->ls_waiters_mutex);
- list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
- if (ktime_to_us(lkb->lkb_wait_time))
- lkb->lkb_wait_time = ktime_get();
- }
- mutex_unlock(&ls->ls_waiters_mutex);
-}
-
-/* lkb is master or local copy */
-
-static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int b, len = r->res_ls->ls_lvblen;
-
- /* b=1 lvb returned to caller
- b=0 lvb written to rsb or invalidated
- b=-1 do nothing */
-
- b = dlm_lvb_operations[lkb->lkb_grmode + 1][lkb->lkb_rqmode + 1];
-
- if (b == 1) {
- if (!lkb->lkb_lvbptr)
- return;
-
- if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
- return;
-
- if (!r->res_lvbptr)
- return;
-
- memcpy(lkb->lkb_lvbptr, r->res_lvbptr, len);
- lkb->lkb_lvbseq = r->res_lvbseq;
-
- } else if (b == 0) {
- if (lkb->lkb_exflags & DLM_LKF_IVVALBLK) {
- rsb_set_flag(r, RSB_VALNOTVALID);
- return;
- }
-
- if (!lkb->lkb_lvbptr)
- return;
-
- if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
- return;
-
- if (!r->res_lvbptr)
- r->res_lvbptr = dlm_allocate_lvb(r->res_ls);
-
- if (!r->res_lvbptr)
- return;
-
- memcpy(r->res_lvbptr, lkb->lkb_lvbptr, len);
- r->res_lvbseq++;
- lkb->lkb_lvbseq = r->res_lvbseq;
- rsb_clear_flag(r, RSB_VALNOTVALID);
- }
-
- if (rsb_flag(r, RSB_VALNOTVALID))
- lkb->lkb_sbflags |= DLM_SBF_VALNOTVALID;
-}
-
-static void set_lvb_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- if (lkb->lkb_grmode < DLM_LOCK_PW)
- return;
-
- if (lkb->lkb_exflags & DLM_LKF_IVVALBLK) {
- rsb_set_flag(r, RSB_VALNOTVALID);
- return;
- }
-
- if (!lkb->lkb_lvbptr)
- return;
-
- if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
- return;
-
- if (!r->res_lvbptr)
- r->res_lvbptr = dlm_allocate_lvb(r->res_ls);
-
- if (!r->res_lvbptr)
- return;
-
- memcpy(r->res_lvbptr, lkb->lkb_lvbptr, r->res_ls->ls_lvblen);
- r->res_lvbseq++;
- rsb_clear_flag(r, RSB_VALNOTVALID);
-}
-
-/* lkb is process copy (pc) */
-
-static void set_lvb_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb,
- struct dlm_message *ms)
-{
- int b;
-
- if (!lkb->lkb_lvbptr)
- return;
-
- if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
- return;
-
- b = dlm_lvb_operations[lkb->lkb_grmode + 1][lkb->lkb_rqmode + 1];
- if (b == 1) {
- int len = receive_extralen(ms);
- if (len > DLM_RESNAME_MAXLEN)
- len = DLM_RESNAME_MAXLEN;
- memcpy(lkb->lkb_lvbptr, ms->m_extra, len);
- lkb->lkb_lvbseq = ms->m_lvbseq;
- }
-}
-
-/* Manipulate lkb's on rsb's convert/granted/waiting queues
- remove_lock -- used for unlock, removes lkb from granted
- revert_lock -- used for cancel, moves lkb from convert to granted
- grant_lock -- used for request and convert, adds lkb to granted or
- moves lkb from convert or waiting to granted
-
- Each of these is used for master or local copy lkb's. There is
- also a _pc() variation used to make the corresponding change on
- a process copy (pc) lkb. */
-
-static void _remove_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- del_lkb(r, lkb);
- lkb->lkb_grmode = DLM_LOCK_IV;
- /* this unhold undoes the original ref from create_lkb()
- so this leads to the lkb being freed */
- unhold_lkb(lkb);
-}
-
-static void remove_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- set_lvb_unlock(r, lkb);
- _remove_lock(r, lkb);
-}
-
-static void remove_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- _remove_lock(r, lkb);
-}
-
-/* returns: 0 did nothing
- 1 moved lock to granted
- -1 removed lock */
-
-static int revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int rv = 0;
-
- lkb->lkb_rqmode = DLM_LOCK_IV;
-
- switch (lkb->lkb_status) {
- case DLM_LKSTS_GRANTED:
- break;
- case DLM_LKSTS_CONVERT:
- move_lkb(r, lkb, DLM_LKSTS_GRANTED);
- rv = 1;
- break;
- case DLM_LKSTS_WAITING:
- del_lkb(r, lkb);
- lkb->lkb_grmode = DLM_LOCK_IV;
- /* this unhold undoes the original ref from create_lkb()
- so this leads to the lkb being freed */
- unhold_lkb(lkb);
- rv = -1;
- break;
- default:
- log_print("invalid status for revert %d", lkb->lkb_status);
- }
- return rv;
-}
-
-static int revert_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- return revert_lock(r, lkb);
-}
-
-static void _grant_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- if (lkb->lkb_grmode != lkb->lkb_rqmode) {
- lkb->lkb_grmode = lkb->lkb_rqmode;
- if (lkb->lkb_status)
- move_lkb(r, lkb, DLM_LKSTS_GRANTED);
- else
- add_lkb(r, lkb, DLM_LKSTS_GRANTED);
- }
-
- lkb->lkb_rqmode = DLM_LOCK_IV;
-}
-
-static void grant_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- set_lvb_lock(r, lkb);
- _grant_lock(r, lkb);
- lkb->lkb_highbast = 0;
-}
-
-static void grant_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb,
- struct dlm_message *ms)
-{
- set_lvb_lock_pc(r, lkb, ms);
- _grant_lock(r, lkb);
-}
-
-/* called by grant_pending_locks() which means an async grant message must
- be sent to the requesting node in addition to granting the lock if the
- lkb belongs to a remote node. */
-
-static void grant_lock_pending(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- grant_lock(r, lkb);
- if (is_master_copy(lkb))
- send_grant(r, lkb);
- else
- queue_cast(r, lkb, 0);
-}
-
-/* The special CONVDEADLK, ALTPR and ALTCW flags allow the master to
- change the granted/requested modes. We're munging things accordingly in
- the process copy.
- CONVDEADLK: our grmode may have been forced down to NL to resolve a
- conversion deadlock
- ALTPR/ALTCW: our rqmode may have been changed to PR or CW to become
- compatible with other granted locks */
-
-static void munge_demoted(struct dlm_lkb *lkb)
-{
- if (lkb->lkb_rqmode == DLM_LOCK_IV || lkb->lkb_grmode == DLM_LOCK_IV) {
- log_print("munge_demoted %x invalid modes gr %d rq %d",
- lkb->lkb_id, lkb->lkb_grmode, lkb->lkb_rqmode);
- return;
- }
-
- lkb->lkb_grmode = DLM_LOCK_NL;
-}
-
-static void munge_altmode(struct dlm_lkb *lkb, struct dlm_message *ms)
-{
- if (ms->m_type != DLM_MSG_REQUEST_REPLY &&
- ms->m_type != DLM_MSG_GRANT) {
- log_print("munge_altmode %x invalid reply type %d",
- lkb->lkb_id, ms->m_type);
- return;
- }
-
- if (lkb->lkb_exflags & DLM_LKF_ALTPR)
- lkb->lkb_rqmode = DLM_LOCK_PR;
- else if (lkb->lkb_exflags & DLM_LKF_ALTCW)
- lkb->lkb_rqmode = DLM_LOCK_CW;
- else {
- log_print("munge_altmode invalid exflags %x", lkb->lkb_exflags);
- dlm_print_lkb(lkb);
- }
-}
-
-static inline int first_in_list(struct dlm_lkb *lkb, struct list_head *head)
-{
- struct dlm_lkb *first = list_entry(head->next, struct dlm_lkb,
- lkb_statequeue);
- if (lkb->lkb_id == first->lkb_id)
- return 1;
-
- return 0;
-}
-
-/* Check if the given lkb conflicts with another lkb on the queue. */
-
-static int queue_conflict(struct list_head *head, struct dlm_lkb *lkb)
-{
- struct dlm_lkb *this;
-
- list_for_each_entry(this, head, lkb_statequeue) {
- if (this == lkb)
- continue;
- if (!modes_compat(this, lkb))
- return 1;
- }
- return 0;
-}
-
-/*
- * "A conversion deadlock arises with a pair of lock requests in the converting
- * queue for one resource. The granted mode of each lock blocks the requested
- * mode of the other lock."
- *
- * Part 2: if the granted mode of lkb is preventing an earlier lkb in the
- * convert queue from being granted, then deadlk/demote lkb.
- *
- * Example:
- * Granted Queue: empty
- * Convert Queue: NL->EX (first lock)
- * PR->EX (second lock)
- *
- * The first lock can't be granted because of the granted mode of the second
- * lock and the second lock can't be granted because it's not first in the
- * list. We either cancel lkb's conversion (PR->EX) and return EDEADLK, or we
- * demote the granted mode of lkb (from PR to NL) if it has the CONVDEADLK
- * flag set and return DEMOTED in the lksb flags.
- *
- * Originally, this function detected conv-deadlk in a more limited scope:
- * - if !modes_compat(lkb1, lkb2) && !modes_compat(lkb2, lkb1), or
- * - if lkb1 was the first entry in the queue (not just earlier), and was
- * blocked by the granted mode of lkb2, and there was nothing on the
- * granted queue preventing lkb1 from being granted immediately, i.e.
- * lkb2 was the only thing preventing lkb1 from being granted.
- *
- * That second condition meant we'd only say there was conv-deadlk if
- * resolving it (by demotion) would lead to the first lock on the convert
- * queue being granted right away. It allowed conversion deadlocks to exist
- * between locks on the convert queue while they couldn't be granted anyway.
- *
- * Now, we detect and take action on conversion deadlocks immediately when
- * they're created, even if they may not be immediately consequential. If
- * lkb1 exists anywhere in the convert queue and lkb2 comes in with a granted
- * mode that would prevent lkb1's conversion from being granted, we do a
- * deadlk/demote on lkb2 right away and don't let it onto the convert queue.
- * I think this means that the lkb_is_ahead condition below should always
- * be zero, i.e. there will never be conv-deadlk between two locks that are
- * both already on the convert queue.
- */
-
-static int conversion_deadlock_detect(struct dlm_rsb *r, struct dlm_lkb *lkb2)
-{
- struct dlm_lkb *lkb1;
- int lkb_is_ahead = 0;
-
- list_for_each_entry(lkb1, &r->res_convertqueue, lkb_statequeue) {
- if (lkb1 == lkb2) {
- lkb_is_ahead = 1;
- continue;
- }
-
- if (!lkb_is_ahead) {
- if (!modes_compat(lkb2, lkb1))
- return 1;
- } else {
- if (!modes_compat(lkb2, lkb1) &&
- !modes_compat(lkb1, lkb2))
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * Return 1 if the lock can be granted, 0 otherwise.
- * Also detect and resolve conversion deadlocks.
- *
- * lkb is the lock to be granted
- *
- * now is 1 if the function is being called in the context of the
- * immediate request, it is 0 if called later, after the lock has been
- * queued.
- *
- * References are from chapter 6 of "VAXcluster Principles" by Roy Davis
- */
-
-static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
-{
- int8_t conv = (lkb->lkb_grmode != DLM_LOCK_IV);
-
- /*
- * 6-10: Version 5.4 introduced an option to address the phenomenon of
- * a new request for a NL mode lock being blocked.
- *
- * 6-11: If the optional EXPEDITE flag is used with the new NL mode
- * request, then it would be granted. In essence, the use of this flag
- * tells the Lock Manager to expedite theis request by not considering
- * what may be in the CONVERTING or WAITING queues... As of this
- * writing, the EXPEDITE flag can be used only with new requests for NL
- * mode locks. This flag is not valid for conversion requests.
- *
- * A shortcut. Earlier checks return an error if EXPEDITE is used in a
- * conversion or used with a non-NL requested mode. We also know an
- * EXPEDITE request is always granted immediately, so now must always
- * be 1. The full condition to grant an expedite request: (now &&
- * !conv && lkb->rqmode == DLM_LOCK_NL && (flags & EXPEDITE)) can
- * therefore be shortened to just checking the flag.
- */
-
- if (lkb->lkb_exflags & DLM_LKF_EXPEDITE)
- return 1;
-
- /*
- * A shortcut. Without this, !queue_conflict(grantqueue, lkb) would be
- * added to the remaining conditions.
- */
-
- if (queue_conflict(&r->res_grantqueue, lkb))
- goto out;
-
- /*
- * 6-3: By default, a conversion request is immediately granted if the
- * requested mode is compatible with the modes of all other granted
- * locks
- */
-
- if (queue_conflict(&r->res_convertqueue, lkb))
- goto out;
-
- /*
- * 6-5: But the default algorithm for deciding whether to grant or
- * queue conversion requests does not by itself guarantee that such
- * requests are serviced on a "first come first serve" basis. This, in
- * turn, can lead to a phenomenon known as "indefinate postponement".
- *
- * 6-7: This issue is dealt with by using the optional QUECVT flag with
- * the system service employed to request a lock conversion. This flag
- * forces certain conversion requests to be queued, even if they are
- * compatible with the granted modes of other locks on the same
- * resource. Thus, the use of this flag results in conversion requests
- * being ordered on a "first come first servce" basis.
- *
- * DCT: This condition is all about new conversions being able to occur
- * "in place" while the lock remains on the granted queue (assuming
- * nothing else conflicts.) IOW if QUECVT isn't set, a conversion
- * doesn't _have_ to go onto the convert queue where it's processed in
- * order. The "now" variable is necessary to distinguish converts
- * being received and processed for the first time now, because once a
- * convert is moved to the conversion queue the condition below applies
- * requiring fifo granting.
- */
-
- if (now && conv && !(lkb->lkb_exflags & DLM_LKF_QUECVT))
- return 1;
-
- /*
- * Even if the convert is compat with all granted locks,
- * QUECVT forces it behind other locks on the convert queue.
- */
-
- if (now && conv && (lkb->lkb_exflags & DLM_LKF_QUECVT)) {
- if (list_empty(&r->res_convertqueue))
- return 1;
- else
- goto out;
- }
-
- /*
- * The NOORDER flag is set to avoid the standard vms rules on grant
- * order.
- */
-
- if (lkb->lkb_exflags & DLM_LKF_NOORDER)
- return 1;
-
- /*
- * 6-3: Once in that queue [CONVERTING], a conversion request cannot be
- * granted until all other conversion requests ahead of it are granted
- * and/or canceled.
- */
-
- if (!now && conv && first_in_list(lkb, &r->res_convertqueue))
- return 1;
-
- /*
- * 6-4: By default, a new request is immediately granted only if all
- * three of the following conditions are satisfied when the request is
- * issued:
- * - The queue of ungranted conversion requests for the resource is
- * empty.
- * - The queue of ungranted new requests for the resource is empty.
- * - The mode of the new request is compatible with the most
- * restrictive mode of all granted locks on the resource.
- */
-
- if (now && !conv && list_empty(&r->res_convertqueue) &&
- list_empty(&r->res_waitqueue))
- return 1;
-
- /*
- * 6-4: Once a lock request is in the queue of ungranted new requests,
- * it cannot be granted until the queue of ungranted conversion
- * requests is empty, all ungranted new requests ahead of it are
- * granted and/or canceled, and it is compatible with the granted mode
- * of the most restrictive lock granted on the resource.
- */
-
- if (!now && !conv && list_empty(&r->res_convertqueue) &&
- first_in_list(lkb, &r->res_waitqueue))
- return 1;
- out:
- return 0;
-}
-
-static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
- int *err)
-{
- int rv;
- int8_t alt = 0, rqmode = lkb->lkb_rqmode;
- int8_t is_convert = (lkb->lkb_grmode != DLM_LOCK_IV);
-
- if (err)
- *err = 0;
-
- rv = _can_be_granted(r, lkb, now);
- if (rv)
- goto out;
-
- /*
- * The CONVDEADLK flag is non-standard and tells the dlm to resolve
- * conversion deadlocks by demoting grmode to NL, otherwise the dlm
- * cancels one of the locks.
- */
-
- if (is_convert && can_be_queued(lkb) &&
- conversion_deadlock_detect(r, lkb)) {
- if (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) {
- lkb->lkb_grmode = DLM_LOCK_NL;
- lkb->lkb_sbflags |= DLM_SBF_DEMOTED;
- } else if (!(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
- if (err)
- *err = -EDEADLK;
- else {
- log_print("can_be_granted deadlock %x now %d",
- lkb->lkb_id, now);
- dlm_dump_rsb(r);
- }
- }
- goto out;
- }
-
- /*
- * The ALTPR and ALTCW flags are non-standard and tell the dlm to try
- * to grant a request in a mode other than the normal rqmode. It's a
- * simple way to provide a big optimization to applications that can
- * use them.
- */
-
- if (rqmode != DLM_LOCK_PR && (lkb->lkb_exflags & DLM_LKF_ALTPR))
- alt = DLM_LOCK_PR;
- else if (rqmode != DLM_LOCK_CW && (lkb->lkb_exflags & DLM_LKF_ALTCW))
- alt = DLM_LOCK_CW;
-
- if (alt) {
- lkb->lkb_rqmode = alt;
- rv = _can_be_granted(r, lkb, now);
- if (rv)
- lkb->lkb_sbflags |= DLM_SBF_ALTMODE;
- else
- lkb->lkb_rqmode = rqmode;
- }
- out:
- return rv;
-}
-
-/* FIXME: I don't think that can_be_granted() can/will demote or find deadlock
- for locks pending on the convert list. Once verified (watch for these
- log_prints), we should be able to just call _can_be_granted() and not
- bother with the demote/deadlk cases here (and there's no easy way to deal
- with a deadlk here, we'd have to generate something like grant_lock with
- the deadlk error.) */
-
-/* Returns the highest requested mode of all blocked conversions; sets
- cw if there's a blocked conversion to DLM_LOCK_CW. */
-
-static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw)
-{
- struct dlm_lkb *lkb, *s;
- int hi, demoted, quit, grant_restart, demote_restart;
- int deadlk;
-
- quit = 0;
- restart:
- grant_restart = 0;
- demote_restart = 0;
- hi = DLM_LOCK_IV;
-
- list_for_each_entry_safe(lkb, s, &r->res_convertqueue, lkb_statequeue) {
- demoted = is_demoted(lkb);
- deadlk = 0;
-
- if (can_be_granted(r, lkb, 0, &deadlk)) {
- grant_lock_pending(r, lkb);
- grant_restart = 1;
- continue;
- }
-
- if (!demoted && is_demoted(lkb)) {
- log_print("WARN: pending demoted %x node %d %s",
- lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
- demote_restart = 1;
- continue;
- }
-
- if (deadlk) {
- log_print("WARN: pending deadlock %x node %d %s",
- lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
- dlm_dump_rsb(r);
- continue;
- }
-
- hi = max_t(int, lkb->lkb_rqmode, hi);
-
- if (cw && lkb->lkb_rqmode == DLM_LOCK_CW)
- *cw = 1;
- }
-
- if (grant_restart)
- goto restart;
- if (demote_restart && !quit) {
- quit = 1;
- goto restart;
- }
-
- return max_t(int, high, hi);
-}
-
-static int grant_pending_wait(struct dlm_rsb *r, int high, int *cw)
-{
- struct dlm_lkb *lkb, *s;
-
- list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
- if (can_be_granted(r, lkb, 0, NULL))
- grant_lock_pending(r, lkb);
- else {
- high = max_t(int, lkb->lkb_rqmode, high);
- if (lkb->lkb_rqmode == DLM_LOCK_CW)
- *cw = 1;
- }
- }
-
- return high;
-}
-
-/* cw of 1 means there's a lock with a rqmode of DLM_LOCK_CW that's blocked
- on either the convert or waiting queue.
- high is the largest rqmode of all locks blocked on the convert or
- waiting queue. */
-
-static int lock_requires_bast(struct dlm_lkb *gr, int high, int cw)
-{
- if (gr->lkb_grmode == DLM_LOCK_PR && cw) {
- if (gr->lkb_highbast < DLM_LOCK_EX)
- return 1;
- return 0;
- }
-
- if (gr->lkb_highbast < high &&
- !__dlm_compat_matrix[gr->lkb_grmode+1][high+1])
- return 1;
- return 0;
-}
-
-static void grant_pending_locks(struct dlm_rsb *r)
-{
- struct dlm_lkb *lkb, *s;
- int high = DLM_LOCK_IV;
- int cw = 0;
-
- DLM_ASSERT(is_master(r), dlm_dump_rsb(r););
-
- high = grant_pending_convert(r, high, &cw);
- high = grant_pending_wait(r, high, &cw);
-
- if (high == DLM_LOCK_IV)
- return;
-
- /*
- * If there are locks left on the wait/convert queue then send blocking
- * ASTs to granted locks based on the largest requested mode (high)
- * found above.
- */
-
- list_for_each_entry_safe(lkb, s, &r->res_grantqueue, lkb_statequeue) {
- if (lkb->lkb_bastfn && lock_requires_bast(lkb, high, cw)) {
- if (cw && high == DLM_LOCK_PR &&
- lkb->lkb_grmode == DLM_LOCK_PR)
- queue_bast(r, lkb, DLM_LOCK_CW);
- else
- queue_bast(r, lkb, high);
- lkb->lkb_highbast = high;
- }
- }
-}
-
-static int modes_require_bast(struct dlm_lkb *gr, struct dlm_lkb *rq)
-{
- if ((gr->lkb_grmode == DLM_LOCK_PR && rq->lkb_rqmode == DLM_LOCK_CW) ||
- (gr->lkb_grmode == DLM_LOCK_CW && rq->lkb_rqmode == DLM_LOCK_PR)) {
- if (gr->lkb_highbast < DLM_LOCK_EX)
- return 1;
- return 0;
- }
-
- if (gr->lkb_highbast < rq->lkb_rqmode && !modes_compat(gr, rq))
- return 1;
- return 0;
-}
-
-static void send_bast_queue(struct dlm_rsb *r, struct list_head *head,
- struct dlm_lkb *lkb)
-{
- struct dlm_lkb *gr;
-
- list_for_each_entry(gr, head, lkb_statequeue) {
- /* skip self when sending basts to convertqueue */
- if (gr == lkb)
- continue;
- if (gr->lkb_bastfn && modes_require_bast(gr, lkb)) {
- queue_bast(r, gr, lkb->lkb_rqmode);
- gr->lkb_highbast = lkb->lkb_rqmode;
- }
- }
-}
-
-static void send_blocking_asts(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- send_bast_queue(r, &r->res_grantqueue, lkb);
-}
-
-static void send_blocking_asts_all(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- send_bast_queue(r, &r->res_grantqueue, lkb);
- send_bast_queue(r, &r->res_convertqueue, lkb);
-}
-
-/* set_master(r, lkb) -- set the master nodeid of a resource
-
- The purpose of this function is to set the nodeid field in the given
- lkb using the nodeid field in the given rsb. If the rsb's nodeid is
- known, it can just be copied to the lkb and the function will return
- 0. If the rsb's nodeid is _not_ known, it needs to be looked up
- before it can be copied to the lkb.
-
- When the rsb nodeid is being looked up remotely, the initial lkb
- causing the lookup is kept on the ls_waiters list waiting for the
- lookup reply. Other lkb's waiting for the same rsb lookup are kept
- on the rsb's res_lookup list until the master is verified.
-
- Return values:
- 0: nodeid is set in rsb/lkb and the caller should go ahead and use it
- 1: the rsb master is not available and the lkb has been placed on
- a wait queue
-*/
-
-static int set_master(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- struct dlm_ls *ls = r->res_ls;
- int i, error, dir_nodeid, ret_nodeid, our_nodeid = dlm_our_nodeid();
-
- if (rsb_flag(r, RSB_MASTER_UNCERTAIN)) {
- rsb_clear_flag(r, RSB_MASTER_UNCERTAIN);
- r->res_first_lkid = lkb->lkb_id;
- lkb->lkb_nodeid = r->res_nodeid;
- return 0;
- }
-
- if (r->res_first_lkid && r->res_first_lkid != lkb->lkb_id) {
- list_add_tail(&lkb->lkb_rsb_lookup, &r->res_lookup);
- return 1;
- }
-
- if (r->res_nodeid == 0) {
- lkb->lkb_nodeid = 0;
- return 0;
- }
-
- if (r->res_nodeid > 0) {
- lkb->lkb_nodeid = r->res_nodeid;
- return 0;
- }
-
- DLM_ASSERT(r->res_nodeid == -1, dlm_dump_rsb(r););
-
- dir_nodeid = dlm_dir_nodeid(r);
-
- if (dir_nodeid != our_nodeid) {
- r->res_first_lkid = lkb->lkb_id;
- send_lookup(r, lkb);
- return 1;
- }
-
- for (i = 0; i < 2; i++) {
- /* It's possible for dlm_scand to remove an old rsb for
- this same resource from the toss list, us to create
- a new one, look up the master locally, and find it
- already exists just before dlm_scand does the
- dir_remove() on the previous rsb. */
-
- error = dlm_dir_lookup(ls, our_nodeid, r->res_name,
- r->res_length, &ret_nodeid);
- if (!error)
- break;
- log_debug(ls, "dir_lookup error %d %s", error, r->res_name);
- schedule();
- }
- if (error && error != -EEXIST)
- return error;
-
- if (ret_nodeid == our_nodeid) {
- r->res_first_lkid = 0;
- r->res_nodeid = 0;
- lkb->lkb_nodeid = 0;
- } else {
- r->res_first_lkid = lkb->lkb_id;
- r->res_nodeid = ret_nodeid;
- lkb->lkb_nodeid = ret_nodeid;
- }
- return 0;
-}
-
-static void process_lookup_list(struct dlm_rsb *r)
-{
- struct dlm_lkb *lkb, *safe;
-
- list_for_each_entry_safe(lkb, safe, &r->res_lookup, lkb_rsb_lookup) {
- list_del_init(&lkb->lkb_rsb_lookup);
- _request_lock(r, lkb);
- schedule();
- }
-}
-
-/* confirm_master -- confirm (or deny) an rsb's master nodeid */
-
-static void confirm_master(struct dlm_rsb *r, int error)
-{
- struct dlm_lkb *lkb;
-
- if (!r->res_first_lkid)
- return;
-
- switch (error) {
- case 0:
- case -EINPROGRESS:
- r->res_first_lkid = 0;
- process_lookup_list(r);
- break;
-
- case -EAGAIN:
- case -EBADR:
- case -ENOTBLK:
- /* the remote request failed and won't be retried (it was
- a NOQUEUE, or has been canceled/unlocked); make a waiting
- lkb the first_lkid */
-
- r->res_first_lkid = 0;
-
- if (!list_empty(&r->res_lookup)) {
- lkb = list_entry(r->res_lookup.next, struct dlm_lkb,
- lkb_rsb_lookup);
- list_del_init(&lkb->lkb_rsb_lookup);
- r->res_first_lkid = lkb->lkb_id;
- _request_lock(r, lkb);
- }
- break;
-
- default:
- log_error(r->res_ls, "confirm_master unknown error %d", error);
- }
-}
-
-static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
- int namelen, unsigned long timeout_cs,
- void (*ast) (void *astparam),
- void *astparam,
- void (*bast) (void *astparam, int mode),
- struct dlm_args *args)
-{
- int rv = -EINVAL;
-
- /* check for invalid arg usage */
-
- if (mode < 0 || mode > DLM_LOCK_EX)
- goto out;
-
- if (!(flags & DLM_LKF_CONVERT) && (namelen > DLM_RESNAME_MAXLEN))
- goto out;
-
- if (flags & DLM_LKF_CANCEL)
- goto out;
-
- if (flags & DLM_LKF_QUECVT && !(flags & DLM_LKF_CONVERT))
- goto out;
-
- if (flags & DLM_LKF_CONVDEADLK && !(flags & DLM_LKF_CONVERT))
- goto out;
-
- if (flags & DLM_LKF_CONVDEADLK && flags & DLM_LKF_NOQUEUE)
- goto out;
-
- if (flags & DLM_LKF_EXPEDITE && flags & DLM_LKF_CONVERT)
- goto out;
-
- if (flags & DLM_LKF_EXPEDITE && flags & DLM_LKF_QUECVT)
- goto out;
-
- if (flags & DLM_LKF_EXPEDITE && flags & DLM_LKF_NOQUEUE)
- goto out;
-
- if (flags & DLM_LKF_EXPEDITE && mode != DLM_LOCK_NL)
- goto out;
-
- if (!ast || !lksb)
- goto out;
-
- if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr)
- goto out;
-
- if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid)
- goto out;
-
- /* these args will be copied to the lkb in validate_lock_args,
- it cannot be done now because when converting locks, fields in
- an active lkb cannot be modified before locking the rsb */
-
- args->flags = flags;
- args->astfn = ast;
- args->astparam = astparam;
- args->bastfn = bast;
- args->timeout = timeout_cs;
- args->mode = mode;
- args->lksb = lksb;
- rv = 0;
- out:
- return rv;
-}
-
-static int set_unlock_args(uint32_t flags, void *astarg, struct dlm_args *args)
-{
- if (flags & ~(DLM_LKF_CANCEL | DLM_LKF_VALBLK | DLM_LKF_IVVALBLK |
- DLM_LKF_FORCEUNLOCK))
- return -EINVAL;
-
- if (flags & DLM_LKF_CANCEL && flags & DLM_LKF_FORCEUNLOCK)
- return -EINVAL;
-
- args->flags = flags;
- args->astparam = astarg;
- return 0;
-}
-
-static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_args *args)
-{
- int rv = -EINVAL;
-
- if (args->flags & DLM_LKF_CONVERT) {
- if (lkb->lkb_flags & DLM_IFL_MSTCPY)
- goto out;
-
- if (args->flags & DLM_LKF_QUECVT &&
- !__quecvt_compat_matrix[lkb->lkb_grmode+1][args->mode+1])
- goto out;
-
- rv = -EBUSY;
- if (lkb->lkb_status != DLM_LKSTS_GRANTED)
- goto out;
-
- if (lkb->lkb_wait_type)
- goto out;
-
- if (is_overlap(lkb))
- goto out;
- }
-
- lkb->lkb_exflags = args->flags;
- lkb->lkb_sbflags = 0;
- lkb->lkb_astfn = args->astfn;
- lkb->lkb_astparam = args->astparam;
- lkb->lkb_bastfn = args->bastfn;
- lkb->lkb_rqmode = args->mode;
- lkb->lkb_lksb = args->lksb;
- lkb->lkb_lvbptr = args->lksb->sb_lvbptr;
- lkb->lkb_ownpid = (int) current->pid;
- lkb->lkb_timeout_cs = args->timeout;
- rv = 0;
- out:
- if (rv)
- log_debug(ls, "validate_lock_args %d %x %x %x %d %d %s",
- rv, lkb->lkb_id, lkb->lkb_flags, args->flags,
- lkb->lkb_status, lkb->lkb_wait_type,
- lkb->lkb_resource->res_name);
- return rv;
-}
-
-/* when dlm_unlock() sees -EBUSY with CANCEL/FORCEUNLOCK it returns 0
- for success */
-
-/* note: it's valid for lkb_nodeid/res_nodeid to be -1 when we get here
- because there may be a lookup in progress and it's valid to do
- cancel/unlockf on it */
-
-static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
-{
- struct dlm_ls *ls = lkb->lkb_resource->res_ls;
- int rv = -EINVAL;
-
- if (lkb->lkb_flags & DLM_IFL_MSTCPY) {
- log_error(ls, "unlock on MSTCPY %x", lkb->lkb_id);
- dlm_print_lkb(lkb);
- goto out;
- }
-
- /* an lkb may still exist even though the lock is EOL'ed due to a
- cancel, unlock or failed noqueue request; an app can't use these
- locks; return same error as if the lkid had not been found at all */
-
- if (lkb->lkb_flags & DLM_IFL_ENDOFLIFE) {
- log_debug(ls, "unlock on ENDOFLIFE %x", lkb->lkb_id);
- rv = -ENOENT;
- goto out;
- }
-
- /* an lkb may be waiting for an rsb lookup to complete where the
- lookup was initiated by another lock */
-
- if (!list_empty(&lkb->lkb_rsb_lookup)) {
- if (args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) {
- log_debug(ls, "unlock on rsb_lookup %x", lkb->lkb_id);
- list_del_init(&lkb->lkb_rsb_lookup);
- queue_cast(lkb->lkb_resource, lkb,
- args->flags & DLM_LKF_CANCEL ?
- -DLM_ECANCEL : -DLM_EUNLOCK);
- unhold_lkb(lkb); /* undoes create_lkb() */
- }
- /* caller changes -EBUSY to 0 for CANCEL and FORCEUNLOCK */
- rv = -EBUSY;
- goto out;
- }
-
- /* cancel not allowed with another cancel/unlock in progress */
-
- if (args->flags & DLM_LKF_CANCEL) {
- if (lkb->lkb_exflags & DLM_LKF_CANCEL)
- goto out;
-
- if (is_overlap(lkb))
- goto out;
-
- /* don't let scand try to do a cancel */
- del_timeout(lkb);
-
- if (lkb->lkb_flags & DLM_IFL_RESEND) {
- lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
- rv = -EBUSY;
- goto out;
- }
-
- /* there's nothing to cancel */
- if (lkb->lkb_status == DLM_LKSTS_GRANTED &&
- !lkb->lkb_wait_type) {
- rv = -EBUSY;
- goto out;
- }
-
- switch (lkb->lkb_wait_type) {
- case DLM_MSG_LOOKUP:
- case DLM_MSG_REQUEST:
- lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
- rv = -EBUSY;
- goto out;
- case DLM_MSG_UNLOCK:
- case DLM_MSG_CANCEL:
- goto out;
- }
- /* add_to_waiters() will set OVERLAP_CANCEL */
- goto out_ok;
- }
-
- /* do we need to allow a force-unlock if there's a normal unlock
- already in progress? in what conditions could the normal unlock
- fail such that we'd want to send a force-unlock to be sure? */
-
- if (args->flags & DLM_LKF_FORCEUNLOCK) {
- if (lkb->lkb_exflags & DLM_LKF_FORCEUNLOCK)
- goto out;
-
- if (is_overlap_unlock(lkb))
- goto out;
-
- /* don't let scand try to do a cancel */
- del_timeout(lkb);
-
- if (lkb->lkb_flags & DLM_IFL_RESEND) {
- lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
- rv = -EBUSY;
- goto out;
- }
-
- switch (lkb->lkb_wait_type) {
- case DLM_MSG_LOOKUP:
- case DLM_MSG_REQUEST:
- lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
- rv = -EBUSY;
- goto out;
- case DLM_MSG_UNLOCK:
- goto out;
- }
- /* add_to_waiters() will set OVERLAP_UNLOCK */
- goto out_ok;
- }
-
- /* normal unlock not allowed if there's any op in progress */
- rv = -EBUSY;
- if (lkb->lkb_wait_type || lkb->lkb_wait_count)
- goto out;
-
- out_ok:
- /* an overlapping op shouldn't blow away exflags from other op */
- lkb->lkb_exflags |= args->flags;
- lkb->lkb_sbflags = 0;
- lkb->lkb_astparam = args->astparam;
- rv = 0;
- out:
- if (rv)
- log_debug(ls, "validate_unlock_args %d %x %x %x %x %d %s", rv,
- lkb->lkb_id, lkb->lkb_flags, lkb->lkb_exflags,
- args->flags, lkb->lkb_wait_type,
- lkb->lkb_resource->res_name);
- return rv;
-}
-
-/*
- * Four stage 4 varieties:
- * do_request(), do_convert(), do_unlock(), do_cancel()
- * These are called on the master node for the given lock and
- * from the central locking logic.
- */
-
-static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int error = 0;
-
- if (can_be_granted(r, lkb, 1, NULL)) {
- grant_lock(r, lkb);
- queue_cast(r, lkb, 0);
- goto out;
- }
-
- if (can_be_queued(lkb)) {
- error = -EINPROGRESS;
- add_lkb(r, lkb, DLM_LKSTS_WAITING);
- add_timeout(lkb);
- goto out;
- }
-
- error = -EAGAIN;
- queue_cast(r, lkb, -EAGAIN);
- out:
- return error;
-}
-
-static void do_request_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
- int error)
-{
- switch (error) {
- case -EAGAIN:
- if (force_blocking_asts(lkb))
- send_blocking_asts_all(r, lkb);
- break;
- case -EINPROGRESS:
- send_blocking_asts(r, lkb);
- break;
- }
-}
-
-static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int error = 0;
- int deadlk = 0;
-
- /* changing an existing lock may allow others to be granted */
-
- if (can_be_granted(r, lkb, 1, &deadlk)) {
- grant_lock(r, lkb);
- queue_cast(r, lkb, 0);
- goto out;
- }
-
- /* can_be_granted() detected that this lock would block in a conversion
- deadlock, so we leave it on the granted queue and return EDEADLK in
- the ast for the convert. */
-
- if (deadlk) {
- /* it's left on the granted queue */
- revert_lock(r, lkb);
- queue_cast(r, lkb, -EDEADLK);
- error = -EDEADLK;
- goto out;
- }
-
- /* is_demoted() means the can_be_granted() above set the grmode
- to NL, and left us on the granted queue. This auto-demotion
- (due to CONVDEADLK) might mean other locks, and/or this lock, are
- now grantable. We have to try to grant other converting locks
- before we try again to grant this one. */
-
- if (is_demoted(lkb)) {
- grant_pending_convert(r, DLM_LOCK_IV, NULL);
- if (_can_be_granted(r, lkb, 1)) {
- grant_lock(r, lkb);
- queue_cast(r, lkb, 0);
- goto out;
- }
- /* else fall through and move to convert queue */
- }
-
- if (can_be_queued(lkb)) {
- error = -EINPROGRESS;
- del_lkb(r, lkb);
- add_lkb(r, lkb, DLM_LKSTS_CONVERT);
- add_timeout(lkb);
- goto out;
- }
-
- error = -EAGAIN;
- queue_cast(r, lkb, -EAGAIN);
- out:
- return error;
-}
-
-static void do_convert_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
- int error)
-{
- switch (error) {
- case 0:
- grant_pending_locks(r);
- /* grant_pending_locks also sends basts */
- break;
- case -EAGAIN:
- if (force_blocking_asts(lkb))
- send_blocking_asts_all(r, lkb);
- break;
- case -EINPROGRESS:
- send_blocking_asts(r, lkb);
- break;
- }
-}
-
-static int do_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- remove_lock(r, lkb);
- queue_cast(r, lkb, -DLM_EUNLOCK);
- return -DLM_EUNLOCK;
-}
-
-static void do_unlock_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
- int error)
-{
- grant_pending_locks(r);
-}
-
-/* returns: 0 did nothing, -DLM_ECANCEL canceled lock */
-
-static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int error;
-
- error = revert_lock(r, lkb);
- if (error) {
- queue_cast(r, lkb, -DLM_ECANCEL);
- return -DLM_ECANCEL;
- }
- return 0;
-}
-
-static void do_cancel_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
- int error)
-{
- if (error)
- grant_pending_locks(r);
-}
-
-/*
- * Four stage 3 varieties:
- * _request_lock(), _convert_lock(), _unlock_lock(), _cancel_lock()
- */
-
-/* add a new lkb to a possibly new rsb, called by requesting process */
-
-static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int error;
-
- /* set_master: sets lkb nodeid from r */
-
- error = set_master(r, lkb);
- if (error < 0)
- goto out;
- if (error) {
- error = 0;
- goto out;
- }
-
- if (is_remote(r)) {
- /* receive_request() calls do_request() on remote node */
- error = send_request(r, lkb);
- } else {
- error = do_request(r, lkb);
- /* for remote locks the request_reply is sent
- between do_request and do_request_effects */
- do_request_effects(r, lkb, error);
- }
- out:
- return error;
-}
-
-/* change some property of an existing lkb, e.g. mode */
-
-static int _convert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int error;
-
- if (is_remote(r)) {
- /* receive_convert() calls do_convert() on remote node */
- error = send_convert(r, lkb);
- } else {
- error = do_convert(r, lkb);
- /* for remote locks the convert_reply is sent
- between do_convert and do_convert_effects */
- do_convert_effects(r, lkb, error);
- }
-
- return error;
-}
-
-/* remove an existing lkb from the granted queue */
-
-static int _unlock_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int error;
-
- if (is_remote(r)) {
- /* receive_unlock() calls do_unlock() on remote node */
- error = send_unlock(r, lkb);
- } else {
- error = do_unlock(r, lkb);
- /* for remote locks the unlock_reply is sent
- between do_unlock and do_unlock_effects */
- do_unlock_effects(r, lkb, error);
- }
-
- return error;
-}
-
-/* remove an existing lkb from the convert or wait queue */
-
-static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int error;
-
- if (is_remote(r)) {
- /* receive_cancel() calls do_cancel() on remote node */
- error = send_cancel(r, lkb);
- } else {
- error = do_cancel(r, lkb);
- /* for remote locks the cancel_reply is sent
- between do_cancel and do_cancel_effects */
- do_cancel_effects(r, lkb, error);
- }
-
- return error;
-}
-
-/*
- * Four stage 2 varieties:
- * request_lock(), convert_lock(), unlock_lock(), cancel_lock()
- */
-
-static int request_lock(struct dlm_ls *ls, struct dlm_lkb *lkb, char *name,
- int len, struct dlm_args *args)
-{
- struct dlm_rsb *r;
- int error;
-
- error = validate_lock_args(ls, lkb, args);
- if (error)
- goto out;
-
- error = find_rsb(ls, name, len, R_CREATE, &r);
- if (error)
- goto out;
-
- lock_rsb(r);
-
- attach_lkb(r, lkb);
- lkb->lkb_lksb->sb_lkid = lkb->lkb_id;
-
- error = _request_lock(r, lkb);
-
- unlock_rsb(r);
- put_rsb(r);
-
- out:
- return error;
-}
-
-static int convert_lock(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_args *args)
-{
- struct dlm_rsb *r;
- int error;
-
- r = lkb->lkb_resource;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_lock_args(ls, lkb, args);
- if (error)
- goto out;
-
- error = _convert_lock(r, lkb);
- out:
- unlock_rsb(r);
- put_rsb(r);
- return error;
-}
-
-static int unlock_lock(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_args *args)
-{
- struct dlm_rsb *r;
- int error;
-
- r = lkb->lkb_resource;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_unlock_args(lkb, args);
- if (error)
- goto out;
-
- error = _unlock_lock(r, lkb);
- out:
- unlock_rsb(r);
- put_rsb(r);
- return error;
-}
-
-static int cancel_lock(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_args *args)
-{
- struct dlm_rsb *r;
- int error;
-
- r = lkb->lkb_resource;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_unlock_args(lkb, args);
- if (error)
- goto out;
-
- error = _cancel_lock(r, lkb);
- out:
- unlock_rsb(r);
- put_rsb(r);
- return error;
-}
-
-/*
- * Two stage 1 varieties: dlm_lock() and dlm_unlock()
- */
-
-int dlm_lock(dlm_lockspace_t *lockspace,
- int mode,
- struct dlm_lksb *lksb,
- uint32_t flags,
- void *name,
- unsigned int namelen,
- uint32_t parent_lkid,
- void (*ast) (void *astarg),
- void *astarg,
- void (*bast) (void *astarg, int mode))
-{
- struct dlm_ls *ls;
- struct dlm_lkb *lkb;
- struct dlm_args args;
- int error, convert = flags & DLM_LKF_CONVERT;
-
- ls = dlm_find_lockspace_local(lockspace);
- if (!ls)
- return -EINVAL;
-
- dlm_lock_recovery(ls);
-
- if (convert)
- error = find_lkb(ls, lksb->sb_lkid, &lkb);
- else
- error = create_lkb(ls, &lkb);
-
- if (error)
- goto out;
-
- error = set_lock_args(mode, lksb, flags, namelen, 0, ast,
- astarg, bast, &args);
- if (error)
- goto out_put;
-
- if (convert)
- error = convert_lock(ls, lkb, &args);
- else
- error = request_lock(ls, lkb, name, namelen, &args);
-
- if (error == -EINPROGRESS)
- error = 0;
- out_put:
- if (convert || error)
- __put_lkb(ls, lkb);
- if (error == -EAGAIN || error == -EDEADLK)
- error = 0;
- out:
- dlm_unlock_recovery(ls);
- dlm_put_lockspace(ls);
- return error;
-}
-
-int dlm_unlock(dlm_lockspace_t *lockspace,
- uint32_t lkid,
- uint32_t flags,
- struct dlm_lksb *lksb,
- void *astarg)
-{
- struct dlm_ls *ls;
- struct dlm_lkb *lkb;
- struct dlm_args args;
- int error;
-
- ls = dlm_find_lockspace_local(lockspace);
- if (!ls)
- return -EINVAL;
-
- dlm_lock_recovery(ls);
-
- error = find_lkb(ls, lkid, &lkb);
- if (error)
- goto out;
-
- error = set_unlock_args(flags, astarg, &args);
- if (error)
- goto out_put;
-
- if (flags & DLM_LKF_CANCEL)
- error = cancel_lock(ls, lkb, &args);
- else
- error = unlock_lock(ls, lkb, &args);
-
- if (error == -DLM_EUNLOCK || error == -DLM_ECANCEL)
- error = 0;
- if (error == -EBUSY && (flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)))
- error = 0;
- out_put:
- dlm_put_lkb(lkb);
- out:
- dlm_unlock_recovery(ls);
- dlm_put_lockspace(ls);
- return error;
-}
-
-/*
- * send/receive routines for remote operations and replies
- *
- * send_args
- * send_common
- * send_request receive_request
- * send_convert receive_convert
- * send_unlock receive_unlock
- * send_cancel receive_cancel
- * send_grant receive_grant
- * send_bast receive_bast
- * send_lookup receive_lookup
- * send_remove receive_remove
- *
- * send_common_reply
- * receive_request_reply send_request_reply
- * receive_convert_reply send_convert_reply
- * receive_unlock_reply send_unlock_reply
- * receive_cancel_reply send_cancel_reply
- * receive_lookup_reply send_lookup_reply
- */
-
-static int _create_message(struct dlm_ls *ls, int mb_len,
- int to_nodeid, int mstype,
- struct dlm_message **ms_ret,
- struct dlm_mhandle **mh_ret)
-{
- struct dlm_message *ms;
- struct dlm_mhandle *mh;
- char *mb;
-
- /* get_buffer gives us a message handle (mh) that we need to
- pass into lowcomms_commit and a message buffer (mb) that we
- write our data into */
-
- mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_NOFS, &mb);
- if (!mh)
- return -ENOBUFS;
-
- memset(mb, 0, mb_len);
-
- ms = (struct dlm_message *) mb;
-
- ms->m_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR);
- ms->m_header.h_lockspace = ls->ls_global_id;
- ms->m_header.h_nodeid = dlm_our_nodeid();
- ms->m_header.h_length = mb_len;
- ms->m_header.h_cmd = DLM_MSG;
-
- ms->m_type = mstype;
-
- *mh_ret = mh;
- *ms_ret = ms;
- return 0;
-}
-
-static int create_message(struct dlm_rsb *r, struct dlm_lkb *lkb,
- int to_nodeid, int mstype,
- struct dlm_message **ms_ret,
- struct dlm_mhandle **mh_ret)
-{
- int mb_len = sizeof(struct dlm_message);
-
- switch (mstype) {
- case DLM_MSG_REQUEST:
- case DLM_MSG_LOOKUP:
- case DLM_MSG_REMOVE:
- mb_len += r->res_length;
- break;
- case DLM_MSG_CONVERT:
- case DLM_MSG_UNLOCK:
- case DLM_MSG_REQUEST_REPLY:
- case DLM_MSG_CONVERT_REPLY:
- case DLM_MSG_GRANT:
- if (lkb && lkb->lkb_lvbptr)
- mb_len += r->res_ls->ls_lvblen;
- break;
- }
-
- return _create_message(r->res_ls, mb_len, to_nodeid, mstype,
- ms_ret, mh_ret);
-}
-
-/* further lowcomms enhancements or alternate implementations may make
- the return value from this function useful at some point */
-
-static int send_message(struct dlm_mhandle *mh, struct dlm_message *ms)
-{
- dlm_message_out(ms);
- dlm_lowcomms_commit_buffer(mh);
- return 0;
-}
-
-static void send_args(struct dlm_rsb *r, struct dlm_lkb *lkb,
- struct dlm_message *ms)
-{
- ms->m_nodeid = lkb->lkb_nodeid;
- ms->m_pid = lkb->lkb_ownpid;
- ms->m_lkid = lkb->lkb_id;
- ms->m_remid = lkb->lkb_remid;
- ms->m_exflags = lkb->lkb_exflags;
- ms->m_sbflags = lkb->lkb_sbflags;
- ms->m_flags = lkb->lkb_flags;
- ms->m_lvbseq = lkb->lkb_lvbseq;
- ms->m_status = lkb->lkb_status;
- ms->m_grmode = lkb->lkb_grmode;
- ms->m_rqmode = lkb->lkb_rqmode;
- ms->m_hash = r->res_hash;
-
- /* m_result and m_bastmode are set from function args,
- not from lkb fields */
-
- if (lkb->lkb_bastfn)
- ms->m_asts |= DLM_CB_BAST;
- if (lkb->lkb_astfn)
- ms->m_asts |= DLM_CB_CAST;
-
- /* compare with switch in create_message; send_remove() doesn't
- use send_args() */
-
- switch (ms->m_type) {
- case DLM_MSG_REQUEST:
- case DLM_MSG_LOOKUP:
- memcpy(ms->m_extra, r->res_name, r->res_length);
- break;
- case DLM_MSG_CONVERT:
- case DLM_MSG_UNLOCK:
- case DLM_MSG_REQUEST_REPLY:
- case DLM_MSG_CONVERT_REPLY:
- case DLM_MSG_GRANT:
- if (!lkb->lkb_lvbptr)
- break;
- memcpy(ms->m_extra, lkb->lkb_lvbptr, r->res_ls->ls_lvblen);
- break;
- }
-}
-
-static int send_common(struct dlm_rsb *r, struct dlm_lkb *lkb, int mstype)
-{
- struct dlm_message *ms;
- struct dlm_mhandle *mh;
- int to_nodeid, error;
-
- to_nodeid = r->res_nodeid;
-
- error = add_to_waiters(lkb, mstype, to_nodeid);
- if (error)
- return error;
-
- error = create_message(r, lkb, to_nodeid, mstype, &ms, &mh);
- if (error)
- goto fail;
-
- send_args(r, lkb, ms);
-
- error = send_message(mh, ms);
- if (error)
- goto fail;
- return 0;
-
- fail:
- remove_from_waiters(lkb, msg_reply_type(mstype));
- return error;
-}
-
-static int send_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- return send_common(r, lkb, DLM_MSG_REQUEST);
-}
-
-static int send_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- int error;
-
- error = send_common(r, lkb, DLM_MSG_CONVERT);
-
- /* down conversions go without a reply from the master */
- if (!error && down_conversion(lkb)) {
- remove_from_waiters(lkb, DLM_MSG_CONVERT_REPLY);
- r->res_ls->ls_stub_ms.m_flags = DLM_IFL_STUB_MS;
- r->res_ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY;
- r->res_ls->ls_stub_ms.m_result = 0;
- __receive_convert_reply(r, lkb, &r->res_ls->ls_stub_ms);
- }
-
- return error;
-}
-
-/* FIXME: if this lkb is the only lock we hold on the rsb, then set
- MASTER_UNCERTAIN to force the next request on the rsb to confirm
- that the master is still correct. */
-
-static int send_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- return send_common(r, lkb, DLM_MSG_UNLOCK);
-}
-
-static int send_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- return send_common(r, lkb, DLM_MSG_CANCEL);
-}
-
-static int send_grant(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- struct dlm_message *ms;
- struct dlm_mhandle *mh;
- int to_nodeid, error;
-
- to_nodeid = lkb->lkb_nodeid;
-
- error = create_message(r, lkb, to_nodeid, DLM_MSG_GRANT, &ms, &mh);
- if (error)
- goto out;
-
- send_args(r, lkb, ms);
-
- ms->m_result = 0;
-
- error = send_message(mh, ms);
- out:
- return error;
-}
-
-static int send_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int mode)
-{
- struct dlm_message *ms;
- struct dlm_mhandle *mh;
- int to_nodeid, error;
-
- to_nodeid = lkb->lkb_nodeid;
-
- error = create_message(r, NULL, to_nodeid, DLM_MSG_BAST, &ms, &mh);
- if (error)
- goto out;
-
- send_args(r, lkb, ms);
-
- ms->m_bastmode = mode;
-
- error = send_message(mh, ms);
- out:
- return error;
-}
-
-static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- struct dlm_message *ms;
- struct dlm_mhandle *mh;
- int to_nodeid, error;
-
- to_nodeid = dlm_dir_nodeid(r);
-
- error = add_to_waiters(lkb, DLM_MSG_LOOKUP, to_nodeid);
- if (error)
- return error;
-
- error = create_message(r, NULL, to_nodeid, DLM_MSG_LOOKUP, &ms, &mh);
- if (error)
- goto fail;
-
- send_args(r, lkb, ms);
-
- error = send_message(mh, ms);
- if (error)
- goto fail;
- return 0;
-
- fail:
- remove_from_waiters(lkb, DLM_MSG_LOOKUP_REPLY);
- return error;
-}
-
-static int send_remove(struct dlm_rsb *r)
-{
- struct dlm_message *ms;
- struct dlm_mhandle *mh;
- int to_nodeid, error;
-
- to_nodeid = dlm_dir_nodeid(r);
-
- error = create_message(r, NULL, to_nodeid, DLM_MSG_REMOVE, &ms, &mh);
- if (error)
- goto out;
-
- memcpy(ms->m_extra, r->res_name, r->res_length);
- ms->m_hash = r->res_hash;
-
- error = send_message(mh, ms);
- out:
- return error;
-}
-
-static int send_common_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
- int mstype, int rv)
-{
- struct dlm_message *ms;
- struct dlm_mhandle *mh;
- int to_nodeid, error;
-
- to_nodeid = lkb->lkb_nodeid;
-
- error = create_message(r, lkb, to_nodeid, mstype, &ms, &mh);
- if (error)
- goto out;
-
- send_args(r, lkb, ms);
-
- ms->m_result = rv;
-
- error = send_message(mh, ms);
- out:
- return error;
-}
-
-static int send_request_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
-{
- return send_common_reply(r, lkb, DLM_MSG_REQUEST_REPLY, rv);
-}
-
-static int send_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
-{
- return send_common_reply(r, lkb, DLM_MSG_CONVERT_REPLY, rv);
-}
-
-static int send_unlock_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
-{
- return send_common_reply(r, lkb, DLM_MSG_UNLOCK_REPLY, rv);
-}
-
-static int send_cancel_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
-{
- return send_common_reply(r, lkb, DLM_MSG_CANCEL_REPLY, rv);
-}
-
-static int send_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms_in,
- int ret_nodeid, int rv)
-{
- struct dlm_rsb *r = &ls->ls_stub_rsb;
- struct dlm_message *ms;
- struct dlm_mhandle *mh;
- int error, nodeid = ms_in->m_header.h_nodeid;
-
- error = create_message(r, NULL, nodeid, DLM_MSG_LOOKUP_REPLY, &ms, &mh);
- if (error)
- goto out;
-
- ms->m_lkid = ms_in->m_lkid;
- ms->m_result = rv;
- ms->m_nodeid = ret_nodeid;
-
- error = send_message(mh, ms);
- out:
- return error;
-}
-
-/* which args we save from a received message depends heavily on the type
- of message, unlike the send side where we can safely send everything about
- the lkb for any type of message */
-
-static void receive_flags(struct dlm_lkb *lkb, struct dlm_message *ms)
-{
- lkb->lkb_exflags = ms->m_exflags;
- lkb->lkb_sbflags = ms->m_sbflags;
- lkb->lkb_flags = (lkb->lkb_flags & 0xFFFF0000) |
- (ms->m_flags & 0x0000FFFF);
-}
-
-static void receive_flags_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
-{
- if (ms->m_flags == DLM_IFL_STUB_MS)
- return;
-
- lkb->lkb_sbflags = ms->m_sbflags;
- lkb->lkb_flags = (lkb->lkb_flags & 0xFFFF0000) |
- (ms->m_flags & 0x0000FFFF);
-}
-
-static int receive_extralen(struct dlm_message *ms)
-{
- return (ms->m_header.h_length - sizeof(struct dlm_message));
-}
-
-static int receive_lvb(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_message *ms)
-{
- int len;
-
- if (lkb->lkb_exflags & DLM_LKF_VALBLK) {
- if (!lkb->lkb_lvbptr)
- lkb->lkb_lvbptr = dlm_allocate_lvb(ls);
- if (!lkb->lkb_lvbptr)
- return -ENOMEM;
- len = receive_extralen(ms);
- if (len > DLM_RESNAME_MAXLEN)
- len = DLM_RESNAME_MAXLEN;
- memcpy(lkb->lkb_lvbptr, ms->m_extra, len);
- }
- return 0;
-}
-
-static void fake_bastfn(void *astparam, int mode)
-{
- log_print("fake_bastfn should not be called");
-}
-
-static void fake_astfn(void *astparam)
-{
- log_print("fake_astfn should not be called");
-}
-
-static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_message *ms)
-{
- lkb->lkb_nodeid = ms->m_header.h_nodeid;
- lkb->lkb_ownpid = ms->m_pid;
- lkb->lkb_remid = ms->m_lkid;
- lkb->lkb_grmode = DLM_LOCK_IV;
- lkb->lkb_rqmode = ms->m_rqmode;
-
- lkb->lkb_bastfn = (ms->m_asts & DLM_CB_BAST) ? &fake_bastfn : NULL;
- lkb->lkb_astfn = (ms->m_asts & DLM_CB_CAST) ? &fake_astfn : NULL;
-
- if (lkb->lkb_exflags & DLM_LKF_VALBLK) {
- /* lkb was just created so there won't be an lvb yet */
- lkb->lkb_lvbptr = dlm_allocate_lvb(ls);
- if (!lkb->lkb_lvbptr)
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int receive_convert_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_message *ms)
-{
- if (lkb->lkb_status != DLM_LKSTS_GRANTED)
- return -EBUSY;
-
- if (receive_lvb(ls, lkb, ms))
- return -ENOMEM;
-
- lkb->lkb_rqmode = ms->m_rqmode;
- lkb->lkb_lvbseq = ms->m_lvbseq;
-
- return 0;
-}
-
-static int receive_unlock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_message *ms)
-{
- if (receive_lvb(ls, lkb, ms))
- return -ENOMEM;
- return 0;
-}
-
-/* We fill in the stub-lkb fields with the info that send_xxxx_reply()
- uses to send a reply and that the remote end uses to process the reply. */
-
-static void setup_stub_lkb(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb = &ls->ls_stub_lkb;
- lkb->lkb_nodeid = ms->m_header.h_nodeid;
- lkb->lkb_remid = ms->m_lkid;
-}
-
-/* This is called after the rsb is locked so that we can safely inspect
- fields in the lkb. */
-
-static int validate_message(struct dlm_lkb *lkb, struct dlm_message *ms)
-{
- int from = ms->m_header.h_nodeid;
- int error = 0;
-
- switch (ms->m_type) {
- case DLM_MSG_CONVERT:
- case DLM_MSG_UNLOCK:
- case DLM_MSG_CANCEL:
- if (!is_master_copy(lkb) || lkb->lkb_nodeid != from)
- error = -EINVAL;
- break;
-
- case DLM_MSG_CONVERT_REPLY:
- case DLM_MSG_UNLOCK_REPLY:
- case DLM_MSG_CANCEL_REPLY:
- case DLM_MSG_GRANT:
- case DLM_MSG_BAST:
- if (!is_process_copy(lkb) || lkb->lkb_nodeid != from)
- error = -EINVAL;
- break;
-
- case DLM_MSG_REQUEST_REPLY:
- if (!is_process_copy(lkb))
- error = -EINVAL;
- else if (lkb->lkb_nodeid != -1 && lkb->lkb_nodeid != from)
- error = -EINVAL;
- break;
-
- default:
- error = -EINVAL;
- }
-
- if (error)
- log_error(lkb->lkb_resource->res_ls,
- "ignore invalid message %d from %d %x %x %x %d",
- ms->m_type, from, lkb->lkb_id, lkb->lkb_remid,
- lkb->lkb_flags, lkb->lkb_nodeid);
- return error;
-}
-
-static void receive_request(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- struct dlm_rsb *r;
- int error, namelen;
-
- error = create_lkb(ls, &lkb);
- if (error)
- goto fail;
-
- receive_flags(lkb, ms);
- lkb->lkb_flags |= DLM_IFL_MSTCPY;
- error = receive_request_args(ls, lkb, ms);
- if (error) {
- __put_lkb(ls, lkb);
- goto fail;
- }
-
- namelen = receive_extralen(ms);
-
- error = find_rsb(ls, ms->m_extra, namelen, R_MASTER, &r);
- if (error) {
- __put_lkb(ls, lkb);
- goto fail;
- }
-
- lock_rsb(r);
-
- attach_lkb(r, lkb);
- error = do_request(r, lkb);
- send_request_reply(r, lkb, error);
- do_request_effects(r, lkb, error);
-
- unlock_rsb(r);
- put_rsb(r);
-
- if (error == -EINPROGRESS)
- error = 0;
- if (error)
- dlm_put_lkb(lkb);
- return;
-
- fail:
- setup_stub_lkb(ls, ms);
- send_request_reply(&ls->ls_stub_rsb, &ls->ls_stub_lkb, error);
-}
-
-static void receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- struct dlm_rsb *r;
- int error, reply = 1;
-
- error = find_lkb(ls, ms->m_remid, &lkb);
- if (error)
- goto fail;
-
- r = lkb->lkb_resource;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_message(lkb, ms);
- if (error)
- goto out;
-
- receive_flags(lkb, ms);
-
- error = receive_convert_args(ls, lkb, ms);
- if (error) {
- send_convert_reply(r, lkb, error);
- goto out;
- }
-
- reply = !down_conversion(lkb);
-
- error = do_convert(r, lkb);
- if (reply)
- send_convert_reply(r, lkb, error);
- do_convert_effects(r, lkb, error);
- out:
- unlock_rsb(r);
- put_rsb(r);
- dlm_put_lkb(lkb);
- return;
-
- fail:
- setup_stub_lkb(ls, ms);
- send_convert_reply(&ls->ls_stub_rsb, &ls->ls_stub_lkb, error);
-}
-
-static void receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- struct dlm_rsb *r;
- int error;
-
- error = find_lkb(ls, ms->m_remid, &lkb);
- if (error)
- goto fail;
-
- r = lkb->lkb_resource;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_message(lkb, ms);
- if (error)
- goto out;
-
- receive_flags(lkb, ms);
-
- error = receive_unlock_args(ls, lkb, ms);
- if (error) {
- send_unlock_reply(r, lkb, error);
- goto out;
- }
-
- error = do_unlock(r, lkb);
- send_unlock_reply(r, lkb, error);
- do_unlock_effects(r, lkb, error);
- out:
- unlock_rsb(r);
- put_rsb(r);
- dlm_put_lkb(lkb);
- return;
-
- fail:
- setup_stub_lkb(ls, ms);
- send_unlock_reply(&ls->ls_stub_rsb, &ls->ls_stub_lkb, error);
-}
-
-static void receive_cancel(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- struct dlm_rsb *r;
- int error;
-
- error = find_lkb(ls, ms->m_remid, &lkb);
- if (error)
- goto fail;
-
- receive_flags(lkb, ms);
-
- r = lkb->lkb_resource;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_message(lkb, ms);
- if (error)
- goto out;
-
- error = do_cancel(r, lkb);
- send_cancel_reply(r, lkb, error);
- do_cancel_effects(r, lkb, error);
- out:
- unlock_rsb(r);
- put_rsb(r);
- dlm_put_lkb(lkb);
- return;
-
- fail:
- setup_stub_lkb(ls, ms);
- send_cancel_reply(&ls->ls_stub_rsb, &ls->ls_stub_lkb, error);
-}
-
-static void receive_grant(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- struct dlm_rsb *r;
- int error;
-
- error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_grant from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
-
- r = lkb->lkb_resource;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_message(lkb, ms);
- if (error)
- goto out;
-
- receive_flags_reply(lkb, ms);
- if (is_altmode(lkb))
- munge_altmode(lkb, ms);
- grant_lock_pc(r, lkb, ms);
- queue_cast(r, lkb, 0);
- out:
- unlock_rsb(r);
- put_rsb(r);
- dlm_put_lkb(lkb);
-}
-
-static void receive_bast(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- struct dlm_rsb *r;
- int error;
-
- error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_bast from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
-
- r = lkb->lkb_resource;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_message(lkb, ms);
- if (error)
- goto out;
-
- queue_bast(r, lkb, ms->m_bastmode);
- out:
- unlock_rsb(r);
- put_rsb(r);
- dlm_put_lkb(lkb);
-}
-
-static void receive_lookup(struct dlm_ls *ls, struct dlm_message *ms)
-{
- int len, error, ret_nodeid, dir_nodeid, from_nodeid, our_nodeid;
-
- from_nodeid = ms->m_header.h_nodeid;
- our_nodeid = dlm_our_nodeid();
-
- len = receive_extralen(ms);
-
- dir_nodeid = dlm_hash2nodeid(ls, ms->m_hash);
- if (dir_nodeid != our_nodeid) {
- log_error(ls, "lookup dir_nodeid %d from %d",
- dir_nodeid, from_nodeid);
- error = -EINVAL;
- ret_nodeid = -1;
- goto out;
- }
-
- error = dlm_dir_lookup(ls, from_nodeid, ms->m_extra, len, &ret_nodeid);
-
- /* Optimization: we're master so treat lookup as a request */
- if (!error && ret_nodeid == our_nodeid) {
- receive_request(ls, ms);
- return;
- }
- out:
- send_lookup_reply(ls, ms, ret_nodeid, error);
-}
-
-static void receive_remove(struct dlm_ls *ls, struct dlm_message *ms)
-{
- int len, dir_nodeid, from_nodeid;
-
- from_nodeid = ms->m_header.h_nodeid;
-
- len = receive_extralen(ms);
-
- dir_nodeid = dlm_hash2nodeid(ls, ms->m_hash);
- if (dir_nodeid != dlm_our_nodeid()) {
- log_error(ls, "remove dir entry dir_nodeid %d from %d",
- dir_nodeid, from_nodeid);
- return;
- }
-
- dlm_dir_remove_entry(ls, from_nodeid, ms->m_extra, len);
-}
-
-static void receive_purge(struct dlm_ls *ls, struct dlm_message *ms)
-{
- do_purge(ls, ms->m_nodeid, ms->m_pid);
-}
-
-static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- struct dlm_rsb *r;
- int error, mstype, result;
-
- error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_request_reply from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
-
- r = lkb->lkb_resource;
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_message(lkb, ms);
- if (error)
- goto out;
-
- mstype = lkb->lkb_wait_type;
- error = remove_from_waiters(lkb, DLM_MSG_REQUEST_REPLY);
- if (error)
- goto out;
-
- /* Optimization: the dir node was also the master, so it took our
- lookup as a request and sent request reply instead of lookup reply */
- if (mstype == DLM_MSG_LOOKUP) {
- r->res_nodeid = ms->m_header.h_nodeid;
- lkb->lkb_nodeid = r->res_nodeid;
- }
-
- /* this is the value returned from do_request() on the master */
- result = ms->m_result;
-
- switch (result) {
- case -EAGAIN:
- /* request would block (be queued) on remote master */
- queue_cast(r, lkb, -EAGAIN);
- confirm_master(r, -EAGAIN);
- unhold_lkb(lkb); /* undoes create_lkb() */
- break;
-
- case -EINPROGRESS:
- case 0:
- /* request was queued or granted on remote master */
- receive_flags_reply(lkb, ms);
- lkb->lkb_remid = ms->m_lkid;
- if (is_altmode(lkb))
- munge_altmode(lkb, ms);
- if (result) {
- add_lkb(r, lkb, DLM_LKSTS_WAITING);
- add_timeout(lkb);
- } else {
- grant_lock_pc(r, lkb, ms);
- queue_cast(r, lkb, 0);
- }
- confirm_master(r, result);
- break;
-
- case -EBADR:
- case -ENOTBLK:
- /* find_rsb failed to find rsb or rsb wasn't master */
- log_debug(ls, "receive_request_reply %x %x master diff %d %d",
- lkb->lkb_id, lkb->lkb_flags, r->res_nodeid, result);
- r->res_nodeid = -1;
- lkb->lkb_nodeid = -1;
-
- if (is_overlap(lkb)) {
- /* we'll ignore error in cancel/unlock reply */
- queue_cast_overlap(r, lkb);
- confirm_master(r, result);
- unhold_lkb(lkb); /* undoes create_lkb() */
- } else
- _request_lock(r, lkb);
- break;
-
- default:
- log_error(ls, "receive_request_reply %x error %d",
- lkb->lkb_id, result);
- }
-
- if (is_overlap_unlock(lkb) && (result == 0 || result == -EINPROGRESS)) {
- log_debug(ls, "receive_request_reply %x result %d unlock",
- lkb->lkb_id, result);
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
- send_unlock(r, lkb);
- } else if (is_overlap_cancel(lkb) && (result == -EINPROGRESS)) {
- log_debug(ls, "receive_request_reply %x cancel", lkb->lkb_id);
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
- send_cancel(r, lkb);
- } else {
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
- }
- out:
- unlock_rsb(r);
- put_rsb(r);
- dlm_put_lkb(lkb);
-}
-
-static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
- struct dlm_message *ms)
-{
- /* this is the value returned from do_convert() on the master */
- switch (ms->m_result) {
- case -EAGAIN:
- /* convert would block (be queued) on remote master */
- queue_cast(r, lkb, -EAGAIN);
- break;
-
- case -EDEADLK:
- receive_flags_reply(lkb, ms);
- revert_lock_pc(r, lkb);
- queue_cast(r, lkb, -EDEADLK);
- break;
-
- case -EINPROGRESS:
- /* convert was queued on remote master */
- receive_flags_reply(lkb, ms);
- if (is_demoted(lkb))
- munge_demoted(lkb);
- del_lkb(r, lkb);
- add_lkb(r, lkb, DLM_LKSTS_CONVERT);
- add_timeout(lkb);
- break;
-
- case 0:
- /* convert was granted on remote master */
- receive_flags_reply(lkb, ms);
- if (is_demoted(lkb))
- munge_demoted(lkb);
- grant_lock_pc(r, lkb, ms);
- queue_cast(r, lkb, 0);
- break;
-
- default:
- log_error(r->res_ls, "receive_convert_reply %x error %d",
- lkb->lkb_id, ms->m_result);
- }
-}
-
-static void _receive_convert_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
-{
- struct dlm_rsb *r = lkb->lkb_resource;
- int error;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_message(lkb, ms);
- if (error)
- goto out;
-
- /* stub reply can happen with waiters_mutex held */
- error = remove_from_waiters_ms(lkb, ms);
- if (error)
- goto out;
-
- __receive_convert_reply(r, lkb, ms);
- out:
- unlock_rsb(r);
- put_rsb(r);
-}
-
-static void receive_convert_reply(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- int error;
-
- error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_convert_reply from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
-
- _receive_convert_reply(lkb, ms);
- dlm_put_lkb(lkb);
-}
-
-static void _receive_unlock_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
-{
- struct dlm_rsb *r = lkb->lkb_resource;
- int error;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_message(lkb, ms);
- if (error)
- goto out;
-
- /* stub reply can happen with waiters_mutex held */
- error = remove_from_waiters_ms(lkb, ms);
- if (error)
- goto out;
-
- /* this is the value returned from do_unlock() on the master */
-
- switch (ms->m_result) {
- case -DLM_EUNLOCK:
- receive_flags_reply(lkb, ms);
- remove_lock_pc(r, lkb);
- queue_cast(r, lkb, -DLM_EUNLOCK);
- break;
- case -ENOENT:
- break;
- default:
- log_error(r->res_ls, "receive_unlock_reply %x error %d",
- lkb->lkb_id, ms->m_result);
- }
- out:
- unlock_rsb(r);
- put_rsb(r);
-}
-
-static void receive_unlock_reply(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- int error;
-
- error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_unlock_reply from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
-
- _receive_unlock_reply(lkb, ms);
- dlm_put_lkb(lkb);
-}
-
-static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
-{
- struct dlm_rsb *r = lkb->lkb_resource;
- int error;
-
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_message(lkb, ms);
- if (error)
- goto out;
-
- /* stub reply can happen with waiters_mutex held */
- error = remove_from_waiters_ms(lkb, ms);
- if (error)
- goto out;
-
- /* this is the value returned from do_cancel() on the master */
-
- switch (ms->m_result) {
- case -DLM_ECANCEL:
- receive_flags_reply(lkb, ms);
- revert_lock_pc(r, lkb);
- queue_cast(r, lkb, -DLM_ECANCEL);
- break;
- case 0:
- break;
- default:
- log_error(r->res_ls, "receive_cancel_reply %x error %d",
- lkb->lkb_id, ms->m_result);
- }
- out:
- unlock_rsb(r);
- put_rsb(r);
-}
-
-static void receive_cancel_reply(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- int error;
-
- error = find_lkb(ls, ms->m_remid, &lkb);
- if (error) {
- log_debug(ls, "receive_cancel_reply from %d no lkb %x",
- ms->m_header.h_nodeid, ms->m_remid);
- return;
- }
-
- _receive_cancel_reply(lkb, ms);
- dlm_put_lkb(lkb);
-}
-
-static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms)
-{
- struct dlm_lkb *lkb;
- struct dlm_rsb *r;
- int error, ret_nodeid;
-
- error = find_lkb(ls, ms->m_lkid, &lkb);
- if (error) {
- log_error(ls, "receive_lookup_reply no lkb");
- return;
- }
-
- /* ms->m_result is the value returned by dlm_dir_lookup on dir node
- FIXME: will a non-zero error ever be returned? */
-
- r = lkb->lkb_resource;
- hold_rsb(r);
- lock_rsb(r);
-
- error = remove_from_waiters(lkb, DLM_MSG_LOOKUP_REPLY);
- if (error)
- goto out;
-
- ret_nodeid = ms->m_nodeid;
- if (ret_nodeid == dlm_our_nodeid()) {
- r->res_nodeid = 0;
- ret_nodeid = 0;
- r->res_first_lkid = 0;
- } else {
- /* set_master() will copy res_nodeid to lkb_nodeid */
- r->res_nodeid = ret_nodeid;
- }
-
- if (is_overlap(lkb)) {
- log_debug(ls, "receive_lookup_reply %x unlock %x",
- lkb->lkb_id, lkb->lkb_flags);
- queue_cast_overlap(r, lkb);
- unhold_lkb(lkb); /* undoes create_lkb() */
- goto out_list;
- }
-
- _request_lock(r, lkb);
-
- out_list:
- if (!ret_nodeid)
- process_lookup_list(r);
- out:
- unlock_rsb(r);
- put_rsb(r);
- dlm_put_lkb(lkb);
-}
-
-static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms)
-{
- if (!dlm_is_member(ls, ms->m_header.h_nodeid)) {
- log_debug(ls, "ignore non-member message %d from %d %x %x %d",
- ms->m_type, ms->m_header.h_nodeid, ms->m_lkid,
- ms->m_remid, ms->m_result);
- return;
- }
-
- switch (ms->m_type) {
-
- /* messages sent to a master node */
-
- case DLM_MSG_REQUEST:
- receive_request(ls, ms);
- break;
-
- case DLM_MSG_CONVERT:
- receive_convert(ls, ms);
- break;
-
- case DLM_MSG_UNLOCK:
- receive_unlock(ls, ms);
- break;
-
- case DLM_MSG_CANCEL:
- receive_cancel(ls, ms);
- break;
-
- /* messages sent from a master node (replies to above) */
-
- case DLM_MSG_REQUEST_REPLY:
- receive_request_reply(ls, ms);
- break;
-
- case DLM_MSG_CONVERT_REPLY:
- receive_convert_reply(ls, ms);
- break;
-
- case DLM_MSG_UNLOCK_REPLY:
- receive_unlock_reply(ls, ms);
- break;
-
- case DLM_MSG_CANCEL_REPLY:
- receive_cancel_reply(ls, ms);
- break;
-
- /* messages sent from a master node (only two types of async msg) */
-
- case DLM_MSG_GRANT:
- receive_grant(ls, ms);
- break;
-
- case DLM_MSG_BAST:
- receive_bast(ls, ms);
- break;
-
- /* messages sent to a dir node */
-
- case DLM_MSG_LOOKUP:
- receive_lookup(ls, ms);
- break;
-
- case DLM_MSG_REMOVE:
- receive_remove(ls, ms);
- break;
-
- /* messages sent from a dir node (remove has no reply) */
-
- case DLM_MSG_LOOKUP_REPLY:
- receive_lookup_reply(ls, ms);
- break;
-
- /* other messages */
-
- case DLM_MSG_PURGE:
- receive_purge(ls, ms);
- break;
-
- default:
- log_error(ls, "unknown message type %d", ms->m_type);
- }
-}
-
-/* If the lockspace is in recovery mode (locking stopped), then normal
- messages are saved on the requestqueue for processing after recovery is
- done. When not in recovery mode, we wait for dlm_recoverd to drain saved
- messages off the requestqueue before we process new ones. This occurs right
- after recovery completes when we transition from saving all messages on
- requestqueue, to processing all the saved messages, to processing new
- messages as they arrive. */
-
-static void dlm_receive_message(struct dlm_ls *ls, struct dlm_message *ms,
- int nodeid)
-{
- if (dlm_locking_stopped(ls)) {
- dlm_add_requestqueue(ls, nodeid, ms);
- } else {
- dlm_wait_requestqueue(ls);
- _receive_message(ls, ms);
- }
-}
-
-/* This is called by dlm_recoverd to process messages that were saved on
- the requestqueue. */
-
-void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms)
-{
- _receive_message(ls, ms);
-}
-
-/* This is called by the midcomms layer when something is received for
- the lockspace. It could be either a MSG (normal message sent as part of
- standard locking activity) or an RCOM (recovery message sent as part of
- lockspace recovery). */
-
-void dlm_receive_buffer(union dlm_packet *p, int nodeid)
-{
- struct dlm_header *hd = &p->header;
- struct dlm_ls *ls;
- int type = 0;
-
- switch (hd->h_cmd) {
- case DLM_MSG:
- dlm_message_in(&p->message);
- type = p->message.m_type;
- break;
- case DLM_RCOM:
- dlm_rcom_in(&p->rcom);
- type = p->rcom.rc_type;
- break;
- default:
- log_print("invalid h_cmd %d from %u", hd->h_cmd, nodeid);
- return;
- }
-
- if (hd->h_nodeid != nodeid) {
- log_print("invalid h_nodeid %d from %d lockspace %x",
- hd->h_nodeid, nodeid, hd->h_lockspace);
- return;
- }
-
- ls = dlm_find_lockspace_global(hd->h_lockspace);
- if (!ls) {
- if (dlm_config.ci_log_debug)
- log_print("invalid lockspace %x from %d cmd %d type %d",
- hd->h_lockspace, nodeid, hd->h_cmd, type);
-
- if (hd->h_cmd == DLM_RCOM && type == DLM_RCOM_STATUS)
- dlm_send_ls_not_ready(nodeid, &p->rcom);
- return;
- }
-
- /* this rwsem allows dlm_ls_stop() to wait for all dlm_recv threads to
- be inactive (in this ls) before transitioning to recovery mode */
-
- down_read(&ls->ls_recv_active);
- if (hd->h_cmd == DLM_MSG)
- dlm_receive_message(ls, &p->message, nodeid);
- else
- dlm_receive_rcom(ls, &p->rcom, nodeid);
- up_read(&ls->ls_recv_active);
-
- dlm_put_lockspace(ls);
-}
-
-static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_message *ms_stub)
-{
- if (middle_conversion(lkb)) {
- hold_lkb(lkb);
- memset(ms_stub, 0, sizeof(struct dlm_message));
- ms_stub->m_flags = DLM_IFL_STUB_MS;
- ms_stub->m_type = DLM_MSG_CONVERT_REPLY;
- ms_stub->m_result = -EINPROGRESS;
- ms_stub->m_header.h_nodeid = lkb->lkb_nodeid;
- _receive_convert_reply(lkb, ms_stub);
-
- /* Same special case as in receive_rcom_lock_args() */
- lkb->lkb_grmode = DLM_LOCK_IV;
- rsb_set_flag(lkb->lkb_resource, RSB_RECOVER_CONVERT);
- unhold_lkb(lkb);
-
- } else if (lkb->lkb_rqmode >= lkb->lkb_grmode) {
- lkb->lkb_flags |= DLM_IFL_RESEND;
- }
-
- /* lkb->lkb_rqmode < lkb->lkb_grmode shouldn't happen since down
- conversions are async; there's no reply from the remote master */
-}
-
-/* A waiting lkb needs recovery if the master node has failed, or
- the master node is changing (only when no directory is used) */
-
-static int waiter_needs_recovery(struct dlm_ls *ls, struct dlm_lkb *lkb)
-{
- if (dlm_is_removed(ls, lkb->lkb_nodeid))
- return 1;
-
- if (!dlm_no_directory(ls))
- return 0;
-
- if (dlm_dir_nodeid(lkb->lkb_resource) != lkb->lkb_nodeid)
- return 1;
-
- return 0;
-}
-
-/* Recovery for locks that are waiting for replies from nodes that are now
- gone. We can just complete unlocks and cancels by faking a reply from the
- dead node. Requests and up-conversions we flag to be resent after
- recovery. Down-conversions can just be completed with a fake reply like
- unlocks. Conversions between PR and CW need special attention. */
-
-void dlm_recover_waiters_pre(struct dlm_ls *ls)
-{
- struct dlm_lkb *lkb, *safe;
- struct dlm_message *ms_stub;
- int wait_type, stub_unlock_result, stub_cancel_result;
-
- ms_stub = kmalloc(sizeof(struct dlm_message), GFP_KERNEL);
- if (!ms_stub) {
- log_error(ls, "dlm_recover_waiters_pre no mem");
- return;
- }
-
- mutex_lock(&ls->ls_waiters_mutex);
-
- list_for_each_entry_safe(lkb, safe, &ls->ls_waiters, lkb_wait_reply) {
-
- /* exclude debug messages about unlocks because there can be so
- many and they aren't very interesting */
-
- if (lkb->lkb_wait_type != DLM_MSG_UNLOCK) {
- log_debug(ls, "recover_waiter %x nodeid %d "
- "msg %d to %d", lkb->lkb_id, lkb->lkb_nodeid,
- lkb->lkb_wait_type, lkb->lkb_wait_nodeid);
- }
-
- /* all outstanding lookups, regardless of destination will be
- resent after recovery is done */
-
- if (lkb->lkb_wait_type == DLM_MSG_LOOKUP) {
- lkb->lkb_flags |= DLM_IFL_RESEND;
- continue;
- }
-
- if (!waiter_needs_recovery(ls, lkb))
- continue;
-
- wait_type = lkb->lkb_wait_type;
- stub_unlock_result = -DLM_EUNLOCK;
- stub_cancel_result = -DLM_ECANCEL;
-
- /* Main reply may have been received leaving a zero wait_type,
- but a reply for the overlapping op may not have been
- received. In that case we need to fake the appropriate
- reply for the overlap op. */
-
- if (!wait_type) {
- if (is_overlap_cancel(lkb)) {
- wait_type = DLM_MSG_CANCEL;
- if (lkb->lkb_grmode == DLM_LOCK_IV)
- stub_cancel_result = 0;
- }
- if (is_overlap_unlock(lkb)) {
- wait_type = DLM_MSG_UNLOCK;
- if (lkb->lkb_grmode == DLM_LOCK_IV)
- stub_unlock_result = -ENOENT;
- }
-
- log_debug(ls, "rwpre overlap %x %x %d %d %d",
- lkb->lkb_id, lkb->lkb_flags, wait_type,
- stub_cancel_result, stub_unlock_result);
- }
-
- switch (wait_type) {
-
- case DLM_MSG_REQUEST:
- lkb->lkb_flags |= DLM_IFL_RESEND;
- break;
-
- case DLM_MSG_CONVERT:
- recover_convert_waiter(ls, lkb, ms_stub);
- break;
-
- case DLM_MSG_UNLOCK:
- hold_lkb(lkb);
- memset(ms_stub, 0, sizeof(struct dlm_message));
- ms_stub->m_flags = DLM_IFL_STUB_MS;
- ms_stub->m_type = DLM_MSG_UNLOCK_REPLY;
- ms_stub->m_result = stub_unlock_result;
- ms_stub->m_header.h_nodeid = lkb->lkb_nodeid;
- _receive_unlock_reply(lkb, ms_stub);
- dlm_put_lkb(lkb);
- break;
-
- case DLM_MSG_CANCEL:
- hold_lkb(lkb);
- memset(ms_stub, 0, sizeof(struct dlm_message));
- ms_stub->m_flags = DLM_IFL_STUB_MS;
- ms_stub->m_type = DLM_MSG_CANCEL_REPLY;
- ms_stub->m_result = stub_cancel_result;
- ms_stub->m_header.h_nodeid = lkb->lkb_nodeid;
- _receive_cancel_reply(lkb, ms_stub);
- dlm_put_lkb(lkb);
- break;
-
- default:
- log_error(ls, "invalid lkb wait_type %d %d",
- lkb->lkb_wait_type, wait_type);
- }
- schedule();
- }
- mutex_unlock(&ls->ls_waiters_mutex);
- kfree(ms_stub);
-}
-
-static struct dlm_lkb *find_resend_waiter(struct dlm_ls *ls)
-{
- struct dlm_lkb *lkb;
- int found = 0;
-
- mutex_lock(&ls->ls_waiters_mutex);
- list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
- if (lkb->lkb_flags & DLM_IFL_RESEND) {
- hold_lkb(lkb);
- found = 1;
- break;
- }
- }
- mutex_unlock(&ls->ls_waiters_mutex);
-
- if (!found)
- lkb = NULL;
- return lkb;
-}
-
-/* Deal with lookups and lkb's marked RESEND from _pre. We may now be the
- master or dir-node for r. Processing the lkb may result in it being placed
- back on waiters. */
-
-/* We do this after normal locking has been enabled and any saved messages
- (in requestqueue) have been processed. We should be confident that at
- this point we won't get or process a reply to any of these waiting
- operations. But, new ops may be coming in on the rsbs/locks here from
- userspace or remotely. */
-
-/* there may have been an overlap unlock/cancel prior to recovery or after
- recovery. if before, the lkb may still have a pos wait_count; if after, the
- overlap flag would just have been set and nothing new sent. we can be
- confident here than any replies to either the initial op or overlap ops
- prior to recovery have been received. */
-
-int dlm_recover_waiters_post(struct dlm_ls *ls)
-{
- struct dlm_lkb *lkb;
- struct dlm_rsb *r;
- int error = 0, mstype, err, oc, ou;
-
- while (1) {
- if (dlm_locking_stopped(ls)) {
- log_debug(ls, "recover_waiters_post aborted");
- error = -EINTR;
- break;
- }
-
- lkb = find_resend_waiter(ls);
- if (!lkb)
- break;
-
- r = lkb->lkb_resource;
- hold_rsb(r);
- lock_rsb(r);
-
- mstype = lkb->lkb_wait_type;
- oc = is_overlap_cancel(lkb);
- ou = is_overlap_unlock(lkb);
- err = 0;
-
- log_debug(ls, "recover_waiter %x nodeid %d msg %d r_nodeid %d",
- lkb->lkb_id, lkb->lkb_nodeid, mstype, r->res_nodeid);
-
- /* At this point we assume that we won't get a reply to any
- previous op or overlap op on this lock. First, do a big
- remove_from_waiters() for all previous ops. */
-
- lkb->lkb_flags &= ~DLM_IFL_RESEND;
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
- lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
- lkb->lkb_wait_type = 0;
- lkb->lkb_wait_count = 0;
- mutex_lock(&ls->ls_waiters_mutex);
- list_del_init(&lkb->lkb_wait_reply);
- mutex_unlock(&ls->ls_waiters_mutex);
- unhold_lkb(lkb); /* for waiters list */
-
- if (oc || ou) {
- /* do an unlock or cancel instead of resending */
- switch (mstype) {
- case DLM_MSG_LOOKUP:
- case DLM_MSG_REQUEST:
- queue_cast(r, lkb, ou ? -DLM_EUNLOCK :
- -DLM_ECANCEL);
- unhold_lkb(lkb); /* undoes create_lkb() */
- break;
- case DLM_MSG_CONVERT:
- if (oc) {
- queue_cast(r, lkb, -DLM_ECANCEL);
- } else {
- lkb->lkb_exflags |= DLM_LKF_FORCEUNLOCK;
- _unlock_lock(r, lkb);
- }
- break;
- default:
- err = 1;
- }
- } else {
- switch (mstype) {
- case DLM_MSG_LOOKUP:
- case DLM_MSG_REQUEST:
- _request_lock(r, lkb);
- if (is_master(r))
- confirm_master(r, 0);
- break;
- case DLM_MSG_CONVERT:
- _convert_lock(r, lkb);
- break;
- default:
- err = 1;
- }
- }
-
- if (err)
- log_error(ls, "recover_waiters_post %x %d %x %d %d",
- lkb->lkb_id, mstype, lkb->lkb_flags, oc, ou);
- unlock_rsb(r);
- put_rsb(r);
- dlm_put_lkb(lkb);
- }
-
- return error;
-}
-
-static void purge_queue(struct dlm_rsb *r, struct list_head *queue,
- int (*test)(struct dlm_ls *ls, struct dlm_lkb *lkb))
-{
- struct dlm_ls *ls = r->res_ls;
- struct dlm_lkb *lkb, *safe;
-
- list_for_each_entry_safe(lkb, safe, queue, lkb_statequeue) {
- if (test(ls, lkb)) {
- rsb_set_flag(r, RSB_LOCKS_PURGED);
- del_lkb(r, lkb);
- /* this put should free the lkb */
- if (!dlm_put_lkb(lkb))
- log_error(ls, "purged lkb not released");
- }
- }
-}
-
-static int purge_dead_test(struct dlm_ls *ls, struct dlm_lkb *lkb)
-{
- return (is_master_copy(lkb) && dlm_is_removed(ls, lkb->lkb_nodeid));
-}
-
-static int purge_mstcpy_test(struct dlm_ls *ls, struct dlm_lkb *lkb)
-{
- return is_master_copy(lkb);
-}
-
-static void purge_dead_locks(struct dlm_rsb *r)
-{
- purge_queue(r, &r->res_grantqueue, &purge_dead_test);
- purge_queue(r, &r->res_convertqueue, &purge_dead_test);
- purge_queue(r, &r->res_waitqueue, &purge_dead_test);
-}
-
-void dlm_purge_mstcpy_locks(struct dlm_rsb *r)
-{
- purge_queue(r, &r->res_grantqueue, &purge_mstcpy_test);
- purge_queue(r, &r->res_convertqueue, &purge_mstcpy_test);
- purge_queue(r, &r->res_waitqueue, &purge_mstcpy_test);
-}
-
-/* Get rid of locks held by nodes that are gone. */
-
-int dlm_purge_locks(struct dlm_ls *ls)
-{
- struct dlm_rsb *r;
-
- log_debug(ls, "dlm_purge_locks");
-
- down_write(&ls->ls_root_sem);
- list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
- hold_rsb(r);
- lock_rsb(r);
- if (is_master(r))
- purge_dead_locks(r);
- unlock_rsb(r);
- unhold_rsb(r);
-
- schedule();
- }
- up_write(&ls->ls_root_sem);
-
- return 0;
-}
-
-static struct dlm_rsb *find_purged_rsb(struct dlm_ls *ls, int bucket)
-{
- struct rb_node *n;
- struct dlm_rsb *r, *r_ret = NULL;
-
- spin_lock(&ls->ls_rsbtbl[bucket].lock);
- for (n = rb_first(&ls->ls_rsbtbl[bucket].keep); n; n = rb_next(n)) {
- r = rb_entry(n, struct dlm_rsb, res_hashnode);
- if (!rsb_flag(r, RSB_LOCKS_PURGED))
- continue;
- hold_rsb(r);
- rsb_clear_flag(r, RSB_LOCKS_PURGED);
- r_ret = r;
- break;
- }
- spin_unlock(&ls->ls_rsbtbl[bucket].lock);
- return r_ret;
-}
-
-void dlm_grant_after_purge(struct dlm_ls *ls)
-{
- struct dlm_rsb *r;
- int bucket = 0;
-
- while (1) {
- r = find_purged_rsb(ls, bucket);
- if (!r) {
- if (bucket == ls->ls_rsbtbl_size - 1)
- break;
- bucket++;
- continue;
- }
- lock_rsb(r);
- if (is_master(r)) {
- grant_pending_locks(r);
- confirm_master(r, 0);
- }
- unlock_rsb(r);
- put_rsb(r);
- schedule();
- }
-}
-
-static struct dlm_lkb *search_remid_list(struct list_head *head, int nodeid,
- uint32_t remid)
-{
- struct dlm_lkb *lkb;
-
- list_for_each_entry(lkb, head, lkb_statequeue) {
- if (lkb->lkb_nodeid == nodeid && lkb->lkb_remid == remid)
- return lkb;
- }
- return NULL;
-}
-
-static struct dlm_lkb *search_remid(struct dlm_rsb *r, int nodeid,
- uint32_t remid)
-{
- struct dlm_lkb *lkb;
-
- lkb = search_remid_list(&r->res_grantqueue, nodeid, remid);
- if (lkb)
- return lkb;
- lkb = search_remid_list(&r->res_convertqueue, nodeid, remid);
- if (lkb)
- return lkb;
- lkb = search_remid_list(&r->res_waitqueue, nodeid, remid);
- if (lkb)
- return lkb;
- return NULL;
-}
-
-/* needs at least dlm_rcom + rcom_lock */
-static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
- struct dlm_rsb *r, struct dlm_rcom *rc)
-{
- struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf;
-
- lkb->lkb_nodeid = rc->rc_header.h_nodeid;
- lkb->lkb_ownpid = le32_to_cpu(rl->rl_ownpid);
- lkb->lkb_remid = le32_to_cpu(rl->rl_lkid);
- lkb->lkb_exflags = le32_to_cpu(rl->rl_exflags);
- lkb->lkb_flags = le32_to_cpu(rl->rl_flags) & 0x0000FFFF;
- lkb->lkb_flags |= DLM_IFL_MSTCPY;
- lkb->lkb_lvbseq = le32_to_cpu(rl->rl_lvbseq);
- lkb->lkb_rqmode = rl->rl_rqmode;
- lkb->lkb_grmode = rl->rl_grmode;
- /* don't set lkb_status because add_lkb wants to itself */
-
- lkb->lkb_bastfn = (rl->rl_asts & DLM_CB_BAST) ? &fake_bastfn : NULL;
- lkb->lkb_astfn = (rl->rl_asts & DLM_CB_CAST) ? &fake_astfn : NULL;
-
- if (lkb->lkb_exflags & DLM_LKF_VALBLK) {
- int lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) -
- sizeof(struct rcom_lock);
- if (lvblen > ls->ls_lvblen)
- return -EINVAL;
- lkb->lkb_lvbptr = dlm_allocate_lvb(ls);
- if (!lkb->lkb_lvbptr)
- return -ENOMEM;
- memcpy(lkb->lkb_lvbptr, rl->rl_lvb, lvblen);
- }
-
- /* Conversions between PR and CW (middle modes) need special handling.
- The real granted mode of these converting locks cannot be determined
- until all locks have been rebuilt on the rsb (recover_conversion) */
-
- if (rl->rl_wait_type == cpu_to_le16(DLM_MSG_CONVERT) &&
- middle_conversion(lkb)) {
- rl->rl_status = DLM_LKSTS_CONVERT;
- lkb->lkb_grmode = DLM_LOCK_IV;
- rsb_set_flag(r, RSB_RECOVER_CONVERT);
- }
-
- return 0;
-}
-
-/* This lkb may have been recovered in a previous aborted recovery so we need
- to check if the rsb already has an lkb with the given remote nodeid/lkid.
- If so we just send back a standard reply. If not, we create a new lkb with
- the given values and send back our lkid. We send back our lkid by sending
- back the rcom_lock struct we got but with the remid field filled in. */
-
-/* needs at least dlm_rcom + rcom_lock */
-int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
-{
- struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf;
- struct dlm_rsb *r;
- struct dlm_lkb *lkb;
- int error;
-
- if (rl->rl_parent_lkid) {
- error = -EOPNOTSUPP;
- goto out;
- }
-
- error = find_rsb(ls, rl->rl_name, le16_to_cpu(rl->rl_namelen),
- R_MASTER, &r);
- if (error)
- goto out;
-
- lock_rsb(r);
-
- lkb = search_remid(r, rc->rc_header.h_nodeid, le32_to_cpu(rl->rl_lkid));
- if (lkb) {
- error = -EEXIST;
- goto out_remid;
- }
-
- error = create_lkb(ls, &lkb);
- if (error)
- goto out_unlock;
-
- error = receive_rcom_lock_args(ls, lkb, r, rc);
- if (error) {
- __put_lkb(ls, lkb);
- goto out_unlock;
- }
-
- attach_lkb(r, lkb);
- add_lkb(r, lkb, rl->rl_status);
- error = 0;
-
- out_remid:
- /* this is the new value returned to the lock holder for
- saving in its process-copy lkb */
- rl->rl_remid = cpu_to_le32(lkb->lkb_id);
-
- out_unlock:
- unlock_rsb(r);
- put_rsb(r);
- out:
- if (error)
- log_debug(ls, "recover_master_copy %d %x", error,
- le32_to_cpu(rl->rl_lkid));
- rl->rl_result = cpu_to_le32(error);
- return error;
-}
-
-/* needs at least dlm_rcom + rcom_lock */
-int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
-{
- struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf;
- struct dlm_rsb *r;
- struct dlm_lkb *lkb;
- int error;
-
- error = find_lkb(ls, le32_to_cpu(rl->rl_lkid), &lkb);
- if (error) {
- log_error(ls, "recover_process_copy no lkid %x",
- le32_to_cpu(rl->rl_lkid));
- return error;
- }
-
- DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
-
- error = le32_to_cpu(rl->rl_result);
-
- r = lkb->lkb_resource;
- hold_rsb(r);
- lock_rsb(r);
-
- switch (error) {
- case -EBADR:
- /* There's a chance the new master received our lock before
- dlm_recover_master_reply(), this wouldn't happen if we did
- a barrier between recover_masters and recover_locks. */
- log_debug(ls, "master copy not ready %x r %lx %s", lkb->lkb_id,
- (unsigned long)r, r->res_name);
- dlm_send_rcom_lock(r, lkb);
- goto out;
- case -EEXIST:
- log_debug(ls, "master copy exists %x", lkb->lkb_id);
- /* fall through */
- case 0:
- lkb->lkb_remid = le32_to_cpu(rl->rl_remid);
- break;
- default:
- log_error(ls, "dlm_recover_process_copy unknown error %d %x",
- error, lkb->lkb_id);
- }
-
- /* an ack for dlm_recover_locks() which waits for replies from
- all the locks it sends to new masters */
- dlm_recovered_lock(r);
- out:
- unlock_rsb(r);
- put_rsb(r);
- dlm_put_lkb(lkb);
-
- return 0;
-}
-
-int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
- int mode, uint32_t flags, void *name, unsigned int namelen,
- unsigned long timeout_cs)
-{
- struct dlm_lkb *lkb;
- struct dlm_args args;
- int error;
-
- dlm_lock_recovery(ls);
-
- error = create_lkb(ls, &lkb);
- if (error) {
- kfree(ua);
- goto out;
- }
-
- if (flags & DLM_LKF_VALBLK) {
- ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_NOFS);
- if (!ua->lksb.sb_lvbptr) {
- kfree(ua);
- __put_lkb(ls, lkb);
- error = -ENOMEM;
- goto out;
- }
- }
-
- /* After ua is attached to lkb it will be freed by dlm_free_lkb().
- When DLM_IFL_USER is set, the dlm knows that this is a userspace
- lock and that lkb_astparam is the dlm_user_args structure. */
-
- error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs,
- fake_astfn, ua, fake_bastfn, &args);
- lkb->lkb_flags |= DLM_IFL_USER;
-
- if (error) {
- __put_lkb(ls, lkb);
- goto out;
- }
-
- error = request_lock(ls, lkb, name, namelen, &args);
-
- switch (error) {
- case 0:
- break;
- case -EINPROGRESS:
- error = 0;
- break;
- case -EAGAIN:
- error = 0;
- /* fall through */
- default:
- __put_lkb(ls, lkb);
- goto out;
- }
-
- /* add this new lkb to the per-process list of locks */
- spin_lock(&ua->proc->locks_spin);
- hold_lkb(lkb);
- list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks);
- spin_unlock(&ua->proc->locks_spin);
- out:
- dlm_unlock_recovery(ls);
- return error;
-}
-
-int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
- unsigned long timeout_cs)
-{
- struct dlm_lkb *lkb;
- struct dlm_args args;
- struct dlm_user_args *ua;
- int error;
-
- dlm_lock_recovery(ls);
-
- error = find_lkb(ls, lkid, &lkb);
- if (error)
- goto out;
-
- /* user can change the params on its lock when it converts it, or
- add an lvb that didn't exist before */
-
- ua = lkb->lkb_ua;
-
- if (flags & DLM_LKF_VALBLK && !ua->lksb.sb_lvbptr) {
- ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_NOFS);
- if (!ua->lksb.sb_lvbptr) {
- error = -ENOMEM;
- goto out_put;
- }
- }
- if (lvb_in && ua->lksb.sb_lvbptr)
- memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN);
-
- ua->xid = ua_tmp->xid;
- ua->castparam = ua_tmp->castparam;
- ua->castaddr = ua_tmp->castaddr;
- ua->bastparam = ua_tmp->bastparam;
- ua->bastaddr = ua_tmp->bastaddr;
- ua->user_lksb = ua_tmp->user_lksb;
-
- error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs,
- fake_astfn, ua, fake_bastfn, &args);
- if (error)
- goto out_put;
-
- error = convert_lock(ls, lkb, &args);
-
- if (error == -EINPROGRESS || error == -EAGAIN || error == -EDEADLK)
- error = 0;
- out_put:
- dlm_put_lkb(lkb);
- out:
- dlm_unlock_recovery(ls);
- kfree(ua_tmp);
- return error;
-}
-
-int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- uint32_t flags, uint32_t lkid, char *lvb_in)
-{
- struct dlm_lkb *lkb;
- struct dlm_args args;
- struct dlm_user_args *ua;
- int error;
-
- dlm_lock_recovery(ls);
-
- error = find_lkb(ls, lkid, &lkb);
- if (error)
- goto out;
-
- ua = lkb->lkb_ua;
-
- if (lvb_in && ua->lksb.sb_lvbptr)
- memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN);
- if (ua_tmp->castparam)
- ua->castparam = ua_tmp->castparam;
- ua->user_lksb = ua_tmp->user_lksb;
-
- error = set_unlock_args(flags, ua, &args);
- if (error)
- goto out_put;
-
- error = unlock_lock(ls, lkb, &args);
-
- if (error == -DLM_EUNLOCK)
- error = 0;
- /* from validate_unlock_args() */
- if (error == -EBUSY && (flags & DLM_LKF_FORCEUNLOCK))
- error = 0;
- if (error)
- goto out_put;
-
- spin_lock(&ua->proc->locks_spin);
- /* dlm_user_add_cb() may have already taken lkb off the proc list */
- if (!list_empty(&lkb->lkb_ownqueue))
- list_move(&lkb->lkb_ownqueue, &ua->proc->unlocking);
- spin_unlock(&ua->proc->locks_spin);
- out_put:
- dlm_put_lkb(lkb);
- out:
- dlm_unlock_recovery(ls);
- kfree(ua_tmp);
- return error;
-}
-
-int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- uint32_t flags, uint32_t lkid)
-{
- struct dlm_lkb *lkb;
- struct dlm_args args;
- struct dlm_user_args *ua;
- int error;
-
- dlm_lock_recovery(ls);
-
- error = find_lkb(ls, lkid, &lkb);
- if (error)
- goto out;
-
- ua = lkb->lkb_ua;
- if (ua_tmp->castparam)
- ua->castparam = ua_tmp->castparam;
- ua->user_lksb = ua_tmp->user_lksb;
-
- error = set_unlock_args(flags, ua, &args);
- if (error)
- goto out_put;
-
- error = cancel_lock(ls, lkb, &args);
-
- if (error == -DLM_ECANCEL)
- error = 0;
- /* from validate_unlock_args() */
- if (error == -EBUSY)
- error = 0;
- out_put:
- dlm_put_lkb(lkb);
- out:
- dlm_unlock_recovery(ls);
- kfree(ua_tmp);
- return error;
-}
-
-int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid)
-{
- struct dlm_lkb *lkb;
- struct dlm_args args;
- struct dlm_user_args *ua;
- struct dlm_rsb *r;
- int error;
-
- dlm_lock_recovery(ls);
-
- error = find_lkb(ls, lkid, &lkb);
- if (error)
- goto out;
-
- ua = lkb->lkb_ua;
-
- error = set_unlock_args(flags, ua, &args);
- if (error)
- goto out_put;
-
- /* same as cancel_lock(), but set DEADLOCK_CANCEL after lock_rsb */
-
- r = lkb->lkb_resource;
- hold_rsb(r);
- lock_rsb(r);
-
- error = validate_unlock_args(lkb, &args);
- if (error)
- goto out_r;
- lkb->lkb_flags |= DLM_IFL_DEADLOCK_CANCEL;
-
- error = _cancel_lock(r, lkb);
- out_r:
- unlock_rsb(r);
- put_rsb(r);
-
- if (error == -DLM_ECANCEL)
- error = 0;
- /* from validate_unlock_args() */
- if (error == -EBUSY)
- error = 0;
- out_put:
- dlm_put_lkb(lkb);
- out:
- dlm_unlock_recovery(ls);
- return error;
-}
-
-/* lkb's that are removed from the waiters list by revert are just left on the
- orphans list with the granted orphan locks, to be freed by purge */
-
-static int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb)
-{
- struct dlm_args args;
- int error;
-
- hold_lkb(lkb);
- mutex_lock(&ls->ls_orphans_mutex);
- list_add_tail(&lkb->lkb_ownqueue, &ls->ls_orphans);
- mutex_unlock(&ls->ls_orphans_mutex);
-
- set_unlock_args(0, lkb->lkb_ua, &args);
-
- error = cancel_lock(ls, lkb, &args);
- if (error == -DLM_ECANCEL)
- error = 0;
- return error;
-}
-
-/* The force flag allows the unlock to go ahead even if the lkb isn't granted.
- Regardless of what rsb queue the lock is on, it's removed and freed. */
-
-static int unlock_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb)
-{
- struct dlm_args args;
- int error;
-
- set_unlock_args(DLM_LKF_FORCEUNLOCK, lkb->lkb_ua, &args);
-
- error = unlock_lock(ls, lkb, &args);
- if (error == -DLM_EUNLOCK)
- error = 0;
- return error;
-}
-
-/* We have to release clear_proc_locks mutex before calling unlock_proc_lock()
- (which does lock_rsb) due to deadlock with receiving a message that does
- lock_rsb followed by dlm_user_add_cb() */
-
-static struct dlm_lkb *del_proc_lock(struct dlm_ls *ls,
- struct dlm_user_proc *proc)
-{
- struct dlm_lkb *lkb = NULL;
-
- mutex_lock(&ls->ls_clear_proc_locks);
- if (list_empty(&proc->locks))
- goto out;
-
- lkb = list_entry(proc->locks.next, struct dlm_lkb, lkb_ownqueue);
- list_del_init(&lkb->lkb_ownqueue);
-
- if (lkb->lkb_exflags & DLM_LKF_PERSISTENT)
- lkb->lkb_flags |= DLM_IFL_ORPHAN;
- else
- lkb->lkb_flags |= DLM_IFL_DEAD;
- out:
- mutex_unlock(&ls->ls_clear_proc_locks);
- return lkb;
-}
-
-/* The ls_clear_proc_locks mutex protects against dlm_user_add_cb() which
- 1) references lkb->ua which we free here and 2) adds lkbs to proc->asts,
- which we clear here. */
-
-/* proc CLOSING flag is set so no more device_reads should look at proc->asts
- list, and no more device_writes should add lkb's to proc->locks list; so we
- shouldn't need to take asts_spin or locks_spin here. this assumes that
- device reads/writes/closes are serialized -- FIXME: we may need to serialize
- them ourself. */
-
-void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
-{
- struct dlm_lkb *lkb, *safe;
-
- dlm_lock_recovery(ls);
-
- while (1) {
- lkb = del_proc_lock(ls, proc);
- if (!lkb)
- break;
- del_timeout(lkb);
- if (lkb->lkb_exflags & DLM_LKF_PERSISTENT)
- orphan_proc_lock(ls, lkb);
- else
- unlock_proc_lock(ls, lkb);
-
- /* this removes the reference for the proc->locks list
- added by dlm_user_request, it may result in the lkb
- being freed */
-
- dlm_put_lkb(lkb);
- }
-
- mutex_lock(&ls->ls_clear_proc_locks);
-
- /* in-progress unlocks */
- list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) {
- list_del_init(&lkb->lkb_ownqueue);
- lkb->lkb_flags |= DLM_IFL_DEAD;
- dlm_put_lkb(lkb);
- }
-
- list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_cb_list) {
- memset(&lkb->lkb_callbacks, 0,
- sizeof(struct dlm_callback) * DLM_CALLBACKS_SIZE);
- list_del_init(&lkb->lkb_cb_list);
- dlm_put_lkb(lkb);
- }
-
- mutex_unlock(&ls->ls_clear_proc_locks);
- dlm_unlock_recovery(ls);
-}
-
-static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
-{
- struct dlm_lkb *lkb, *safe;
-
- while (1) {
- lkb = NULL;
- spin_lock(&proc->locks_spin);
- if (!list_empty(&proc->locks)) {
- lkb = list_entry(proc->locks.next, struct dlm_lkb,
- lkb_ownqueue);
- list_del_init(&lkb->lkb_ownqueue);
- }
- spin_unlock(&proc->locks_spin);
-
- if (!lkb)
- break;
-
- lkb->lkb_flags |= DLM_IFL_DEAD;
- unlock_proc_lock(ls, lkb);
- dlm_put_lkb(lkb); /* ref from proc->locks list */
- }
-
- spin_lock(&proc->locks_spin);
- list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) {
- list_del_init(&lkb->lkb_ownqueue);
- lkb->lkb_flags |= DLM_IFL_DEAD;
- dlm_put_lkb(lkb);
- }
- spin_unlock(&proc->locks_spin);
-
- spin_lock(&proc->asts_spin);
- list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_cb_list) {
- memset(&lkb->lkb_callbacks, 0,
- sizeof(struct dlm_callback) * DLM_CALLBACKS_SIZE);
- list_del_init(&lkb->lkb_cb_list);
- dlm_put_lkb(lkb);
- }
- spin_unlock(&proc->asts_spin);
-}
-
-/* pid of 0 means purge all orphans */
-
-static void do_purge(struct dlm_ls *ls, int nodeid, int pid)
-{
- struct dlm_lkb *lkb, *safe;
-
- mutex_lock(&ls->ls_orphans_mutex);
- list_for_each_entry_safe(lkb, safe, &ls->ls_orphans, lkb_ownqueue) {
- if (pid && lkb->lkb_ownpid != pid)
- continue;
- unlock_proc_lock(ls, lkb);
- list_del_init(&lkb->lkb_ownqueue);
- dlm_put_lkb(lkb);
- }
- mutex_unlock(&ls->ls_orphans_mutex);
-}
-
-static int send_purge(struct dlm_ls *ls, int nodeid, int pid)
-{
- struct dlm_message *ms;
- struct dlm_mhandle *mh;
- int error;
-
- error = _create_message(ls, sizeof(struct dlm_message), nodeid,
- DLM_MSG_PURGE, &ms, &mh);
- if (error)
- return error;
- ms->m_nodeid = nodeid;
- ms->m_pid = pid;
-
- return send_message(mh, ms);
-}
-
-int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
- int nodeid, int pid)
-{
- int error = 0;
-
- if (nodeid != dlm_our_nodeid()) {
- error = send_purge(ls, nodeid, pid);
- } else {
- dlm_lock_recovery(ls);
- if (pid == current->pid)
- purge_proc_locks(ls, proc);
- else
- do_purge(ls, nodeid, pid);
- dlm_unlock_recovery(ls);
- }
- return error;
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/lock.h b/ANDROID_3.4.5/fs/dlm/lock.h
deleted file mode 100644
index 1a255307..00000000
--- a/ANDROID_3.4.5/fs/dlm/lock.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005-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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __LOCK_DOT_H__
-#define __LOCK_DOT_H__
-
-void dlm_dump_rsb(struct dlm_rsb *r);
-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(union dlm_packet *p, int nodeid);
-int dlm_modes_compat(int mode1, int mode2);
-void dlm_put_rsb(struct dlm_rsb *r);
-void dlm_hold_rsb(struct dlm_rsb *r);
-int dlm_put_lkb(struct dlm_lkb *lkb);
-void dlm_scan_rsbs(struct dlm_ls *ls);
-int dlm_lock_recovery_try(struct dlm_ls *ls);
-void dlm_unlock_recovery(struct dlm_ls *ls);
-void dlm_scan_waiters(struct dlm_ls *ls);
-void dlm_scan_timeout(struct dlm_ls *ls);
-void dlm_adjust_timeouts(struct dlm_ls *ls);
-
-int dlm_search_rsb_tree(struct rb_root *tree, char *name, int len,
- unsigned int flags, struct dlm_rsb **r_ret);
-
-int dlm_purge_locks(struct dlm_ls *ls);
-void dlm_purge_mstcpy_locks(struct dlm_rsb *r);
-void dlm_grant_after_purge(struct dlm_ls *ls);
-int dlm_recover_waiters_post(struct dlm_ls *ls);
-void dlm_recover_waiters_pre(struct dlm_ls *ls);
-int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
-int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
-
-int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode,
- uint32_t flags, void *name, unsigned int namelen,
- unsigned long timeout_cs);
-int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
- unsigned long timeout_cs);
-int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- uint32_t flags, uint32_t lkid, char *lvb_in);
-int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- uint32_t flags, uint32_t lkid);
-int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
- int nodeid, int pid);
-int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid);
-void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc);
-
-static inline int is_master(struct dlm_rsb *r)
-{
- return !r->res_nodeid;
-}
-
-static inline void lock_rsb(struct dlm_rsb *r)
-{
- mutex_lock(&r->res_mutex);
-}
-
-static inline void unlock_rsb(struct dlm_rsb *r)
-{
- mutex_unlock(&r->res_mutex);
-}
-
-#endif
-
diff --git a/ANDROID_3.4.5/fs/dlm/lockspace.c b/ANDROID_3.4.5/fs/dlm/lockspace.c
deleted file mode 100644
index a1ea25fa..00000000
--- a/ANDROID_3.4.5/fs/dlm/lockspace.c
+++ /dev/null
@@ -1,872 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2011 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 "dir.h"
-#include "lowcomms.h"
-#include "config.h"
-#include "memory.h"
-#include "lock.h"
-#include "recover.h"
-#include "requestqueue.h"
-#include "user.h"
-#include "ast.h"
-
-static 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 const 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;
-
-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;
-}
-
-static int dlm_uevent(struct kset *kset, struct kobject *kobj,
- struct kobj_uevent_env *env)
-{
- struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
-
- add_uevent_var(env, "LOCKSPACE=%s", ls->ls_name);
- return 0;
-}
-
-static struct kset_uevent_ops dlm_uevent_ops = {
- .uevent = dlm_uevent,
-};
-
-int __init dlm_lockspace_init(void)
-{
- ls_count = 0;
- mutex_init(&ls_lock);
- INIT_LIST_HEAD(&lslist);
- spin_lock_init(&lslist_lock);
-
- dlm_kset = kset_create_and_add("dlm", &dlm_uevent_ops, kernel_kobj);
- if (!dlm_kset) {
- printk(KERN_WARNING "%s: can not create kset\n", __func__);
- return -ENOMEM;
- }
- return 0;
-}
-
-void dlm_lockspace_exit(void)
-{
- kset_unregister(dlm_kset);
-}
-
-static struct dlm_ls *find_ls_to_scan(void)
-{
- struct dlm_ls *ls;
-
- spin_lock(&lslist_lock);
- list_for_each_entry(ls, &lslist, ls_list) {
- if (time_after_eq(jiffies, ls->ls_scan_time +
- dlm_config.ci_scan_secs * HZ)) {
- spin_unlock(&lslist_lock);
- return ls;
- }
- }
- spin_unlock(&lslist_lock);
- return NULL;
-}
-
-static int dlm_scand(void *data)
-{
- struct dlm_ls *ls;
-
- while (!kthread_should_stop()) {
- ls = find_ls_to_scan();
- if (ls) {
- if (dlm_lock_recovery_try(ls)) {
- ls->ls_scan_time = jiffies;
- dlm_scan_rsbs(ls);
- dlm_scan_timeout(ls);
- dlm_scan_waiters(ls);
- dlm_unlock_recovery(ls);
- } else {
- ls->ls_scan_time += HZ;
- }
- continue;
- }
- 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);
-}
-
-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) {
- WARN_ON(ls->ls_create_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;
-
- error = dlm_scand_start();
- if (error) {
- log_print("cannot start dlm_scand thread %d", error);
- goto 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();
- fail:
- return error;
-}
-
-static void threads_stop(void)
-{
- dlm_scand_stop();
- dlm_lowcomms_stop();
-}
-
-static int new_lockspace(const char *name, const char *cluster,
- uint32_t flags, int lvblen,
- const struct dlm_lockspace_ops *ops, void *ops_arg,
- int *ops_result, dlm_lockspace_t **lockspace)
-{
- struct dlm_ls *ls;
- int i, size, error;
- int do_unreg = 0;
- int namelen = strlen(name);
-
- if (namelen > DLM_LOCKSPACE_LEN)
- return -EINVAL;
-
- if (!lvblen || (lvblen % 8))
- return -EINVAL;
-
- if (!try_module_get(THIS_MODULE))
- return -EINVAL;
-
- if (!dlm_user_daemon_available()) {
- log_print("dlm user daemon not available");
- error = -EUNATCH;
- goto out;
- }
-
- if (ops && ops_result) {
- if (!dlm_config.ci_recover_callbacks)
- *ops_result = -EOPNOTSUPP;
- else
- *ops_result = 0;
- }
-
- if (dlm_config.ci_recover_callbacks && cluster &&
- strncmp(cluster, dlm_config.ci_cluster_name, DLM_LOCKSPACE_LEN)) {
- log_print("dlm cluster name %s mismatch %s",
- dlm_config.ci_cluster_name, cluster);
- error = -EBADR;
- goto out;
- }
-
- error = 0;
-
- spin_lock(&lslist_lock);
- list_for_each_entry(ls, &lslist, ls_list) {
- WARN_ON(ls->ls_create_count <= 0);
- if (ls->ls_namelen != namelen)
- continue;
- if (memcmp(ls->ls_name, name, namelen))
- continue;
- if (flags & DLM_LSFL_NEWEXCL) {
- error = -EEXIST;
- break;
- }
- ls->ls_create_count++;
- *lockspace = ls;
- error = 1;
- break;
- }
- spin_unlock(&lslist_lock);
-
- if (error)
- goto out;
-
- error = -ENOMEM;
-
- ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_NOFS);
- if (!ls)
- goto out;
- memcpy(ls->ls_name, name, namelen);
- ls->ls_namelen = namelen;
- ls->ls_lvblen = lvblen;
- ls->ls_count = 0;
- ls->ls_flags = 0;
- ls->ls_scan_time = jiffies;
-
- if (ops && dlm_config.ci_recover_callbacks) {
- ls->ls_ops = ops;
- ls->ls_ops_arg = ops_arg;
- }
-
- if (flags & DLM_LSFL_TIMEWARN)
- set_bit(LSFL_TIMEWARN, &ls->ls_flags);
-
- /* ls_exflags are forced to match among nodes, and we don't
- need to require all nodes to have some flags set */
- ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
- DLM_LSFL_NEWEXCL));
-
- size = dlm_config.ci_rsbtbl_size;
- ls->ls_rsbtbl_size = size;
-
- ls->ls_rsbtbl = vmalloc(sizeof(struct dlm_rsbtable) * size);
- if (!ls->ls_rsbtbl)
- goto out_lsfree;
- for (i = 0; i < size; i++) {
- ls->ls_rsbtbl[i].keep.rb_node = NULL;
- ls->ls_rsbtbl[i].toss.rb_node = NULL;
- spin_lock_init(&ls->ls_rsbtbl[i].lock);
- }
-
- idr_init(&ls->ls_lkbidr);
- spin_lock_init(&ls->ls_lkbidr_spin);
-
- size = dlm_config.ci_dirtbl_size;
- ls->ls_dirtbl_size = size;
-
- ls->ls_dirtbl = vmalloc(sizeof(struct dlm_dirtable) * size);
- if (!ls->ls_dirtbl)
- goto out_lkbfree;
- for (i = 0; i < size; i++) {
- INIT_LIST_HEAD(&ls->ls_dirtbl[i].list);
- spin_lock_init(&ls->ls_dirtbl[i].lock);
- }
-
- INIT_LIST_HEAD(&ls->ls_waiters);
- mutex_init(&ls->ls_waiters_mutex);
- INIT_LIST_HEAD(&ls->ls_orphans);
- mutex_init(&ls->ls_orphans_mutex);
- INIT_LIST_HEAD(&ls->ls_timeout);
- mutex_init(&ls->ls_timeout_mutex);
-
- INIT_LIST_HEAD(&ls->ls_new_rsb);
- spin_lock_init(&ls->ls_new_rsb_spin);
-
- INIT_LIST_HEAD(&ls->ls_nodes);
- INIT_LIST_HEAD(&ls->ls_nodes_gone);
- ls->ls_num_nodes = 0;
- ls->ls_low_nodeid = 0;
- ls->ls_total_weight = 0;
- ls->ls_node_array = NULL;
-
- memset(&ls->ls_stub_rsb, 0, sizeof(struct dlm_rsb));
- ls->ls_stub_rsb.res_ls = ls;
-
- ls->ls_debug_rsb_dentry = NULL;
- ls->ls_debug_waiters_dentry = NULL;
-
- init_waitqueue_head(&ls->ls_uevent_wait);
- ls->ls_uevent_result = 0;
- init_completion(&ls->ls_members_done);
- ls->ls_members_result = -1;
-
- mutex_init(&ls->ls_cb_mutex);
- INIT_LIST_HEAD(&ls->ls_cb_delay);
-
- ls->ls_recoverd_task = NULL;
- mutex_init(&ls->ls_recoverd_active);
- spin_lock_init(&ls->ls_recover_lock);
- spin_lock_init(&ls->ls_rcom_spin);
- get_random_bytes(&ls->ls_rcom_seq, sizeof(uint64_t));
- ls->ls_recover_status = 0;
- ls->ls_recover_seq = 0;
- ls->ls_recover_args = NULL;
- init_rwsem(&ls->ls_in_recovery);
- init_rwsem(&ls->ls_recv_active);
- INIT_LIST_HEAD(&ls->ls_requestqueue);
- mutex_init(&ls->ls_requestqueue_mutex);
- mutex_init(&ls->ls_clear_proc_locks);
-
- ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
- if (!ls->ls_recover_buf)
- goto out_dirfree;
-
- ls->ls_slot = 0;
- ls->ls_num_slots = 0;
- ls->ls_slots_size = 0;
- ls->ls_slots = NULL;
-
- INIT_LIST_HEAD(&ls->ls_recover_list);
- spin_lock_init(&ls->ls_recover_list_lock);
- ls->ls_recover_list_count = 0;
- ls->ls_local_handle = ls;
- init_waitqueue_head(&ls->ls_wait_general);
- INIT_LIST_HEAD(&ls->ls_root_list);
- init_rwsem(&ls->ls_root_sem);
-
- down_write(&ls->ls_in_recovery);
-
- spin_lock(&lslist_lock);
- ls->ls_create_count = 1;
- list_add(&ls->ls_list, &lslist);
- spin_unlock(&lslist_lock);
-
- if (flags & DLM_LSFL_FS) {
- error = dlm_callback_start(ls);
- if (error) {
- log_error(ls, "can't start dlm_callback %d", error);
- goto out_delist;
- }
- }
-
- /* needs to find ls in lslist */
- error = dlm_recoverd_start(ls);
- if (error) {
- log_error(ls, "can't start dlm_recoverd %d", error);
- goto out_callback;
- }
-
- ls->ls_kobj.kset = dlm_kset;
- error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
- "%s", ls->ls_name);
- if (error)
- goto out_recoverd;
- kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
-
- /* let kobject handle freeing of ls if there's an error */
- do_unreg = 1;
-
- /* This uevent triggers dlm_controld in userspace to add us to the
- group of nodes that are members of this lockspace (managed by the
- cluster infrastructure.) Once it's done that, it tells us who the
- current lockspace members are (via configfs) and then tells the
- lockspace to start running (via sysfs) in dlm_ls_start(). */
-
- error = do_uevent(ls, 1);
- if (error)
- goto out_recoverd;
-
- wait_for_completion(&ls->ls_members_done);
- error = ls->ls_members_result;
- if (error)
- goto out_members;
-
- dlm_create_debug_file(ls);
-
- log_debug(ls, "join complete");
- *lockspace = ls;
- return 0;
-
- out_members:
- do_uevent(ls, 0);
- dlm_clear_members(ls);
- kfree(ls->ls_node_array);
- out_recoverd:
- dlm_recoverd_stop(ls);
- out_callback:
- dlm_callback_stop(ls);
- out_delist:
- spin_lock(&lslist_lock);
- list_del(&ls->ls_list);
- spin_unlock(&lslist_lock);
- kfree(ls->ls_recover_buf);
- out_dirfree:
- vfree(ls->ls_dirtbl);
- out_lkbfree:
- idr_destroy(&ls->ls_lkbidr);
- vfree(ls->ls_rsbtbl);
- out_lsfree:
- if (do_unreg)
- kobject_put(&ls->ls_kobj);
- else
- kfree(ls);
- out:
- module_put(THIS_MODULE);
- return error;
-}
-
-int dlm_new_lockspace(const char *name, const char *cluster,
- uint32_t flags, int lvblen,
- const struct dlm_lockspace_ops *ops, void *ops_arg,
- int *ops_result, dlm_lockspace_t **lockspace)
-{
- int error = 0;
-
- mutex_lock(&ls_lock);
- if (!ls_count)
- error = threads_start();
- if (error)
- goto out;
-
- error = new_lockspace(name, cluster, flags, lvblen, ops, ops_arg,
- ops_result, lockspace);
- if (!error)
- ls_count++;
- if (error > 0)
- error = 0;
- if (!ls_count)
- threads_stop();
- out:
- mutex_unlock(&ls_lock);
- return error;
-}
-
-static int lkb_idr_is_local(int id, void *p, void *data)
-{
- struct dlm_lkb *lkb = p;
-
- if (!lkb->lkb_nodeid)
- return 1;
- return 0;
-}
-
-static int lkb_idr_is_any(int id, void *p, void *data)
-{
- return 1;
-}
-
-static int lkb_idr_free(int id, void *p, void *data)
-{
- struct dlm_lkb *lkb = p;
-
- if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
- dlm_free_lvb(lkb->lkb_lvbptr);
-
- dlm_free_lkb(lkb);
- return 0;
-}
-
-/* NOTE: We check the lkbidr here rather than the resource table.
- This is because there may be LKBs queued as ASTs that have been unlinked
- from their RSBs and are pending deletion once the AST has been delivered */
-
-static int lockspace_busy(struct dlm_ls *ls, int force)
-{
- int rv;
-
- spin_lock(&ls->ls_lkbidr_spin);
- if (force == 0) {
- rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_any, ls);
- } else if (force == 1) {
- rv = idr_for_each(&ls->ls_lkbidr, lkb_idr_is_local, ls);
- } else {
- rv = 0;
- }
- spin_unlock(&ls->ls_lkbidr_spin);
- return rv;
-}
-
-static int release_lockspace(struct dlm_ls *ls, int force)
-{
- struct dlm_rsb *rsb;
- struct rb_node *n;
- int i, busy, rv;
-
- busy = lockspace_busy(ls, force);
-
- spin_lock(&lslist_lock);
- if (ls->ls_create_count == 1) {
- if (busy) {
- rv = -EBUSY;
- } else {
- /* remove_lockspace takes ls off lslist */
- ls->ls_create_count = 0;
- rv = 0;
- }
- } else if (ls->ls_create_count > 1) {
- rv = --ls->ls_create_count;
- } else {
- rv = -EINVAL;
- }
- spin_unlock(&lslist_lock);
-
- if (rv) {
- log_debug(ls, "release_lockspace no remove %d", rv);
- return rv;
- }
-
- dlm_device_deregister(ls);
-
- if (force < 3 && dlm_user_daemon_available())
- do_uevent(ls, 0);
-
- dlm_recoverd_stop(ls);
-
- dlm_callback_stop(ls);
-
- remove_lockspace(ls);
-
- dlm_delete_debug_file(ls);
-
- kfree(ls->ls_recover_buf);
-
- /*
- * Free direntry structs.
- */
-
- dlm_dir_clear(ls);
- vfree(ls->ls_dirtbl);
-
- /*
- * Free all lkb's in idr
- */
-
- idr_for_each(&ls->ls_lkbidr, lkb_idr_free, ls);
- idr_remove_all(&ls->ls_lkbidr);
- idr_destroy(&ls->ls_lkbidr);
-
- /*
- * Free all rsb's on rsbtbl[] lists
- */
-
- for (i = 0; i < ls->ls_rsbtbl_size; i++) {
- while ((n = rb_first(&ls->ls_rsbtbl[i].keep))) {
- rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
- rb_erase(n, &ls->ls_rsbtbl[i].keep);
- dlm_free_rsb(rsb);
- }
-
- while ((n = rb_first(&ls->ls_rsbtbl[i].toss))) {
- rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
- rb_erase(n, &ls->ls_rsbtbl[i].toss);
- dlm_free_rsb(rsb);
- }
- }
-
- vfree(ls->ls_rsbtbl);
-
- while (!list_empty(&ls->ls_new_rsb)) {
- rsb = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb,
- res_hashchain);
- list_del(&rsb->res_hashchain);
- dlm_free_rsb(rsb);
- }
-
- /*
- * Free structures on any other lists
- */
-
- dlm_purge_requestqueue(ls);
- kfree(ls->ls_recover_args);
- dlm_clear_free_entries(ls);
- dlm_clear_members(ls);
- dlm_clear_members_gone(ls);
- kfree(ls->ls_node_array);
- log_debug(ls, "release_lockspace final free");
- kobject_put(&ls->ls_kobj);
- /* The ls structure will be freed when the kobject is done with */
-
- module_put(THIS_MODULE);
- return 0;
-}
-
-/*
- * Called when a system has released all its locks and is not going to use the
- * lockspace any longer. We free everything we're managing for this lockspace.
- * Remaining nodes will go through the recovery process as if we'd died. The
- * lockspace must continue to function as usual, participating in recoveries,
- * until this returns.
- *
- * Force has 4 possible values:
- * 0 - don't destroy locksapce if it has any LKBs
- * 1 - destroy lockspace if it has remote LKBs but not if it has local LKBs
- * 2 - destroy lockspace regardless of LKBs
- * 3 - destroy lockspace as part of a forced shutdown
- */
-
-int dlm_release_lockspace(void *lockspace, int force)
-{
- struct dlm_ls *ls;
- int error;
-
- ls = dlm_find_lockspace_local(lockspace);
- if (!ls)
- return -EINVAL;
- dlm_put_lockspace(ls);
-
- mutex_lock(&ls_lock);
- error = release_lockspace(ls, force);
- if (!error)
- ls_count--;
- if (!ls_count)
- threads_stop();
- mutex_unlock(&ls_lock);
-
- return error;
-}
-
-void dlm_stop_lockspaces(void)
-{
- struct dlm_ls *ls;
-
- restart:
- spin_lock(&lslist_lock);
- list_for_each_entry(ls, &lslist, ls_list) {
- if (!test_bit(LSFL_RUNNING, &ls->ls_flags))
- continue;
- spin_unlock(&lslist_lock);
- log_error(ls, "no userland control daemon, stopping lockspace");
- dlm_ls_stop(ls);
- goto restart;
- }
- spin_unlock(&lslist_lock);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/lockspace.h b/ANDROID_3.4.5/fs/dlm/lockspace.h
deleted file mode 100644
index f879f879..00000000
--- a/ANDROID_3.4.5/fs/dlm/lockspace.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __LOCKSPACE_DOT_H__
-#define __LOCKSPACE_DOT_H__
-
-int dlm_lockspace_init(void);
-void dlm_lockspace_exit(void);
-struct dlm_ls *dlm_find_lockspace_global(uint32_t id);
-struct dlm_ls *dlm_find_lockspace_local(void *id);
-struct dlm_ls *dlm_find_lockspace_device(int minor);
-void dlm_put_lockspace(struct dlm_ls *ls);
-void dlm_stop_lockspaces(void);
-
-#endif /* __LOCKSPACE_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/lowcomms.c b/ANDROID_3.4.5/fs/dlm/lowcomms.c
deleted file mode 100644
index 133ef6dc..00000000
--- a/ANDROID_3.4.5/fs/dlm/lowcomms.c
+++ /dev/null
@@ -1,1567 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2009 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-/*
- * lowcomms.c
- *
- * This is the "low-level" comms layer.
- *
- * It is responsible for sending/receiving messages
- * from other nodes in the cluster.
- *
- * Cluster nodes are referred to by their nodeids. nodeids are
- * simply 32 bit numbers to the locking module - if they need to
- * be expanded for the cluster infrastructure then that is its
- * responsibility. It is this layer's
- * responsibility to resolve these into IP address or
- * whatever it needs for inter-node communication.
- *
- * The comms level is two kernel threads that deal mainly with
- * the receiving of messages from other nodes and passing them
- * up to the mid-level comms layer (which understands the
- * message format) for execution by the locking core, and
- * a send thread which does all the setting up of connections
- * to remote nodes and the sending of data. Threads are not allowed
- * to send their own data because it may cause them to wait in times
- * of high load. Also, this way, the sending thread can collect together
- * messages bound for one node and send them in one block.
- *
- * lowcomms will choose to use either TCP or SCTP as its transport layer
- * depending on the configuration variable 'protocol'. This should be set
- * to 0 (default) for TCP or 1 for SCTP. It should be configured using a
- * cluster-wide mechanism as it must be the same on all nodes of the cluster
- * for the DLM to function.
- *
- */
-
-#include <asm/ioctls.h>
-#include <net/sock.h>
-#include <net/tcp.h>
-#include <linux/pagemap.h>
-#include <linux/file.h>
-#include <linux/mutex.h>
-#include <linux/sctp.h>
-#include <linux/slab.h>
-#include <net/sctp/sctp.h>
-#include <net/sctp/user.h>
-#include <net/ipv6.h>
-
-#include "dlm_internal.h"
-#include "lowcomms.h"
-#include "midcomms.h"
-#include "config.h"
-
-#define NEEDED_RMEM (4*1024*1024)
-#define CONN_HASH_SIZE 32
-
-/* Number of messages to send before rescheduling */
-#define MAX_SEND_MSG_COUNT 25
-
-struct cbuf {
- unsigned int base;
- unsigned int len;
- unsigned int mask;
-};
-
-static void cbuf_add(struct cbuf *cb, int n)
-{
- cb->len += n;
-}
-
-static int cbuf_data(struct cbuf *cb)
-{
- return ((cb->base + cb->len) & cb->mask);
-}
-
-static void cbuf_init(struct cbuf *cb, int size)
-{
- cb->base = cb->len = 0;
- cb->mask = size-1;
-}
-
-static void cbuf_eat(struct cbuf *cb, int n)
-{
- cb->len -= n;
- cb->base += n;
- cb->base &= cb->mask;
-}
-
-static bool cbuf_empty(struct cbuf *cb)
-{
- return cb->len == 0;
-}
-
-struct connection {
- struct socket *sock; /* NULL if not connected */
- uint32_t nodeid; /* So we know who we are in the list */
- struct mutex sock_mutex;
- unsigned long flags;
-#define CF_READ_PENDING 1
-#define CF_WRITE_PENDING 2
-#define CF_CONNECT_PENDING 3
-#define CF_INIT_PENDING 4
-#define CF_IS_OTHERCON 5
-#define CF_CLOSE 6
-#define CF_APP_LIMITED 7
- struct list_head writequeue; /* List of outgoing writequeue_entries */
- spinlock_t writequeue_lock;
- int (*rx_action) (struct connection *); /* What to do when active */
- void (*connect_action) (struct connection *); /* What to do to connect */
- struct page *rx_page;
- struct cbuf cb;
- int retries;
-#define MAX_CONNECT_RETRIES 3
- int sctp_assoc;
- struct hlist_node list;
- struct connection *othercon;
- struct work_struct rwork; /* Receive workqueue */
- struct work_struct swork; /* Send workqueue */
-};
-#define sock2con(x) ((struct connection *)(x)->sk_user_data)
-
-/* An entry waiting to be sent */
-struct writequeue_entry {
- struct list_head list;
- struct page *page;
- int offset;
- int len;
- int end;
- int users;
- struct connection *con;
-};
-
-static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT];
-static int dlm_local_count;
-
-/* Work queues */
-static struct workqueue_struct *recv_workqueue;
-static struct workqueue_struct *send_workqueue;
-
-static struct hlist_head connection_hash[CONN_HASH_SIZE];
-static DEFINE_MUTEX(connections_lock);
-static struct kmem_cache *con_cache;
-
-static void process_recv_sockets(struct work_struct *work);
-static void process_send_sockets(struct work_struct *work);
-
-
-/* This is deliberately very simple because most clusters have simple
- sequential nodeids, so we should be able to go straight to a connection
- struct in the array */
-static inline int nodeid_hash(int nodeid)
-{
- return nodeid & (CONN_HASH_SIZE-1);
-}
-
-static struct connection *__find_con(int nodeid)
-{
- int r;
- struct hlist_node *h;
- struct connection *con;
-
- r = nodeid_hash(nodeid);
-
- hlist_for_each_entry(con, h, &connection_hash[r], list) {
- if (con->nodeid == nodeid)
- return con;
- }
- return NULL;
-}
-
-/*
- * If 'allocation' is zero then we don't attempt to create a new
- * connection structure for this node.
- */
-static struct connection *__nodeid2con(int nodeid, gfp_t alloc)
-{
- struct connection *con = NULL;
- int r;
-
- con = __find_con(nodeid);
- if (con || !alloc)
- return con;
-
- con = kmem_cache_zalloc(con_cache, alloc);
- if (!con)
- return NULL;
-
- r = nodeid_hash(nodeid);
- hlist_add_head(&con->list, &connection_hash[r]);
-
- con->nodeid = nodeid;
- mutex_init(&con->sock_mutex);
- INIT_LIST_HEAD(&con->writequeue);
- spin_lock_init(&con->writequeue_lock);
- INIT_WORK(&con->swork, process_send_sockets);
- INIT_WORK(&con->rwork, process_recv_sockets);
-
- /* Setup action pointers for child sockets */
- if (con->nodeid) {
- struct connection *zerocon = __find_con(0);
-
- con->connect_action = zerocon->connect_action;
- if (!con->rx_action)
- con->rx_action = zerocon->rx_action;
- }
-
- return con;
-}
-
-/* Loop round all connections */
-static void foreach_conn(void (*conn_func)(struct connection *c))
-{
- int i;
- struct hlist_node *h, *n;
- struct connection *con;
-
- for (i = 0; i < CONN_HASH_SIZE; i++) {
- hlist_for_each_entry_safe(con, h, n, &connection_hash[i], list){
- conn_func(con);
- }
- }
-}
-
-static struct connection *nodeid2con(int nodeid, gfp_t allocation)
-{
- struct connection *con;
-
- mutex_lock(&connections_lock);
- con = __nodeid2con(nodeid, allocation);
- mutex_unlock(&connections_lock);
-
- return con;
-}
-
-/* This is a bit drastic, but only called when things go wrong */
-static struct connection *assoc2con(int assoc_id)
-{
- int i;
- struct hlist_node *h;
- struct connection *con;
-
- mutex_lock(&connections_lock);
-
- for (i = 0 ; i < CONN_HASH_SIZE; i++) {
- hlist_for_each_entry(con, h, &connection_hash[i], list) {
- if (con->sctp_assoc == assoc_id) {
- mutex_unlock(&connections_lock);
- return con;
- }
- }
- }
- mutex_unlock(&connections_lock);
- return NULL;
-}
-
-static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
-{
- struct sockaddr_storage addr;
- int error;
-
- if (!dlm_local_count)
- return -1;
-
- error = dlm_nodeid_to_addr(nodeid, &addr);
- if (error)
- return error;
-
- if (dlm_local_addr[0]->ss_family == AF_INET) {
- struct sockaddr_in *in4 = (struct sockaddr_in *) &addr;
- struct sockaddr_in *ret4 = (struct sockaddr_in *) retaddr;
- ret4->sin_addr.s_addr = in4->sin_addr.s_addr;
- } else {
- struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &addr;
- struct sockaddr_in6 *ret6 = (struct sockaddr_in6 *) retaddr;
- ret6->sin6_addr = in6->sin6_addr;
- }
-
- return 0;
-}
-
-/* Data available on socket or listen socket received a connect */
-static void lowcomms_data_ready(struct sock *sk, int count_unused)
-{
- struct connection *con = sock2con(sk);
- if (con && !test_and_set_bit(CF_READ_PENDING, &con->flags))
- queue_work(recv_workqueue, &con->rwork);
-}
-
-static void lowcomms_write_space(struct sock *sk)
-{
- struct connection *con = sock2con(sk);
-
- if (!con)
- return;
-
- clear_bit(SOCK_NOSPACE, &con->sock->flags);
-
- if (test_and_clear_bit(CF_APP_LIMITED, &con->flags)) {
- con->sock->sk->sk_write_pending--;
- clear_bit(SOCK_ASYNC_NOSPACE, &con->sock->flags);
- }
-
- if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
- queue_work(send_workqueue, &con->swork);
-}
-
-static inline void lowcomms_connect_sock(struct connection *con)
-{
- if (test_bit(CF_CLOSE, &con->flags))
- return;
- if (!test_and_set_bit(CF_CONNECT_PENDING, &con->flags))
- queue_work(send_workqueue, &con->swork);
-}
-
-static void lowcomms_state_change(struct sock *sk)
-{
- if (sk->sk_state == TCP_ESTABLISHED)
- lowcomms_write_space(sk);
-}
-
-int dlm_lowcomms_connect_node(int nodeid)
-{
- struct connection *con;
-
- /* with sctp there's no connecting without sending */
- if (dlm_config.ci_protocol != 0)
- return 0;
-
- if (nodeid == dlm_our_nodeid())
- return 0;
-
- con = nodeid2con(nodeid, GFP_NOFS);
- if (!con)
- return -ENOMEM;
- lowcomms_connect_sock(con);
- return 0;
-}
-
-/* Make a socket active */
-static int add_sock(struct socket *sock, struct connection *con)
-{
- con->sock = sock;
-
- /* Install a data_ready callback */
- con->sock->sk->sk_data_ready = lowcomms_data_ready;
- con->sock->sk->sk_write_space = lowcomms_write_space;
- con->sock->sk->sk_state_change = lowcomms_state_change;
- con->sock->sk->sk_user_data = con;
- con->sock->sk->sk_allocation = GFP_NOFS;
- return 0;
-}
-
-/* Add the port number to an IPv6 or 4 sockaddr and return the address
- length */
-static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
- int *addr_len)
-{
- saddr->ss_family = dlm_local_addr[0]->ss_family;
- if (saddr->ss_family == AF_INET) {
- struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr;
- in4_addr->sin_port = cpu_to_be16(port);
- *addr_len = sizeof(struct sockaddr_in);
- memset(&in4_addr->sin_zero, 0, sizeof(in4_addr->sin_zero));
- } else {
- struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)saddr;
- in6_addr->sin6_port = cpu_to_be16(port);
- *addr_len = sizeof(struct sockaddr_in6);
- }
- memset((char *)saddr + *addr_len, 0, sizeof(struct sockaddr_storage) - *addr_len);
-}
-
-/* Close a remote connection and tidy up */
-static void close_connection(struct connection *con, bool and_other)
-{
- mutex_lock(&con->sock_mutex);
-
- if (con->sock) {
- sock_release(con->sock);
- con->sock = NULL;
- }
- if (con->othercon && and_other) {
- /* Will only re-enter once. */
- close_connection(con->othercon, false);
- }
- if (con->rx_page) {
- __free_page(con->rx_page);
- con->rx_page = NULL;
- }
-
- con->retries = 0;
- mutex_unlock(&con->sock_mutex);
-}
-
-/* We only send shutdown messages to nodes that are not part of the cluster */
-static void sctp_send_shutdown(sctp_assoc_t associd)
-{
- static char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
- struct msghdr outmessage;
- struct cmsghdr *cmsg;
- struct sctp_sndrcvinfo *sinfo;
- int ret;
- struct connection *con;
-
- con = nodeid2con(0,0);
- BUG_ON(con == NULL);
-
- outmessage.msg_name = NULL;
- outmessage.msg_namelen = 0;
- outmessage.msg_control = outcmsg;
- outmessage.msg_controllen = sizeof(outcmsg);
- outmessage.msg_flags = MSG_EOR;
-
- cmsg = CMSG_FIRSTHDR(&outmessage);
- cmsg->cmsg_level = IPPROTO_SCTP;
- cmsg->cmsg_type = SCTP_SNDRCV;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
- outmessage.msg_controllen = cmsg->cmsg_len;
- sinfo = CMSG_DATA(cmsg);
- memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
-
- sinfo->sinfo_flags |= MSG_EOF;
- sinfo->sinfo_assoc_id = associd;
-
- ret = kernel_sendmsg(con->sock, &outmessage, NULL, 0, 0);
-
- if (ret != 0)
- log_print("send EOF to node failed: %d", ret);
-}
-
-static void sctp_init_failed_foreach(struct connection *con)
-{
- con->sctp_assoc = 0;
- if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) {
- if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
- queue_work(send_workqueue, &con->swork);
- }
-}
-
-/* INIT failed but we don't know which node...
- restart INIT on all pending nodes */
-static void sctp_init_failed(void)
-{
- mutex_lock(&connections_lock);
-
- foreach_conn(sctp_init_failed_foreach);
-
- mutex_unlock(&connections_lock);
-}
-
-/* Something happened to an association */
-static void process_sctp_notification(struct connection *con,
- struct msghdr *msg, char *buf)
-{
- union sctp_notification *sn = (union sctp_notification *)buf;
-
- if (sn->sn_header.sn_type == SCTP_ASSOC_CHANGE) {
- switch (sn->sn_assoc_change.sac_state) {
-
- case SCTP_COMM_UP:
- case SCTP_RESTART:
- {
- /* Check that the new node is in the lockspace */
- struct sctp_prim prim;
- int nodeid;
- int prim_len, ret;
- int addr_len;
- struct connection *new_con;
-
- /*
- * We get this before any data for an association.
- * We verify that the node is in the cluster and
- * then peel off a socket for it.
- */
- if ((int)sn->sn_assoc_change.sac_assoc_id <= 0) {
- log_print("COMM_UP for invalid assoc ID %d",
- (int)sn->sn_assoc_change.sac_assoc_id);
- sctp_init_failed();
- return;
- }
- memset(&prim, 0, sizeof(struct sctp_prim));
- prim_len = sizeof(struct sctp_prim);
- prim.ssp_assoc_id = sn->sn_assoc_change.sac_assoc_id;
-
- ret = kernel_getsockopt(con->sock,
- IPPROTO_SCTP,
- SCTP_PRIMARY_ADDR,
- (char*)&prim,
- &prim_len);
- if (ret < 0) {
- log_print("getsockopt/sctp_primary_addr on "
- "new assoc %d failed : %d",
- (int)sn->sn_assoc_change.sac_assoc_id,
- ret);
-
- /* Retry INIT later */
- new_con = assoc2con(sn->sn_assoc_change.sac_assoc_id);
- if (new_con)
- clear_bit(CF_CONNECT_PENDING, &con->flags);
- return;
- }
- make_sockaddr(&prim.ssp_addr, 0, &addr_len);
- if (dlm_addr_to_nodeid(&prim.ssp_addr, &nodeid)) {
- unsigned char *b=(unsigned char *)&prim.ssp_addr;
- log_print("reject connect from unknown addr");
- print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE,
- b, sizeof(struct sockaddr_storage));
- sctp_send_shutdown(prim.ssp_assoc_id);
- return;
- }
-
- new_con = nodeid2con(nodeid, GFP_NOFS);
- if (!new_con)
- return;
-
- /* Peel off a new sock */
- sctp_lock_sock(con->sock->sk);
- ret = sctp_do_peeloff(con->sock->sk,
- sn->sn_assoc_change.sac_assoc_id,
- &new_con->sock);
- sctp_release_sock(con->sock->sk);
- if (ret < 0) {
- log_print("Can't peel off a socket for "
- "connection %d to node %d: err=%d",
- (int)sn->sn_assoc_change.sac_assoc_id,
- nodeid, ret);
- return;
- }
- add_sock(new_con->sock, new_con);
-
- log_print("connecting to %d sctp association %d",
- nodeid, (int)sn->sn_assoc_change.sac_assoc_id);
-
- /* Send any pending writes */
- clear_bit(CF_CONNECT_PENDING, &new_con->flags);
- clear_bit(CF_INIT_PENDING, &con->flags);
- if (!test_and_set_bit(CF_WRITE_PENDING, &new_con->flags)) {
- queue_work(send_workqueue, &new_con->swork);
- }
- if (!test_and_set_bit(CF_READ_PENDING, &new_con->flags))
- queue_work(recv_workqueue, &new_con->rwork);
- }
- break;
-
- case SCTP_COMM_LOST:
- case SCTP_SHUTDOWN_COMP:
- {
- con = assoc2con(sn->sn_assoc_change.sac_assoc_id);
- if (con) {
- con->sctp_assoc = 0;
- }
- }
- break;
-
- /* We don't know which INIT failed, so clear the PENDING flags
- * on them all. if assoc_id is zero then it will then try
- * again */
-
- case SCTP_CANT_STR_ASSOC:
- {
- log_print("Can't start SCTP association - retrying");
- sctp_init_failed();
- }
- break;
-
- default:
- log_print("unexpected SCTP assoc change id=%d state=%d",
- (int)sn->sn_assoc_change.sac_assoc_id,
- sn->sn_assoc_change.sac_state);
- }
- }
-}
-
-/* Data received from remote end */
-static int receive_from_sock(struct connection *con)
-{
- int ret = 0;
- struct msghdr msg = {};
- struct kvec iov[2];
- unsigned len;
- int r;
- int call_again_soon = 0;
- int nvec;
- char incmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
-
- mutex_lock(&con->sock_mutex);
-
- if (con->sock == NULL) {
- ret = -EAGAIN;
- goto out_close;
- }
-
- if (con->rx_page == NULL) {
- /*
- * This doesn't need to be atomic, but I think it should
- * improve performance if it is.
- */
- con->rx_page = alloc_page(GFP_ATOMIC);
- if (con->rx_page == NULL)
- goto out_resched;
- cbuf_init(&con->cb, PAGE_CACHE_SIZE);
- }
-
- /* Only SCTP needs these really */
- memset(&incmsg, 0, sizeof(incmsg));
- msg.msg_control = incmsg;
- msg.msg_controllen = sizeof(incmsg);
-
- /*
- * iov[0] is the bit of the circular buffer between the current end
- * point (cb.base + cb.len) and the end of the buffer.
- */
- iov[0].iov_len = con->cb.base - cbuf_data(&con->cb);
- iov[0].iov_base = page_address(con->rx_page) + cbuf_data(&con->cb);
- iov[1].iov_len = 0;
- nvec = 1;
-
- /*
- * iov[1] is the bit of the circular buffer between the start of the
- * buffer and the start of the currently used section (cb.base)
- */
- if (cbuf_data(&con->cb) >= con->cb.base) {
- iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb);
- iov[1].iov_len = con->cb.base;
- iov[1].iov_base = page_address(con->rx_page);
- nvec = 2;
- }
- len = iov[0].iov_len + iov[1].iov_len;
-
- r = ret = kernel_recvmsg(con->sock, &msg, iov, nvec, len,
- MSG_DONTWAIT | MSG_NOSIGNAL);
- if (ret <= 0)
- goto out_close;
-
- /* Process SCTP notifications */
- if (msg.msg_flags & MSG_NOTIFICATION) {
- msg.msg_control = incmsg;
- msg.msg_controllen = sizeof(incmsg);
-
- process_sctp_notification(con, &msg,
- page_address(con->rx_page) + con->cb.base);
- mutex_unlock(&con->sock_mutex);
- return 0;
- }
- BUG_ON(con->nodeid == 0);
-
- if (ret == len)
- call_again_soon = 1;
- cbuf_add(&con->cb, ret);
- ret = dlm_process_incoming_buffer(con->nodeid,
- page_address(con->rx_page),
- con->cb.base, con->cb.len,
- PAGE_CACHE_SIZE);
- if (ret == -EBADMSG) {
- log_print("lowcomms: addr=%p, base=%u, len=%u, "
- "iov_len=%u, iov_base[0]=%p, read=%d",
- page_address(con->rx_page), con->cb.base, con->cb.len,
- len, iov[0].iov_base, r);
- }
- if (ret < 0)
- goto out_close;
- cbuf_eat(&con->cb, ret);
-
- if (cbuf_empty(&con->cb) && !call_again_soon) {
- __free_page(con->rx_page);
- con->rx_page = NULL;
- }
-
- if (call_again_soon)
- goto out_resched;
- mutex_unlock(&con->sock_mutex);
- return 0;
-
-out_resched:
- if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
- queue_work(recv_workqueue, &con->rwork);
- mutex_unlock(&con->sock_mutex);
- return -EAGAIN;
-
-out_close:
- mutex_unlock(&con->sock_mutex);
- if (ret != -EAGAIN) {
- close_connection(con, false);
- /* Reconnect when there is something to send */
- }
- /* Don't return success if we really got EOF */
- if (ret == 0)
- ret = -EAGAIN;
-
- return ret;
-}
-
-/* Listening socket is busy, accept a connection */
-static int tcp_accept_from_sock(struct connection *con)
-{
- int result;
- struct sockaddr_storage peeraddr;
- struct socket *newsock;
- int len;
- int nodeid;
- struct connection *newcon;
- struct connection *addcon;
-
- memset(&peeraddr, 0, sizeof(peeraddr));
- result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM,
- IPPROTO_TCP, &newsock);
- if (result < 0)
- return -ENOMEM;
-
- mutex_lock_nested(&con->sock_mutex, 0);
-
- result = -ENOTCONN;
- if (con->sock == NULL)
- goto accept_err;
-
- newsock->type = con->sock->type;
- newsock->ops = con->sock->ops;
-
- result = con->sock->ops->accept(con->sock, newsock, O_NONBLOCK);
- if (result < 0)
- goto accept_err;
-
- /* Get the connected socket's peer */
- memset(&peeraddr, 0, sizeof(peeraddr));
- if (newsock->ops->getname(newsock, (struct sockaddr *)&peeraddr,
- &len, 2)) {
- result = -ECONNABORTED;
- goto accept_err;
- }
-
- /* Get the new node's NODEID */
- make_sockaddr(&peeraddr, 0, &len);
- if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) {
- unsigned char *b=(unsigned char *)&peeraddr;
- log_print("connect from non cluster node");
- print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE,
- b, sizeof(struct sockaddr_storage));
- sock_release(newsock);
- mutex_unlock(&con->sock_mutex);
- return -1;
- }
-
- log_print("got connection from %d", nodeid);
-
- /* Check to see if we already have a connection to this node. This
- * could happen if the two nodes initiate a connection at roughly
- * the same time and the connections cross on the wire.
- * In this case we store the incoming one in "othercon"
- */
- newcon = nodeid2con(nodeid, GFP_NOFS);
- if (!newcon) {
- result = -ENOMEM;
- goto accept_err;
- }
- mutex_lock_nested(&newcon->sock_mutex, 1);
- if (newcon->sock) {
- struct connection *othercon = newcon->othercon;
-
- if (!othercon) {
- othercon = kmem_cache_zalloc(con_cache, GFP_NOFS);
- if (!othercon) {
- log_print("failed to allocate incoming socket");
- mutex_unlock(&newcon->sock_mutex);
- result = -ENOMEM;
- goto accept_err;
- }
- othercon->nodeid = nodeid;
- othercon->rx_action = receive_from_sock;
- mutex_init(&othercon->sock_mutex);
- INIT_WORK(&othercon->swork, process_send_sockets);
- INIT_WORK(&othercon->rwork, process_recv_sockets);
- set_bit(CF_IS_OTHERCON, &othercon->flags);
- }
- if (!othercon->sock) {
- newcon->othercon = othercon;
- othercon->sock = newsock;
- newsock->sk->sk_user_data = othercon;
- add_sock(newsock, othercon);
- addcon = othercon;
- }
- else {
- printk("Extra connection from node %d attempted\n", nodeid);
- result = -EAGAIN;
- mutex_unlock(&newcon->sock_mutex);
- goto accept_err;
- }
- }
- else {
- newsock->sk->sk_user_data = newcon;
- newcon->rx_action = receive_from_sock;
- add_sock(newsock, newcon);
- addcon = newcon;
- }
-
- mutex_unlock(&newcon->sock_mutex);
-
- /*
- * Add it to the active queue in case we got data
- * between processing the accept adding the socket
- * to the read_sockets list
- */
- if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
- queue_work(recv_workqueue, &addcon->rwork);
- mutex_unlock(&con->sock_mutex);
-
- return 0;
-
-accept_err:
- mutex_unlock(&con->sock_mutex);
- sock_release(newsock);
-
- if (result != -EAGAIN)
- log_print("error accepting connection from node: %d", result);
- return result;
-}
-
-static void free_entry(struct writequeue_entry *e)
-{
- __free_page(e->page);
- kfree(e);
-}
-
-/* Initiate an SCTP association.
- This is a special case of send_to_sock() in that we don't yet have a
- peeled-off socket for this association, so we use the listening socket
- and add the primary IP address of the remote node.
- */
-static void sctp_init_assoc(struct connection *con)
-{
- struct sockaddr_storage rem_addr;
- char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
- struct msghdr outmessage;
- struct cmsghdr *cmsg;
- struct sctp_sndrcvinfo *sinfo;
- struct connection *base_con;
- struct writequeue_entry *e;
- int len, offset;
- int ret;
- int addrlen;
- struct kvec iov[1];
-
- if (test_and_set_bit(CF_INIT_PENDING, &con->flags))
- return;
-
- if (con->retries++ > MAX_CONNECT_RETRIES)
- return;
-
- if (nodeid_to_addr(con->nodeid, (struct sockaddr *)&rem_addr)) {
- log_print("no address for nodeid %d", con->nodeid);
- return;
- }
- base_con = nodeid2con(0, 0);
- BUG_ON(base_con == NULL);
-
- make_sockaddr(&rem_addr, dlm_config.ci_tcp_port, &addrlen);
-
- outmessage.msg_name = &rem_addr;
- outmessage.msg_namelen = addrlen;
- outmessage.msg_control = outcmsg;
- outmessage.msg_controllen = sizeof(outcmsg);
- outmessage.msg_flags = MSG_EOR;
-
- spin_lock(&con->writequeue_lock);
-
- if (list_empty(&con->writequeue)) {
- spin_unlock(&con->writequeue_lock);
- log_print("writequeue empty for nodeid %d", con->nodeid);
- return;
- }
-
- e = list_first_entry(&con->writequeue, struct writequeue_entry, list);
- len = e->len;
- offset = e->offset;
- spin_unlock(&con->writequeue_lock);
-
- /* Send the first block off the write queue */
- iov[0].iov_base = page_address(e->page)+offset;
- iov[0].iov_len = len;
-
- cmsg = CMSG_FIRSTHDR(&outmessage);
- cmsg->cmsg_level = IPPROTO_SCTP;
- cmsg->cmsg_type = SCTP_SNDRCV;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
- sinfo = CMSG_DATA(cmsg);
- memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
- sinfo->sinfo_ppid = cpu_to_le32(dlm_our_nodeid());
- outmessage.msg_controllen = cmsg->cmsg_len;
-
- ret = kernel_sendmsg(base_con->sock, &outmessage, iov, 1, len);
- if (ret < 0) {
- log_print("Send first packet to node %d failed: %d",
- con->nodeid, ret);
-
- /* Try again later */
- clear_bit(CF_CONNECT_PENDING, &con->flags);
- clear_bit(CF_INIT_PENDING, &con->flags);
- }
- else {
- spin_lock(&con->writequeue_lock);
- e->offset += ret;
- e->len -= ret;
-
- if (e->len == 0 && e->users == 0) {
- list_del(&e->list);
- free_entry(e);
- }
- spin_unlock(&con->writequeue_lock);
- }
-}
-
-/* Connect a new socket to its peer */
-static void tcp_connect_to_sock(struct connection *con)
-{
- int result = -EHOSTUNREACH;
- struct sockaddr_storage saddr, src_addr;
- int addr_len;
- struct socket *sock = NULL;
- int one = 1;
-
- if (con->nodeid == 0) {
- log_print("attempt to connect sock 0 foiled");
- return;
- }
-
- mutex_lock(&con->sock_mutex);
- if (con->retries++ > MAX_CONNECT_RETRIES)
- goto out;
-
- /* Some odd races can cause double-connects, ignore them */
- if (con->sock) {
- result = 0;
- goto out;
- }
-
- /* Create a socket to communicate with */
- result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM,
- IPPROTO_TCP, &sock);
- if (result < 0)
- goto out_err;
-
- memset(&saddr, 0, sizeof(saddr));
- if (dlm_nodeid_to_addr(con->nodeid, &saddr))
- goto out_err;
-
- sock->sk->sk_user_data = con;
- con->rx_action = receive_from_sock;
- con->connect_action = tcp_connect_to_sock;
- add_sock(sock, con);
-
- /* Bind to our cluster-known address connecting to avoid
- routing problems */
- memcpy(&src_addr, dlm_local_addr[0], sizeof(src_addr));
- make_sockaddr(&src_addr, 0, &addr_len);
- result = sock->ops->bind(sock, (struct sockaddr *) &src_addr,
- addr_len);
- if (result < 0) {
- log_print("could not bind for connect: %d", result);
- /* This *may* not indicate a critical error */
- }
-
- make_sockaddr(&saddr, dlm_config.ci_tcp_port, &addr_len);
-
- log_print("connecting to %d", con->nodeid);
-
- /* Turn off Nagle's algorithm */
- kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&one,
- sizeof(one));
-
- result =
- sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len,
- O_NONBLOCK);
- if (result == -EINPROGRESS)
- result = 0;
- if (result == 0)
- goto out;
-
-out_err:
- if (con->sock) {
- sock_release(con->sock);
- con->sock = NULL;
- } else if (sock) {
- sock_release(sock);
- }
- /*
- * Some errors are fatal and this list might need adjusting. For other
- * errors we try again until the max number of retries is reached.
- */
- if (result != -EHOSTUNREACH && result != -ENETUNREACH &&
- result != -ENETDOWN && result != -EINVAL
- && result != -EPROTONOSUPPORT) {
- lowcomms_connect_sock(con);
- result = 0;
- }
-out:
- mutex_unlock(&con->sock_mutex);
- return;
-}
-
-static struct socket *tcp_create_listen_sock(struct connection *con,
- struct sockaddr_storage *saddr)
-{
- struct socket *sock = NULL;
- int result = 0;
- int one = 1;
- int addr_len;
-
- if (dlm_local_addr[0]->ss_family == AF_INET)
- addr_len = sizeof(struct sockaddr_in);
- else
- addr_len = sizeof(struct sockaddr_in6);
-
- /* Create a socket to communicate with */
- result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_STREAM,
- IPPROTO_TCP, &sock);
- if (result < 0) {
- log_print("Can't create listening comms socket");
- goto create_out;
- }
-
- /* Turn off Nagle's algorithm */
- kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&one,
- sizeof(one));
-
- result = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- (char *)&one, sizeof(one));
-
- if (result < 0) {
- log_print("Failed to set SO_REUSEADDR on socket: %d", result);
- }
- sock->sk->sk_user_data = con;
- con->rx_action = tcp_accept_from_sock;
- con->connect_action = tcp_connect_to_sock;
- con->sock = sock;
-
- /* Bind to our port */
- make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len);
- result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len);
- if (result < 0) {
- log_print("Can't bind to port %d", dlm_config.ci_tcp_port);
- sock_release(sock);
- sock = NULL;
- con->sock = NULL;
- goto create_out;
- }
- result = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
- (char *)&one, sizeof(one));
- if (result < 0) {
- log_print("Set keepalive failed: %d", result);
- }
-
- result = sock->ops->listen(sock, 5);
- if (result < 0) {
- log_print("Can't listen on port %d", dlm_config.ci_tcp_port);
- sock_release(sock);
- sock = NULL;
- goto create_out;
- }
-
-create_out:
- return sock;
-}
-
-/* Get local addresses */
-static void init_local(void)
-{
- struct sockaddr_storage sas, *addr;
- int i;
-
- dlm_local_count = 0;
- for (i = 0; i < DLM_MAX_ADDR_COUNT; i++) {
- if (dlm_our_addr(&sas, i))
- break;
-
- addr = kmalloc(sizeof(*addr), GFP_NOFS);
- if (!addr)
- break;
- memcpy(addr, &sas, sizeof(*addr));
- dlm_local_addr[dlm_local_count++] = addr;
- }
-}
-
-/* Bind to an IP address. SCTP allows multiple address so it can do
- multi-homing */
-static int add_sctp_bind_addr(struct connection *sctp_con,
- struct sockaddr_storage *addr,
- int addr_len, int num)
-{
- int result = 0;
-
- if (num == 1)
- result = kernel_bind(sctp_con->sock,
- (struct sockaddr *) addr,
- addr_len);
- else
- result = kernel_setsockopt(sctp_con->sock, SOL_SCTP,
- SCTP_SOCKOPT_BINDX_ADD,
- (char *)addr, addr_len);
-
- if (result < 0)
- log_print("Can't bind to port %d addr number %d",
- dlm_config.ci_tcp_port, num);
-
- return result;
-}
-
-/* Initialise SCTP socket and bind to all interfaces */
-static int sctp_listen_for_all(void)
-{
- struct socket *sock = NULL;
- struct sockaddr_storage localaddr;
- struct sctp_event_subscribe subscribe;
- int result = -EINVAL, num = 1, i, addr_len;
- struct connection *con = nodeid2con(0, GFP_NOFS);
- int bufsize = NEEDED_RMEM;
-
- if (!con)
- return -ENOMEM;
-
- log_print("Using SCTP for communications");
-
- result = sock_create_kern(dlm_local_addr[0]->ss_family, SOCK_SEQPACKET,
- IPPROTO_SCTP, &sock);
- if (result < 0) {
- log_print("Can't create comms socket, check SCTP is loaded");
- goto out;
- }
-
- /* Listen for events */
- memset(&subscribe, 0, sizeof(subscribe));
- subscribe.sctp_data_io_event = 1;
- subscribe.sctp_association_event = 1;
- subscribe.sctp_send_failure_event = 1;
- subscribe.sctp_shutdown_event = 1;
- subscribe.sctp_partial_delivery_event = 1;
-
- result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE,
- (char *)&bufsize, sizeof(bufsize));
- if (result)
- log_print("Error increasing buffer space on socket %d", result);
-
- result = kernel_setsockopt(sock, SOL_SCTP, SCTP_EVENTS,
- (char *)&subscribe, sizeof(subscribe));
- if (result < 0) {
- log_print("Failed to set SCTP_EVENTS on socket: result=%d",
- result);
- goto create_delsock;
- }
-
- /* Init con struct */
- sock->sk->sk_user_data = con;
- con->sock = sock;
- con->sock->sk->sk_data_ready = lowcomms_data_ready;
- con->rx_action = receive_from_sock;
- con->connect_action = sctp_init_assoc;
-
- /* Bind to all interfaces. */
- for (i = 0; i < dlm_local_count; i++) {
- memcpy(&localaddr, dlm_local_addr[i], sizeof(localaddr));
- make_sockaddr(&localaddr, dlm_config.ci_tcp_port, &addr_len);
-
- result = add_sctp_bind_addr(con, &localaddr, addr_len, num);
- if (result)
- goto create_delsock;
- ++num;
- }
-
- result = sock->ops->listen(sock, 5);
- if (result < 0) {
- log_print("Can't set socket listening");
- goto create_delsock;
- }
-
- return 0;
-
-create_delsock:
- sock_release(sock);
- con->sock = NULL;
-out:
- return result;
-}
-
-static int tcp_listen_for_all(void)
-{
- struct socket *sock = NULL;
- struct connection *con = nodeid2con(0, GFP_NOFS);
- int result = -EINVAL;
-
- if (!con)
- return -ENOMEM;
-
- /* We don't support multi-homed hosts */
- if (dlm_local_addr[1] != NULL) {
- log_print("TCP protocol can't handle multi-homed hosts, "
- "try SCTP");
- return -EINVAL;
- }
-
- log_print("Using TCP for communications");
-
- sock = tcp_create_listen_sock(con, dlm_local_addr[0]);
- if (sock) {
- add_sock(sock, con);
- result = 0;
- }
- else {
- result = -EADDRINUSE;
- }
-
- return result;
-}
-
-
-
-static struct writequeue_entry *new_writequeue_entry(struct connection *con,
- gfp_t allocation)
-{
- struct writequeue_entry *entry;
-
- entry = kmalloc(sizeof(struct writequeue_entry), allocation);
- if (!entry)
- return NULL;
-
- entry->page = alloc_page(allocation);
- if (!entry->page) {
- kfree(entry);
- return NULL;
- }
-
- entry->offset = 0;
- entry->len = 0;
- entry->end = 0;
- entry->users = 0;
- entry->con = con;
-
- return entry;
-}
-
-void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
-{
- struct connection *con;
- struct writequeue_entry *e;
- int offset = 0;
- int users = 0;
-
- con = nodeid2con(nodeid, allocation);
- if (!con)
- return NULL;
-
- spin_lock(&con->writequeue_lock);
- e = list_entry(con->writequeue.prev, struct writequeue_entry, list);
- if ((&e->list == &con->writequeue) ||
- (PAGE_CACHE_SIZE - e->end < len)) {
- e = NULL;
- } else {
- offset = e->end;
- e->end += len;
- users = e->users++;
- }
- spin_unlock(&con->writequeue_lock);
-
- if (e) {
- got_one:
- *ppc = page_address(e->page) + offset;
- return e;
- }
-
- e = new_writequeue_entry(con, allocation);
- if (e) {
- spin_lock(&con->writequeue_lock);
- offset = e->end;
- e->end += len;
- users = e->users++;
- list_add_tail(&e->list, &con->writequeue);
- spin_unlock(&con->writequeue_lock);
- goto got_one;
- }
- return NULL;
-}
-
-void dlm_lowcomms_commit_buffer(void *mh)
-{
- struct writequeue_entry *e = (struct writequeue_entry *)mh;
- struct connection *con = e->con;
- int users;
-
- spin_lock(&con->writequeue_lock);
- users = --e->users;
- if (users)
- goto out;
- e->len = e->end - e->offset;
- spin_unlock(&con->writequeue_lock);
-
- if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) {
- queue_work(send_workqueue, &con->swork);
- }
- return;
-
-out:
- spin_unlock(&con->writequeue_lock);
- return;
-}
-
-/* Send a message */
-static void send_to_sock(struct connection *con)
-{
- int ret = 0;
- const int msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
- struct writequeue_entry *e;
- int len, offset;
- int count = 0;
-
- mutex_lock(&con->sock_mutex);
- if (con->sock == NULL)
- goto out_connect;
-
- spin_lock(&con->writequeue_lock);
- for (;;) {
- e = list_entry(con->writequeue.next, struct writequeue_entry,
- list);
- if ((struct list_head *) e == &con->writequeue)
- break;
-
- len = e->len;
- offset = e->offset;
- BUG_ON(len == 0 && e->users == 0);
- spin_unlock(&con->writequeue_lock);
-
- ret = 0;
- if (len) {
- ret = kernel_sendpage(con->sock, e->page, offset, len,
- msg_flags);
- if (ret == -EAGAIN || ret == 0) {
- if (ret == -EAGAIN &&
- test_bit(SOCK_ASYNC_NOSPACE, &con->sock->flags) &&
- !test_and_set_bit(CF_APP_LIMITED, &con->flags)) {
- /* Notify TCP that we're limited by the
- * application window size.
- */
- set_bit(SOCK_NOSPACE, &con->sock->flags);
- con->sock->sk->sk_write_pending++;
- }
- cond_resched();
- goto out;
- }
- if (ret <= 0)
- goto send_error;
- }
-
- /* Don't starve people filling buffers */
- if (++count >= MAX_SEND_MSG_COUNT) {
- cond_resched();
- count = 0;
- }
-
- spin_lock(&con->writequeue_lock);
- e->offset += ret;
- e->len -= ret;
-
- if (e->len == 0 && e->users == 0) {
- list_del(&e->list);
- free_entry(e);
- continue;
- }
- }
- spin_unlock(&con->writequeue_lock);
-out:
- mutex_unlock(&con->sock_mutex);
- return;
-
-send_error:
- mutex_unlock(&con->sock_mutex);
- close_connection(con, false);
- lowcomms_connect_sock(con);
- return;
-
-out_connect:
- mutex_unlock(&con->sock_mutex);
- if (!test_bit(CF_INIT_PENDING, &con->flags))
- lowcomms_connect_sock(con);
- return;
-}
-
-static void clean_one_writequeue(struct connection *con)
-{
- struct writequeue_entry *e, *safe;
-
- spin_lock(&con->writequeue_lock);
- list_for_each_entry_safe(e, safe, &con->writequeue, list) {
- list_del(&e->list);
- free_entry(e);
- }
- spin_unlock(&con->writequeue_lock);
-}
-
-/* Called from recovery when it knows that a node has
- left the cluster */
-int dlm_lowcomms_close(int nodeid)
-{
- struct connection *con;
-
- log_print("closing connection to node %d", nodeid);
- con = nodeid2con(nodeid, 0);
- if (con) {
- clear_bit(CF_CONNECT_PENDING, &con->flags);
- clear_bit(CF_WRITE_PENDING, &con->flags);
- set_bit(CF_CLOSE, &con->flags);
- if (cancel_work_sync(&con->swork))
- log_print("canceled swork for node %d", nodeid);
- if (cancel_work_sync(&con->rwork))
- log_print("canceled rwork for node %d", nodeid);
- clean_one_writequeue(con);
- close_connection(con, true);
- }
- return 0;
-}
-
-/* Receive workqueue function */
-static void process_recv_sockets(struct work_struct *work)
-{
- struct connection *con = container_of(work, struct connection, rwork);
- int err;
-
- clear_bit(CF_READ_PENDING, &con->flags);
- do {
- err = con->rx_action(con);
- } while (!err);
-}
-
-/* Send workqueue function */
-static void process_send_sockets(struct work_struct *work)
-{
- struct connection *con = container_of(work, struct connection, swork);
-
- if (test_and_clear_bit(CF_CONNECT_PENDING, &con->flags)) {
- con->connect_action(con);
- set_bit(CF_WRITE_PENDING, &con->flags);
- }
- if (test_and_clear_bit(CF_WRITE_PENDING, &con->flags))
- send_to_sock(con);
-}
-
-
-/* Discard all entries on the write queues */
-static void clean_writequeues(void)
-{
- foreach_conn(clean_one_writequeue);
-}
-
-static void work_stop(void)
-{
- destroy_workqueue(recv_workqueue);
- destroy_workqueue(send_workqueue);
-}
-
-static int work_start(void)
-{
- recv_workqueue = alloc_workqueue("dlm_recv",
- WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
- if (!recv_workqueue) {
- log_print("can't start dlm_recv");
- return -ENOMEM;
- }
-
- send_workqueue = alloc_workqueue("dlm_send",
- WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
- if (!send_workqueue) {
- log_print("can't start dlm_send");
- destroy_workqueue(recv_workqueue);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void stop_conn(struct connection *con)
-{
- con->flags |= 0x0F;
- if (con->sock && con->sock->sk)
- con->sock->sk->sk_user_data = NULL;
-}
-
-static void free_conn(struct connection *con)
-{
- close_connection(con, true);
- if (con->othercon)
- kmem_cache_free(con_cache, con->othercon);
- hlist_del(&con->list);
- kmem_cache_free(con_cache, con);
-}
-
-void dlm_lowcomms_stop(void)
-{
- /* Set all the flags to prevent any
- socket activity.
- */
- mutex_lock(&connections_lock);
- foreach_conn(stop_conn);
- mutex_unlock(&connections_lock);
-
- work_stop();
-
- mutex_lock(&connections_lock);
- clean_writequeues();
-
- foreach_conn(free_conn);
-
- mutex_unlock(&connections_lock);
- kmem_cache_destroy(con_cache);
-}
-
-int dlm_lowcomms_start(void)
-{
- int error = -EINVAL;
- struct connection *con;
- int i;
-
- for (i = 0; i < CONN_HASH_SIZE; i++)
- INIT_HLIST_HEAD(&connection_hash[i]);
-
- init_local();
- if (!dlm_local_count) {
- error = -ENOTCONN;
- log_print("no local IP address has been set");
- goto out;
- }
-
- error = -ENOMEM;
- con_cache = kmem_cache_create("dlm_conn", sizeof(struct connection),
- __alignof__(struct connection), 0,
- NULL);
- if (!con_cache)
- goto out;
-
- /* Start listening */
- if (dlm_config.ci_protocol == 0)
- error = tcp_listen_for_all();
- else
- error = sctp_listen_for_all();
- if (error)
- goto fail_unlisten;
-
- error = work_start();
- if (error)
- goto fail_unlisten;
-
- return 0;
-
-fail_unlisten:
- con = nodeid2con(0,0);
- if (con) {
- close_connection(con, false);
- kmem_cache_free(con_cache, con);
- }
- kmem_cache_destroy(con_cache);
-
-out:
- return error;
-}
diff --git a/ANDROID_3.4.5/fs/dlm/lowcomms.h b/ANDROID_3.4.5/fs/dlm/lowcomms.h
deleted file mode 100644
index 1311e642..00000000
--- a/ANDROID_3.4.5/fs/dlm/lowcomms.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2009 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __LOWCOMMS_DOT_H__
-#define __LOWCOMMS_DOT_H__
-
-int dlm_lowcomms_start(void);
-void dlm_lowcomms_stop(void);
-int dlm_lowcomms_close(int nodeid);
-void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc);
-void dlm_lowcomms_commit_buffer(void *mh);
-int dlm_lowcomms_connect_node(int nodeid);
-
-#endif /* __LOWCOMMS_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/lvb_table.h b/ANDROID_3.4.5/fs/dlm/lvb_table.h
deleted file mode 100644
index cc3e92f3..00000000
--- a/ANDROID_3.4.5/fs/dlm/lvb_table.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __LVB_TABLE_DOT_H__
-#define __LVB_TABLE_DOT_H__
-
-extern const int dlm_lvb_operations[8][8];
-
-#endif
diff --git a/ANDROID_3.4.5/fs/dlm/main.c b/ANDROID_3.4.5/fs/dlm/main.c
deleted file mode 100644
index 5a59efa0..00000000
--- a/ANDROID_3.4.5/fs/dlm/main.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** 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 "lock.h"
-#include "user.h"
-#include "memory.h"
-#include "config.h"
-
-static int __init init_dlm(void)
-{
- int error;
-
- error = dlm_memory_init();
- if (error)
- goto out;
-
- error = dlm_lockspace_init();
- if (error)
- goto out_mem;
-
- error = dlm_config_init();
- if (error)
- goto out_lockspace;
-
- error = dlm_register_debugfs();
- if (error)
- goto out_config;
-
- error = dlm_user_init();
- if (error)
- goto out_debug;
-
- error = dlm_netlink_init();
- if (error)
- goto out_user;
-
- error = dlm_plock_init();
- if (error)
- goto out_netlink;
-
- printk("DLM installed\n");
-
- return 0;
-
- out_netlink:
- dlm_netlink_exit();
- out_user:
- dlm_user_exit();
- out_debug:
- dlm_unregister_debugfs();
- out_config:
- dlm_config_exit();
- out_lockspace:
- dlm_lockspace_exit();
- out_mem:
- dlm_memory_exit();
- out:
- return error;
-}
-
-static void __exit exit_dlm(void)
-{
- dlm_plock_exit();
- dlm_netlink_exit();
- dlm_user_exit();
- dlm_config_exit();
- dlm_memory_exit();
- dlm_lockspace_exit();
- dlm_unregister_debugfs();
-}
-
-module_init(init_dlm);
-module_exit(exit_dlm);
-
-MODULE_DESCRIPTION("Distributed Lock Manager");
-MODULE_AUTHOR("Red Hat, Inc.");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL_GPL(dlm_new_lockspace);
-EXPORT_SYMBOL_GPL(dlm_release_lockspace);
-EXPORT_SYMBOL_GPL(dlm_lock);
-EXPORT_SYMBOL_GPL(dlm_unlock);
-
diff --git a/ANDROID_3.4.5/fs/dlm/member.c b/ANDROID_3.4.5/fs/dlm/member.c
deleted file mode 100644
index 862640a3..00000000
--- a/ANDROID_3.4.5/fs/dlm/member.c
+++ /dev/null
@@ -1,720 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005-2011 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 "recover.h"
-#include "rcom.h"
-#include "config.h"
-#include "lowcomms.h"
-
-int dlm_slots_version(struct dlm_header *h)
-{
- if ((h->h_version & 0x0000FFFF) < DLM_HEADER_SLOTS)
- return 0;
- return 1;
-}
-
-void dlm_slot_save(struct dlm_ls *ls, struct dlm_rcom *rc,
- struct dlm_member *memb)
-{
- struct rcom_config *rf = (struct rcom_config *)rc->rc_buf;
-
- if (!dlm_slots_version(&rc->rc_header))
- return;
-
- memb->slot = le16_to_cpu(rf->rf_our_slot);
- memb->generation = le32_to_cpu(rf->rf_generation);
-}
-
-void dlm_slots_copy_out(struct dlm_ls *ls, struct dlm_rcom *rc)
-{
- struct dlm_slot *slot;
- struct rcom_slot *ro;
- int i;
-
- ro = (struct rcom_slot *)(rc->rc_buf + sizeof(struct rcom_config));
-
- /* ls_slots array is sparse, but not rcom_slots */
-
- for (i = 0; i < ls->ls_slots_size; i++) {
- slot = &ls->ls_slots[i];
- if (!slot->nodeid)
- continue;
- ro->ro_nodeid = cpu_to_le32(slot->nodeid);
- ro->ro_slot = cpu_to_le16(slot->slot);
- ro++;
- }
-}
-
-#define SLOT_DEBUG_LINE 128
-
-static void log_debug_slots(struct dlm_ls *ls, uint32_t gen, int num_slots,
- struct rcom_slot *ro0, struct dlm_slot *array,
- int array_size)
-{
- char line[SLOT_DEBUG_LINE];
- int len = SLOT_DEBUG_LINE - 1;
- int pos = 0;
- int ret, i;
-
- if (!dlm_config.ci_log_debug)
- return;
-
- memset(line, 0, sizeof(line));
-
- if (array) {
- for (i = 0; i < array_size; i++) {
- if (!array[i].nodeid)
- continue;
-
- ret = snprintf(line + pos, len - pos, " %d:%d",
- array[i].slot, array[i].nodeid);
- if (ret >= len - pos)
- break;
- pos += ret;
- }
- } else if (ro0) {
- for (i = 0; i < num_slots; i++) {
- ret = snprintf(line + pos, len - pos, " %d:%d",
- ro0[i].ro_slot, ro0[i].ro_nodeid);
- if (ret >= len - pos)
- break;
- pos += ret;
- }
- }
-
- log_debug(ls, "generation %u slots %d%s", gen, num_slots, line);
-}
-
-int dlm_slots_copy_in(struct dlm_ls *ls)
-{
- struct dlm_member *memb;
- struct dlm_rcom *rc = ls->ls_recover_buf;
- struct rcom_config *rf = (struct rcom_config *)rc->rc_buf;
- struct rcom_slot *ro0, *ro;
- int our_nodeid = dlm_our_nodeid();
- int i, num_slots;
- uint32_t gen;
-
- if (!dlm_slots_version(&rc->rc_header))
- return -1;
-
- gen = le32_to_cpu(rf->rf_generation);
- if (gen <= ls->ls_generation) {
- log_error(ls, "dlm_slots_copy_in gen %u old %u",
- gen, ls->ls_generation);
- }
- ls->ls_generation = gen;
-
- num_slots = le16_to_cpu(rf->rf_num_slots);
- if (!num_slots)
- return -1;
-
- ro0 = (struct rcom_slot *)(rc->rc_buf + sizeof(struct rcom_config));
-
- for (i = 0, ro = ro0; i < num_slots; i++, ro++) {
- ro->ro_nodeid = le32_to_cpu(ro->ro_nodeid);
- ro->ro_slot = le16_to_cpu(ro->ro_slot);
- }
-
- log_debug_slots(ls, gen, num_slots, ro0, NULL, 0);
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- for (i = 0, ro = ro0; i < num_slots; i++, ro++) {
- if (ro->ro_nodeid != memb->nodeid)
- continue;
- memb->slot = ro->ro_slot;
- memb->slot_prev = memb->slot;
- break;
- }
-
- if (memb->nodeid == our_nodeid) {
- if (ls->ls_slot && ls->ls_slot != memb->slot) {
- log_error(ls, "dlm_slots_copy_in our slot "
- "changed %d %d", ls->ls_slot,
- memb->slot);
- return -1;
- }
-
- if (!ls->ls_slot)
- ls->ls_slot = memb->slot;
- }
-
- if (!memb->slot) {
- log_error(ls, "dlm_slots_copy_in nodeid %d no slot",
- memb->nodeid);
- return -1;
- }
- }
-
- return 0;
-}
-
-/* for any nodes that do not support slots, we will not have set memb->slot
- in wait_status_all(), so memb->slot will remain -1, and we will not
- assign slots or set ls_num_slots here */
-
-int dlm_slots_assign(struct dlm_ls *ls, int *num_slots, int *slots_size,
- struct dlm_slot **slots_out, uint32_t *gen_out)
-{
- struct dlm_member *memb;
- struct dlm_slot *array;
- int our_nodeid = dlm_our_nodeid();
- int array_size, max_slots, i;
- int need = 0;
- int max = 0;
- int num = 0;
- uint32_t gen = 0;
-
- /* our own memb struct will have slot -1 gen 0 */
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- if (memb->nodeid == our_nodeid) {
- memb->slot = ls->ls_slot;
- memb->generation = ls->ls_generation;
- break;
- }
- }
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- if (memb->generation > gen)
- gen = memb->generation;
-
- /* node doesn't support slots */
-
- if (memb->slot == -1)
- return -1;
-
- /* node needs a slot assigned */
-
- if (!memb->slot)
- need++;
-
- /* node has a slot assigned */
-
- num++;
-
- if (!max || max < memb->slot)
- max = memb->slot;
-
- /* sanity check, once slot is assigned it shouldn't change */
-
- if (memb->slot_prev && memb->slot && memb->slot_prev != memb->slot) {
- log_error(ls, "nodeid %d slot changed %d %d",
- memb->nodeid, memb->slot_prev, memb->slot);
- return -1;
- }
- memb->slot_prev = memb->slot;
- }
-
- array_size = max + need;
-
- array = kzalloc(array_size * sizeof(struct dlm_slot), GFP_NOFS);
- if (!array)
- return -ENOMEM;
-
- num = 0;
-
- /* fill in slots (offsets) that are used */
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- if (!memb->slot)
- continue;
-
- if (memb->slot > array_size) {
- log_error(ls, "invalid slot number %d", memb->slot);
- kfree(array);
- return -1;
- }
-
- array[memb->slot - 1].nodeid = memb->nodeid;
- array[memb->slot - 1].slot = memb->slot;
- num++;
- }
-
- /* assign new slots from unused offsets */
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- if (memb->slot)
- continue;
-
- for (i = 0; i < array_size; i++) {
- if (array[i].nodeid)
- continue;
-
- memb->slot = i + 1;
- memb->slot_prev = memb->slot;
- array[i].nodeid = memb->nodeid;
- array[i].slot = memb->slot;
- num++;
-
- if (!ls->ls_slot && memb->nodeid == our_nodeid)
- ls->ls_slot = memb->slot;
- break;
- }
-
- if (!memb->slot) {
- log_error(ls, "no free slot found");
- kfree(array);
- return -1;
- }
- }
-
- gen++;
-
- log_debug_slots(ls, gen, num, NULL, array, array_size);
-
- max_slots = (dlm_config.ci_buffer_size - sizeof(struct dlm_rcom) -
- sizeof(struct rcom_config)) / sizeof(struct rcom_slot);
-
- if (num > max_slots) {
- log_error(ls, "num_slots %d exceeds max_slots %d",
- num, max_slots);
- kfree(array);
- return -1;
- }
-
- *gen_out = gen;
- *slots_out = array;
- *slots_size = array_size;
- *num_slots = num;
- return 0;
-}
-
-static void add_ordered_member(struct dlm_ls *ls, struct dlm_member *new)
-{
- struct dlm_member *memb = NULL;
- struct list_head *tmp;
- struct list_head *newlist = &new->list;
- struct list_head *head = &ls->ls_nodes;
-
- list_for_each(tmp, head) {
- memb = list_entry(tmp, struct dlm_member, list);
- if (new->nodeid < memb->nodeid)
- break;
- }
-
- if (!memb)
- list_add_tail(newlist, head);
- else {
- /* FIXME: can use list macro here */
- newlist->prev = tmp->prev;
- newlist->next = tmp;
- tmp->prev->next = newlist;
- tmp->prev = newlist;
- }
-}
-
-static int dlm_add_member(struct dlm_ls *ls, struct dlm_config_node *node)
-{
- struct dlm_member *memb;
- int error;
-
- memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS);
- if (!memb)
- return -ENOMEM;
-
- error = dlm_lowcomms_connect_node(node->nodeid);
- if (error < 0) {
- kfree(memb);
- return error;
- }
-
- memb->nodeid = node->nodeid;
- memb->weight = node->weight;
- memb->comm_seq = node->comm_seq;
- add_ordered_member(ls, memb);
- ls->ls_num_nodes++;
- return 0;
-}
-
-static struct dlm_member *find_memb(struct list_head *head, int nodeid)
-{
- struct dlm_member *memb;
-
- list_for_each_entry(memb, head, list) {
- if (memb->nodeid == nodeid)
- return memb;
- }
- return NULL;
-}
-
-int dlm_is_member(struct dlm_ls *ls, int nodeid)
-{
- if (find_memb(&ls->ls_nodes, nodeid))
- return 1;
- return 0;
-}
-
-int dlm_is_removed(struct dlm_ls *ls, int nodeid)
-{
- if (find_memb(&ls->ls_nodes_gone, nodeid))
- return 1;
- return 0;
-}
-
-static void clear_memb_list(struct list_head *head)
-{
- struct dlm_member *memb;
-
- while (!list_empty(head)) {
- memb = list_entry(head->next, struct dlm_member, list);
- list_del(&memb->list);
- kfree(memb);
- }
-}
-
-void dlm_clear_members(struct dlm_ls *ls)
-{
- clear_memb_list(&ls->ls_nodes);
- ls->ls_num_nodes = 0;
-}
-
-void dlm_clear_members_gone(struct dlm_ls *ls)
-{
- clear_memb_list(&ls->ls_nodes_gone);
-}
-
-static void make_member_array(struct dlm_ls *ls)
-{
- struct dlm_member *memb;
- int i, w, x = 0, total = 0, all_zero = 0, *array;
-
- kfree(ls->ls_node_array);
- ls->ls_node_array = NULL;
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- if (memb->weight)
- total += memb->weight;
- }
-
- /* all nodes revert to weight of 1 if all have weight 0 */
-
- if (!total) {
- total = ls->ls_num_nodes;
- all_zero = 1;
- }
-
- ls->ls_total_weight = total;
-
- array = kmalloc(sizeof(int) * total, GFP_NOFS);
- if (!array)
- return;
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- if (!all_zero && !memb->weight)
- continue;
-
- if (all_zero)
- w = 1;
- else
- w = memb->weight;
-
- DLM_ASSERT(x < total, printk("total %d x %d\n", total, x););
-
- for (i = 0; i < w; i++)
- array[x++] = memb->nodeid;
- }
-
- ls->ls_node_array = array;
-}
-
-/* send a status request to all members just to establish comms connections */
-
-static int ping_members(struct dlm_ls *ls)
-{
- struct dlm_member *memb;
- int error = 0;
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- error = dlm_recovery_stopped(ls);
- if (error)
- break;
- error = dlm_rcom_status(ls, memb->nodeid, 0);
- if (error)
- break;
- }
- if (error)
- log_debug(ls, "ping_members aborted %d last nodeid %d",
- error, ls->ls_recover_nodeid);
- return error;
-}
-
-static void dlm_lsop_recover_prep(struct dlm_ls *ls)
-{
- if (!ls->ls_ops || !ls->ls_ops->recover_prep)
- return;
- ls->ls_ops->recover_prep(ls->ls_ops_arg);
-}
-
-static void dlm_lsop_recover_slot(struct dlm_ls *ls, struct dlm_member *memb)
-{
- struct dlm_slot slot;
- uint32_t seq;
- int error;
-
- if (!ls->ls_ops || !ls->ls_ops->recover_slot)
- return;
-
- /* if there is no comms connection with this node
- or the present comms connection is newer
- than the one when this member was added, then
- we consider the node to have failed (versus
- being removed due to dlm_release_lockspace) */
-
- error = dlm_comm_seq(memb->nodeid, &seq);
-
- if (!error && seq == memb->comm_seq)
- return;
-
- slot.nodeid = memb->nodeid;
- slot.slot = memb->slot;
-
- ls->ls_ops->recover_slot(ls->ls_ops_arg, &slot);
-}
-
-void dlm_lsop_recover_done(struct dlm_ls *ls)
-{
- struct dlm_member *memb;
- struct dlm_slot *slots;
- int i, num;
-
- if (!ls->ls_ops || !ls->ls_ops->recover_done)
- return;
-
- num = ls->ls_num_nodes;
-
- slots = kzalloc(num * sizeof(struct dlm_slot), GFP_KERNEL);
- if (!slots)
- return;
-
- i = 0;
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- if (i == num) {
- log_error(ls, "dlm_lsop_recover_done bad num %d", num);
- goto out;
- }
- slots[i].nodeid = memb->nodeid;
- slots[i].slot = memb->slot;
- i++;
- }
-
- ls->ls_ops->recover_done(ls->ls_ops_arg, slots, num,
- ls->ls_slot, ls->ls_generation);
- out:
- kfree(slots);
-}
-
-static struct dlm_config_node *find_config_node(struct dlm_recover *rv,
- int nodeid)
-{
- int i;
-
- for (i = 0; i < rv->nodes_count; i++) {
- if (rv->nodes[i].nodeid == nodeid)
- return &rv->nodes[i];
- }
- return NULL;
-}
-
-int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
-{
- struct dlm_member *memb, *safe;
- struct dlm_config_node *node;
- int i, error, neg = 0, low = -1;
-
- /* previously removed members that we've not finished removing need to
- count as a negative change so the "neg" recovery steps will happen */
-
- list_for_each_entry(memb, &ls->ls_nodes_gone, list) {
- log_debug(ls, "prev removed member %d", memb->nodeid);
- neg++;
- }
-
- /* move departed members from ls_nodes to ls_nodes_gone */
-
- list_for_each_entry_safe(memb, safe, &ls->ls_nodes, list) {
- node = find_config_node(rv, memb->nodeid);
- if (node && !node->new)
- continue;
-
- if (!node) {
- log_debug(ls, "remove member %d", memb->nodeid);
- } else {
- /* removed and re-added */
- log_debug(ls, "remove member %d comm_seq %u %u",
- memb->nodeid, memb->comm_seq, node->comm_seq);
- }
-
- neg++;
- list_move(&memb->list, &ls->ls_nodes_gone);
- ls->ls_num_nodes--;
- dlm_lsop_recover_slot(ls, memb);
- }
-
- /* add new members to ls_nodes */
-
- for (i = 0; i < rv->nodes_count; i++) {
- node = &rv->nodes[i];
- if (dlm_is_member(ls, node->nodeid))
- continue;
- dlm_add_member(ls, node);
- log_debug(ls, "add member %d", node->nodeid);
- }
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- if (low == -1 || memb->nodeid < low)
- low = memb->nodeid;
- }
- ls->ls_low_nodeid = low;
-
- make_member_array(ls);
- *neg_out = neg;
-
- error = ping_members(ls);
- if (!error || error == -EPROTO) {
- /* new_lockspace() may be waiting to know if the config
- is good or bad */
- ls->ls_members_result = error;
- complete(&ls->ls_members_done);
- }
-
- log_debug(ls, "dlm_recover_members %d nodes", ls->ls_num_nodes);
- return error;
-}
-
-/* Userspace guarantees that dlm_ls_stop() has completed on all nodes before
- dlm_ls_start() is called on any of them to start the new recovery. */
-
-int dlm_ls_stop(struct dlm_ls *ls)
-{
- int new;
-
- /*
- * Prevent dlm_recv from being in the middle of something when we do
- * the stop. This includes ensuring dlm_recv isn't processing a
- * recovery message (rcom), while dlm_recoverd is aborting and
- * resetting things from an in-progress recovery. i.e. we want
- * dlm_recoverd to abort its recovery without worrying about dlm_recv
- * processing an rcom at the same time. Stopping dlm_recv also makes
- * it easy for dlm_receive_message() to check locking stopped and add a
- * message to the requestqueue without races.
- */
-
- down_write(&ls->ls_recv_active);
-
- /*
- * Abort any recovery that's in progress (see RECOVERY_STOP,
- * dlm_recovery_stopped()) and tell any other threads running in the
- * dlm to quit any processing (see RUNNING, dlm_locking_stopped()).
- */
-
- spin_lock(&ls->ls_recover_lock);
- set_bit(LSFL_RECOVERY_STOP, &ls->ls_flags);
- new = test_and_clear_bit(LSFL_RUNNING, &ls->ls_flags);
- ls->ls_recover_seq++;
- spin_unlock(&ls->ls_recover_lock);
-
- /*
- * Let dlm_recv run again, now any normal messages will be saved on the
- * requestqueue for later.
- */
-
- up_write(&ls->ls_recv_active);
-
- /*
- * This in_recovery lock does two things:
- * 1) Keeps this function from returning until all threads are out
- * of locking routines and locking is truly stopped.
- * 2) Keeps any new requests from being processed until it's unlocked
- * when recovery is complete.
- */
-
- if (new)
- down_write(&ls->ls_in_recovery);
-
- /*
- * The recoverd suspend/resume makes sure that dlm_recoverd (if
- * running) has noticed RECOVERY_STOP above and quit processing the
- * previous recovery.
- */
-
- dlm_recoverd_suspend(ls);
-
- spin_lock(&ls->ls_recover_lock);
- kfree(ls->ls_slots);
- ls->ls_slots = NULL;
- ls->ls_num_slots = 0;
- ls->ls_slots_size = 0;
- ls->ls_recover_status = 0;
- spin_unlock(&ls->ls_recover_lock);
-
- dlm_recoverd_resume(ls);
-
- if (!ls->ls_recover_begin)
- ls->ls_recover_begin = jiffies;
-
- dlm_lsop_recover_prep(ls);
- return 0;
-}
-
-int dlm_ls_start(struct dlm_ls *ls)
-{
- struct dlm_recover *rv = NULL, *rv_old;
- struct dlm_config_node *nodes;
- int error, count;
-
- rv = kzalloc(sizeof(struct dlm_recover), GFP_NOFS);
- if (!rv)
- return -ENOMEM;
-
- error = dlm_config_nodes(ls->ls_name, &nodes, &count);
- if (error < 0)
- goto fail;
-
- spin_lock(&ls->ls_recover_lock);
-
- /* the lockspace needs to be stopped before it can be started */
-
- if (!dlm_locking_stopped(ls)) {
- spin_unlock(&ls->ls_recover_lock);
- log_error(ls, "start ignored: lockspace running");
- error = -EINVAL;
- goto fail;
- }
-
- rv->nodes = nodes;
- rv->nodes_count = count;
- rv->seq = ++ls->ls_recover_seq;
- rv_old = ls->ls_recover_args;
- ls->ls_recover_args = rv;
- spin_unlock(&ls->ls_recover_lock);
-
- if (rv_old) {
- log_error(ls, "unused recovery %llx %d",
- (unsigned long long)rv_old->seq, rv_old->nodes_count);
- kfree(rv_old->nodes);
- kfree(rv_old);
- }
-
- dlm_recoverd_kick(ls);
- return 0;
-
- fail:
- kfree(rv);
- kfree(nodes);
- return error;
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/member.h b/ANDROID_3.4.5/fs/dlm/member.h
deleted file mode 100644
index 3deb7066..00000000
--- a/ANDROID_3.4.5/fs/dlm/member.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005-2011 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __MEMBER_DOT_H__
-#define __MEMBER_DOT_H__
-
-int dlm_ls_stop(struct dlm_ls *ls);
-int dlm_ls_start(struct dlm_ls *ls);
-void dlm_clear_members(struct dlm_ls *ls);
-void dlm_clear_members_gone(struct dlm_ls *ls);
-int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv,int *neg_out);
-int dlm_is_removed(struct dlm_ls *ls, int nodeid);
-int dlm_is_member(struct dlm_ls *ls, int nodeid);
-int dlm_slots_version(struct dlm_header *h);
-void dlm_slot_save(struct dlm_ls *ls, struct dlm_rcom *rc,
- struct dlm_member *memb);
-void dlm_slots_copy_out(struct dlm_ls *ls, struct dlm_rcom *rc);
-int dlm_slots_copy_in(struct dlm_ls *ls);
-int dlm_slots_assign(struct dlm_ls *ls, int *num_slots, int *slots_size,
- struct dlm_slot **slots_out, uint32_t *gen_out);
-void dlm_lsop_recover_done(struct dlm_ls *ls);
-
-#endif /* __MEMBER_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/memory.c b/ANDROID_3.4.5/fs/dlm/memory.c
deleted file mode 100644
index da64df75..00000000
--- a/ANDROID_3.4.5/fs/dlm/memory.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** 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 "config.h"
-#include "memory.h"
-
-static struct kmem_cache *lkb_cache;
-static struct kmem_cache *rsb_cache;
-
-
-int __init dlm_memory_init(void)
-{
- int ret = 0;
-
- lkb_cache = kmem_cache_create("dlm_lkb", sizeof(struct dlm_lkb),
- __alignof__(struct dlm_lkb), 0, NULL);
- if (!lkb_cache)
- ret = -ENOMEM;
-
- rsb_cache = kmem_cache_create("dlm_rsb", sizeof(struct dlm_rsb),
- __alignof__(struct dlm_rsb), 0, NULL);
- if (!rsb_cache) {
- kmem_cache_destroy(lkb_cache);
- ret = -ENOMEM;
- }
-
- return ret;
-}
-
-void dlm_memory_exit(void)
-{
- if (lkb_cache)
- kmem_cache_destroy(lkb_cache);
- if (rsb_cache)
- kmem_cache_destroy(rsb_cache);
-}
-
-char *dlm_allocate_lvb(struct dlm_ls *ls)
-{
- char *p;
-
- p = kzalloc(ls->ls_lvblen, GFP_NOFS);
- return p;
-}
-
-void dlm_free_lvb(char *p)
-{
- kfree(p);
-}
-
-struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls)
-{
- struct dlm_rsb *r;
-
- r = kmem_cache_zalloc(rsb_cache, GFP_NOFS);
- return r;
-}
-
-void dlm_free_rsb(struct dlm_rsb *r)
-{
- if (r->res_lvbptr)
- dlm_free_lvb(r->res_lvbptr);
- kmem_cache_free(rsb_cache, r);
-}
-
-struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls)
-{
- struct dlm_lkb *lkb;
-
- lkb = kmem_cache_zalloc(lkb_cache, GFP_NOFS);
- return lkb;
-}
-
-void dlm_free_lkb(struct dlm_lkb *lkb)
-{
- if (lkb->lkb_flags & DLM_IFL_USER) {
- struct dlm_user_args *ua;
- ua = lkb->lkb_ua;
- if (ua) {
- if (ua->lksb.sb_lvbptr)
- kfree(ua->lksb.sb_lvbptr);
- kfree(ua);
- }
- }
- kmem_cache_free(lkb_cache, lkb);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/memory.h b/ANDROID_3.4.5/fs/dlm/memory.h
deleted file mode 100644
index 177c11cb..00000000
--- a/ANDROID_3.4.5/fs/dlm/memory.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __MEMORY_DOT_H__
-#define __MEMORY_DOT_H__
-
-int dlm_memory_init(void);
-void dlm_memory_exit(void);
-struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls);
-void dlm_free_rsb(struct dlm_rsb *r);
-struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls);
-void dlm_free_lkb(struct dlm_lkb *l);
-char *dlm_allocate_lvb(struct dlm_ls *ls);
-void dlm_free_lvb(char *l);
-
-#endif /* __MEMORY_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/midcomms.c b/ANDROID_3.4.5/fs/dlm/midcomms.c
deleted file mode 100644
index f3396c62..00000000
--- a/ANDROID_3.4.5/fs/dlm/midcomms.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2008 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-/*
- * midcomms.c
- *
- * This is the appallingly named "mid-level" comms layer.
- *
- * Its purpose is to take packets from the "real" comms layer,
- * split them up into packets and pass them to the interested
- * part of the locking mechanism.
- *
- * It also takes messages from the locking layer, formats them
- * into packets and sends them to the comms layer.
- */
-
-#include "dlm_internal.h"
-#include "lowcomms.h"
-#include "config.h"
-#include "lock.h"
-#include "midcomms.h"
-
-
-static void copy_from_cb(void *dst, const void *base, unsigned offset,
- unsigned len, unsigned limit)
-{
- unsigned copy = len;
-
- if ((copy + offset) > limit)
- copy = limit - offset;
- memcpy(dst, base + offset, copy);
- len -= copy;
- if (len)
- memcpy(dst + copy, base, len);
-}
-
-/*
- * Called from the low-level comms layer to process a buffer of
- * commands.
- *
- * Only complete messages are processed here, any "spare" bytes from
- * the end of a buffer are saved and tacked onto the front of the next
- * message that comes in. I doubt this will happen very often but we
- * need to be able to cope with it and I don't want the task to be waiting
- * for packets to come in when there is useful work to be done.
- */
-
-int dlm_process_incoming_buffer(int nodeid, const void *base,
- unsigned offset, unsigned len, unsigned limit)
-{
- union {
- unsigned char __buf[DLM_INBUF_LEN];
- /* this is to force proper alignment on some arches */
- union dlm_packet p;
- } __tmp;
- union dlm_packet *p = &__tmp.p;
- int ret = 0;
- int err = 0;
- uint16_t msglen;
- uint32_t lockspace;
-
- while (len > sizeof(struct dlm_header)) {
-
- /* Copy just the header to check the total length. The
- message may wrap around the end of the buffer back to the
- start, so we need to use a temp buffer and copy_from_cb. */
-
- copy_from_cb(p, base, offset, sizeof(struct dlm_header),
- limit);
-
- msglen = le16_to_cpu(p->header.h_length);
- lockspace = p->header.h_lockspace;
-
- err = -EINVAL;
- if (msglen < sizeof(struct dlm_header))
- break;
- if (p->header.h_cmd == DLM_MSG) {
- if (msglen < sizeof(struct dlm_message))
- break;
- } else {
- if (msglen < sizeof(struct dlm_rcom))
- break;
- }
- err = -E2BIG;
- if (msglen > dlm_config.ci_buffer_size) {
- log_print("message size %d from %d too big, buf len %d",
- msglen, nodeid, len);
- break;
- }
- err = 0;
-
- /* If only part of the full message is contained in this
- buffer, then do nothing and wait for lowcomms to call
- us again later with more data. We return 0 meaning
- we've consumed none of the input buffer. */
-
- if (msglen > len)
- break;
-
- /* Allocate a larger temp buffer if the full message won't fit
- in the buffer on the stack (which should work for most
- ordinary messages). */
-
- if (msglen > sizeof(__tmp) && p == &__tmp.p) {
- p = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
- if (p == NULL)
- return ret;
- }
-
- copy_from_cb(p, base, offset, msglen, limit);
-
- BUG_ON(lockspace != p->header.h_lockspace);
-
- ret += msglen;
- offset += msglen;
- offset &= (limit - 1);
- len -= msglen;
-
- dlm_receive_buffer(p, nodeid);
- }
-
- if (p != &__tmp.p)
- kfree(p);
-
- return err ? err : ret;
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/midcomms.h b/ANDROID_3.4.5/fs/dlm/midcomms.h
deleted file mode 100644
index 95852a5f..00000000
--- a/ANDROID_3.4.5/fs/dlm/midcomms.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __MIDCOMMS_DOT_H__
-#define __MIDCOMMS_DOT_H__
-
-int dlm_process_incoming_buffer(int nodeid, const void *base, unsigned offset,
- unsigned len, unsigned limit);
-
-#endif /* __MIDCOMMS_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/netlink.c b/ANDROID_3.4.5/fs/dlm/netlink.c
deleted file mode 100644
index ef17e016..00000000
--- a/ANDROID_3.4.5/fs/dlm/netlink.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 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 <net/genetlink.h>
-#include <linux/dlm.h>
-#include <linux/dlm_netlink.h>
-#include <linux/gfp.h>
-
-#include "dlm_internal.h"
-
-static uint32_t dlm_nl_seqnum;
-static uint32_t listener_nlpid;
-
-static struct genl_family family = {
- .id = GENL_ID_GENERATE,
- .name = DLM_GENL_NAME,
- .version = DLM_GENL_VERSION,
-};
-
-static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size)
-{
- struct sk_buff *skb;
- void *data;
-
- skb = genlmsg_new(size, GFP_NOFS);
- if (!skb)
- return -ENOMEM;
-
- /* add the message headers */
- data = genlmsg_put(skb, 0, dlm_nl_seqnum++, &family, 0, cmd);
- if (!data) {
- nlmsg_free(skb);
- return -EINVAL;
- }
-
- *skbp = skb;
- return 0;
-}
-
-static struct dlm_lock_data *mk_data(struct sk_buff *skb)
-{
- struct nlattr *ret;
-
- ret = nla_reserve(skb, DLM_TYPE_LOCK, sizeof(struct dlm_lock_data));
- if (!ret)
- return NULL;
- return nla_data(ret);
-}
-
-static int send_data(struct sk_buff *skb)
-{
- struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
- void *data = genlmsg_data(genlhdr);
- int rv;
-
- rv = genlmsg_end(skb, data);
- if (rv < 0) {
- nlmsg_free(skb);
- return rv;
- }
-
- return genlmsg_unicast(&init_net, skb, listener_nlpid);
-}
-
-static int user_cmd(struct sk_buff *skb, struct genl_info *info)
-{
- listener_nlpid = info->snd_pid;
- printk("user_cmd nlpid %u\n", listener_nlpid);
- return 0;
-}
-
-static struct genl_ops dlm_nl_ops = {
- .cmd = DLM_CMD_HELLO,
- .doit = user_cmd,
-};
-
-int __init dlm_netlink_init(void)
-{
- return genl_register_family_with_ops(&family, &dlm_nl_ops, 1);
-}
-
-void dlm_netlink_exit(void)
-{
- genl_unregister_family(&family);
-}
-
-static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb)
-{
- struct dlm_rsb *r = lkb->lkb_resource;
-
- memset(data, 0, sizeof(struct dlm_lock_data));
-
- data->version = DLM_LOCK_DATA_VERSION;
- data->nodeid = lkb->lkb_nodeid;
- data->ownpid = lkb->lkb_ownpid;
- data->id = lkb->lkb_id;
- data->remid = lkb->lkb_remid;
- data->status = lkb->lkb_status;
- data->grmode = lkb->lkb_grmode;
- data->rqmode = lkb->lkb_rqmode;
- if (lkb->lkb_ua)
- data->xid = lkb->lkb_ua->xid;
- if (r) {
- data->lockspace_id = r->res_ls->ls_global_id;
- data->resource_namelen = r->res_length;
- memcpy(data->resource_name, r->res_name, r->res_length);
- }
-}
-
-void dlm_timeout_warn(struct dlm_lkb *lkb)
-{
- struct sk_buff *uninitialized_var(send_skb);
- struct dlm_lock_data *data;
- size_t size;
- int rv;
-
- size = nla_total_size(sizeof(struct dlm_lock_data)) +
- nla_total_size(0); /* why this? */
-
- rv = prepare_data(DLM_CMD_TIMEOUT, &send_skb, size);
- if (rv < 0)
- return;
-
- data = mk_data(send_skb);
- if (!data) {
- nlmsg_free(send_skb);
- return;
- }
-
- fill_data(data, lkb);
-
- send_data(send_skb);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/plock.c b/ANDROID_3.4.5/fs/dlm/plock.c
deleted file mode 100644
index 01fd5c11..00000000
--- a/ANDROID_3.4.5/fs/dlm/plock.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright (C) 2005-2008 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 version 2.
- */
-
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/poll.h>
-#include <linux/dlm.h>
-#include <linux/dlm_plock.h>
-#include <linux/slab.h>
-
-#include "dlm_internal.h"
-#include "lockspace.h"
-
-static spinlock_t ops_lock;
-static struct list_head send_list;
-static struct list_head recv_list;
-static wait_queue_head_t send_wq;
-static wait_queue_head_t recv_wq;
-
-struct plock_op {
- struct list_head list;
- int done;
- struct dlm_plock_info info;
-};
-
-struct plock_xop {
- struct plock_op xop;
- void *callback;
- void *fl;
- void *file;
- struct file_lock flc;
-};
-
-
-static inline void set_version(struct dlm_plock_info *info)
-{
- info->version[0] = DLM_PLOCK_VERSION_MAJOR;
- info->version[1] = DLM_PLOCK_VERSION_MINOR;
- info->version[2] = DLM_PLOCK_VERSION_PATCH;
-}
-
-static int check_version(struct dlm_plock_info *info)
-{
- if ((DLM_PLOCK_VERSION_MAJOR != info->version[0]) ||
- (DLM_PLOCK_VERSION_MINOR < info->version[1])) {
- log_print("plock device version mismatch: "
- "kernel (%u.%u.%u), user (%u.%u.%u)",
- DLM_PLOCK_VERSION_MAJOR,
- DLM_PLOCK_VERSION_MINOR,
- DLM_PLOCK_VERSION_PATCH,
- info->version[0],
- info->version[1],
- info->version[2]);
- return -EINVAL;
- }
- return 0;
-}
-
-static void send_op(struct plock_op *op)
-{
- set_version(&op->info);
- INIT_LIST_HEAD(&op->list);
- spin_lock(&ops_lock);
- list_add_tail(&op->list, &send_list);
- spin_unlock(&ops_lock);
- wake_up(&send_wq);
-}
-
-/* If a process was killed while waiting for the only plock on a file,
- locks_remove_posix will not see any lock on the file so it won't
- send an unlock-close to us to pass on to userspace to clean up the
- abandoned waiter. So, we have to insert the unlock-close when the
- lock call is interrupted. */
-
-static void do_unlock_close(struct dlm_ls *ls, u64 number,
- struct file *file, struct file_lock *fl)
-{
- struct plock_op *op;
-
- op = kzalloc(sizeof(*op), GFP_NOFS);
- if (!op)
- return;
-
- op->info.optype = DLM_PLOCK_OP_UNLOCK;
- op->info.pid = fl->fl_pid;
- op->info.fsid = ls->ls_global_id;
- op->info.number = number;
- op->info.start = 0;
- op->info.end = OFFSET_MAX;
- if (fl->fl_lmops && fl->fl_lmops->lm_grant)
- op->info.owner = (__u64) fl->fl_pid;
- else
- op->info.owner = (__u64)(long) fl->fl_owner;
-
- op->info.flags |= DLM_PLOCK_FL_CLOSE;
- send_op(op);
-}
-
-int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
- int cmd, struct file_lock *fl)
-{
- struct dlm_ls *ls;
- struct plock_op *op;
- struct plock_xop *xop;
- int rv;
-
- ls = dlm_find_lockspace_local(lockspace);
- if (!ls)
- return -EINVAL;
-
- xop = kzalloc(sizeof(*xop), GFP_NOFS);
- if (!xop) {
- rv = -ENOMEM;
- goto out;
- }
-
- op = &xop->xop;
- op->info.optype = DLM_PLOCK_OP_LOCK;
- op->info.pid = fl->fl_pid;
- op->info.ex = (fl->fl_type == F_WRLCK);
- op->info.wait = IS_SETLKW(cmd);
- op->info.fsid = ls->ls_global_id;
- op->info.number = number;
- op->info.start = fl->fl_start;
- op->info.end = fl->fl_end;
- if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
- /* fl_owner is lockd which doesn't distinguish
- processes on the nfs client */
- op->info.owner = (__u64) fl->fl_pid;
- xop->callback = fl->fl_lmops->lm_grant;
- locks_init_lock(&xop->flc);
- locks_copy_lock(&xop->flc, fl);
- xop->fl = fl;
- xop->file = file;
- } else {
- op->info.owner = (__u64)(long) fl->fl_owner;
- xop->callback = NULL;
- }
-
- send_op(op);
-
- if (xop->callback == NULL) {
- rv = wait_event_killable(recv_wq, (op->done != 0));
- if (rv == -ERESTARTSYS) {
- log_debug(ls, "dlm_posix_lock: wait killed %llx",
- (unsigned long long)number);
- spin_lock(&ops_lock);
- list_del(&op->list);
- spin_unlock(&ops_lock);
- kfree(xop);
- do_unlock_close(ls, number, file, fl);
- goto out;
- }
- } else {
- rv = FILE_LOCK_DEFERRED;
- goto out;
- }
-
- spin_lock(&ops_lock);
- if (!list_empty(&op->list)) {
- log_error(ls, "dlm_posix_lock: op on list %llx",
- (unsigned long long)number);
- list_del(&op->list);
- }
- spin_unlock(&ops_lock);
-
- rv = op->info.rv;
-
- if (!rv) {
- if (posix_lock_file_wait(file, fl) < 0)
- log_error(ls, "dlm_posix_lock: vfs lock error %llx",
- (unsigned long long)number);
- }
-
- kfree(xop);
-out:
- dlm_put_lockspace(ls);
- return rv;
-}
-EXPORT_SYMBOL_GPL(dlm_posix_lock);
-
-/* Returns failure iff a successful lock operation should be canceled */
-static int dlm_plock_callback(struct plock_op *op)
-{
- struct file *file;
- struct file_lock *fl;
- struct file_lock *flc;
- int (*notify)(void *, void *, int) = NULL;
- struct plock_xop *xop = (struct plock_xop *)op;
- int rv = 0;
-
- spin_lock(&ops_lock);
- if (!list_empty(&op->list)) {
- log_print("dlm_plock_callback: op on list %llx",
- (unsigned long long)op->info.number);
- list_del(&op->list);
- }
- spin_unlock(&ops_lock);
-
- /* check if the following 2 are still valid or make a copy */
- file = xop->file;
- flc = &xop->flc;
- fl = xop->fl;
- notify = xop->callback;
-
- if (op->info.rv) {
- notify(fl, NULL, op->info.rv);
- goto out;
- }
-
- /* got fs lock; bookkeep locally as well: */
- flc->fl_flags &= ~FL_SLEEP;
- if (posix_lock_file(file, flc, NULL)) {
- /*
- * This can only happen in the case of kmalloc() failure.
- * The filesystem's own lock is the authoritative lock,
- * so a failure to get the lock locally is not a disaster.
- * As long as the fs cannot reliably cancel locks (especially
- * in a low-memory situation), we're better off ignoring
- * this failure than trying to recover.
- */
- log_print("dlm_plock_callback: vfs lock error %llx file %p fl %p",
- (unsigned long long)op->info.number, file, fl);
- }
-
- rv = notify(fl, NULL, 0);
- if (rv) {
- /* XXX: We need to cancel the fs lock here: */
- log_print("dlm_plock_callback: lock granted after lock request "
- "failed; dangling lock!\n");
- goto out;
- }
-
-out:
- kfree(xop);
- return rv;
-}
-
-int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
- struct file_lock *fl)
-{
- struct dlm_ls *ls;
- struct plock_op *op;
- int rv;
-
- ls = dlm_find_lockspace_local(lockspace);
- if (!ls)
- return -EINVAL;
-
- op = kzalloc(sizeof(*op), GFP_NOFS);
- if (!op) {
- rv = -ENOMEM;
- goto out;
- }
-
- if (posix_lock_file_wait(file, fl) < 0)
- log_error(ls, "dlm_posix_unlock: vfs unlock error %llx",
- (unsigned long long)number);
-
- op->info.optype = DLM_PLOCK_OP_UNLOCK;
- op->info.pid = fl->fl_pid;
- op->info.fsid = ls->ls_global_id;
- op->info.number = number;
- op->info.start = fl->fl_start;
- op->info.end = fl->fl_end;
- if (fl->fl_lmops && fl->fl_lmops->lm_grant)
- op->info.owner = (__u64) fl->fl_pid;
- else
- op->info.owner = (__u64)(long) fl->fl_owner;
-
- if (fl->fl_flags & FL_CLOSE) {
- op->info.flags |= DLM_PLOCK_FL_CLOSE;
- send_op(op);
- rv = 0;
- goto out;
- }
-
- send_op(op);
- wait_event(recv_wq, (op->done != 0));
-
- spin_lock(&ops_lock);
- if (!list_empty(&op->list)) {
- log_error(ls, "dlm_posix_unlock: op on list %llx",
- (unsigned long long)number);
- list_del(&op->list);
- }
- spin_unlock(&ops_lock);
-
- rv = op->info.rv;
-
- if (rv == -ENOENT)
- rv = 0;
-
- kfree(op);
-out:
- dlm_put_lockspace(ls);
- return rv;
-}
-EXPORT_SYMBOL_GPL(dlm_posix_unlock);
-
-int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
- struct file_lock *fl)
-{
- struct dlm_ls *ls;
- struct plock_op *op;
- int rv;
-
- ls = dlm_find_lockspace_local(lockspace);
- if (!ls)
- return -EINVAL;
-
- op = kzalloc(sizeof(*op), GFP_NOFS);
- if (!op) {
- rv = -ENOMEM;
- goto out;
- }
-
- op->info.optype = DLM_PLOCK_OP_GET;
- op->info.pid = fl->fl_pid;
- op->info.ex = (fl->fl_type == F_WRLCK);
- op->info.fsid = ls->ls_global_id;
- op->info.number = number;
- op->info.start = fl->fl_start;
- op->info.end = fl->fl_end;
- if (fl->fl_lmops && fl->fl_lmops->lm_grant)
- op->info.owner = (__u64) fl->fl_pid;
- else
- op->info.owner = (__u64)(long) fl->fl_owner;
-
- send_op(op);
- wait_event(recv_wq, (op->done != 0));
-
- spin_lock(&ops_lock);
- if (!list_empty(&op->list)) {
- log_error(ls, "dlm_posix_get: op on list %llx",
- (unsigned long long)number);
- list_del(&op->list);
- }
- spin_unlock(&ops_lock);
-
- /* info.rv from userspace is 1 for conflict, 0 for no-conflict,
- -ENOENT if there are no locks on the file */
-
- rv = op->info.rv;
-
- fl->fl_type = F_UNLCK;
- if (rv == -ENOENT)
- rv = 0;
- else if (rv > 0) {
- locks_init_lock(fl);
- fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
- fl->fl_flags = FL_POSIX;
- fl->fl_pid = op->info.pid;
- fl->fl_start = op->info.start;
- fl->fl_end = op->info.end;
- rv = 0;
- }
-
- kfree(op);
-out:
- dlm_put_lockspace(ls);
- return rv;
-}
-EXPORT_SYMBOL_GPL(dlm_posix_get);
-
-/* a read copies out one plock request from the send list */
-static ssize_t dev_read(struct file *file, char __user *u, size_t count,
- loff_t *ppos)
-{
- struct dlm_plock_info info;
- struct plock_op *op = NULL;
-
- if (count < sizeof(info))
- return -EINVAL;
-
- spin_lock(&ops_lock);
- if (!list_empty(&send_list)) {
- op = list_entry(send_list.next, struct plock_op, list);
- if (op->info.flags & DLM_PLOCK_FL_CLOSE)
- list_del(&op->list);
- else
- list_move(&op->list, &recv_list);
- memcpy(&info, &op->info, sizeof(info));
- }
- spin_unlock(&ops_lock);
-
- if (!op)
- return -EAGAIN;
-
- /* there is no need to get a reply from userspace for unlocks
- that were generated by the vfs cleaning up for a close
- (the process did not make an unlock call). */
-
- if (op->info.flags & DLM_PLOCK_FL_CLOSE)
- kfree(op);
-
- if (copy_to_user(u, &info, sizeof(info)))
- return -EFAULT;
- return sizeof(info);
-}
-
-/* a write copies in one plock result that should match a plock_op
- on the recv list */
-static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
- loff_t *ppos)
-{
- struct dlm_plock_info info;
- struct plock_op *op;
- int found = 0, do_callback = 0;
-
- if (count != sizeof(info))
- return -EINVAL;
-
- if (copy_from_user(&info, u, sizeof(info)))
- return -EFAULT;
-
- if (check_version(&info))
- return -EINVAL;
-
- spin_lock(&ops_lock);
- list_for_each_entry(op, &recv_list, list) {
- if (op->info.fsid == info.fsid &&
- op->info.number == info.number &&
- op->info.owner == info.owner) {
- struct plock_xop *xop = (struct plock_xop *)op;
- list_del_init(&op->list);
- memcpy(&op->info, &info, sizeof(info));
- if (xop->callback)
- do_callback = 1;
- else
- op->done = 1;
- found = 1;
- break;
- }
- }
- spin_unlock(&ops_lock);
-
- if (found) {
- if (do_callback)
- dlm_plock_callback(op);
- else
- wake_up(&recv_wq);
- } else
- log_print("dev_write no op %x %llx", info.fsid,
- (unsigned long long)info.number);
- return count;
-}
-
-static unsigned int dev_poll(struct file *file, poll_table *wait)
-{
- unsigned int mask = 0;
-
- poll_wait(file, &send_wq, wait);
-
- spin_lock(&ops_lock);
- if (!list_empty(&send_list))
- mask = POLLIN | POLLRDNORM;
- spin_unlock(&ops_lock);
-
- return mask;
-}
-
-static const struct file_operations dev_fops = {
- .read = dev_read,
- .write = dev_write,
- .poll = dev_poll,
- .owner = THIS_MODULE,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice plock_dev_misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DLM_PLOCK_MISC_NAME,
- .fops = &dev_fops
-};
-
-int dlm_plock_init(void)
-{
- int rv;
-
- spin_lock_init(&ops_lock);
- INIT_LIST_HEAD(&send_list);
- INIT_LIST_HEAD(&recv_list);
- init_waitqueue_head(&send_wq);
- init_waitqueue_head(&recv_wq);
-
- rv = misc_register(&plock_dev_misc);
- if (rv)
- log_print("dlm_plock_init: misc_register failed %d", rv);
- return rv;
-}
-
-void dlm_plock_exit(void)
-{
- if (misc_deregister(&plock_dev_misc) < 0)
- log_print("dlm_plock_exit: misc_deregister failed");
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/rcom.c b/ANDROID_3.4.5/fs/dlm/rcom.c
deleted file mode 100644
index ac5c616c..00000000
--- a/ANDROID_3.4.5/fs/dlm/rcom.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2005-2008 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 "lowcomms.h"
-#include "midcomms.h"
-#include "rcom.h"
-#include "recover.h"
-#include "dir.h"
-#include "config.h"
-#include "memory.h"
-#include "lock.h"
-#include "util.h"
-#include "member.h"
-
-
-static int rcom_response(struct dlm_ls *ls)
-{
- return test_bit(LSFL_RCOM_READY, &ls->ls_flags);
-}
-
-static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len,
- struct dlm_rcom **rc_ret, struct dlm_mhandle **mh_ret)
-{
- struct dlm_rcom *rc;
- struct dlm_mhandle *mh;
- char *mb;
- int mb_len = sizeof(struct dlm_rcom) + len;
-
- mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_NOFS, &mb);
- if (!mh) {
- log_print("create_rcom to %d type %d len %d ENOBUFS",
- to_nodeid, type, len);
- return -ENOBUFS;
- }
- memset(mb, 0, mb_len);
-
- rc = (struct dlm_rcom *) mb;
-
- rc->rc_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR);
- rc->rc_header.h_lockspace = ls->ls_global_id;
- rc->rc_header.h_nodeid = dlm_our_nodeid();
- rc->rc_header.h_length = mb_len;
- rc->rc_header.h_cmd = DLM_RCOM;
-
- rc->rc_type = type;
-
- spin_lock(&ls->ls_recover_lock);
- rc->rc_seq = ls->ls_recover_seq;
- spin_unlock(&ls->ls_recover_lock);
-
- *mh_ret = mh;
- *rc_ret = rc;
- return 0;
-}
-
-static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh,
- struct dlm_rcom *rc)
-{
- dlm_rcom_out(rc);
- dlm_lowcomms_commit_buffer(mh);
-}
-
-static void set_rcom_status(struct dlm_ls *ls, struct rcom_status *rs,
- uint32_t flags)
-{
- rs->rs_flags = cpu_to_le32(flags);
-}
-
-/* When replying to a status request, a node also sends back its
- configuration values. The requesting node then checks that the remote
- node is configured the same way as itself. */
-
-static void set_rcom_config(struct dlm_ls *ls, struct rcom_config *rf,
- uint32_t num_slots)
-{
- rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen);
- rf->rf_lsflags = cpu_to_le32(ls->ls_exflags);
-
- rf->rf_our_slot = cpu_to_le16(ls->ls_slot);
- rf->rf_num_slots = cpu_to_le16(num_slots);
- rf->rf_generation = cpu_to_le32(ls->ls_generation);
-}
-
-static int check_rcom_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
-{
- struct rcom_config *rf = (struct rcom_config *) rc->rc_buf;
-
- if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) {
- log_error(ls, "version mismatch: %x nodeid %d: %x",
- DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid,
- rc->rc_header.h_version);
- return -EPROTO;
- }
-
- if (le32_to_cpu(rf->rf_lvblen) != ls->ls_lvblen ||
- le32_to_cpu(rf->rf_lsflags) != ls->ls_exflags) {
- log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x",
- ls->ls_lvblen, ls->ls_exflags, nodeid,
- le32_to_cpu(rf->rf_lvblen),
- le32_to_cpu(rf->rf_lsflags));
- return -EPROTO;
- }
- return 0;
-}
-
-static void allow_sync_reply(struct dlm_ls *ls, uint64_t *new_seq)
-{
- spin_lock(&ls->ls_rcom_spin);
- *new_seq = ++ls->ls_rcom_seq;
- set_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
- spin_unlock(&ls->ls_rcom_spin);
-}
-
-static void disallow_sync_reply(struct dlm_ls *ls)
-{
- spin_lock(&ls->ls_rcom_spin);
- clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
- clear_bit(LSFL_RCOM_READY, &ls->ls_flags);
- spin_unlock(&ls->ls_rcom_spin);
-}
-
-/*
- * low nodeid gathers one slot value at a time from each node.
- * it sets need_slots=0, and saves rf_our_slot returned from each
- * rcom_config.
- *
- * other nodes gather all slot values at once from the low nodeid.
- * they set need_slots=1, and ignore the rf_our_slot returned from each
- * rcom_config. they use the rf_num_slots returned from the low
- * node's rcom_config.
- */
-
-int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags)
-{
- struct dlm_rcom *rc;
- struct dlm_mhandle *mh;
- int error = 0;
-
- ls->ls_recover_nodeid = nodeid;
-
- if (nodeid == dlm_our_nodeid()) {
- rc = ls->ls_recover_buf;
- rc->rc_result = dlm_recover_status(ls);
- goto out;
- }
-
- error = create_rcom(ls, nodeid, DLM_RCOM_STATUS,
- sizeof(struct rcom_status), &rc, &mh);
- if (error)
- goto out;
-
- set_rcom_status(ls, (struct rcom_status *)rc->rc_buf, status_flags);
-
- allow_sync_reply(ls, &rc->rc_id);
- memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size);
-
- send_rcom(ls, mh, rc);
-
- error = dlm_wait_function(ls, &rcom_response);
- disallow_sync_reply(ls);
- if (error)
- goto out;
-
- rc = ls->ls_recover_buf;
-
- if (rc->rc_result == -ESRCH) {
- /* we pretend the remote lockspace exists with 0 status */
- log_debug(ls, "remote node %d not ready", nodeid);
- rc->rc_result = 0;
- error = 0;
- } else {
- error = check_rcom_config(ls, rc, nodeid);
- }
-
- /* the caller looks at rc_result for the remote recovery status */
- out:
- return error;
-}
-
-static void receive_rcom_status(struct dlm_ls *ls, struct dlm_rcom *rc_in)
-{
- struct dlm_rcom *rc;
- struct dlm_mhandle *mh;
- struct rcom_status *rs;
- uint32_t status;
- int nodeid = rc_in->rc_header.h_nodeid;
- int len = sizeof(struct rcom_config);
- int num_slots = 0;
- int error;
-
- if (!dlm_slots_version(&rc_in->rc_header)) {
- status = dlm_recover_status(ls);
- goto do_create;
- }
-
- rs = (struct rcom_status *)rc_in->rc_buf;
-
- if (!(rs->rs_flags & DLM_RSF_NEED_SLOTS)) {
- status = dlm_recover_status(ls);
- goto do_create;
- }
-
- spin_lock(&ls->ls_recover_lock);
- status = ls->ls_recover_status;
- num_slots = ls->ls_num_slots;
- spin_unlock(&ls->ls_recover_lock);
- len += num_slots * sizeof(struct rcom_slot);
-
- do_create:
- error = create_rcom(ls, nodeid, DLM_RCOM_STATUS_REPLY,
- len, &rc, &mh);
- if (error)
- return;
-
- rc->rc_id = rc_in->rc_id;
- rc->rc_seq_reply = rc_in->rc_seq;
- rc->rc_result = status;
-
- set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, num_slots);
-
- if (!num_slots)
- goto do_send;
-
- spin_lock(&ls->ls_recover_lock);
- if (ls->ls_num_slots != num_slots) {
- spin_unlock(&ls->ls_recover_lock);
- log_debug(ls, "receive_rcom_status num_slots %d to %d",
- num_slots, ls->ls_num_slots);
- rc->rc_result = 0;
- set_rcom_config(ls, (struct rcom_config *)rc->rc_buf, 0);
- goto do_send;
- }
-
- dlm_slots_copy_out(ls, rc);
- spin_unlock(&ls->ls_recover_lock);
-
- do_send:
- send_rcom(ls, mh, rc);
-}
-
-static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
-{
- spin_lock(&ls->ls_rcom_spin);
- if (!test_bit(LSFL_RCOM_WAIT, &ls->ls_flags) ||
- rc_in->rc_id != ls->ls_rcom_seq) {
- log_debug(ls, "reject reply %d from %d seq %llx expect %llx",
- rc_in->rc_type, rc_in->rc_header.h_nodeid,
- (unsigned long long)rc_in->rc_id,
- (unsigned long long)ls->ls_rcom_seq);
- goto out;
- }
- memcpy(ls->ls_recover_buf, rc_in, rc_in->rc_header.h_length);
- set_bit(LSFL_RCOM_READY, &ls->ls_flags);
- clear_bit(LSFL_RCOM_WAIT, &ls->ls_flags);
- wake_up(&ls->ls_wait_general);
- out:
- spin_unlock(&ls->ls_rcom_spin);
-}
-
-int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len)
-{
- struct dlm_rcom *rc;
- struct dlm_mhandle *mh;
- int error = 0;
- int max_size = dlm_config.ci_buffer_size - sizeof(struct dlm_rcom);
-
- ls->ls_recover_nodeid = nodeid;
-
- if (nodeid == dlm_our_nodeid()) {
- ls->ls_recover_buf->rc_header.h_length =
- dlm_config.ci_buffer_size;
- dlm_copy_master_names(ls, last_name, last_len,
- ls->ls_recover_buf->rc_buf,
- max_size, nodeid);
- goto out;
- }
-
- error = create_rcom(ls, nodeid, DLM_RCOM_NAMES, last_len, &rc, &mh);
- if (error)
- goto out;
- memcpy(rc->rc_buf, last_name, last_len);
-
- allow_sync_reply(ls, &rc->rc_id);
- memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size);
-
- send_rcom(ls, mh, rc);
-
- error = dlm_wait_function(ls, &rcom_response);
- disallow_sync_reply(ls);
- out:
- return error;
-}
-
-static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in)
-{
- struct dlm_rcom *rc;
- struct dlm_mhandle *mh;
- int error, inlen, outlen, nodeid;
-
- nodeid = rc_in->rc_header.h_nodeid;
- inlen = rc_in->rc_header.h_length - sizeof(struct dlm_rcom);
- outlen = dlm_config.ci_buffer_size - sizeof(struct dlm_rcom);
-
- error = create_rcom(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen, &rc, &mh);
- if (error)
- return;
- rc->rc_id = rc_in->rc_id;
- rc->rc_seq_reply = rc_in->rc_seq;
-
- dlm_copy_master_names(ls, rc_in->rc_buf, inlen, rc->rc_buf, outlen,
- nodeid);
- send_rcom(ls, mh, rc);
-}
-
-int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid)
-{
- struct dlm_rcom *rc;
- struct dlm_mhandle *mh;
- struct dlm_ls *ls = r->res_ls;
- int error;
-
- error = create_rcom(ls, dir_nodeid, DLM_RCOM_LOOKUP, r->res_length,
- &rc, &mh);
- if (error)
- goto out;
- memcpy(rc->rc_buf, r->res_name, r->res_length);
- rc->rc_id = (unsigned long) r;
-
- send_rcom(ls, mh, rc);
- out:
- return error;
-}
-
-static void receive_rcom_lookup(struct dlm_ls *ls, struct dlm_rcom *rc_in)
-{
- struct dlm_rcom *rc;
- struct dlm_mhandle *mh;
- int error, ret_nodeid, nodeid = rc_in->rc_header.h_nodeid;
- int len = rc_in->rc_header.h_length - sizeof(struct dlm_rcom);
-
- error = create_rcom(ls, nodeid, DLM_RCOM_LOOKUP_REPLY, 0, &rc, &mh);
- if (error)
- return;
-
- error = dlm_dir_lookup(ls, nodeid, rc_in->rc_buf, len, &ret_nodeid);
- if (error)
- ret_nodeid = error;
- rc->rc_result = ret_nodeid;
- rc->rc_id = rc_in->rc_id;
- rc->rc_seq_reply = rc_in->rc_seq;
-
- send_rcom(ls, mh, rc);
-}
-
-static void receive_rcom_lookup_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
-{
- dlm_recover_master_reply(ls, rc_in);
-}
-
-static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb,
- struct rcom_lock *rl)
-{
- memset(rl, 0, sizeof(*rl));
-
- rl->rl_ownpid = cpu_to_le32(lkb->lkb_ownpid);
- rl->rl_lkid = cpu_to_le32(lkb->lkb_id);
- rl->rl_exflags = cpu_to_le32(lkb->lkb_exflags);
- rl->rl_flags = cpu_to_le32(lkb->lkb_flags);
- rl->rl_lvbseq = cpu_to_le32(lkb->lkb_lvbseq);
- rl->rl_rqmode = lkb->lkb_rqmode;
- rl->rl_grmode = lkb->lkb_grmode;
- rl->rl_status = lkb->lkb_status;
- rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type);
-
- if (lkb->lkb_bastfn)
- rl->rl_asts |= DLM_CB_BAST;
- if (lkb->lkb_astfn)
- rl->rl_asts |= DLM_CB_CAST;
-
- rl->rl_namelen = cpu_to_le16(r->res_length);
- memcpy(rl->rl_name, r->res_name, r->res_length);
-
- /* FIXME: might we have an lvb without DLM_LKF_VALBLK set ?
- If so, receive_rcom_lock_args() won't take this copy. */
-
- if (lkb->lkb_lvbptr)
- memcpy(rl->rl_lvb, lkb->lkb_lvbptr, r->res_ls->ls_lvblen);
-}
-
-int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
-{
- struct dlm_ls *ls = r->res_ls;
- struct dlm_rcom *rc;
- struct dlm_mhandle *mh;
- struct rcom_lock *rl;
- int error, len = sizeof(struct rcom_lock);
-
- if (lkb->lkb_lvbptr)
- len += ls->ls_lvblen;
-
- error = create_rcom(ls, r->res_nodeid, DLM_RCOM_LOCK, len, &rc, &mh);
- if (error)
- goto out;
-
- rl = (struct rcom_lock *) rc->rc_buf;
- pack_rcom_lock(r, lkb, rl);
- rc->rc_id = (unsigned long) r;
-
- send_rcom(ls, mh, rc);
- out:
- return error;
-}
-
-/* needs at least dlm_rcom + rcom_lock */
-static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in)
-{
- struct dlm_rcom *rc;
- struct dlm_mhandle *mh;
- int error, nodeid = rc_in->rc_header.h_nodeid;
-
- dlm_recover_master_copy(ls, rc_in);
-
- error = create_rcom(ls, nodeid, DLM_RCOM_LOCK_REPLY,
- sizeof(struct rcom_lock), &rc, &mh);
- if (error)
- return;
-
- /* We send back the same rcom_lock struct we received, but
- dlm_recover_master_copy() has filled in rl_remid and rl_result */
-
- memcpy(rc->rc_buf, rc_in->rc_buf, sizeof(struct rcom_lock));
- rc->rc_id = rc_in->rc_id;
- rc->rc_seq_reply = rc_in->rc_seq;
-
- send_rcom(ls, mh, rc);
-}
-
-/* If the lockspace doesn't exist then still send a status message
- back; it's possible that it just doesn't have its global_id yet. */
-
-int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
-{
- struct dlm_rcom *rc;
- struct rcom_config *rf;
- struct dlm_mhandle *mh;
- char *mb;
- int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
-
- mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_NOFS, &mb);
- if (!mh)
- return -ENOBUFS;
- memset(mb, 0, mb_len);
-
- rc = (struct dlm_rcom *) mb;
-
- rc->rc_header.h_version = (DLM_HEADER_MAJOR | DLM_HEADER_MINOR);
- rc->rc_header.h_lockspace = rc_in->rc_header.h_lockspace;
- rc->rc_header.h_nodeid = dlm_our_nodeid();
- rc->rc_header.h_length = mb_len;
- rc->rc_header.h_cmd = DLM_RCOM;
-
- rc->rc_type = DLM_RCOM_STATUS_REPLY;
- rc->rc_id = rc_in->rc_id;
- rc->rc_seq_reply = rc_in->rc_seq;
- rc->rc_result = -ESRCH;
-
- rf = (struct rcom_config *) rc->rc_buf;
- rf->rf_lvblen = cpu_to_le32(~0U);
-
- dlm_rcom_out(rc);
- dlm_lowcomms_commit_buffer(mh);
-
- return 0;
-}
-
-static int is_old_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
-{
- uint64_t seq;
- int rv = 0;
-
- switch (rc->rc_type) {
- case DLM_RCOM_STATUS_REPLY:
- case DLM_RCOM_NAMES_REPLY:
- case DLM_RCOM_LOOKUP_REPLY:
- case DLM_RCOM_LOCK_REPLY:
- spin_lock(&ls->ls_recover_lock);
- seq = ls->ls_recover_seq;
- spin_unlock(&ls->ls_recover_lock);
- if (rc->rc_seq_reply != seq) {
- log_debug(ls, "ignoring old reply %x from %d "
- "seq_reply %llx expect %llx",
- rc->rc_type, rc->rc_header.h_nodeid,
- (unsigned long long)rc->rc_seq_reply,
- (unsigned long long)seq);
- rv = 1;
- }
- }
- return rv;
-}
-
-/* Called by dlm_recv; corresponds to dlm_receive_message() but special
- recovery-only comms are sent through here. */
-
-void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
-{
- int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock);
-
- if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) {
- log_debug(ls, "ignoring recovery message %x from %d",
- rc->rc_type, nodeid);
- goto out;
- }
-
- if (is_old_reply(ls, rc))
- goto out;
-
- switch (rc->rc_type) {
- case DLM_RCOM_STATUS:
- receive_rcom_status(ls, rc);
- break;
-
- case DLM_RCOM_NAMES:
- receive_rcom_names(ls, rc);
- break;
-
- case DLM_RCOM_LOOKUP:
- receive_rcom_lookup(ls, rc);
- break;
-
- case DLM_RCOM_LOCK:
- if (rc->rc_header.h_length < lock_size)
- goto Eshort;
- receive_rcom_lock(ls, rc);
- break;
-
- case DLM_RCOM_STATUS_REPLY:
- receive_sync_reply(ls, rc);
- break;
-
- case DLM_RCOM_NAMES_REPLY:
- receive_sync_reply(ls, rc);
- break;
-
- case DLM_RCOM_LOOKUP_REPLY:
- receive_rcom_lookup_reply(ls, rc);
- break;
-
- case DLM_RCOM_LOCK_REPLY:
- if (rc->rc_header.h_length < lock_size)
- goto Eshort;
- dlm_recover_process_copy(ls, rc);
- break;
-
- default:
- log_error(ls, "receive_rcom bad type %d", rc->rc_type);
- }
-out:
- return;
-Eshort:
- log_error(ls, "recovery message %x from %d is too short",
- rc->rc_type, nodeid);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/rcom.h b/ANDROID_3.4.5/fs/dlm/rcom.h
deleted file mode 100644
index 206723ab..00000000
--- a/ANDROID_3.4.5/fs/dlm/rcom.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2005-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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __RCOM_DOT_H__
-#define __RCOM_DOT_H__
-
-int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags);
-int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name,int last_len);
-int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid);
-int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
-void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid);
-int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in);
-
-#endif
-
diff --git a/ANDROID_3.4.5/fs/dlm/recover.c b/ANDROID_3.4.5/fs/dlm/recover.c
deleted file mode 100644
index 34d5adf1..00000000
--- a/ANDROID_3.4.5/fs/dlm/recover.c
+++ /dev/null
@@ -1,840 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 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 "dir.h"
-#include "config.h"
-#include "ast.h"
-#include "memory.h"
-#include "rcom.h"
-#include "lock.h"
-#include "lowcomms.h"
-#include "member.h"
-#include "recover.h"
-
-
-/*
- * Recovery waiting routines: these functions wait for a particular reply from
- * a remote node, or for the remote node to report a certain status. They need
- * to abort if the lockspace is stopped indicating a node has failed (perhaps
- * the one being waited for).
- */
-
-/*
- * Wait until given function returns non-zero or lockspace is stopped
- * (LS_RECOVERY_STOP set due to failure of a node in ls_nodes). When another
- * function thinks it could have completed the waited-on task, they should wake
- * up ls_wait_general to get an immediate response rather than waiting for the
- * timer to detect the result. A timer wakes us up periodically while waiting
- * to see if we should abort due to a node failure. This should only be called
- * by the dlm_recoverd thread.
- */
-
-static void dlm_wait_timer_fn(unsigned long data)
-{
- struct dlm_ls *ls = (struct dlm_ls *) data;
- mod_timer(&ls->ls_timer, jiffies + (dlm_config.ci_recover_timer * HZ));
- wake_up(&ls->ls_wait_general);
-}
-
-int dlm_wait_function(struct dlm_ls *ls, int (*testfn) (struct dlm_ls *ls))
-{
- int error = 0;
-
- init_timer(&ls->ls_timer);
- ls->ls_timer.function = dlm_wait_timer_fn;
- ls->ls_timer.data = (long) ls;
- ls->ls_timer.expires = jiffies + (dlm_config.ci_recover_timer * HZ);
- add_timer(&ls->ls_timer);
-
- wait_event(ls->ls_wait_general, testfn(ls) || dlm_recovery_stopped(ls));
- del_timer_sync(&ls->ls_timer);
-
- if (dlm_recovery_stopped(ls)) {
- log_debug(ls, "dlm_wait_function aborted");
- error = -EINTR;
- }
- return error;
-}
-
-/*
- * An efficient way for all nodes to wait for all others to have a certain
- * status. The node with the lowest nodeid polls all the others for their
- * status (wait_status_all) and all the others poll the node with the low id
- * for its accumulated result (wait_status_low). When all nodes have set
- * status flag X, then status flag X_ALL will be set on the low nodeid.
- */
-
-uint32_t dlm_recover_status(struct dlm_ls *ls)
-{
- uint32_t status;
- spin_lock(&ls->ls_recover_lock);
- status = ls->ls_recover_status;
- spin_unlock(&ls->ls_recover_lock);
- return status;
-}
-
-static void _set_recover_status(struct dlm_ls *ls, uint32_t status)
-{
- ls->ls_recover_status |= status;
-}
-
-void dlm_set_recover_status(struct dlm_ls *ls, uint32_t status)
-{
- spin_lock(&ls->ls_recover_lock);
- _set_recover_status(ls, status);
- spin_unlock(&ls->ls_recover_lock);
-}
-
-static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status,
- int save_slots)
-{
- struct dlm_rcom *rc = ls->ls_recover_buf;
- struct dlm_member *memb;
- int error = 0, delay;
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- delay = 0;
- for (;;) {
- if (dlm_recovery_stopped(ls)) {
- error = -EINTR;
- goto out;
- }
-
- error = dlm_rcom_status(ls, memb->nodeid, 0);
- if (error)
- goto out;
-
- if (save_slots)
- dlm_slot_save(ls, rc, memb);
-
- if (rc->rc_result & wait_status)
- break;
- if (delay < 1000)
- delay += 20;
- msleep(delay);
- }
- }
- out:
- return error;
-}
-
-static int wait_status_low(struct dlm_ls *ls, uint32_t wait_status,
- uint32_t status_flags)
-{
- struct dlm_rcom *rc = ls->ls_recover_buf;
- int error = 0, delay = 0, nodeid = ls->ls_low_nodeid;
-
- for (;;) {
- if (dlm_recovery_stopped(ls)) {
- error = -EINTR;
- goto out;
- }
-
- error = dlm_rcom_status(ls, nodeid, status_flags);
- if (error)
- break;
-
- if (rc->rc_result & wait_status)
- break;
- if (delay < 1000)
- delay += 20;
- msleep(delay);
- }
- out:
- return error;
-}
-
-static int wait_status(struct dlm_ls *ls, uint32_t status)
-{
- uint32_t status_all = status << 1;
- int error;
-
- if (ls->ls_low_nodeid == dlm_our_nodeid()) {
- error = wait_status_all(ls, status, 0);
- if (!error)
- dlm_set_recover_status(ls, status_all);
- } else
- error = wait_status_low(ls, status_all, 0);
-
- return error;
-}
-
-int dlm_recover_members_wait(struct dlm_ls *ls)
-{
- struct dlm_member *memb;
- struct dlm_slot *slots;
- int num_slots, slots_size;
- int error, rv;
- uint32_t gen;
-
- list_for_each_entry(memb, &ls->ls_nodes, list) {
- memb->slot = -1;
- memb->generation = 0;
- }
-
- if (ls->ls_low_nodeid == dlm_our_nodeid()) {
- error = wait_status_all(ls, DLM_RS_NODES, 1);
- if (error)
- goto out;
-
- /* slots array is sparse, slots_size may be > num_slots */
-
- rv = dlm_slots_assign(ls, &num_slots, &slots_size, &slots, &gen);
- if (!rv) {
- spin_lock(&ls->ls_recover_lock);
- _set_recover_status(ls, DLM_RS_NODES_ALL);
- ls->ls_num_slots = num_slots;
- ls->ls_slots_size = slots_size;
- ls->ls_slots = slots;
- ls->ls_generation = gen;
- spin_unlock(&ls->ls_recover_lock);
- } else {
- dlm_set_recover_status(ls, DLM_RS_NODES_ALL);
- }
- } else {
- error = wait_status_low(ls, DLM_RS_NODES_ALL, DLM_RSF_NEED_SLOTS);
- if (error)
- goto out;
-
- dlm_slots_copy_in(ls);
- }
- out:
- return error;
-}
-
-int dlm_recover_directory_wait(struct dlm_ls *ls)
-{
- return wait_status(ls, DLM_RS_DIR);
-}
-
-int dlm_recover_locks_wait(struct dlm_ls *ls)
-{
- return wait_status(ls, DLM_RS_LOCKS);
-}
-
-int dlm_recover_done_wait(struct dlm_ls *ls)
-{
- return wait_status(ls, DLM_RS_DONE);
-}
-
-/*
- * The recover_list contains all the rsb's for which we've requested the new
- * master nodeid. As replies are returned from the resource directories the
- * rsb's are removed from the list. When the list is empty we're done.
- *
- * The recover_list is later similarly used for all rsb's for which we've sent
- * new lkb's and need to receive new corresponding lkid's.
- *
- * We use the address of the rsb struct as a simple local identifier for the
- * rsb so we can match an rcom reply with the rsb it was sent for.
- */
-
-static int recover_list_empty(struct dlm_ls *ls)
-{
- int empty;
-
- spin_lock(&ls->ls_recover_list_lock);
- empty = list_empty(&ls->ls_recover_list);
- spin_unlock(&ls->ls_recover_list_lock);
-
- return empty;
-}
-
-static void recover_list_add(struct dlm_rsb *r)
-{
- struct dlm_ls *ls = r->res_ls;
-
- spin_lock(&ls->ls_recover_list_lock);
- if (list_empty(&r->res_recover_list)) {
- list_add_tail(&r->res_recover_list, &ls->ls_recover_list);
- ls->ls_recover_list_count++;
- dlm_hold_rsb(r);
- }
- spin_unlock(&ls->ls_recover_list_lock);
-}
-
-static void recover_list_del(struct dlm_rsb *r)
-{
- struct dlm_ls *ls = r->res_ls;
-
- spin_lock(&ls->ls_recover_list_lock);
- list_del_init(&r->res_recover_list);
- ls->ls_recover_list_count--;
- spin_unlock(&ls->ls_recover_list_lock);
-
- dlm_put_rsb(r);
-}
-
-static struct dlm_rsb *recover_list_find(struct dlm_ls *ls, uint64_t id)
-{
- struct dlm_rsb *r = NULL;
-
- spin_lock(&ls->ls_recover_list_lock);
-
- list_for_each_entry(r, &ls->ls_recover_list, res_recover_list) {
- if (id == (unsigned long) r)
- goto out;
- }
- r = NULL;
- out:
- spin_unlock(&ls->ls_recover_list_lock);
- return r;
-}
-
-static void recover_list_clear(struct dlm_ls *ls)
-{
- struct dlm_rsb *r, *s;
-
- spin_lock(&ls->ls_recover_list_lock);
- list_for_each_entry_safe(r, s, &ls->ls_recover_list, res_recover_list) {
- list_del_init(&r->res_recover_list);
- r->res_recover_locks_count = 0;
- dlm_put_rsb(r);
- ls->ls_recover_list_count--;
- }
-
- if (ls->ls_recover_list_count != 0) {
- log_error(ls, "warning: recover_list_count %d",
- ls->ls_recover_list_count);
- ls->ls_recover_list_count = 0;
- }
- spin_unlock(&ls->ls_recover_list_lock);
-}
-
-
-/* Master recovery: find new master node for rsb's that were
- mastered on nodes that have been removed.
-
- dlm_recover_masters
- recover_master
- dlm_send_rcom_lookup -> receive_rcom_lookup
- dlm_dir_lookup
- receive_rcom_lookup_reply <-
- dlm_recover_master_reply
- set_new_master
- set_master_lkbs
- set_lock_master
-*/
-
-/*
- * Set the lock master for all LKBs in a lock queue
- * If we are the new master of the rsb, we may have received new
- * MSTCPY locks from other nodes already which we need to ignore
- * when setting the new nodeid.
- */
-
-static void set_lock_master(struct list_head *queue, int nodeid)
-{
- struct dlm_lkb *lkb;
-
- list_for_each_entry(lkb, queue, lkb_statequeue)
- if (!(lkb->lkb_flags & DLM_IFL_MSTCPY))
- lkb->lkb_nodeid = nodeid;
-}
-
-static void set_master_lkbs(struct dlm_rsb *r)
-{
- set_lock_master(&r->res_grantqueue, r->res_nodeid);
- set_lock_master(&r->res_convertqueue, r->res_nodeid);
- set_lock_master(&r->res_waitqueue, r->res_nodeid);
-}
-
-/*
- * Propagate the new master nodeid to locks
- * The NEW_MASTER flag tells dlm_recover_locks() which rsb's to consider.
- * The NEW_MASTER2 flag tells recover_lvb() and set_locks_purged() which
- * rsb's to consider.
- */
-
-static void set_new_master(struct dlm_rsb *r, int nodeid)
-{
- lock_rsb(r);
- r->res_nodeid = nodeid;
- set_master_lkbs(r);
- rsb_set_flag(r, RSB_NEW_MASTER);
- rsb_set_flag(r, RSB_NEW_MASTER2);
- unlock_rsb(r);
-}
-
-/*
- * We do async lookups on rsb's that need new masters. The rsb's
- * waiting for a lookup reply are kept on the recover_list.
- */
-
-static int recover_master(struct dlm_rsb *r)
-{
- struct dlm_ls *ls = r->res_ls;
- int error, dir_nodeid, ret_nodeid, our_nodeid = dlm_our_nodeid();
-
- dir_nodeid = dlm_dir_nodeid(r);
-
- if (dir_nodeid == our_nodeid) {
- error = dlm_dir_lookup(ls, our_nodeid, r->res_name,
- r->res_length, &ret_nodeid);
- if (error)
- log_error(ls, "recover dir lookup error %d", error);
-
- if (ret_nodeid == our_nodeid)
- ret_nodeid = 0;
- set_new_master(r, ret_nodeid);
- } else {
- recover_list_add(r);
- error = dlm_send_rcom_lookup(r, dir_nodeid);
- }
-
- return error;
-}
-
-/*
- * When not using a directory, most resource names will hash to a new static
- * master nodeid and the resource will need to be remastered.
- */
-
-static int recover_master_static(struct dlm_rsb *r)
-{
- int master = dlm_dir_nodeid(r);
-
- if (master == dlm_our_nodeid())
- master = 0;
-
- if (r->res_nodeid != master) {
- if (is_master(r))
- dlm_purge_mstcpy_locks(r);
- set_new_master(r, master);
- return 1;
- }
- return 0;
-}
-
-/*
- * Go through local root resources and for each rsb which has a master which
- * has departed, get the new master nodeid from the directory. The dir will
- * assign mastery to the first node to look up the new master. That means
- * we'll discover in this lookup if we're the new master of any rsb's.
- *
- * We fire off all the dir lookup requests individually and asynchronously to
- * the correct dir node.
- */
-
-int dlm_recover_masters(struct dlm_ls *ls)
-{
- struct dlm_rsb *r;
- int error = 0, count = 0;
-
- log_debug(ls, "dlm_recover_masters");
-
- down_read(&ls->ls_root_sem);
- list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
- if (dlm_recovery_stopped(ls)) {
- up_read(&ls->ls_root_sem);
- error = -EINTR;
- goto out;
- }
-
- if (dlm_no_directory(ls))
- count += recover_master_static(r);
- else if (!is_master(r) &&
- (dlm_is_removed(ls, r->res_nodeid) ||
- rsb_flag(r, RSB_NEW_MASTER))) {
- recover_master(r);
- count++;
- }
-
- schedule();
- }
- up_read(&ls->ls_root_sem);
-
- log_debug(ls, "dlm_recover_masters %d resources", count);
-
- error = dlm_wait_function(ls, &recover_list_empty);
- out:
- if (error)
- recover_list_clear(ls);
- return error;
-}
-
-int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
-{
- struct dlm_rsb *r;
- int nodeid;
-
- r = recover_list_find(ls, rc->rc_id);
- if (!r) {
- log_error(ls, "dlm_recover_master_reply no id %llx",
- (unsigned long long)rc->rc_id);
- goto out;
- }
-
- nodeid = rc->rc_result;
- if (nodeid == dlm_our_nodeid())
- nodeid = 0;
-
- set_new_master(r, nodeid);
- recover_list_del(r);
-
- if (recover_list_empty(ls))
- wake_up(&ls->ls_wait_general);
- out:
- return 0;
-}
-
-
-/* Lock recovery: rebuild the process-copy locks we hold on a
- remastered rsb on the new rsb master.
-
- dlm_recover_locks
- recover_locks
- recover_locks_queue
- dlm_send_rcom_lock -> receive_rcom_lock
- dlm_recover_master_copy
- receive_rcom_lock_reply <-
- dlm_recover_process_copy
-*/
-
-
-/*
- * keep a count of the number of lkb's we send to the new master; when we get
- * an equal number of replies then recovery for the rsb is done
- */
-
-static int recover_locks_queue(struct dlm_rsb *r, struct list_head *head)
-{
- struct dlm_lkb *lkb;
- int error = 0;
-
- list_for_each_entry(lkb, head, lkb_statequeue) {
- error = dlm_send_rcom_lock(r, lkb);
- if (error)
- break;
- r->res_recover_locks_count++;
- }
-
- return error;
-}
-
-static int recover_locks(struct dlm_rsb *r)
-{
- int error = 0;
-
- lock_rsb(r);
-
- DLM_ASSERT(!r->res_recover_locks_count, dlm_dump_rsb(r););
-
- error = recover_locks_queue(r, &r->res_grantqueue);
- if (error)
- goto out;
- error = recover_locks_queue(r, &r->res_convertqueue);
- if (error)
- goto out;
- error = recover_locks_queue(r, &r->res_waitqueue);
- if (error)
- goto out;
-
- if (r->res_recover_locks_count)
- recover_list_add(r);
- else
- rsb_clear_flag(r, RSB_NEW_MASTER);
- out:
- unlock_rsb(r);
- return error;
-}
-
-int dlm_recover_locks(struct dlm_ls *ls)
-{
- struct dlm_rsb *r;
- int error, count = 0;
-
- log_debug(ls, "dlm_recover_locks");
-
- down_read(&ls->ls_root_sem);
- list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
- if (is_master(r)) {
- rsb_clear_flag(r, RSB_NEW_MASTER);
- continue;
- }
-
- if (!rsb_flag(r, RSB_NEW_MASTER))
- continue;
-
- if (dlm_recovery_stopped(ls)) {
- error = -EINTR;
- up_read(&ls->ls_root_sem);
- goto out;
- }
-
- error = recover_locks(r);
- if (error) {
- up_read(&ls->ls_root_sem);
- goto out;
- }
-
- count += r->res_recover_locks_count;
- }
- up_read(&ls->ls_root_sem);
-
- log_debug(ls, "dlm_recover_locks %d locks", count);
-
- error = dlm_wait_function(ls, &recover_list_empty);
- out:
- if (error)
- recover_list_clear(ls);
- return error;
-}
-
-void dlm_recovered_lock(struct dlm_rsb *r)
-{
- DLM_ASSERT(rsb_flag(r, RSB_NEW_MASTER), dlm_dump_rsb(r););
-
- r->res_recover_locks_count--;
- if (!r->res_recover_locks_count) {
- rsb_clear_flag(r, RSB_NEW_MASTER);
- recover_list_del(r);
- }
-
- if (recover_list_empty(r->res_ls))
- wake_up(&r->res_ls->ls_wait_general);
-}
-
-/*
- * The lvb needs to be recovered on all master rsb's. This includes setting
- * the VALNOTVALID flag if necessary, and determining the correct lvb contents
- * based on the lvb's of the locks held on the rsb.
- *
- * RSB_VALNOTVALID is set if there are only NL/CR locks on the rsb. If it
- * was already set prior to recovery, it's not cleared, regardless of locks.
- *
- * The LVB contents are only considered for changing when this is a new master
- * of the rsb (NEW_MASTER2). Then, the rsb's lvb is taken from any lkb with
- * mode > CR. If no lkb's exist with mode above CR, the lvb contents are taken
- * from the lkb with the largest lvb sequence number.
- */
-
-static void recover_lvb(struct dlm_rsb *r)
-{
- struct dlm_lkb *lkb, *high_lkb = NULL;
- uint32_t high_seq = 0;
- int lock_lvb_exists = 0;
- int big_lock_exists = 0;
- int lvblen = r->res_ls->ls_lvblen;
-
- list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
- if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
- continue;
-
- lock_lvb_exists = 1;
-
- if (lkb->lkb_grmode > DLM_LOCK_CR) {
- big_lock_exists = 1;
- goto setflag;
- }
-
- if (((int)lkb->lkb_lvbseq - (int)high_seq) >= 0) {
- high_lkb = lkb;
- high_seq = lkb->lkb_lvbseq;
- }
- }
-
- list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
- if (!(lkb->lkb_exflags & DLM_LKF_VALBLK))
- continue;
-
- lock_lvb_exists = 1;
-
- if (lkb->lkb_grmode > DLM_LOCK_CR) {
- big_lock_exists = 1;
- goto setflag;
- }
-
- if (((int)lkb->lkb_lvbseq - (int)high_seq) >= 0) {
- high_lkb = lkb;
- high_seq = lkb->lkb_lvbseq;
- }
- }
-
- setflag:
- if (!lock_lvb_exists)
- goto out;
-
- if (!big_lock_exists)
- rsb_set_flag(r, RSB_VALNOTVALID);
-
- /* don't mess with the lvb unless we're the new master */
- if (!rsb_flag(r, RSB_NEW_MASTER2))
- goto out;
-
- if (!r->res_lvbptr) {
- r->res_lvbptr = dlm_allocate_lvb(r->res_ls);
- if (!r->res_lvbptr)
- goto out;
- }
-
- if (big_lock_exists) {
- r->res_lvbseq = lkb->lkb_lvbseq;
- memcpy(r->res_lvbptr, lkb->lkb_lvbptr, lvblen);
- } else if (high_lkb) {
- r->res_lvbseq = high_lkb->lkb_lvbseq;
- memcpy(r->res_lvbptr, high_lkb->lkb_lvbptr, lvblen);
- } else {
- r->res_lvbseq = 0;
- memset(r->res_lvbptr, 0, lvblen);
- }
- out:
- return;
-}
-
-/* All master rsb's flagged RECOVER_CONVERT need to be looked at. The locks
- converting PR->CW or CW->PR need to have their lkb_grmode set. */
-
-static void recover_conversion(struct dlm_rsb *r)
-{
- struct dlm_lkb *lkb;
- int grmode = -1;
-
- list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
- if (lkb->lkb_grmode == DLM_LOCK_PR ||
- lkb->lkb_grmode == DLM_LOCK_CW) {
- grmode = lkb->lkb_grmode;
- break;
- }
- }
-
- list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
- if (lkb->lkb_grmode != DLM_LOCK_IV)
- continue;
- if (grmode == -1)
- lkb->lkb_grmode = lkb->lkb_rqmode;
- else
- lkb->lkb_grmode = grmode;
- }
-}
-
-/* We've become the new master for this rsb and waiting/converting locks may
- need to be granted in dlm_grant_after_purge() due to locks that may have
- existed from a removed node. */
-
-static void set_locks_purged(struct dlm_rsb *r)
-{
- if (!list_empty(&r->res_waitqueue) || !list_empty(&r->res_convertqueue))
- rsb_set_flag(r, RSB_LOCKS_PURGED);
-}
-
-void dlm_recover_rsbs(struct dlm_ls *ls)
-{
- struct dlm_rsb *r;
- int count = 0;
-
- log_debug(ls, "dlm_recover_rsbs");
-
- down_read(&ls->ls_root_sem);
- list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
- lock_rsb(r);
- if (is_master(r)) {
- if (rsb_flag(r, RSB_RECOVER_CONVERT))
- recover_conversion(r);
- if (rsb_flag(r, RSB_NEW_MASTER2))
- set_locks_purged(r);
- recover_lvb(r);
- count++;
- }
- rsb_clear_flag(r, RSB_RECOVER_CONVERT);
- rsb_clear_flag(r, RSB_NEW_MASTER2);
- unlock_rsb(r);
- }
- up_read(&ls->ls_root_sem);
-
- log_debug(ls, "dlm_recover_rsbs %d rsbs", count);
-}
-
-/* Create a single list of all root rsb's to be used during recovery */
-
-int dlm_create_root_list(struct dlm_ls *ls)
-{
- struct rb_node *n;
- struct dlm_rsb *r;
- int i, error = 0;
-
- down_write(&ls->ls_root_sem);
- if (!list_empty(&ls->ls_root_list)) {
- log_error(ls, "root list not empty");
- error = -EINVAL;
- goto out;
- }
-
- for (i = 0; i < ls->ls_rsbtbl_size; i++) {
- spin_lock(&ls->ls_rsbtbl[i].lock);
- for (n = rb_first(&ls->ls_rsbtbl[i].keep); n; n = rb_next(n)) {
- r = rb_entry(n, struct dlm_rsb, res_hashnode);
- 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)) {
- spin_unlock(&ls->ls_rsbtbl[i].lock);
- continue;
- }
-
- for (n = rb_first(&ls->ls_rsbtbl[i].toss); n; n = rb_next(n)) {
- r = rb_entry(n, struct dlm_rsb, res_hashnode);
- list_add(&r->res_root_list, &ls->ls_root_list);
- dlm_hold_rsb(r);
- }
- spin_unlock(&ls->ls_rsbtbl[i].lock);
- }
- out:
- up_write(&ls->ls_root_sem);
- return error;
-}
-
-void dlm_release_root_list(struct dlm_ls *ls)
-{
- struct dlm_rsb *r, *safe;
-
- down_write(&ls->ls_root_sem);
- list_for_each_entry_safe(r, safe, &ls->ls_root_list, res_root_list) {
- list_del_init(&r->res_root_list);
- dlm_put_rsb(r);
- }
- 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 rb_node *n, *next;
- struct dlm_rsb *rsb;
- int i;
-
- for (i = 0; i < ls->ls_rsbtbl_size; i++) {
- spin_lock(&ls->ls_rsbtbl[i].lock);
- for (n = rb_first(&ls->ls_rsbtbl[i].toss); n; n = next) {
- next = rb_next(n);;
- rsb = rb_entry(n, struct dlm_rsb, res_hashnode);
- if (dlm_no_directory(ls) || !is_master(rsb)) {
- rb_erase(n, &ls->ls_rsbtbl[i].toss);
- dlm_free_rsb(rsb);
- }
- }
- spin_unlock(&ls->ls_rsbtbl[i].lock);
- }
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/recover.h b/ANDROID_3.4.5/fs/dlm/recover.h
deleted file mode 100644
index ebd0363f..00000000
--- a/ANDROID_3.4.5/fs/dlm/recover.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __RECOVER_DOT_H__
-#define __RECOVER_DOT_H__
-
-int dlm_wait_function(struct dlm_ls *ls, int (*testfn) (struct dlm_ls *ls));
-uint32_t dlm_recover_status(struct dlm_ls *ls);
-void dlm_set_recover_status(struct dlm_ls *ls, uint32_t status);
-int dlm_recover_members_wait(struct dlm_ls *ls);
-int dlm_recover_directory_wait(struct dlm_ls *ls);
-int dlm_recover_locks_wait(struct dlm_ls *ls);
-int dlm_recover_done_wait(struct dlm_ls *ls);
-int dlm_recover_masters(struct dlm_ls *ls);
-int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc);
-int dlm_recover_locks(struct dlm_ls *ls);
-void dlm_recovered_lock(struct dlm_rsb *r);
-int dlm_create_root_list(struct dlm_ls *ls);
-void dlm_release_root_list(struct dlm_ls *ls);
-void dlm_clear_toss_list(struct dlm_ls *ls);
-void dlm_recover_rsbs(struct dlm_ls *ls);
-
-#endif /* __RECOVER_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/recoverd.c b/ANDROID_3.4.5/fs/dlm/recoverd.c
deleted file mode 100644
index 3780caf7..00000000
--- a/ANDROID_3.4.5/fs/dlm/recoverd.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2011 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 "dir.h"
-#include "ast.h"
-#include "recover.h"
-#include "lowcomms.h"
-#include "lock.h"
-#include "requestqueue.h"
-#include "recoverd.h"
-
-
-/* If the start for which we're re-enabling locking (seq) has been superseded
- by a newer stop (ls_recover_seq), we need to leave locking disabled.
-
- We suspend dlm_recv threads here to avoid the race where dlm_recv a) sees
- locking stopped and b) adds a message to the requestqueue, but dlm_recoverd
- enables locking and clears the requestqueue between a and b. */
-
-static int enable_locking(struct dlm_ls *ls, uint64_t seq)
-{
- int error = -EINTR;
-
- down_write(&ls->ls_recv_active);
-
- spin_lock(&ls->ls_recover_lock);
- if (ls->ls_recover_seq == seq) {
- set_bit(LSFL_RUNNING, &ls->ls_flags);
- /* unblocks processes waiting to enter the dlm */
- up_write(&ls->ls_in_recovery);
- error = 0;
- }
- spin_unlock(&ls->ls_recover_lock);
-
- up_write(&ls->ls_recv_active);
- return error;
-}
-
-static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
-{
- unsigned long start;
- int error, neg = 0;
-
- log_debug(ls, "dlm_recover %llx", (unsigned long long)rv->seq);
-
- mutex_lock(&ls->ls_recoverd_active);
-
- dlm_callback_suspend(ls);
-
- /*
- * 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.
- */
-
- dlm_create_root_list(ls);
-
- /*
- * Add or remove nodes from the lockspace's ls_nodes list.
- */
-
- error = dlm_recover_members(ls, rv, &neg);
- if (error) {
- log_debug(ls, "dlm_recover_members error %d", error);
- goto fail;
- }
-
- dlm_set_recover_status(ls, DLM_RS_NODES);
-
- error = dlm_recover_members_wait(ls);
- if (error) {
- log_debug(ls, "dlm_recover_members_wait error %d", error);
- goto fail;
- }
-
- start = jiffies;
-
- /*
- * Rebuild our own share of the directory by collecting from all other
- * nodes their master rsb names that hash to us.
- */
-
- error = dlm_recover_directory(ls);
- if (error) {
- log_debug(ls, "dlm_recover_directory error %d", error);
- goto fail;
- }
-
- dlm_set_recover_status(ls, DLM_RS_DIR);
-
- error = dlm_recover_directory_wait(ls);
- if (error) {
- log_debug(ls, "dlm_recover_directory_wait error %d", error);
- goto fail;
- }
-
- /*
- * We may have outstanding operations that are waiting for a reply from
- * a failed node. Mark these to be resent after recovery. Unlock and
- * cancel ops can just be completed.
- */
-
- dlm_recover_waiters_pre(ls);
-
- error = dlm_recovery_stopped(ls);
- if (error)
- goto fail;
-
- if (neg || dlm_no_directory(ls)) {
- /*
- * Clear lkb's for departed nodes.
- */
-
- dlm_purge_locks(ls);
-
- /*
- * Get new master nodeid's for rsb's that were mastered on
- * departed nodes.
- */
-
- error = dlm_recover_masters(ls);
- if (error) {
- log_debug(ls, "dlm_recover_masters error %d", error);
- goto fail;
- }
-
- /*
- * Send our locks on remastered rsb's to the new masters.
- */
-
- error = dlm_recover_locks(ls);
- if (error) {
- log_debug(ls, "dlm_recover_locks error %d", error);
- goto fail;
- }
-
- dlm_set_recover_status(ls, DLM_RS_LOCKS);
-
- error = dlm_recover_locks_wait(ls);
- if (error) {
- log_debug(ls, "dlm_recover_locks_wait error %d", error);
- goto fail;
- }
-
- /*
- * Finalize state in master rsb's now that all locks can be
- * checked. This includes conversion resolution and lvb
- * settings.
- */
-
- dlm_recover_rsbs(ls);
- } else {
- /*
- * Other lockspace members may be going through the "neg" steps
- * while also adding us to the lockspace, in which case they'll
- * be doing the recover_locks (RS_LOCKS) barrier.
- */
- dlm_set_recover_status(ls, DLM_RS_LOCKS);
-
- error = dlm_recover_locks_wait(ls);
- if (error) {
- log_debug(ls, "dlm_recover_locks_wait error %d", error);
- goto fail;
- }
- }
-
- dlm_release_root_list(ls);
-
- /*
- * Purge directory-related requests that are saved in requestqueue.
- * All dir requests from before recovery are invalid now due to the dir
- * rebuild and will be resent by the requesting nodes.
- */
-
- dlm_purge_requestqueue(ls);
-
- dlm_set_recover_status(ls, DLM_RS_DONE);
-
- error = dlm_recover_done_wait(ls);
- if (error) {
- log_debug(ls, "dlm_recover_done_wait error %d", error);
- goto fail;
- }
-
- dlm_clear_members_gone(ls);
-
- dlm_adjust_timeouts(ls);
-
- dlm_callback_resume(ls);
-
- error = enable_locking(ls, rv->seq);
- if (error) {
- log_debug(ls, "enable_locking error %d", error);
- goto fail;
- }
-
- error = dlm_process_requestqueue(ls);
- if (error) {
- log_debug(ls, "dlm_process_requestqueue error %d", error);
- goto fail;
- }
-
- error = dlm_recover_waiters_post(ls);
- if (error) {
- log_debug(ls, "dlm_recover_waiters_post error %d", error);
- goto fail;
- }
-
- dlm_grant_after_purge(ls);
-
- log_debug(ls, "dlm_recover %llx generation %u done: %u ms",
- (unsigned long long)rv->seq, ls->ls_generation,
- jiffies_to_msecs(jiffies - start));
- mutex_unlock(&ls->ls_recoverd_active);
-
- dlm_lsop_recover_done(ls);
- return 0;
-
- fail:
- dlm_release_root_list(ls);
- log_debug(ls, "dlm_recover %llx error %d",
- (unsigned long long)rv->seq, error);
- mutex_unlock(&ls->ls_recoverd_active);
- return error;
-}
-
-/* The dlm_ls_start() that created the rv we take here may already have been
- stopped via dlm_ls_stop(); in that case we need to leave the RECOVERY_STOP
- flag set. */
-
-static void do_ls_recovery(struct dlm_ls *ls)
-{
- struct dlm_recover *rv = NULL;
-
- spin_lock(&ls->ls_recover_lock);
- rv = ls->ls_recover_args;
- ls->ls_recover_args = NULL;
- if (rv && ls->ls_recover_seq == rv->seq)
- clear_bit(LSFL_RECOVERY_STOP, &ls->ls_flags);
- spin_unlock(&ls->ls_recover_lock);
-
- if (rv) {
- ls_recover(ls, rv);
- kfree(rv->nodes);
- kfree(rv);
- }
-}
-
-static int dlm_recoverd(void *arg)
-{
- struct dlm_ls *ls;
-
- ls = dlm_find_lockspace_local(arg);
- if (!ls) {
- log_print("dlm_recoverd: no lockspace %p", arg);
- return -1;
- }
-
- while (!kthread_should_stop()) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (!test_bit(LSFL_WORK, &ls->ls_flags))
- schedule();
- set_current_state(TASK_RUNNING);
-
- if (test_and_clear_bit(LSFL_WORK, &ls->ls_flags))
- do_ls_recovery(ls);
- }
-
- dlm_put_lockspace(ls);
- return 0;
-}
-
-void dlm_recoverd_kick(struct dlm_ls *ls)
-{
- set_bit(LSFL_WORK, &ls->ls_flags);
- wake_up_process(ls->ls_recoverd_task);
-}
-
-int dlm_recoverd_start(struct dlm_ls *ls)
-{
- struct task_struct *p;
- int error = 0;
-
- p = kthread_run(dlm_recoverd, ls, "dlm_recoverd");
- if (IS_ERR(p))
- error = PTR_ERR(p);
- else
- ls->ls_recoverd_task = p;
- return error;
-}
-
-void dlm_recoverd_stop(struct dlm_ls *ls)
-{
- kthread_stop(ls->ls_recoverd_task);
-}
-
-void dlm_recoverd_suspend(struct dlm_ls *ls)
-{
- wake_up(&ls->ls_wait_general);
- mutex_lock(&ls->ls_recoverd_active);
-}
-
-void dlm_recoverd_resume(struct dlm_ls *ls)
-{
- mutex_unlock(&ls->ls_recoverd_active);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/recoverd.h b/ANDROID_3.4.5/fs/dlm/recoverd.h
deleted file mode 100644
index 866657c5..00000000
--- a/ANDROID_3.4.5/fs/dlm/recoverd.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __RECOVERD_DOT_H__
-#define __RECOVERD_DOT_H__
-
-void dlm_recoverd_kick(struct dlm_ls *ls);
-void dlm_recoverd_stop(struct dlm_ls *ls);
-int dlm_recoverd_start(struct dlm_ls *ls);
-void dlm_recoverd_suspend(struct dlm_ls *ls);
-void dlm_recoverd_resume(struct dlm_ls *ls);
-
-#endif /* __RECOVERD_DOT_H__ */
-
diff --git a/ANDROID_3.4.5/fs/dlm/requestqueue.c b/ANDROID_3.4.5/fs/dlm/requestqueue.c
deleted file mode 100644
index a44fa228..00000000
--- a/ANDROID_3.4.5/fs/dlm/requestqueue.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005-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 "member.h"
-#include "lock.h"
-#include "dir.h"
-#include "config.h"
-#include "requestqueue.h"
-
-struct rq_entry {
- struct list_head list;
- int nodeid;
- struct dlm_message request;
-};
-
-/*
- * Requests received while the lockspace is in recovery get added to the
- * request queue and processed when recovery is complete. This happens when
- * the lockspace is suspended on some nodes before it is on others, or the
- * lockspace is enabled on some while still suspended on others.
- */
-
-void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms)
-{
- struct rq_entry *e;
- int length = ms->m_header.h_length - sizeof(struct dlm_message);
-
- e = kmalloc(sizeof(struct rq_entry) + length, GFP_NOFS);
- if (!e) {
- log_print("dlm_add_requestqueue: out of memory len %d", length);
- return;
- }
-
- e->nodeid = nodeid;
- memcpy(&e->request, ms, ms->m_header.h_length);
-
- mutex_lock(&ls->ls_requestqueue_mutex);
- list_add_tail(&e->list, &ls->ls_requestqueue);
- mutex_unlock(&ls->ls_requestqueue_mutex);
-}
-
-/*
- * Called by dlm_recoverd to process normal messages saved while recovery was
- * happening. Normal locking has been enabled before this is called. dlm_recv
- * upon receiving a message, will wait for all saved messages to be drained
- * here before processing the message it got. If a new dlm_ls_stop() arrives
- * while we're processing these saved messages, it may block trying to suspend
- * dlm_recv if dlm_recv is waiting for us in dlm_wait_requestqueue. In that
- * case, we don't abort since locking_stopped is still 0. If dlm_recv is not
- * waiting for us, then this processing may be aborted due to locking_stopped.
- */
-
-int dlm_process_requestqueue(struct dlm_ls *ls)
-{
- struct rq_entry *e;
- int error = 0;
-
- mutex_lock(&ls->ls_requestqueue_mutex);
-
- for (;;) {
- if (list_empty(&ls->ls_requestqueue)) {
- mutex_unlock(&ls->ls_requestqueue_mutex);
- error = 0;
- break;
- }
- e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list);
- mutex_unlock(&ls->ls_requestqueue_mutex);
-
- dlm_receive_message_saved(ls, &e->request);
-
- mutex_lock(&ls->ls_requestqueue_mutex);
- list_del(&e->list);
- kfree(e);
-
- if (dlm_locking_stopped(ls)) {
- log_debug(ls, "process_requestqueue abort running");
- mutex_unlock(&ls->ls_requestqueue_mutex);
- error = -EINTR;
- break;
- }
- schedule();
- }
-
- return error;
-}
-
-/*
- * After recovery is done, locking is resumed and dlm_recoverd takes all the
- * saved requests and processes them as they would have been by dlm_recv. At
- * the same time, dlm_recv will start receiving new requests from remote nodes.
- * We want to delay dlm_recv processing new requests until dlm_recoverd has
- * finished processing the old saved requests. We don't check for locking
- * stopped here because dlm_ls_stop won't stop locking until it's suspended us
- * (dlm_recv).
- */
-
-void dlm_wait_requestqueue(struct dlm_ls *ls)
-{
- for (;;) {
- mutex_lock(&ls->ls_requestqueue_mutex);
- if (list_empty(&ls->ls_requestqueue))
- break;
- mutex_unlock(&ls->ls_requestqueue_mutex);
- schedule();
- }
- mutex_unlock(&ls->ls_requestqueue_mutex);
-}
-
-static int purge_request(struct dlm_ls *ls, struct dlm_message *ms, int nodeid)
-{
- uint32_t type = ms->m_type;
-
- /* the ls is being cleaned up and freed by release_lockspace */
- if (!ls->ls_count)
- return 1;
-
- if (dlm_is_removed(ls, nodeid))
- return 1;
-
- /* directory operations are always purged because the directory is
- always rebuilt during recovery and the lookups resent */
-
- if (type == DLM_MSG_REMOVE ||
- type == DLM_MSG_LOOKUP ||
- type == DLM_MSG_LOOKUP_REPLY)
- return 1;
-
- if (!dlm_no_directory(ls))
- return 0;
-
- /* with no directory, the master is likely to change as a part of
- recovery; requests to/from the defunct master need to be purged */
-
- switch (type) {
- case DLM_MSG_REQUEST:
- case DLM_MSG_CONVERT:
- case DLM_MSG_UNLOCK:
- case DLM_MSG_CANCEL:
- /* we're no longer the master of this resource, the sender
- will resend to the new master (see waiter_needs_recovery) */
-
- if (dlm_hash2nodeid(ls, ms->m_hash) != dlm_our_nodeid())
- return 1;
- break;
-
- case DLM_MSG_REQUEST_REPLY:
- case DLM_MSG_CONVERT_REPLY:
- case DLM_MSG_UNLOCK_REPLY:
- case DLM_MSG_CANCEL_REPLY:
- case DLM_MSG_GRANT:
- /* this reply is from the former master of the resource,
- we'll resend to the new master if needed */
-
- if (dlm_hash2nodeid(ls, ms->m_hash) != nodeid)
- return 1;
- break;
- }
-
- return 0;
-}
-
-void dlm_purge_requestqueue(struct dlm_ls *ls)
-{
- struct dlm_message *ms;
- struct rq_entry *e, *safe;
-
- mutex_lock(&ls->ls_requestqueue_mutex);
- list_for_each_entry_safe(e, safe, &ls->ls_requestqueue, list) {
- ms = &e->request;
-
- if (purge_request(ls, ms, e->nodeid)) {
- list_del(&e->list);
- kfree(e);
- }
- }
- mutex_unlock(&ls->ls_requestqueue_mutex);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/requestqueue.h b/ANDROID_3.4.5/fs/dlm/requestqueue.h
deleted file mode 100644
index 10ce449b..00000000
--- a/ANDROID_3.4.5/fs/dlm/requestqueue.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005-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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __REQUESTQUEUE_DOT_H__
-#define __REQUESTQUEUE_DOT_H__
-
-void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms);
-int dlm_process_requestqueue(struct dlm_ls *ls);
-void dlm_wait_requestqueue(struct dlm_ls *ls);
-void dlm_purge_requestqueue(struct dlm_ls *ls);
-
-#endif
-
diff --git a/ANDROID_3.4.5/fs/dlm/user.c b/ANDROID_3.4.5/fs/dlm/user.c
deleted file mode 100644
index eb4ed9ba..00000000
--- a/ANDROID_3.4.5/fs/dlm/user.c
+++ /dev/null
@@ -1,1012 +0,0 @@
-/*
- * Copyright (C) 2006-2010 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 <linux/miscdevice.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/module.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/signal.h>
-#include <linux/spinlock.h>
-#include <linux/dlm.h>
-#include <linux/dlm_device.h>
-#include <linux/slab.h>
-
-#include "dlm_internal.h"
-#include "lockspace.h"
-#include "lock.h"
-#include "lvb_table.h"
-#include "user.h"
-#include "ast.h"
-
-static const char name_prefix[] = "dlm";
-static const struct file_operations device_fops;
-static atomic_t dlm_monitor_opened;
-static int dlm_monitor_unused = 1;
-
-#ifdef CONFIG_COMPAT
-
-struct dlm_lock_params32 {
- __u8 mode;
- __u8 namelen;
- __u16 unused;
- __u32 flags;
- __u32 lkid;
- __u32 parent;
- __u64 xid;
- __u64 timeout;
- __u32 castparam;
- __u32 castaddr;
- __u32 bastparam;
- __u32 bastaddr;
- __u32 lksb;
- char lvb[DLM_USER_LVB_LEN];
- char name[0];
-};
-
-struct dlm_write_request32 {
- __u32 version[3];
- __u8 cmd;
- __u8 is64bit;
- __u8 unused[2];
-
- union {
- struct dlm_lock_params32 lock;
- struct dlm_lspace_params lspace;
- struct dlm_purge_params purge;
- } i;
-};
-
-struct dlm_lksb32 {
- __u32 sb_status;
- __u32 sb_lkid;
- __u8 sb_flags;
- __u32 sb_lvbptr;
-};
-
-struct dlm_lock_result32 {
- __u32 version[3];
- __u32 length;
- __u32 user_astaddr;
- __u32 user_astparam;
- __u32 user_lksb;
- struct dlm_lksb32 lksb;
- __u8 bast_mode;
- __u8 unused[3];
- /* Offsets may be zero if no data is present */
- __u32 lvb_offset;
-};
-
-static void compat_input(struct dlm_write_request *kb,
- struct dlm_write_request32 *kb32,
- int namelen)
-{
- kb->version[0] = kb32->version[0];
- kb->version[1] = kb32->version[1];
- kb->version[2] = kb32->version[2];
-
- kb->cmd = kb32->cmd;
- kb->is64bit = kb32->is64bit;
- if (kb->cmd == DLM_USER_CREATE_LOCKSPACE ||
- kb->cmd == DLM_USER_REMOVE_LOCKSPACE) {
- kb->i.lspace.flags = kb32->i.lspace.flags;
- kb->i.lspace.minor = kb32->i.lspace.minor;
- memcpy(kb->i.lspace.name, kb32->i.lspace.name, namelen);
- } else if (kb->cmd == DLM_USER_PURGE) {
- kb->i.purge.nodeid = kb32->i.purge.nodeid;
- kb->i.purge.pid = kb32->i.purge.pid;
- } else {
- kb->i.lock.mode = kb32->i.lock.mode;
- kb->i.lock.namelen = kb32->i.lock.namelen;
- kb->i.lock.flags = kb32->i.lock.flags;
- kb->i.lock.lkid = kb32->i.lock.lkid;
- kb->i.lock.parent = kb32->i.lock.parent;
- kb->i.lock.xid = kb32->i.lock.xid;
- kb->i.lock.timeout = kb32->i.lock.timeout;
- kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
- kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
- kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
- kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr;
- kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb;
- memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN);
- memcpy(kb->i.lock.name, kb32->i.lock.name, namelen);
- }
-}
-
-static void compat_output(struct dlm_lock_result *res,
- struct dlm_lock_result32 *res32)
-{
- res32->version[0] = res->version[0];
- res32->version[1] = res->version[1];
- res32->version[2] = res->version[2];
-
- res32->user_astaddr = (__u32)(long)res->user_astaddr;
- res32->user_astparam = (__u32)(long)res->user_astparam;
- res32->user_lksb = (__u32)(long)res->user_lksb;
- res32->bast_mode = res->bast_mode;
-
- res32->lvb_offset = res->lvb_offset;
- res32->length = res->length;
-
- res32->lksb.sb_status = res->lksb.sb_status;
- res32->lksb.sb_flags = res->lksb.sb_flags;
- res32->lksb.sb_lkid = res->lksb.sb_lkid;
- res32->lksb.sb_lvbptr = (__u32)(long)res->lksb.sb_lvbptr;
-}
-#endif
-
-/* Figure out if this lock is at the end of its life and no longer
- available for the application to use. The lkb still exists until
- the final ast is read. A lock becomes EOL in three situations:
- 1. a noqueue request fails with EAGAIN
- 2. an unlock completes with EUNLOCK
- 3. a cancel of a waiting request completes with ECANCEL/EDEADLK
- An EOL lock needs to be removed from the process's list of locks.
- And we can't allow any new operation on an EOL lock. This is
- not related to the lifetime of the lkb struct which is managed
- entirely by refcount. */
-
-static int lkb_is_endoflife(int mode, int status)
-{
- switch (status) {
- case -DLM_EUNLOCK:
- return 1;
- case -DLM_ECANCEL:
- case -ETIMEDOUT:
- case -EDEADLK:
- case -EAGAIN:
- if (mode == DLM_LOCK_IV)
- return 1;
- break;
- }
- return 0;
-}
-
-/* we could possibly check if the cancel of an orphan has resulted in the lkb
- being removed and then remove that lkb from the orphans list and free it */
-
-void dlm_user_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode,
- int status, uint32_t sbflags, uint64_t seq)
-{
- struct dlm_ls *ls;
- struct dlm_user_args *ua;
- struct dlm_user_proc *proc;
- int rv;
-
- if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
- return;
-
- ls = lkb->lkb_resource->res_ls;
- mutex_lock(&ls->ls_clear_proc_locks);
-
- /* If ORPHAN/DEAD flag is set, it means the process is dead so an ast
- can't be delivered. For ORPHAN's, dlm_clear_proc_locks() freed
- lkb->ua so we can't try to use it. This second check is necessary
- for cases where a completion ast is received for an operation that
- began before clear_proc_locks did its cancel/unlock. */
-
- if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
- goto out;
-
- DLM_ASSERT(lkb->lkb_ua, dlm_print_lkb(lkb););
- ua = lkb->lkb_ua;
- proc = ua->proc;
-
- if ((flags & DLM_CB_BAST) && ua->bastaddr == NULL)
- goto out;
-
- if ((flags & DLM_CB_CAST) && lkb_is_endoflife(mode, status))
- lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
-
- spin_lock(&proc->asts_spin);
-
- rv = dlm_add_lkb_callback(lkb, flags, mode, status, sbflags, seq);
- if (rv < 0) {
- spin_unlock(&proc->asts_spin);
- goto out;
- }
-
- if (list_empty(&lkb->lkb_cb_list)) {
- kref_get(&lkb->lkb_ref);
- list_add_tail(&lkb->lkb_cb_list, &proc->asts);
- wake_up_interruptible(&proc->wait);
- }
- spin_unlock(&proc->asts_spin);
-
- if (lkb->lkb_flags & DLM_IFL_ENDOFLIFE) {
- /* N.B. spin_lock locks_spin, not asts_spin */
- spin_lock(&proc->locks_spin);
- if (!list_empty(&lkb->lkb_ownqueue)) {
- list_del_init(&lkb->lkb_ownqueue);
- dlm_put_lkb(lkb);
- }
- spin_unlock(&proc->locks_spin);
- }
- out:
- mutex_unlock(&ls->ls_clear_proc_locks);
-}
-
-static int device_user_lock(struct dlm_user_proc *proc,
- struct dlm_lock_params *params)
-{
- struct dlm_ls *ls;
- struct dlm_user_args *ua;
- int error = -ENOMEM;
-
- ls = dlm_find_lockspace_local(proc->lockspace);
- if (!ls)
- return -ENOENT;
-
- if (!params->castaddr || !params->lksb) {
- error = -EINVAL;
- goto out;
- }
-
- ua = kzalloc(sizeof(struct dlm_user_args), GFP_NOFS);
- if (!ua)
- goto out;
- ua->proc = proc;
- ua->user_lksb = params->lksb;
- ua->castparam = params->castparam;
- ua->castaddr = params->castaddr;
- ua->bastparam = params->bastparam;
- ua->bastaddr = params->bastaddr;
- ua->xid = params->xid;
-
- if (params->flags & DLM_LKF_CONVERT)
- error = dlm_user_convert(ls, ua,
- params->mode, params->flags,
- params->lkid, params->lvb,
- (unsigned long) params->timeout);
- else {
- error = dlm_user_request(ls, ua,
- params->mode, params->flags,
- params->name, params->namelen,
- (unsigned long) params->timeout);
- if (!error)
- error = ua->lksb.sb_lkid;
- }
- out:
- dlm_put_lockspace(ls);
- return error;
-}
-
-static int device_user_unlock(struct dlm_user_proc *proc,
- struct dlm_lock_params *params)
-{
- struct dlm_ls *ls;
- struct dlm_user_args *ua;
- int error = -ENOMEM;
-
- ls = dlm_find_lockspace_local(proc->lockspace);
- if (!ls)
- return -ENOENT;
-
- ua = kzalloc(sizeof(struct dlm_user_args), GFP_NOFS);
- if (!ua)
- goto out;
- ua->proc = proc;
- ua->user_lksb = params->lksb;
- ua->castparam = params->castparam;
- ua->castaddr = params->castaddr;
-
- if (params->flags & DLM_LKF_CANCEL)
- error = dlm_user_cancel(ls, ua, params->flags, params->lkid);
- else
- error = dlm_user_unlock(ls, ua, params->flags, params->lkid,
- params->lvb);
- out:
- dlm_put_lockspace(ls);
- return error;
-}
-
-static int device_user_deadlock(struct dlm_user_proc *proc,
- struct dlm_lock_params *params)
-{
- struct dlm_ls *ls;
- int error;
-
- ls = dlm_find_lockspace_local(proc->lockspace);
- if (!ls)
- return -ENOENT;
-
- error = dlm_user_deadlock(ls, params->flags, params->lkid);
-
- dlm_put_lockspace(ls);
- return error;
-}
-
-static int dlm_device_register(struct dlm_ls *ls, char *name)
-{
- int error, len;
-
- /* The device is already registered. This happens when the
- lockspace is created multiple times from userspace. */
- if (ls->ls_device.name)
- return 0;
-
- error = -ENOMEM;
- len = strlen(name) + strlen(name_prefix) + 2;
- ls->ls_device.name = kzalloc(len, GFP_NOFS);
- if (!ls->ls_device.name)
- goto fail;
-
- snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix,
- name);
- ls->ls_device.fops = &device_fops;
- ls->ls_device.minor = MISC_DYNAMIC_MINOR;
-
- error = misc_register(&ls->ls_device);
- if (error) {
- kfree(ls->ls_device.name);
- }
-fail:
- return error;
-}
-
-int dlm_device_deregister(struct dlm_ls *ls)
-{
- int error;
-
- /* The device is not registered. This happens when the lockspace
- was never used from userspace, or when device_create_lockspace()
- calls dlm_release_lockspace() after the register fails. */
- if (!ls->ls_device.name)
- return 0;
-
- error = misc_deregister(&ls->ls_device);
- if (!error)
- kfree(ls->ls_device.name);
- return error;
-}
-
-static int device_user_purge(struct dlm_user_proc *proc,
- struct dlm_purge_params *params)
-{
- struct dlm_ls *ls;
- int error;
-
- ls = dlm_find_lockspace_local(proc->lockspace);
- if (!ls)
- return -ENOENT;
-
- error = dlm_user_purge(ls, proc, params->nodeid, params->pid);
-
- dlm_put_lockspace(ls);
- return error;
-}
-
-static int device_create_lockspace(struct dlm_lspace_params *params)
-{
- dlm_lockspace_t *lockspace;
- struct dlm_ls *ls;
- int error;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- error = dlm_new_lockspace(params->name, NULL, params->flags,
- DLM_USER_LVB_LEN, NULL, NULL, NULL,
- &lockspace);
- if (error)
- return error;
-
- ls = dlm_find_lockspace_local(lockspace);
- if (!ls)
- return -ENOENT;
-
- error = dlm_device_register(ls, params->name);
- dlm_put_lockspace(ls);
-
- if (error)
- dlm_release_lockspace(lockspace, 0);
- else
- error = ls->ls_device.minor;
-
- return error;
-}
-
-static int device_remove_lockspace(struct dlm_lspace_params *params)
-{
- dlm_lockspace_t *lockspace;
- struct dlm_ls *ls;
- int error, force = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- ls = dlm_find_lockspace_device(params->minor);
- if (!ls)
- return -ENOENT;
-
- if (params->flags & DLM_USER_LSFLG_FORCEFREE)
- force = 2;
-
- lockspace = ls->ls_local_handle;
- dlm_put_lockspace(ls);
-
- /* The final dlm_release_lockspace waits for references to go to
- zero, so all processes will need to close their device for the
- ls before the release will proceed. release also calls the
- device_deregister above. Converting a positive return value
- from release to zero means that userspace won't know when its
- release was the final one, but it shouldn't need to know. */
-
- error = dlm_release_lockspace(lockspace, force);
- if (error > 0)
- error = 0;
- return error;
-}
-
-/* Check the user's version matches ours */
-static int check_version(struct dlm_write_request *req)
-{
- if (req->version[0] != DLM_DEVICE_VERSION_MAJOR ||
- (req->version[0] == DLM_DEVICE_VERSION_MAJOR &&
- req->version[1] > DLM_DEVICE_VERSION_MINOR)) {
-
- printk(KERN_DEBUG "dlm: process %s (%d) version mismatch "
- "user (%d.%d.%d) kernel (%d.%d.%d)\n",
- current->comm,
- task_pid_nr(current),
- req->version[0],
- req->version[1],
- req->version[2],
- DLM_DEVICE_VERSION_MAJOR,
- DLM_DEVICE_VERSION_MINOR,
- DLM_DEVICE_VERSION_PATCH);
- return -EINVAL;
- }
- return 0;
-}
-
-/*
- * device_write
- *
- * device_user_lock
- * dlm_user_request -> request_lock
- * dlm_user_convert -> convert_lock
- *
- * device_user_unlock
- * dlm_user_unlock -> unlock_lock
- * dlm_user_cancel -> cancel_lock
- *
- * device_create_lockspace
- * dlm_new_lockspace
- *
- * device_remove_lockspace
- * dlm_release_lockspace
- */
-
-/* a write to a lockspace device is a lock or unlock request, a write
- to the control device is to create/remove a lockspace */
-
-static ssize_t device_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct dlm_user_proc *proc = file->private_data;
- struct dlm_write_request *kbuf;
- sigset_t tmpsig, allsigs;
- int error;
-
-#ifdef CONFIG_COMPAT
- if (count < sizeof(struct dlm_write_request32))
-#else
- if (count < sizeof(struct dlm_write_request))
-#endif
- return -EINVAL;
-
- kbuf = kzalloc(count + 1, GFP_NOFS);
- if (!kbuf)
- return -ENOMEM;
-
- if (copy_from_user(kbuf, buf, count)) {
- error = -EFAULT;
- goto out_free;
- }
-
- if (check_version(kbuf)) {
- error = -EBADE;
- goto out_free;
- }
-
-#ifdef CONFIG_COMPAT
- if (!kbuf->is64bit) {
- struct dlm_write_request32 *k32buf;
- int namelen = 0;
-
- if (count > sizeof(struct dlm_write_request32))
- namelen = count - sizeof(struct dlm_write_request32);
-
- k32buf = (struct dlm_write_request32 *)kbuf;
-
- /* add 1 after namelen so that the name string is terminated */
- kbuf = kzalloc(sizeof(struct dlm_write_request) + namelen + 1,
- GFP_NOFS);
- if (!kbuf) {
- kfree(k32buf);
- return -ENOMEM;
- }
-
- if (proc)
- set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
-
- compat_input(kbuf, k32buf, namelen);
- kfree(k32buf);
- }
-#endif
-
- /* do we really need this? can a write happen after a close? */
- if ((kbuf->cmd == DLM_USER_LOCK || kbuf->cmd == DLM_USER_UNLOCK) &&
- (proc && test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))) {
- error = -EINVAL;
- goto out_free;
- }
-
- sigfillset(&allsigs);
- sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
-
- error = -EINVAL;
-
- switch (kbuf->cmd)
- {
- case DLM_USER_LOCK:
- if (!proc) {
- log_print("no locking on control device");
- goto out_sig;
- }
- error = device_user_lock(proc, &kbuf->i.lock);
- break;
-
- case DLM_USER_UNLOCK:
- if (!proc) {
- log_print("no locking on control device");
- goto out_sig;
- }
- error = device_user_unlock(proc, &kbuf->i.lock);
- break;
-
- case DLM_USER_DEADLOCK:
- if (!proc) {
- log_print("no locking on control device");
- goto out_sig;
- }
- error = device_user_deadlock(proc, &kbuf->i.lock);
- break;
-
- case DLM_USER_CREATE_LOCKSPACE:
- if (proc) {
- log_print("create/remove only on control device");
- goto out_sig;
- }
- error = device_create_lockspace(&kbuf->i.lspace);
- break;
-
- case DLM_USER_REMOVE_LOCKSPACE:
- if (proc) {
- log_print("create/remove only on control device");
- goto out_sig;
- }
- error = device_remove_lockspace(&kbuf->i.lspace);
- break;
-
- case DLM_USER_PURGE:
- if (!proc) {
- log_print("no locking on control device");
- goto out_sig;
- }
- error = device_user_purge(proc, &kbuf->i.purge);
- break;
-
- default:
- log_print("Unknown command passed to DLM device : %d\n",
- kbuf->cmd);
- }
-
- out_sig:
- sigprocmask(SIG_SETMASK, &tmpsig, NULL);
- out_free:
- kfree(kbuf);
- return error;
-}
-
-/* Every process that opens the lockspace device has its own "proc" structure
- hanging off the open file that's used to keep track of locks owned by the
- process and asts that need to be delivered to the process. */
-
-static int device_open(struct inode *inode, struct file *file)
-{
- struct dlm_user_proc *proc;
- struct dlm_ls *ls;
-
- ls = dlm_find_lockspace_device(iminor(inode));
- if (!ls)
- return -ENOENT;
-
- proc = kzalloc(sizeof(struct dlm_user_proc), GFP_NOFS);
- if (!proc) {
- dlm_put_lockspace(ls);
- return -ENOMEM;
- }
-
- proc->lockspace = ls->ls_local_handle;
- INIT_LIST_HEAD(&proc->asts);
- INIT_LIST_HEAD(&proc->locks);
- INIT_LIST_HEAD(&proc->unlocking);
- spin_lock_init(&proc->asts_spin);
- spin_lock_init(&proc->locks_spin);
- init_waitqueue_head(&proc->wait);
- file->private_data = proc;
-
- return 0;
-}
-
-static int device_close(struct inode *inode, struct file *file)
-{
- struct dlm_user_proc *proc = file->private_data;
- struct dlm_ls *ls;
- sigset_t tmpsig, allsigs;
-
- ls = dlm_find_lockspace_local(proc->lockspace);
- if (!ls)
- return -ENOENT;
-
- sigfillset(&allsigs);
- sigprocmask(SIG_BLOCK, &allsigs, &tmpsig);
-
- set_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags);
-
- dlm_clear_proc_locks(ls, proc);
-
- /* at this point no more lkb's should exist for this lockspace,
- so there's no chance of dlm_user_add_ast() being called and
- looking for lkb->ua->proc */
-
- kfree(proc);
- file->private_data = NULL;
-
- dlm_put_lockspace(ls);
- dlm_put_lockspace(ls); /* for the find in device_open() */
-
- /* FIXME: AUTOFREE: if this ls is no longer used do
- device_remove_lockspace() */
-
- sigprocmask(SIG_SETMASK, &tmpsig, NULL);
- recalc_sigpending();
-
- return 0;
-}
-
-static int copy_result_to_user(struct dlm_user_args *ua, int compat,
- uint32_t flags, int mode, int copy_lvb,
- char __user *buf, size_t count)
-{
-#ifdef CONFIG_COMPAT
- struct dlm_lock_result32 result32;
-#endif
- struct dlm_lock_result result;
- void *resultptr;
- int error=0;
- int len;
- int struct_len;
-
- memset(&result, 0, sizeof(struct dlm_lock_result));
- result.version[0] = DLM_DEVICE_VERSION_MAJOR;
- result.version[1] = DLM_DEVICE_VERSION_MINOR;
- result.version[2] = DLM_DEVICE_VERSION_PATCH;
- memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
- result.user_lksb = ua->user_lksb;
-
- /* FIXME: dlm1 provides for the user's bastparam/addr to not be updated
- in a conversion unless the conversion is successful. See code
- in dlm_user_convert() for updating ua from ua_tmp. OpenVMS, though,
- notes that a new blocking AST address and parameter are set even if
- the conversion fails, so maybe we should just do that. */
-
- if (flags & DLM_CB_BAST) {
- result.user_astaddr = ua->bastaddr;
- result.user_astparam = ua->bastparam;
- result.bast_mode = mode;
- } else {
- result.user_astaddr = ua->castaddr;
- result.user_astparam = ua->castparam;
- }
-
-#ifdef CONFIG_COMPAT
- if (compat)
- len = sizeof(struct dlm_lock_result32);
- else
-#endif
- len = sizeof(struct dlm_lock_result);
- struct_len = len;
-
- /* copy lvb to userspace if there is one, it's been updated, and
- the user buffer has space for it */
-
- if (copy_lvb && ua->lksb.sb_lvbptr && count >= len + DLM_USER_LVB_LEN) {
- if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
- DLM_USER_LVB_LEN)) {
- error = -EFAULT;
- goto out;
- }
-
- result.lvb_offset = len;
- len += DLM_USER_LVB_LEN;
- }
-
- result.length = len;
- resultptr = &result;
-#ifdef CONFIG_COMPAT
- if (compat) {
- compat_output(&result, &result32);
- resultptr = &result32;
- }
-#endif
-
- if (copy_to_user(buf, resultptr, struct_len))
- error = -EFAULT;
- else
- error = len;
- out:
- return error;
-}
-
-static int copy_version_to_user(char __user *buf, size_t count)
-{
- struct dlm_device_version ver;
-
- memset(&ver, 0, sizeof(struct dlm_device_version));
- ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
- ver.version[1] = DLM_DEVICE_VERSION_MINOR;
- ver.version[2] = DLM_DEVICE_VERSION_PATCH;
-
- if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
- return -EFAULT;
- return sizeof(struct dlm_device_version);
-}
-
-/* a read returns a single ast described in a struct dlm_lock_result */
-
-static ssize_t device_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- struct dlm_user_proc *proc = file->private_data;
- struct dlm_lkb *lkb;
- DECLARE_WAITQUEUE(wait, current);
- struct dlm_callback cb;
- int rv, resid, copy_lvb = 0;
-
- if (count == sizeof(struct dlm_device_version)) {
- rv = copy_version_to_user(buf, count);
- return rv;
- }
-
- if (!proc) {
- log_print("non-version read from control device %zu", count);
- return -EINVAL;
- }
-
-#ifdef CONFIG_COMPAT
- if (count < sizeof(struct dlm_lock_result32))
-#else
- if (count < sizeof(struct dlm_lock_result))
-#endif
- return -EINVAL;
-
- try_another:
-
- /* do we really need this? can a read happen after a close? */
- if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
- return -EINVAL;
-
- spin_lock(&proc->asts_spin);
- if (list_empty(&proc->asts)) {
- if (file->f_flags & O_NONBLOCK) {
- spin_unlock(&proc->asts_spin);
- return -EAGAIN;
- }
-
- add_wait_queue(&proc->wait, &wait);
-
- repeat:
- set_current_state(TASK_INTERRUPTIBLE);
- if (list_empty(&proc->asts) && !signal_pending(current)) {
- spin_unlock(&proc->asts_spin);
- schedule();
- spin_lock(&proc->asts_spin);
- goto repeat;
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&proc->wait, &wait);
-
- if (signal_pending(current)) {
- spin_unlock(&proc->asts_spin);
- return -ERESTARTSYS;
- }
- }
-
- /* if we empty lkb_callbacks, we don't want to unlock the spinlock
- without removing lkb_cb_list; so empty lkb_cb_list is always
- consistent with empty lkb_callbacks */
-
- lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_cb_list);
-
- rv = dlm_rem_lkb_callback(lkb->lkb_resource->res_ls, lkb, &cb, &resid);
- if (rv < 0) {
- /* this shouldn't happen; lkb should have been removed from
- list when resid was zero */
- log_print("dlm_rem_lkb_callback empty %x", lkb->lkb_id);
- list_del_init(&lkb->lkb_cb_list);
- spin_unlock(&proc->asts_spin);
- /* removes ref for proc->asts, may cause lkb to be freed */
- dlm_put_lkb(lkb);
- goto try_another;
- }
- if (!resid)
- list_del_init(&lkb->lkb_cb_list);
- spin_unlock(&proc->asts_spin);
-
- if (cb.flags & DLM_CB_SKIP) {
- /* removes ref for proc->asts, may cause lkb to be freed */
- if (!resid)
- dlm_put_lkb(lkb);
- goto try_another;
- }
-
- if (cb.flags & DLM_CB_CAST) {
- int old_mode, new_mode;
-
- old_mode = lkb->lkb_last_cast.mode;
- new_mode = cb.mode;
-
- if (!cb.sb_status && lkb->lkb_lksb->sb_lvbptr &&
- dlm_lvb_operations[old_mode + 1][new_mode + 1])
- copy_lvb = 1;
-
- lkb->lkb_lksb->sb_status = cb.sb_status;
- lkb->lkb_lksb->sb_flags = cb.sb_flags;
- }
-
- rv = copy_result_to_user(lkb->lkb_ua,
- test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
- cb.flags, cb.mode, copy_lvb, buf, count);
-
- /* removes ref for proc->asts, may cause lkb to be freed */
- if (!resid)
- dlm_put_lkb(lkb);
-
- return rv;
-}
-
-static unsigned int device_poll(struct file *file, poll_table *wait)
-{
- struct dlm_user_proc *proc = file->private_data;
-
- poll_wait(file, &proc->wait, wait);
-
- spin_lock(&proc->asts_spin);
- if (!list_empty(&proc->asts)) {
- spin_unlock(&proc->asts_spin);
- return POLLIN | POLLRDNORM;
- }
- spin_unlock(&proc->asts_spin);
- return 0;
-}
-
-int dlm_user_daemon_available(void)
-{
- /* dlm_controld hasn't started (or, has started, but not
- properly populated configfs) */
-
- if (!dlm_our_nodeid())
- return 0;
-
- /* This is to deal with versions of dlm_controld that don't
- know about the monitor device. We assume that if the
- dlm_controld was started (above), but the monitor device
- was never opened, that it's an old version. dlm_controld
- should open the monitor device before populating configfs. */
-
- if (dlm_monitor_unused)
- return 1;
-
- return atomic_read(&dlm_monitor_opened) ? 1 : 0;
-}
-
-static int ctl_device_open(struct inode *inode, struct file *file)
-{
- file->private_data = NULL;
- return 0;
-}
-
-static int ctl_device_close(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-static int monitor_device_open(struct inode *inode, struct file *file)
-{
- atomic_inc(&dlm_monitor_opened);
- dlm_monitor_unused = 0;
- return 0;
-}
-
-static int monitor_device_close(struct inode *inode, struct file *file)
-{
- if (atomic_dec_and_test(&dlm_monitor_opened))
- dlm_stop_lockspaces();
- return 0;
-}
-
-static const struct file_operations device_fops = {
- .open = device_open,
- .release = device_close,
- .read = device_read,
- .write = device_write,
- .poll = device_poll,
- .owner = THIS_MODULE,
- .llseek = noop_llseek,
-};
-
-static const struct file_operations ctl_device_fops = {
- .open = ctl_device_open,
- .release = ctl_device_close,
- .read = device_read,
- .write = device_write,
- .owner = THIS_MODULE,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice ctl_device = {
- .name = "dlm-control",
- .fops = &ctl_device_fops,
- .minor = MISC_DYNAMIC_MINOR,
-};
-
-static const struct file_operations monitor_device_fops = {
- .open = monitor_device_open,
- .release = monitor_device_close,
- .owner = THIS_MODULE,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice monitor_device = {
- .name = "dlm-monitor",
- .fops = &monitor_device_fops,
- .minor = MISC_DYNAMIC_MINOR,
-};
-
-int __init dlm_user_init(void)
-{
- int error;
-
- atomic_set(&dlm_monitor_opened, 0);
-
- error = misc_register(&ctl_device);
- if (error) {
- log_print("misc_register failed for control device");
- goto out;
- }
-
- error = misc_register(&monitor_device);
- if (error) {
- log_print("misc_register failed for monitor device");
- misc_deregister(&ctl_device);
- }
- out:
- return error;
-}
-
-void dlm_user_exit(void)
-{
- misc_deregister(&ctl_device);
- misc_deregister(&monitor_device);
-}
-
diff --git a/ANDROID_3.4.5/fs/dlm/user.h b/ANDROID_3.4.5/fs/dlm/user.h
deleted file mode 100644
index 00499ab8..00000000
--- a/ANDROID_3.4.5/fs/dlm/user.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2006-2010 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.
- */
-
-#ifndef __USER_DOT_H__
-#define __USER_DOT_H__
-
-void dlm_user_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode,
- int status, uint32_t sbflags, uint64_t seq);
-int dlm_user_init(void);
-void dlm_user_exit(void);
-int dlm_device_deregister(struct dlm_ls *ls);
-int dlm_user_daemon_available(void);
-
-#endif
diff --git a/ANDROID_3.4.5/fs/dlm/util.c b/ANDROID_3.4.5/fs/dlm/util.c
deleted file mode 100644
index e36520af..00000000
--- a/ANDROID_3.4.5/fs/dlm/util.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005-2008 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 "rcom.h"
-#include "util.h"
-
-#define DLM_ERRNO_EDEADLK 35
-#define DLM_ERRNO_EBADR 53
-#define DLM_ERRNO_EBADSLT 57
-#define DLM_ERRNO_EPROTO 71
-#define DLM_ERRNO_EOPNOTSUPP 95
-#define DLM_ERRNO_ETIMEDOUT 110
-#define DLM_ERRNO_EINPROGRESS 115
-
-static void header_out(struct dlm_header *hd)
-{
- hd->h_version = cpu_to_le32(hd->h_version);
- hd->h_lockspace = cpu_to_le32(hd->h_lockspace);
- hd->h_nodeid = cpu_to_le32(hd->h_nodeid);
- hd->h_length = cpu_to_le16(hd->h_length);
-}
-
-static void header_in(struct dlm_header *hd)
-{
- hd->h_version = le32_to_cpu(hd->h_version);
- hd->h_lockspace = le32_to_cpu(hd->h_lockspace);
- hd->h_nodeid = le32_to_cpu(hd->h_nodeid);
- hd->h_length = le16_to_cpu(hd->h_length);
-}
-
-/* higher errno values are inconsistent across architectures, so select
- one set of values for on the wire */
-
-static int to_dlm_errno(int err)
-{
- switch (err) {
- case -EDEADLK:
- return -DLM_ERRNO_EDEADLK;
- case -EBADR:
- return -DLM_ERRNO_EBADR;
- case -EBADSLT:
- return -DLM_ERRNO_EBADSLT;
- case -EPROTO:
- return -DLM_ERRNO_EPROTO;
- case -EOPNOTSUPP:
- return -DLM_ERRNO_EOPNOTSUPP;
- case -ETIMEDOUT:
- return -DLM_ERRNO_ETIMEDOUT;
- case -EINPROGRESS:
- return -DLM_ERRNO_EINPROGRESS;
- }
- return err;
-}
-
-static int from_dlm_errno(int err)
-{
- switch (err) {
- case -DLM_ERRNO_EDEADLK:
- return -EDEADLK;
- case -DLM_ERRNO_EBADR:
- return -EBADR;
- case -DLM_ERRNO_EBADSLT:
- return -EBADSLT;
- case -DLM_ERRNO_EPROTO:
- return -EPROTO;
- case -DLM_ERRNO_EOPNOTSUPP:
- return -EOPNOTSUPP;
- case -DLM_ERRNO_ETIMEDOUT:
- return -ETIMEDOUT;
- case -DLM_ERRNO_EINPROGRESS:
- return -EINPROGRESS;
- }
- return err;
-}
-
-void dlm_message_out(struct dlm_message *ms)
-{
- header_out(&ms->m_header);
-
- ms->m_type = cpu_to_le32(ms->m_type);
- ms->m_nodeid = cpu_to_le32(ms->m_nodeid);
- ms->m_pid = cpu_to_le32(ms->m_pid);
- ms->m_lkid = cpu_to_le32(ms->m_lkid);
- ms->m_remid = cpu_to_le32(ms->m_remid);
- ms->m_parent_lkid = cpu_to_le32(ms->m_parent_lkid);
- ms->m_parent_remid = cpu_to_le32(ms->m_parent_remid);
- ms->m_exflags = cpu_to_le32(ms->m_exflags);
- ms->m_sbflags = cpu_to_le32(ms->m_sbflags);
- ms->m_flags = cpu_to_le32(ms->m_flags);
- ms->m_lvbseq = cpu_to_le32(ms->m_lvbseq);
- ms->m_hash = cpu_to_le32(ms->m_hash);
- ms->m_status = cpu_to_le32(ms->m_status);
- ms->m_grmode = cpu_to_le32(ms->m_grmode);
- ms->m_rqmode = cpu_to_le32(ms->m_rqmode);
- ms->m_bastmode = cpu_to_le32(ms->m_bastmode);
- ms->m_asts = cpu_to_le32(ms->m_asts);
- ms->m_result = cpu_to_le32(to_dlm_errno(ms->m_result));
-}
-
-void dlm_message_in(struct dlm_message *ms)
-{
- header_in(&ms->m_header);
-
- ms->m_type = le32_to_cpu(ms->m_type);
- ms->m_nodeid = le32_to_cpu(ms->m_nodeid);
- ms->m_pid = le32_to_cpu(ms->m_pid);
- ms->m_lkid = le32_to_cpu(ms->m_lkid);
- ms->m_remid = le32_to_cpu(ms->m_remid);
- ms->m_parent_lkid = le32_to_cpu(ms->m_parent_lkid);
- ms->m_parent_remid = le32_to_cpu(ms->m_parent_remid);
- ms->m_exflags = le32_to_cpu(ms->m_exflags);
- ms->m_sbflags = le32_to_cpu(ms->m_sbflags);
- ms->m_flags = le32_to_cpu(ms->m_flags);
- ms->m_lvbseq = le32_to_cpu(ms->m_lvbseq);
- ms->m_hash = le32_to_cpu(ms->m_hash);
- ms->m_status = le32_to_cpu(ms->m_status);
- ms->m_grmode = le32_to_cpu(ms->m_grmode);
- ms->m_rqmode = le32_to_cpu(ms->m_rqmode);
- ms->m_bastmode = le32_to_cpu(ms->m_bastmode);
- ms->m_asts = le32_to_cpu(ms->m_asts);
- ms->m_result = from_dlm_errno(le32_to_cpu(ms->m_result));
-}
-
-void dlm_rcom_out(struct dlm_rcom *rc)
-{
- header_out(&rc->rc_header);
-
- rc->rc_type = cpu_to_le32(rc->rc_type);
- rc->rc_result = cpu_to_le32(rc->rc_result);
- rc->rc_id = cpu_to_le64(rc->rc_id);
- rc->rc_seq = cpu_to_le64(rc->rc_seq);
- rc->rc_seq_reply = cpu_to_le64(rc->rc_seq_reply);
-}
-
-void dlm_rcom_in(struct dlm_rcom *rc)
-{
- header_in(&rc->rc_header);
-
- rc->rc_type = le32_to_cpu(rc->rc_type);
- rc->rc_result = le32_to_cpu(rc->rc_result);
- rc->rc_id = le64_to_cpu(rc->rc_id);
- rc->rc_seq = le64_to_cpu(rc->rc_seq);
- rc->rc_seq_reply = le64_to_cpu(rc->rc_seq_reply);
-}
diff --git a/ANDROID_3.4.5/fs/dlm/util.h b/ANDROID_3.4.5/fs/dlm/util.h
deleted file mode 100644
index 2b259151..00000000
--- a/ANDROID_3.4.5/fs/dlm/util.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/******************************************************************************
-*******************************************************************************
-**
-** Copyright (C) 2005 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.
-**
-*******************************************************************************
-******************************************************************************/
-
-#ifndef __UTIL_DOT_H__
-#define __UTIL_DOT_H__
-
-void dlm_message_out(struct dlm_message *ms);
-void dlm_message_in(struct dlm_message *ms);
-void dlm_rcom_out(struct dlm_rcom *rc);
-void dlm_rcom_in(struct dlm_rcom *rc);
-
-#endif
-