Commit e675349e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2: (64 commits)
  ocfs2/net: Add debug interface to o2net
  ocfs2: Only build ocfs2/dlm with the o2cb stack module
  ocfs2/cluster: Get rid of arguments to the timeout routines
  ocfs2: Put tree in MAINTAINERS
  ocfs2: Use BUG_ON
  ocfs2: Convert ocfs2 over to unlocked_ioctl
  ocfs2: Improve rename locking
  fs/ocfs2/aops.c: test for IS_ERR rather than 0
  ocfs2: Add inode stealing for ocfs2_reserve_new_inode
  ocfs2: Add ac_alloc_slot in ocfs2_alloc_context
  ocfs2: Add a new parameter for ocfs2_reserve_suballoc_bits
  ocfs2: Enable cross extent block merge.
  ocfs2: Add support for cross extent block
  ocfs2: Move /sys/o2cb to /sys/fs/o2cb
  sysfs: Allow removal of symlinks in the sysfs root
  ocfs2:  Reconnect after idle time out.
  ocfs2/dlm: Cleanup lockres print
  ocfs2/dlm: Fix lockname in lockres print function
  ocfs2/dlm: Move dlm_print_one_mle() from dlmmaster.c to dlmdebug.c
  ocfs2/dlm: Dumps the purgelist into a debugfs file
  ...
parents ef38ff9d 2309e9e0
What: /sys/o2cb symlink
Date: Dec 2005
KernelVersion: 2.6.16
Contact: ocfs2-devel@oss.oracle.com
Description: This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink will
be removed when new versions of ocfs2-tools which know to look
in /sys/fs/o2cb are sufficiently prevalent. Don't code new
software to look here, it should try /sys/fs/o2cb instead.
See Documentation/ABI/stable/o2cb for more information on usage.
Users: ocfs2-tools. It's sufficient to mail proposed changes to
ocfs2-devel@oss.oracle.com.
What: /sys/fs/o2cb/ (was /sys/o2cb)
Date: Dec 2005
KernelVersion: 2.6.16
Contact: ocfs2-devel@oss.oracle.com
Description: Ocfs2-tools looks at 'interface-revision' for versioning
information. Each logmask/ file controls a set of debug prints
and can be written into with the strings "allow", "deny", or
"off". Reading the file returns the current state.
Users: ocfs2-tools. It's sufficient to mail proposed changes to
ocfs2-devel@oss.oracle.com.
What: /sys/fs/ocfs2/
Date: April 2008
Contact: ocfs2-devel@oss.oracle.com
Description:
The /sys/fs/ocfs2 directory contains knobs used by the
ocfs2-tools to interact with the filesystem.
What: /sys/fs/ocfs2/max_locking_protocol
Date: April 2008
Contact: ocfs2-devel@oss.oracle.com
Description:
The /sys/fs/ocfs2/max_locking_protocol file displays version
of ocfs2 locking supported by the filesystem. This version
covers how ocfs2 uses distributed locking between cluster
nodes.
The protocol version has a major and minor number. Two
cluster nodes can interoperate if they have an identical
major number and an overlapping minor number - thus,
a node with version 1.10 can interoperate with a node
sporting version 1.8, as long as both use the 1.8 protocol.
Reading from this file returns a single line, the major
number and minor number joined by a period, eg "1.10".
This file is read-only. The value is compiled into the
driver.
What: /sys/fs/ocfs2/loaded_cluster_plugins
Date: April 2008
Contact: ocfs2-devel@oss.oracle.com
Description:
The /sys/fs/ocfs2/loaded_cluster_plugins file describes
the available plugins to support ocfs2 cluster operation.
A cluster plugin is required to use ocfs2 in a cluster.
There are currently two available plugins:
* 'o2cb' - The classic o2cb cluster stack that ocfs2 has
used since its inception.
* 'user' - A plugin supporting userspace cluster software
in conjunction with fs/dlm.
Reading from this file returns the names of all loaded
plugins, one per line.
This file is read-only. Its contents may change as
plugins are loaded or removed.
What: /sys/fs/ocfs2/active_cluster_plugin
Date: April 2008
Contact: ocfs2-devel@oss.oracle.com
Description:
The /sys/fs/ocfs2/active_cluster_plugin displays which
cluster plugin is currently in use by the filesystem.
The active plugin will appear in the loaded_cluster_plugins
file as well. Only one plugin can be used at a time.
Reading from this file returns the name of the active plugin
on a single line.
This file is read-only. Which plugin is active depends on
the cluster stack in use. The contents may change
when all filesystems are unmounted and the cluster stack
is changed.
What: /sys/fs/ocfs2/cluster_stack
Date: April 2008
Contact: ocfs2-devel@oss.oracle.com
Description:
The /sys/fs/ocfs2/cluster_stack file contains the name
of current ocfs2 cluster stack. This value is set by
userspace tools when bringing the cluster stack online.
Cluster stack names are 4 characters in length.
When the 'o2cb' cluster stack is used, the 'o2cb' cluster
plugin is active. All other cluster stacks use the 'user'
cluster plugin.
Reading from this file returns the name of the current
cluster stack on a single line.
Writing a new stack name to this file changes the current
cluster stack unless there are mounted ocfs2 filesystems.
If there are mounted filesystems, attempts to change the
stack return an error.
Users:
ocfs2-tools <ocfs2-tools-devel@oss.oracle.com>
...@@ -318,3 +318,13 @@ Why: Not used in-tree. The current out-of-tree users used it to ...@@ -318,3 +318,13 @@ Why: Not used in-tree. The current out-of-tree users used it to
code / infrastructure should be in the kernel and not in some code / infrastructure should be in the kernel and not in some
out-of-tree driver. out-of-tree driver.
Who: Thomas Gleixner <tglx@linutronix.de> Who: Thomas Gleixner <tglx@linutronix.de>
---------------------------
What: /sys/o2cb symlink
When: January 2010
Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb
exists as a symlink for backwards compatibility for old versions of
ocfs2-tools. 2 years should be sufficient time to phase in new versions
which know to look in /sys/fs/o2cb.
Who: ocfs2-devel@oss.oracle.com
...@@ -2952,6 +2952,7 @@ P: Joel Becker ...@@ -2952,6 +2952,7 @@ P: Joel Becker
M: joel.becker@oracle.com M: joel.becker@oracle.com
L: ocfs2-devel@oss.oracle.com L: ocfs2-devel@oss.oracle.com
W: http://oss.oracle.com/projects/ocfs2/ W: http://oss.oracle.com/projects/ocfs2/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git
S: Supported S: Supported
OMNIKEY CARDMAN 4000 DRIVER OMNIKEY CARDMAN 4000 DRIVER
......
...@@ -444,6 +444,32 @@ config OCFS2_FS ...@@ -444,6 +444,32 @@ config OCFS2_FS
For more information on OCFS2, see the file For more information on OCFS2, see the file
<file:Documentation/filesystems/ocfs2.txt>. <file:Documentation/filesystems/ocfs2.txt>.
config OCFS2_FS_O2CB
tristate "O2CB Kernelspace Clustering"
depends on OCFS2_FS
default y
help
OCFS2 includes a simple kernelspace clustering package, the OCFS2
Cluster Base. It only requires a very small userspace component
to configure it. This comes with the standard ocfs2-tools package.
O2CB is limited to maintaining a cluster for OCFS2 file systems.
It cannot manage any other cluster applications.
It is always safe to say Y here, as the clustering method is
run-time selectable.
config OCFS2_FS_USERSPACE_CLUSTER
tristate "OCFS2 Userspace Clustering"
depends on OCFS2_FS && DLM
default y
help
This option will allow OCFS2 to use userspace clustering services
in conjunction with the DLM in fs/dlm. If you are using a
userspace cluster manager, say Y here.
It is safe to say Y, as the clustering method is run-time
selectable.
config OCFS2_DEBUG_MASKLOG config OCFS2_DEBUG_MASKLOG
bool "OCFS2 logging support" bool "OCFS2 logging support"
depends on OCFS2_FS depends on OCFS2_FS
......
...@@ -2,7 +2,12 @@ EXTRA_CFLAGS += -Ifs/ocfs2 ...@@ -2,7 +2,12 @@ EXTRA_CFLAGS += -Ifs/ocfs2
EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES
obj-$(CONFIG_OCFS2_FS) += ocfs2.o obj-$(CONFIG_OCFS2_FS) += \
ocfs2.o \
ocfs2_stackglue.o
obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_stack_o2cb.o
obj-$(CONFIG_OCFS2_FS_USERSPACE_CLUSTER) += ocfs2_stack_user.o
ocfs2-objs := \ ocfs2-objs := \
alloc.o \ alloc.o \
...@@ -31,5 +36,10 @@ ocfs2-objs := \ ...@@ -31,5 +36,10 @@ ocfs2-objs := \
uptodate.o \ uptodate.o \
ver.o ver.o
ocfs2_stackglue-objs := stackglue.o
ocfs2_stack_o2cb-objs := stack_o2cb.o
ocfs2_stack_user-objs := stack_user.o
# cluster/ is always needed when OCFS2_FS for masklog support
obj-$(CONFIG_OCFS2_FS) += cluster/ obj-$(CONFIG_OCFS2_FS) += cluster/
obj-$(CONFIG_OCFS2_FS) += dlm/ obj-$(CONFIG_OCFS2_FS_O2CB) += dlm/
This diff is collapsed.
...@@ -467,11 +467,11 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode, ...@@ -467,11 +467,11 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
unsigned to) unsigned to)
{ {
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
handle_t *handle = NULL; handle_t *handle;
int ret = 0; int ret = 0;
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
if (!handle) { if (IS_ERR(handle)) {
ret = -ENOMEM; ret = -ENOMEM;
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
...@@ -487,7 +487,7 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode, ...@@ -487,7 +487,7 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
} }
out: out:
if (ret) { if (ret) {
if (handle) if (!IS_ERR(handle))
ocfs2_commit_trans(osb, handle); ocfs2_commit_trans(osb, handle);
handle = ERR_PTR(ret); handle = ERR_PTR(ret);
} }
......
obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o
ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \ ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \
quorum.o tcp.o ver.o quorum.o tcp.o netdebug.o ver.o
This diff is collapsed.
...@@ -959,7 +959,10 @@ static int __init init_o2nm(void) ...@@ -959,7 +959,10 @@ static int __init init_o2nm(void)
cluster_print_version(); cluster_print_version();
o2hb_init(); o2hb_init();
o2net_init();
ret = o2net_init();
if (ret)
goto out;
ocfs2_table_header = register_sysctl_table(ocfs2_root_table); ocfs2_table_header = register_sysctl_table(ocfs2_root_table);
if (!ocfs2_table_header) { if (!ocfs2_table_header) {
......
...@@ -57,6 +57,7 @@ static struct kset *o2cb_kset; ...@@ -57,6 +57,7 @@ static struct kset *o2cb_kset;
void o2cb_sys_shutdown(void) void o2cb_sys_shutdown(void)
{ {
mlog_sys_shutdown(); mlog_sys_shutdown();
sysfs_remove_link(NULL, "o2cb");
kset_unregister(o2cb_kset); kset_unregister(o2cb_kset);
} }
...@@ -68,6 +69,14 @@ int o2cb_sys_init(void) ...@@ -68,6 +69,14 @@ int o2cb_sys_init(void)
if (!o2cb_kset) if (!o2cb_kset)
return -ENOMEM; return -ENOMEM;
/*
* Create this symlink for backwards compatibility with old
* versions of ocfs2-tools which look for things in /sys/o2cb.
*/
ret = sysfs_create_link(NULL, &o2cb_kset->kobj, "o2cb");
if (ret)
goto error;
ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group); ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group);
if (ret) if (ret)
goto error; goto error;
......
This diff is collapsed.
...@@ -117,4 +117,36 @@ int o2net_num_connected_peers(void); ...@@ -117,4 +117,36 @@ int o2net_num_connected_peers(void);
int o2net_init(void); int o2net_init(void);
void o2net_exit(void); void o2net_exit(void);
struct o2net_send_tracking;
struct o2net_sock_container;
#ifdef CONFIG_DEBUG_FS
int o2net_debugfs_init(void);
void o2net_debugfs_exit(void);
void o2net_debug_add_nst(struct o2net_send_tracking *nst);
void o2net_debug_del_nst(struct o2net_send_tracking *nst);
void o2net_debug_add_sc(struct o2net_sock_container *sc);
void o2net_debug_del_sc(struct o2net_sock_container *sc);
#else
static int o2net_debugfs_init(void)
{
return 0;
}
static void o2net_debugfs_exit(void)
{
}
static void o2net_debug_add_nst(struct o2net_send_tracking *nst)
{
}
static void o2net_debug_del_nst(struct o2net_send_tracking *nst)
{
}
static void o2net_debug_add_sc(struct o2net_sock_container *sc)
{
}
static void o2net_debug_del_sc(struct o2net_sock_container *sc)
{
}
#endif /* CONFIG_DEBUG_FS */
#endif /* O2CLUSTER_TCP_H */ #endif /* O2CLUSTER_TCP_H */
...@@ -95,6 +95,8 @@ struct o2net_node { ...@@ -95,6 +95,8 @@ struct o2net_node {
unsigned nn_sc_valid:1; unsigned nn_sc_valid:1;
/* if this is set tx just returns it */ /* if this is set tx just returns it */
int nn_persistent_error; int nn_persistent_error;
/* It is only set to 1 after the idle time out. */
atomic_t nn_timeout;
/* threads waiting for an sc to arrive wait on the wq for generation /* threads waiting for an sc to arrive wait on the wq for generation
* to increase. it is increased when a connecting socket succeeds * to increase. it is increased when a connecting socket succeeds
...@@ -164,7 +166,9 @@ struct o2net_sock_container { ...@@ -164,7 +166,9 @@ struct o2net_sock_container {
/* original handlers for the sockets */ /* original handlers for the sockets */
void (*sc_state_change)(struct sock *sk); void (*sc_state_change)(struct sock *sk);
void (*sc_data_ready)(struct sock *sk, int bytes); void (*sc_data_ready)(struct sock *sk, int bytes);
#ifdef CONFIG_DEBUG_FS
struct list_head sc_net_debug_item;
#endif
struct timeval sc_tv_timer; struct timeval sc_tv_timer;
struct timeval sc_tv_data_ready; struct timeval sc_tv_data_ready;
struct timeval sc_tv_advance_start; struct timeval sc_tv_advance_start;
...@@ -206,4 +210,24 @@ struct o2net_status_wait { ...@@ -206,4 +210,24 @@ struct o2net_status_wait {
struct list_head ns_node_item; struct list_head ns_node_item;
}; };
#ifdef CONFIG_DEBUG_FS
/* just for state dumps */
struct o2net_send_tracking {
struct list_head st_net_debug_item;
struct task_struct *st_task;
struct o2net_sock_container *st_sc;
u32 st_id;
u32 st_msg_type;
u32 st_msg_key;
u8 st_node;
struct timeval st_sock_time;
struct timeval st_send_time;
struct timeval st_status_time;
};
#else
struct o2net_send_tracking {
u32 dummy;
};
#endif /* CONFIG_DEBUG_FS */
#endif /* O2CLUSTER_TCP_INTERNAL_H */ #endif /* O2CLUSTER_TCP_INTERNAL_H */
EXTRA_CFLAGS += -Ifs/ocfs2 EXTRA_CFLAGS += -Ifs/ocfs2
obj-$(CONFIG_OCFS2_FS) += ocfs2_dlm.o ocfs2_dlmfs.o obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o ocfs2_dlmfs.o
ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \ ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \
dlmmaster.o dlmast.o dlmconvert.o dlmlock.o dlmunlock.o dlmver.o dlmmaster.o dlmast.o dlmconvert.o dlmlock.o dlmunlock.o dlmver.o
......
...@@ -49,6 +49,41 @@ ...@@ -49,6 +49,41 @@
/* Intended to make it easier for us to switch out hash functions */ /* Intended to make it easier for us to switch out hash functions */
#define dlm_lockid_hash(_n, _l) full_name_hash(_n, _l) #define dlm_lockid_hash(_n, _l) full_name_hash(_n, _l)
enum dlm_mle_type {
DLM_MLE_BLOCK,
DLM_MLE_MASTER,
DLM_MLE_MIGRATION
};
struct dlm_lock_name {
u8 len;
u8 name[DLM_LOCKID_NAME_MAX];
};
struct dlm_master_list_entry {
struct list_head list;
struct list_head hb_events;
struct dlm_ctxt *dlm;
spinlock_t spinlock;
wait_queue_head_t wq;
atomic_t woken;
struct kref mle_refs;
int inuse;
unsigned long maybe_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
unsigned long vote_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
unsigned long response_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
u8 master;
u8 new_master;
enum dlm_mle_type type;
struct o2hb_callback_func mle_hb_up;
struct o2hb_callback_func mle_hb_down;
union {
struct dlm_lock_resource *res;
struct dlm_lock_name name;
} u;
};
enum dlm_ast_type { enum dlm_ast_type {
DLM_AST = 0, DLM_AST = 0,
DLM_BAST, DLM_BAST,
...@@ -101,6 +136,7 @@ struct dlm_ctxt ...@@ -101,6 +136,7 @@ struct dlm_ctxt
struct list_head purge_list; struct list_head purge_list;
struct list_head pending_asts; struct list_head pending_asts;
struct list_head pending_basts; struct list_head pending_basts;
struct list_head tracking_list;
unsigned int purge_count; unsigned int purge_count;
spinlock_t spinlock; spinlock_t spinlock;
spinlock_t ast_lock; spinlock_t ast_lock;
...@@ -122,6 +158,9 @@ struct dlm_ctxt ...@@ -122,6 +158,9 @@ struct dlm_ctxt
atomic_t remote_resources; atomic_t remote_resources;
atomic_t unknown_resources; atomic_t unknown_resources;
struct dlm_debug_ctxt *dlm_debug_ctxt;
struct dentry *dlm_debugfs_subroot;
/* NOTE: Next three are protected by dlm_domain_lock */ /* NOTE: Next three are protected by dlm_domain_lock */
struct kref dlm_refs; struct kref dlm_refs;
enum dlm_ctxt_state dlm_state; enum dlm_ctxt_state dlm_state;
...@@ -270,6 +309,9 @@ struct dlm_lock_resource ...@@ -270,6 +309,9 @@ struct dlm_lock_resource
struct list_head dirty; struct list_head dirty;
struct list_head recovering; // dlm_recovery_ctxt.resources list struct list_head recovering; // dlm_recovery_ctxt.resources list
/* Added during init and removed during release */
struct list_head tracking; /* dlm->tracking_list */
/* unused lock resources have their last_used stamped and are /* unused lock resources have their last_used stamped and are
* put on a list for the dlm thread to run. */ * put on a list for the dlm thread to run. */
unsigned long last_used; unsigned long last_used;
...@@ -963,9 +1005,16 @@ static inline void __dlm_wait_on_lockres(struct dlm_lock_resource *res) ...@@ -963,9 +1005,16 @@ static inline void __dlm_wait_on_lockres(struct dlm_lock_resource *res)
DLM_LOCK_RES_MIGRATING)); DLM_LOCK_RES_MIGRATING));
} }
/* create/destroy slab caches */
int dlm_init_master_caches(void);
void dlm_destroy_master_caches(void);
int dlm_init_lock_cache(void);
void dlm_destroy_lock_cache(void);
int dlm_init_mle_cache(void); int dlm_init_mle_cache(void);
void dlm_destroy_mle_cache(void); void dlm_destroy_mle_cache(void);
void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up); void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up);
int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, int dlm_drop_lockres_ref(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res); struct dlm_lock_resource *res);
......
This diff is collapsed.
/* -*- mode: c; c-basic-offset: 8; -*-
* vim: noexpandtab sw=8 ts=8 sts=0:
*
* dlmdebug.h
*
* Copyright (C) 2008 Oracle. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*
*/
#ifndef DLMDEBUG_H
#define DLMDEBUG_H
void dlm_print_one_mle(struct dlm_master_list_entry *mle);
#ifdef CONFIG_DEBUG_FS
struct dlm_debug_ctxt {
struct kref debug_refcnt;
struct dentry *debug_state_dentry;
struct dentry *debug_lockres_dentry;
struct dentry *debug_mle_dentry;
struct dentry *debug_purgelist_dentry;
};
struct debug_buffer {
int len;
char *buf;
};
struct debug_lockres {
int dl_len;
char *dl_buf;
struct dlm_ctxt *dl_ctxt;
struct dlm_lock_resource *dl_res;
};
int dlm_debug_init(struct dlm_ctxt *dlm);
void dlm_debug_shutdown(struct dlm_ctxt *dlm);
int dlm_create_debugfs_subroot(struct dlm_ctxt *dlm);
void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm);
int dlm_create_debugfs_root(void);
void dlm_destroy_debugfs_root(void);
#else
static int dlm_debug_init(struct dlm_ctxt *dlm)
{
return 0;
}
static void dlm_debug_shutdown(struct dlm_ctxt *dlm)
{
}
static int dlm_create_debugfs_subroot(struct dlm_ctxt *dlm)
{
return 0;
}
static void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm)
{
}
static int dlm_create_debugfs_root(void)
{
return 0;
}
static void dlm_destroy_debugfs_root(void)
{
}
#endif /* CONFIG_DEBUG_FS */
#endif /* DLMDEBUG_H */
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/debugfs.h>
#include "cluster/heartbeat.h" #include "cluster/heartbeat.h"
#include "cluster/nodemanager.h" #include "cluster/nodemanager.h"
...@@ -40,8 +41,8 @@ ...@@ -40,8 +41,8 @@
#include "dlmapi.h" #include "dlmapi.h"
#include "dlmcommon.h" #include "dlmcommon.h"
#include "dlmdomain.h" #include "dlmdomain.h"
#include "dlmdebug.h"
#include "dlmver.h" #include "dlmver.h"
...@@ -298,6 +299,8 @@ static int dlm_wait_on_domain_helper(const char *domain) ...@@ -298,6 +299,8 @@ static int dlm_wait_on_domain_helper(const char *domain)
static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm) static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm)
{ {
dlm_destroy_debugfs_subroot(dlm);
if (dlm->lockres_hash) if (dlm->lockres_hash)
dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES); dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES);
...@@ -395,6 +398,7 @@ static void dlm_destroy_dlm_worker(struct dlm_ctxt *dlm) ...@@ -395,6 +398,7 @@ static void dlm_destroy_dlm_worker(struct dlm_ctxt *dlm)
static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm) static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm)
{ {
dlm_unregister_domain_handlers(dlm); dlm_unregister_domain_handlers(dlm);
dlm_debug_shutdown(dlm);
dlm_complete_thread(dlm); dlm_complete_thread(dlm);
dlm_complete_recovery_thread(dlm); dlm_complete_recovery_thread(dlm);
dlm_destroy_dlm_worker(dlm); dlm_destroy_dlm_worker(dlm);
...@@ -644,6 +648,7 @@ int dlm_shutting_down(struct dlm_ctxt *dlm) ...@@ -644,6 +648,7 @@ int dlm_shutting_down(struct dlm_ctxt *dlm)
void dlm_unregister_domain(struct dlm_ctxt *dlm) void dlm_unregister_domain(struct dlm_ctxt *dlm)
{ {
int leave = 0; int leave = 0;
struct dlm_lock_resource *res;
spin_lock(&dlm_domain_lock); spin_lock(&dlm_domain_lock);
BUG_ON(dlm->dlm_state != DLM_CTXT_JOINED); BUG_ON(dlm->dlm_state != DLM_CTXT_JOINED);
...@@ -673,6 +678,15 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm) ...@@ -673,6 +678,15 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm)
msleep(500); msleep(500);
mlog(0, "%s: more migration to do\n", dlm->name); mlog(0, "%s: more migration to do\n", dlm->name);
} }
/* This list should be empty. If not, print remaining lockres */
if (!list_empty(&dlm->tracking_list)) {
mlog(ML_ERROR, "Following lockres' are still on the "
"tracking list:\n");
list_for_each_entry(res, &dlm->tracking_list, tracking)
dlm_print_one_lock_resource(res);
}
dlm_mark_domain_leaving(dlm); dlm_mark_domain_leaving(dlm);
dlm_leave_domain(dlm); dlm_leave_domain(dlm);
dlm_complete_dlm_shutdown(dlm); dlm_complete_dlm_shutdown(dlm);
...@@ -1405,6 +1419,12 @@ static int dlm_join_domain(struct dlm_ctxt *dlm) ...@@ -1405,6 +1419,12 @@ static int dlm_join_domain(struct dlm_ctxt *dlm)
goto bail; goto bail;
} }
status = dlm_debug_init(dlm);
if (status < 0) {
mlog_errno(status);
goto bail;
}
status = dlm_launch_thread(dlm); status = dlm_launch_thread(dlm);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -1472,6 +1492,7 @@ static int dlm_join_domain(struct dlm_ctxt *dlm) ...@@ -1472,6 +1492,7 @@ static int dlm_join_domain(struct dlm_ctxt *dlm)
if (status) { if (status) {
dlm_unregister_domain_handlers(dlm); dlm_unregister_domain_handlers(dlm);
dlm_debug_shutdown(dlm);
dlm_complete_thread(dlm); dlm_complete_thread(dlm);
dlm_complete_recovery_thread(dlm); dlm_complete_recovery_thread(dlm);
dlm_destroy_dlm_worker(dlm); dlm_destroy_dlm_worker(dlm);
...@@ -1484,6 +1505,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, ...@@ -1484,6 +1505,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
u32 key) u32 key)
{ {
int i; int i;
int ret;
struct dlm_ctxt *dlm = NULL; struct dlm_ctxt *dlm = NULL;
dlm = kzalloc(sizeof(*dlm), GFP_KERNEL); dlm = kzalloc(sizeof(*dlm), GFP_KERNEL);
...@@ -1516,6 +1538,15 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, ...@@ -1516,6 +1538,15 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
dlm->key = key; dlm->key = key;
dlm->node_num = o2nm_this_node(); dlm->node_num = o2nm_this_node();
ret = dlm_create_debugfs_subroot(dlm);
if (ret < 0) {
dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES);
kfree(dlm->name);
kfree(dlm);
dlm = NULL;
goto leave;
}
spin_lock_init(&dlm->spinlock); spin_lock_init(&dlm->spinlock);
spin_lock_init(&dlm->master_lock); spin_lock_init(&dlm->master_lock);
spin_lock_init(&dlm->ast_lock); spin_lock_init(&dlm->ast_lock);
...@@ -1526,6 +1557,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, ...@@ -1526,6 +1557,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
INIT_LIST_HEAD(&dlm->reco.node_data); INIT_LIST_HEAD(&dlm->reco.node_data);
INIT_LIST_HEAD(&dlm->purge_list); INIT_LIST_HEAD(&dlm->purge_list);
INIT_LIST_HEAD(&dlm->dlm_domain_handlers); INIT_LIST_HEAD(&dlm->dlm_domain_handlers);
INIT_LIST_HEAD(&dlm->tracking_list);
dlm->reco.state = 0; dlm->reco.state = 0;
INIT_LIST_HEAD(&dlm->pending_asts); INIT_LIST_HEAD(&dlm->pending_asts);
...@@ -1816,21 +1848,49 @@ static int __init dlm_init(void) ...@@ -1816,21 +1848,49 @@ static int __init dlm_init(void)
dlm_print_version(); dlm_print_version();
status = dlm_init_mle_cache(); status = dlm_init_mle_cache();
if (status) if (status) {
return -1; mlog(ML_ERROR, "Could not create o2dlm_mle slabcache\n");
goto error;
}
status = dlm_init_master_caches();
if (status) {
mlog(ML_ERROR, "Could not create o2dlm_lockres and "
"o2dlm_lockname slabcaches\n");
goto error;
}
status = dlm_init_lock_cache();
if (status) {
mlog(ML_ERROR, "Count not create o2dlm_lock slabcache\n");
goto error;
}
status = dlm_register_net_handlers(); status = dlm_register_net_handlers();
if (status) { if (status) {
dlm_destroy_mle_cache(); mlog(ML_ERROR, "Unable to register network handlers\n");
return -1; goto error;
} }
status = dlm_create_debugfs_root();
if (status)
goto error;
return 0; return 0;
error:
dlm_unregister_net_handlers();
dlm_destroy_lock_cache();
dlm_destroy_master_caches();
dlm_destroy_mle_cache();
return -1;
} }
static void __exit dlm_exit (void) static void __exit dlm_exit (void)
{ {
dlm_destroy_debugfs_root();
dlm_unregister_net_handlers(); dlm_unregister_net_handlers();
dlm_destroy_lock_cache();
dlm_destroy_master_caches();
dlm_destroy_mle_cache(); dlm_destroy_mle_cache();
} }
......
...@@ -53,6 +53,8 @@ ...@@ -53,6 +53,8 @@
#define MLOG_MASK_PREFIX ML_DLM #define MLOG_MASK_PREFIX ML_DLM
#include "cluster/masklog.h" #include "cluster/masklog.h"
static struct kmem_cache *dlm_lock_cache = NULL;
static DEFINE_SPINLOCK(dlm_cookie_lock); static DEFINE_SPINLOCK(dlm_cookie_lock);
static u64 dlm_next_cookie = 1; static u64 dlm_next_cookie = 1;
...@@ -64,6 +66,22 @@ static void dlm_init_lock(struct dlm_lock *newlock, int type, ...@@ -64,6 +66,22 @@ static void dlm_init_lock(struct dlm_lock *newlock, int type,
static void dlm_lock_release(struct kref *kref); static void dlm_lock_release(struct kref *kref);
static void dlm_lock_detach_lockres(struct dlm_lock *lock); static void dlm_lock_detach_lockres(struct dlm_lock *lock);
int dlm_init_lock_cache(void)
{
dlm_lock_cache = kmem_cache_create("o2dlm_lock",
sizeof(struct dlm_lock),
0, SLAB_HWCACHE_ALIGN, NULL);
if (dlm_lock_cache == NULL)
return -ENOMEM;
return 0;
}
void dlm_destroy_lock_cache(void)
{
if (dlm_lock_cache)
kmem_cache_destroy(dlm_lock_cache);
}
/* Tell us whether we can grant a new lock request. /* Tell us whether we can grant a new lock request.
* locking: * locking:
* caller needs: res->spinlock * caller needs: res->spinlock
...@@ -353,7 +371,7 @@ static void dlm_lock_release(struct kref *kref) ...@@ -353,7 +371,7 @@ static void dlm_lock_release(struct kref *kref)
mlog(0, "freeing kernel-allocated lksb\n"); mlog(0, "freeing kernel-allocated lksb\n");
kfree(lock->lksb); kfree(lock->lksb);
} }
kfree(lock); kmem_cache_free(dlm_lock_cache, lock);
} }
/* associate a lock with it's lockres, getting a ref on the lockres */ /* associate a lock with it's lockres, getting a ref on the lockres */
...@@ -412,7 +430,7 @@ struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie, ...@@ -412,7 +430,7 @@ struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
struct dlm_lock *lock; struct dlm_lock *lock;
int kernel_allocated = 0; int kernel_allocated = 0;
lock = kzalloc(sizeof(*lock), GFP_NOFS); lock = (struct dlm_lock *) kmem_cache_zalloc(dlm_lock_cache, GFP_NOFS);
if (!lock) if (!lock)
return NULL; return NULL;
......
...@@ -48,47 +48,11 @@ ...@@ -48,47 +48,11 @@
#include "dlmapi.h" #include "dlmapi.h"
#include "dlmcommon.h" #include "dlmcommon.h"
#include "dlmdomain.h" #include "dlmdomain.h"
#include "dlmdebug.h"
#define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_MASTER) #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_MASTER)
#include "cluster/masklog.h" #include "cluster/masklog.h"
enum dlm_mle_type {
DLM_MLE_BLOCK,
DLM_MLE_MASTER,
DLM_MLE_MIGRATION
};
struct dlm_lock_name
{
u8 len;
u8 name[DLM_LOCKID_NAME_MAX];
};
struct dlm_master_list_entry
{
struct list_head list;
struct list_head hb_events;
struct dlm_ctxt *dlm;
spinlock_t spinlock;
wait_queue_head_t wq;
atomic_t woken;
struct kref mle_refs;
int inuse;
unsigned long maybe_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
unsigned long vote_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
unsigned long response_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
u8 master;
u8 new_master;
enum dlm_mle_type type;
struct o2hb_callback_func mle_hb_up;
struct o2hb_callback_func mle_hb_down;
union {
struct dlm_lock_resource *res;
struct dlm_lock_name name;
} u;
};
static void dlm_mle_node_down(struct dlm_ctxt *dlm, static void dlm_mle_node_down(struct dlm_ctxt *dlm,
struct dlm_master_list_entry *mle, struct dlm_master_list_entry *mle,
struct o2nm_node *node, struct o2nm_node *node,
...@@ -128,98 +92,10 @@ static inline int dlm_mle_equal(struct dlm_ctxt *dlm, ...@@ -128,98 +92,10 @@ static inline int dlm_mle_equal(struct dlm_ctxt *dlm,
return 1; return 1;
} }
#define dlm_print_nodemap(m) _dlm_print_nodemap(m,#m) static struct kmem_cache *dlm_lockres_cache = NULL;
static void _dlm_print_nodemap(unsigned long *map, const char *mapname) static struct kmem_cache *dlm_lockname_cache = NULL;
{
int i;
printk("%s=[ ", mapname);
for (i=0; i<O2NM_MAX_NODES; i++)
if (test_bit(i, map))
printk("%d ", i);
printk("]");
}
static void dlm_print_one_mle(struct dlm_master_list_entry *mle)
{
int refs;
char *type;
char attached;
u8 master;
unsigned int namelen;
const char *name;
struct kref *k;
unsigned long *maybe = mle->maybe_map,
*vote = mle->vote_map,
*resp = mle->response_map,
*node = mle->node_map;
k = &mle->mle_refs;
if (mle->type == DLM_MLE_BLOCK)
type = "BLK";
else if (mle->type == DLM_MLE_MASTER)
type = "MAS";
else
type = "MIG";
refs = atomic_read(&k->refcount);
master = mle->master;
attached = (list_empty(&mle->hb_events) ? 'N' : 'Y');
if (mle->type != DLM_MLE_MASTER) {
namelen = mle->u.name.len;
name = mle->u.name.name;
} else {
namelen = mle->u.res->lockname.len;
name = mle->u.res->lockname.name;
}
mlog(ML_NOTICE, "%.*s: %3s refs=%3d mas=%3u new=%3u evt=%c inuse=%d ",
namelen, name, type, refs, master, mle->new_master, attached,
mle->inuse);
dlm_print_nodemap(maybe);
printk(", ");
dlm_print_nodemap(vote);
printk(", ");
dlm_print_nodemap(resp);
printk(", ");
dlm_print_nodemap(node);
printk(", ");
printk("\n");
}
#if 0
/* Code here is included but defined out as it aids debugging */
static void dlm_dump_mles(struct dlm_ctxt *dlm)
{
struct dlm_master_list_entry *mle;
mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
spin_lock(&dlm->master_lock);
list_for_each_entry(mle, &dlm->master_list, list)
dlm_print_one_mle(mle);
spin_unlock(&dlm->master_lock);
}
int dlm_dump_all_mles(const char __user *data, unsigned int len)
{
struct dlm_ctxt *dlm;
spin_lock(&dlm_domain_lock);
list_for_each_entry(dlm, &dlm_domains, list) {
mlog(ML_NOTICE, "found dlm: %p, name=%s\n", dlm, dlm->name);
dlm_dump_mles(dlm);
}
spin_unlock(&dlm_domain_lock);
return len;
}
EXPORT_SYMBOL_GPL(dlm_dump_all_mles);
#endif /* 0 */
static struct kmem_cache *dlm_mle_cache = NULL; static struct kmem_cache *dlm_mle_cache = NULL;
static void dlm_mle_release(struct kref *kref); static void dlm_mle_release(struct kref *kref);
static void dlm_init_mle(struct dlm_master_list_entry *mle, static void dlm_init_mle(struct dlm_master_list_entry *mle,
enum dlm_mle_type type, enum dlm_mle_type type,
...@@ -507,7 +383,7 @@ static void dlm_mle_node_up(struct dlm_ctxt *dlm, ...@@ -507,7 +383,7 @@ static void dlm_mle_node_up(struct dlm_ctxt *dlm,
int dlm_init_mle_cache(void) int dlm_init_mle_cache(void)
{ {
dlm_mle_cache = kmem_cache_create("dlm_mle_cache", dlm_mle_cache = kmem_cache_create("o2dlm_mle",
sizeof(struct dlm_master_list_entry), sizeof(struct dlm_master_list_entry),
0, SLAB_HWCACHE_ALIGN, 0, SLAB_HWCACHE_ALIGN,
NULL); NULL);
...@@ -560,6 +436,35 @@ static void dlm_mle_release(struct kref *kref) ...@@ -560,6 +436,35 @@ static void dlm_mle_release(struct kref *kref)
* LOCK RESOURCE FUNCTIONS * LOCK RESOURCE FUNCTIONS
*/ */
int dlm_init_master_caches(void)
{
dlm_lockres_cache = kmem_cache_create("o2dlm_lockres",
sizeof(struct dlm_lock_resource),
0, SLAB_HWCACHE_ALIGN, NULL);
if (!dlm_lockres_cache)
goto bail;
dlm_lockname_cache = kmem_cache_create("o2dlm_lockname",
DLM_LOCKID_NAME_MAX, 0,
SLAB_HWCACHE_ALIGN, NULL);
if (!dlm_lockname_cache)
goto bail;
return 0;
bail:
dlm_destroy_master_caches();
return -ENOMEM;
}
void dlm_destroy_master_caches(void)
{
if (dlm_lockname_cache)
kmem_cache_destroy(dlm_lockname_cache);
if (dlm_lockres_cache)
kmem_cache_destroy(dlm_lockres_cache);
}
static void dlm_set_lockres_owner(struct dlm_ctxt *dlm, static void dlm_set_lockres_owner(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res, struct dlm_lock_resource *res,
u8 owner) u8 owner)
...@@ -610,6 +515,14 @@ static void dlm_lockres_release(struct kref *kref) ...@@ -610,6 +515,14 @@ static void dlm_lockres_release(struct kref *kref)
mlog(0, "destroying lockres %.*s\n", res->lockname.len, mlog(0, "destroying lockres %.*s\n", res->lockname.len,
res->lockname.name); res->lockname.name);
if (!list_empty(&res->tracking))
list_del_init(&res->tracking);
else {
mlog(ML_ERROR, "Resource %.*s not on the Tracking list\n",
res->lockname.len, res->lockname.name);
dlm_print_one_lock_resource(res);
}
if (!hlist_unhashed(&res->hash_node) || if (!hlist_unhashed(&res->hash_node) ||
!list_empty(&res->granted) || !list_empty(&res->granted) ||
!list_empty(&res->converting) || !list_empty(&res->converting) ||
...@@ -642,9 +555,9 @@ static void dlm_lockres_release(struct kref *kref) ...@@ -642,9 +555,9 @@ static void dlm_lockres_release(struct kref *kref)
BUG_ON(!list_empty(&res->recovering)); BUG_ON(!list_empty(&res->recovering));
BUG_ON(!list_empty(&res->purge)); BUG_ON(!list_empty(&res->purge));
kfree(res->lockname.name); kmem_cache_free(dlm_lockname_cache, (void *)res->lockname.name);
kfree(res); kmem_cache_free(dlm_lockres_cache, res);
} }
void dlm_lockres_put(struct dlm_lock_resource *res) void dlm_lockres_put(struct dlm_lock_resource *res)
...@@ -677,6 +590,7 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm, ...@@ -677,6 +590,7 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
INIT_LIST_HEAD(&res->dirty); INIT_LIST_HEAD(&res->dirty);
INIT_LIST_HEAD(&res->recovering); INIT_LIST_HEAD(&res->recovering);
INIT_LIST_HEAD(&res->purge); INIT_LIST_HEAD(&res->purge);
INIT_LIST_HEAD(&res->tracking);
atomic_set(&res->asts_reserved, 0); atomic_set(&res->asts_reserved, 0);
res->migration_pending = 0; res->migration_pending = 0;
res->inflight_locks = 0; res->inflight_locks = 0;
...@@ -692,6 +606,8 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm, ...@@ -692,6 +606,8 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
res->last_used = 0; res->last_used = 0;
list_add_tail(&res->tracking, &dlm->tracking_list);
memset(res->lvb, 0, DLM_LVB_LEN); memset(res->lvb, 0, DLM_LVB_LEN);
memset(res->refmap, 0, sizeof(res->refmap)); memset(res->refmap, 0, sizeof(res->refmap));
} }
...@@ -700,20 +616,28 @@ struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm, ...@@ -700,20 +616,28 @@ struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm,
const char *name, const char *name,
unsigned int namelen) unsigned int namelen)
{ {
struct dlm_lock_resource *res; struct dlm_lock_resource *res = NULL;
res = kmalloc(sizeof(struct dlm_lock_resource), GFP_NOFS); res = (struct dlm_lock_resource *)
kmem_cache_zalloc(dlm_lockres_cache, GFP_NOFS);
if (!res) if (!res)
return NULL; goto error;
res->lockname.name = kmalloc(namelen, GFP_NOFS); res->lockname.name = (char *)
if (!res->lockname.name) { kmem_cache_zalloc(dlm_lockname_cache, GFP_NOFS);
kfree(res); if (!res->lockname.name)
return NULL; goto error;
}
dlm_init_lockres(dlm, res, name, namelen); dlm_init_lockres(dlm, res, name, namelen);
return res; return res;
error:
if (res && res->lockname.name)
kmem_cache_free(dlm_lockname_cache, (void *)res->lockname.name);
if (res)
kmem_cache_free(dlm_lockres_cache, res);
return NULL;
} }
void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
......
This diff is collapsed.
...@@ -58,7 +58,7 @@ struct ocfs2_meta_lvb { ...@@ -58,7 +58,7 @@ struct ocfs2_meta_lvb {
#define OCFS2_LOCK_NONBLOCK (0x04) #define OCFS2_LOCK_NONBLOCK (0x04)
int ocfs2_dlm_init(struct ocfs2_super *osb); int ocfs2_dlm_init(struct ocfs2_super *osb);
void ocfs2_dlm_shutdown(struct ocfs2_super *osb); void ocfs2_dlm_shutdown(struct ocfs2_super *osb, int hangup_pending);
void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res); void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res);
void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
enum ocfs2_lock_type type, enum ocfs2_lock_type type,
...@@ -114,5 +114,6 @@ void ocfs2_wake_downconvert_thread(struct ocfs2_super *osb); ...@@ -114,5 +114,6 @@ void ocfs2_wake_downconvert_thread(struct ocfs2_super *osb);
struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void); struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void);
void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug); void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug);
extern const struct dlm_protocol_version ocfs2_locking_protocol; /* To set the locking protocol on module initialization */
void ocfs2_set_locking_protocol(void);
#endif /* DLMGLUE_H */ #endif /* DLMGLUE_H */
...@@ -2242,7 +2242,7 @@ const struct file_operations ocfs2_fops = { ...@@ -2242,7 +2242,7 @@ const struct file_operations ocfs2_fops = {
.open = ocfs2_file_open, .open = ocfs2_file_open,
.aio_read = ocfs2_file_aio_read, .aio_read = ocfs2_file_aio_read,
.aio_write = ocfs2_file_aio_write, .aio_write = ocfs2_file_aio_write,
.ioctl = ocfs2_ioctl, .unlocked_ioctl = ocfs2_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = ocfs2_compat_ioctl, .compat_ioctl = ocfs2_compat_ioctl,
#endif #endif
...@@ -2258,7 +2258,7 @@ const struct file_operations ocfs2_dops = { ...@@ -2258,7 +2258,7 @@ const struct file_operations ocfs2_dops = {
.fsync = ocfs2_sync_file, .fsync = ocfs2_sync_file,
.release = ocfs2_dir_release, .release = ocfs2_dir_release,
.open = ocfs2_dir_open, .open = ocfs2_dir_open,
.ioctl = ocfs2_ioctl, .unlocked_ioctl = ocfs2_ioctl,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = ocfs2_compat_ioctl, .compat_ioctl = ocfs2_compat_ioctl,
#endif #endif
......
...@@ -28,9 +28,6 @@ ...@@ -28,9 +28,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/kmod.h>
#include <dlm/dlmapi.h>
#define MLOG_MASK_PREFIX ML_SUPER #define MLOG_MASK_PREFIX ML_SUPER
#include <cluster/masklog.h> #include <cluster/masklog.h>
...@@ -48,7 +45,6 @@ static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map, ...@@ -48,7 +45,6 @@ static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map,
int bit); int bit);
static inline void __ocfs2_node_map_clear_bit(struct ocfs2_node_map *map, static inline void __ocfs2_node_map_clear_bit(struct ocfs2_node_map *map,
int bit); int bit);
static inline int __ocfs2_node_map_is_empty(struct ocfs2_node_map *map);
/* special case -1 for now /* special case -1 for now
* TODO: should *really* make sure the calling func never passes -1!! */ * TODO: should *really* make sure the calling func never passes -1!! */
...@@ -62,23 +58,23 @@ static void ocfs2_node_map_init(struct ocfs2_node_map *map) ...@@ -62,23 +58,23 @@ static void ocfs2_node_map_init(struct ocfs2_node_map *map)
void ocfs2_init_node_maps(struct ocfs2_super *osb) void ocfs2_init_node_maps(struct ocfs2_super *osb)
{ {
spin_lock_init(&osb->node_map_lock); spin_lock_init(&osb->node_map_lock);
ocfs2_node_map_init(&osb->recovery_map);
ocfs2_node_map_init(&osb->osb_recovering_orphan_dirs); ocfs2_node_map_init(&osb->osb_recovering_orphan_dirs);
} }
static void ocfs2_do_node_down(int node_num, void ocfs2_do_node_down(int node_num, void *data)
struct ocfs2_super *osb)
{ {
struct ocfs2_super *osb = data;
BUG_ON(osb->node_num == node_num); BUG_ON(osb->node_num == node_num);
mlog(0, "ocfs2: node down event for %d\n", node_num); mlog(0, "ocfs2: node down event for %d\n", node_num);
if (!osb->dlm) { if (!osb->cconn) {
/* /*
* No DLM means we're not even ready to participate yet. * No cluster connection means we're not even ready to
* We check the slots after the DLM comes up, so we will * participate yet. We check the slots after the cluster
* notice the node death then. We can safely ignore it * comes up, so we will notice the node death then. We
* here. * can safely ignore it here.
*/ */
return; return;
} }
...@@ -86,61 +82,6 @@ static void ocfs2_do_node_down(int node_num, ...@@ -86,61 +82,6 @@ static void ocfs2_do_node_down(int node_num,
ocfs2_recovery_thread(osb, node_num); ocfs2_recovery_thread(osb, node_num);
} }
/* Called from the dlm when it's about to evict a node. We may also
* get a heartbeat callback later. */
static void ocfs2_dlm_eviction_cb(int node_num,
void *data)
{
struct ocfs2_super *osb = (struct ocfs2_super *) data;
struct super_block *sb = osb->sb;
mlog(ML_NOTICE, "device (%u,%u): dlm has evicted node %d\n",
MAJOR(sb->s_dev), MINOR(sb->s_dev), node_num);
ocfs2_do_node_down(node_num, osb);
}
void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb)
{
/* Not exactly a heartbeat callback, but leads to essentially
* the same path so we set it up here. */
dlm_setup_eviction_cb(&osb->osb_eviction_cb,
ocfs2_dlm_eviction_cb,
osb);
}
void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
{
int ret;
char *argv[5], *envp[3];
if (ocfs2_mount_local(osb))
return;
if (!osb->uuid_str) {
/* This can happen if we don't get far enough in mount... */
mlog(0, "No UUID with which to stop heartbeat!\n\n");
return;
}
argv[0] = (char *)o2nm_get_hb_ctl_path();
argv[1] = "-K";
argv[2] = "-u";
argv[3] = osb->uuid_str;
argv[4] = NULL;
mlog(0, "Run: %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
/* minimal command environment taken from cpu_run_sbin_hotplug */
envp[0] = "HOME=/";
envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
envp[2] = NULL;
ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
if (ret < 0)
mlog_errno(ret);
}
static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map, static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map,
int bit) int bit)
{ {
...@@ -192,112 +133,3 @@ int ocfs2_node_map_test_bit(struct ocfs2_super *osb, ...@@ -192,112 +133,3 @@ int ocfs2_node_map_test_bit(struct ocfs2_super *osb,
return ret; return ret;
} }
static inline int __ocfs2_node_map_is_empty(struct ocfs2_node_map *map)
{
int bit;
bit = find_next_bit(map->map, map->num_nodes, 0);
if (bit < map->num_nodes)
return 0;
return 1;
}
int ocfs2_node_map_is_empty(struct ocfs2_super *osb,
struct ocfs2_node_map *map)
{
int ret;
BUG_ON(map->num_nodes == 0);
spin_lock(&osb->node_map_lock);
ret = __ocfs2_node_map_is_empty(map);
spin_unlock(&osb->node_map_lock);
return ret;
}
#if 0
static void __ocfs2_node_map_dup(struct ocfs2_node_map *target,
struct ocfs2_node_map *from)
{
BUG_ON(from->num_nodes == 0);
ocfs2_node_map_init(target);
__ocfs2_node_map_set(target, from);
}
/* returns 1 if bit is the only bit set in target, 0 otherwise */
int ocfs2_node_map_is_only(struct ocfs2_super *osb,
struct ocfs2_node_map *target,
int bit)
{
struct ocfs2_node_map temp;
int ret;
spin_lock(&osb->node_map_lock);
__ocfs2_node_map_dup(&temp, target);
__ocfs2_node_map_clear_bit(&temp, bit);
ret = __ocfs2_node_map_is_empty(&temp);
spin_unlock(&osb->node_map_lock);
return ret;
}
static void __ocfs2_node_map_set(struct ocfs2_node_map *target,
struct ocfs2_node_map *from)
{
int num_longs, i;
BUG_ON(target->num_nodes != from->num_nodes);
BUG_ON(target->num_nodes == 0);
num_longs = BITS_TO_LONGS(target->num_nodes);
for (i = 0; i < num_longs; i++)
target->map[i] = from->map[i];
}
#endif /* 0 */
/* Returns whether the recovery bit was actually set - it may not be
* if a node is still marked as needing recovery */
int ocfs2_recovery_map_set(struct ocfs2_super *osb,
int num)
{
int set = 0;
spin_lock(&osb->node_map_lock);
if (!test_bit(num, osb->recovery_map.map)) {
__ocfs2_node_map_set_bit(&osb->recovery_map, num);
set = 1;
}
spin_unlock(&osb->node_map_lock);
return set;
}
void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
int num)
{
ocfs2_node_map_clear_bit(osb, &osb->recovery_map, num);
}
int ocfs2_node_map_iterate(struct ocfs2_super *osb,
struct ocfs2_node_map *map,
int idx)
{
int i = idx;
idx = O2NM_INVALID_NODE_NUM;
spin_lock(&osb->node_map_lock);
if ((i != O2NM_INVALID_NODE_NUM) &&
(i >= 0) &&
(i < map->num_nodes)) {
while(i < map->num_nodes) {
if (test_bit(i, map->map)) {
idx = i;
break;
}
i++;
}
}
spin_unlock(&osb->node_map_lock);
return idx;
}
...@@ -28,13 +28,10 @@ ...@@ -28,13 +28,10 @@
void ocfs2_init_node_maps(struct ocfs2_super *osb); void ocfs2_init_node_maps(struct ocfs2_super *osb);
void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb); void ocfs2_do_node_down(int node_num, void *data);
void ocfs2_stop_heartbeat(struct ocfs2_super *osb);
/* node map functions - used to keep track of mounted and in-recovery /* node map functions - used to keep track of mounted and in-recovery
* nodes. */ * nodes. */
int ocfs2_node_map_is_empty(struct ocfs2_super *osb,
struct ocfs2_node_map *map);
void ocfs2_node_map_set_bit(struct ocfs2_super *osb, void ocfs2_node_map_set_bit(struct ocfs2_super *osb,
struct ocfs2_node_map *map, struct ocfs2_node_map *map,
int bit); int bit);
...@@ -44,17 +41,5 @@ void ocfs2_node_map_clear_bit(struct ocfs2_super *osb, ...@@ -44,17 +41,5 @@ void ocfs2_node_map_clear_bit(struct ocfs2_super *osb,
int ocfs2_node_map_test_bit(struct ocfs2_super *osb, int ocfs2_node_map_test_bit(struct ocfs2_super *osb,
struct ocfs2_node_map *map, struct ocfs2_node_map *map,
int bit); int bit);
int ocfs2_node_map_iterate(struct ocfs2_super *osb,
struct ocfs2_node_map *map,
int idx);
static inline int ocfs2_node_map_first_set_bit(struct ocfs2_super *osb,
struct ocfs2_node_map *map)
{
return ocfs2_node_map_iterate(osb, map, 0);
}
int ocfs2_recovery_map_set(struct ocfs2_super *osb,
int num);
void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
int num);
#endif /* OCFS2_HEARTBEAT_H */ #endif /* OCFS2_HEARTBEAT_H */
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/smp_lock.h>
#define MLOG_MASK_PREFIX ML_INODE #define MLOG_MASK_PREFIX ML_INODE
#include <cluster/masklog.h> #include <cluster/masklog.h>
...@@ -112,9 +113,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, ...@@ -112,9 +113,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
return status; return status;
} }
int ocfs2_ioctl(struct inode * inode, struct file * filp, long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{ {
struct inode *inode = filp->f_path.dentry->d_inode;
unsigned int flags; unsigned int flags;
int new_clusters; int new_clusters;
int status; int status;
...@@ -168,9 +169,6 @@ int ocfs2_ioctl(struct inode * inode, struct file * filp, ...@@ -168,9 +169,6 @@ int ocfs2_ioctl(struct inode * inode, struct file * filp,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{ {
struct inode *inode = file->f_path.dentry->d_inode;
int ret;
switch (cmd) { switch (cmd) {
case OCFS2_IOC32_GETFLAGS: case OCFS2_IOC32_GETFLAGS:
cmd = OCFS2_IOC_GETFLAGS; cmd = OCFS2_IOC_GETFLAGS;
...@@ -190,9 +188,6 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) ...@@ -190,9 +188,6 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
lock_kernel(); return ocfs2_ioctl(file, cmd, arg);
ret = ocfs2_ioctl(inode, file, cmd, arg);
unlock_kernel();
return ret;
} }
#endif #endif
...@@ -10,8 +10,7 @@ ...@@ -10,8 +10,7 @@
#ifndef OCFS2_IOCTL_H #ifndef OCFS2_IOCTL_H
#define OCFS2_IOCTL_H #define OCFS2_IOCTL_H
int ocfs2_ioctl(struct inode * inode, struct file * filp, long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
unsigned int cmd, unsigned long arg);
long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg); long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg);
#endif /* OCFS2_IOCTL_H */ #endif /* OCFS2_IOCTL_H */
This diff is collapsed.
...@@ -134,6 +134,10 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb, ...@@ -134,6 +134,10 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
/* Exported only for the journal struct init code in super.c. Do not call. */ /* Exported only for the journal struct init code in super.c. Do not call. */
void ocfs2_complete_recovery(struct work_struct *work); void ocfs2_complete_recovery(struct work_struct *work);
void ocfs2_wait_for_recovery(struct ocfs2_super *osb);
int ocfs2_recovery_init(struct ocfs2_super *osb);
void ocfs2_recovery_exit(struct ocfs2_super *osb);
/* /*
* Journal Control: * Journal Control:
......
...@@ -447,6 +447,8 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, ...@@ -447,6 +447,8 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb,
iput(main_bm_inode); iput(main_bm_inode);
out: out:
if (!status)
ocfs2_init_inode_steal_slot(osb);
mlog_exit(status); mlog_exit(status);
return status; return status;
} }
...@@ -523,6 +525,8 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, ...@@ -523,6 +525,8 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
} }
ac->ac_inode = local_alloc_inode; ac->ac_inode = local_alloc_inode;
/* We should never use localalloc from another slot */
ac->ac_alloc_slot = osb->slot_num;
ac->ac_which = OCFS2_AC_USE_LOCAL; ac->ac_which = OCFS2_AC_USE_LOCAL;
get_bh(osb->local_alloc_bh); get_bh(osb->local_alloc_bh);
ac->ac_bh = osb->local_alloc_bh; ac->ac_bh = osb->local_alloc_bh;
......
...@@ -424,7 +424,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, ...@@ -424,7 +424,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
fe->i_fs_generation = cpu_to_le32(osb->fs_generation); fe->i_fs_generation = cpu_to_le32(osb->fs_generation);
fe->i_blkno = cpu_to_le64(fe_blkno); fe->i_blkno = cpu_to_le64(fe_blkno);
fe->i_suballoc_bit = cpu_to_le16(suballoc_bit); fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
fe->i_suballoc_slot = cpu_to_le16(osb->slot_num); fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
fe->i_uid = cpu_to_le32(current->fsuid); fe->i_uid = cpu_to_le32(current->fsuid);
if (dir->i_mode & S_ISGID) { if (dir->i_mode & S_ISGID) {
fe->i_gid = cpu_to_le32(dir->i_gid); fe->i_gid = cpu_to_le32(dir->i_gid);
...@@ -997,7 +997,7 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -997,7 +997,7 @@ static int ocfs2_rename(struct inode *old_dir,
* *
* And that's why, just like the VFS, we need a file system * And that's why, just like the VFS, we need a file system
* rename lock. */ * rename lock. */
if (old_dentry != new_dentry) { if (old_dir != new_dir && S_ISDIR(old_inode->i_mode)) {
status = ocfs2_rename_lock(osb); status = ocfs2_rename_lock(osb);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
......
This diff is collapsed.
This diff is collapsed.
...@@ -100,7 +100,7 @@ static char *ocfs2_lock_type_strings[] = { ...@@ -100,7 +100,7 @@ static char *ocfs2_lock_type_strings[] = {
static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type) static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
{ {
#ifdef __KERNEL__ #ifdef __KERNEL__
mlog_bug_on_msg(type >= OCFS2_NUM_LOCK_TYPES, "%d\n", type); BUG_ON(type >= OCFS2_NUM_LOCK_TYPES);
#endif #endif
return ocfs2_lock_type_strings[type]; return ocfs2_lock_type_strings[type];
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -36,6 +36,7 @@ typedef int (group_search_t)(struct inode *, ...@@ -36,6 +36,7 @@ typedef int (group_search_t)(struct inode *,
struct ocfs2_alloc_context { struct ocfs2_alloc_context {
struct inode *ac_inode; /* which bitmap are we allocating from? */ struct inode *ac_inode; /* which bitmap are we allocating from? */
struct buffer_head *ac_bh; /* file entry bh */ struct buffer_head *ac_bh; /* file entry bh */
u32 ac_alloc_slot; /* which slot are we allocating from? */
u32 ac_bits_wanted; u32 ac_bits_wanted;
u32 ac_bits_given; u32 ac_bits_given;
#define OCFS2_AC_USE_LOCAL 1 #define OCFS2_AC_USE_LOCAL 1
......
This diff is collapsed.
...@@ -87,7 +87,14 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char ...@@ -87,7 +87,14 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
void sysfs_remove_link(struct kobject * kobj, const char * name) void sysfs_remove_link(struct kobject * kobj, const char * name)
{ {
sysfs_hash_and_remove(kobj->sd, name); struct sysfs_dirent *parent_sd = NULL;
if (!kobj)
parent_sd = &sysfs_root;
else
parent_sd = kobj->sd;
sysfs_hash_and_remove(parent_sd, name);
} }
static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment