/* * The stack currently in use. If not null, active_stack->sp_count > 0, * the module is pinned, and the locking protocol cannot be changed.
*/ staticstruct ocfs2_stack_plugin *active_stack;
/* * If the stack passed by the filesystem isn't the selected one, * we can't continue.
*/ if (strcmp(stack_name, cluster_stack_name)) {
rc = -EBUSY; goto out;
}
if (active_stack) { /* * If the active stack isn't the one we want, it cannot * be selected right now.
*/ if (!strcmp(active_stack->sp_name, plugin_name))
rc = 0; else
rc = -EBUSY; goto out;
}
p = ocfs2_stack_lookup(plugin_name); if (!p || !try_module_get(p->sp_owner)) {
rc = -ENOENT; goto out;
}
active_stack = p;
rc = 0;
out: /* If we found it, pin it */ if (!rc)
active_stack->sp_count++;
spin_unlock(&ocfs2_stack_lock); return rc;
}
/* * This function looks up the appropriate stack and makes it active. If * there is no stack, it tries to load it. It will fail if the stack still * cannot be found. It will also fail if a different stack is in use.
*/ staticint ocfs2_stack_driver_get(constchar *stack_name)
{ int rc; char *plugin_name = OCFS2_STACK_PLUGIN_O2CB;
/* * Classic stack does not pass in a stack name. This is * compatible with older tools as well.
*/ if (!stack_name || !*stack_name)
stack_name = OCFS2_STACK_PLUGIN_O2CB;
if (strlen(stack_name) != OCFS2_STACK_LABEL_LEN) {
printk(KERN_ERR "ocfs2 passed an invalid cluster stack label: \"%s\"\n",
stack_name); return -EINVAL;
}
/* Anything that isn't the classic stack is a user stack */ if (strcmp(stack_name, OCFS2_STACK_PLUGIN_O2CB))
plugin_name = OCFS2_STACK_PLUGIN_USER;
/* * The ocfs2_dlm_lock() and ocfs2_dlm_unlock() functions take no argument * for the ast and bast functions. They will pass the lksb to the ast * and bast. The caller can wrap the lksb with their own structure to * get more information.
*/ int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, int mode, struct ocfs2_dlm_lksb *lksb,
u32 flags, void *name, unsignedint namelen)
{ if (!lksb->lksb_conn)
lksb->lksb_conn = conn; else
BUG_ON(lksb->lksb_conn != conn); return active_stack->sp_ops->dlm_lock(conn, mode, lksb, flags,
name, namelen);
}
EXPORT_SYMBOL_GPL(ocfs2_dlm_lock);
int ocfs2_stack_supports_plocks(void)
{ return active_stack && active_stack->sp_ops->plock;
}
EXPORT_SYMBOL_GPL(ocfs2_stack_supports_plocks);
/* * ocfs2_plock() can only be safely called if * ocfs2_stack_supports_plocks() returned true
*/ int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino, struct file *file, int cmd, struct file_lock *fl)
{
WARN_ON_ONCE(active_stack->sp_ops->plock == NULL); if (active_stack->sp_ops->plock) return active_stack->sp_ops->plock(conn, ino, file, cmd, fl); return -EOPNOTSUPP;
}
EXPORT_SYMBOL_GPL(ocfs2_plock);
int ocfs2_cluster_connect(constchar *stack_name, constchar *cluster_name, int cluster_name_len, constchar *group, int grouplen, struct ocfs2_locking_protocol *lproto, void (*recovery_handler)(int node_num, void *recovery_data), void *recovery_data, struct ocfs2_cluster_connection **conn)
{ int rc = 0; struct ocfs2_cluster_connection *new_conn;
/* The caller will ensure all nodes have the same cluster stack */ int ocfs2_cluster_connect_agnostic(constchar *group, int grouplen, struct ocfs2_locking_protocol *lproto, void (*recovery_handler)(int node_num, void *recovery_data), void *recovery_data, struct ocfs2_cluster_connection **conn)
{ char *stack_name = NULL;
/* If hangup_pending is 0, the stack driver will be dropped */ int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn, int hangup_pending)
{ int ret;
BUG_ON(conn == NULL);
ret = active_stack->sp_ops->disconnect(conn);
/* XXX Should we free it anyway? */ if (!ret) {
kfree(conn); if (!hangup_pending)
ocfs2_stack_driver_put();
}
/* * Leave the group for this filesystem. This is executed by a userspace * program (stored in ocfs2_hb_ctl_path).
*/ staticvoid ocfs2_leave_group(constchar *group)
{ int ret; char *argv[5], *envp[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) {
printk(KERN_ERR "ocfs2: Error %d running user helper " "\"%s %s %s %s\"\n",
ret, argv[0], argv[1], argv[2], argv[3]);
}
}
/* * Hangup is a required post-umount. ocfs2-tools software expects the * filesystem to call "ocfs2_hb_ctl" during unmount. This happens * regardless of whether the DLM got started, so we can't do it * in ocfs2_cluster_disconnect(). The ocfs2_leave_group() function does * the actual work.
*/ void ocfs2_cluster_hangup(constchar *group, int grouplen)
{
BUG_ON(group == NULL);
BUG_ON(group[grouplen] != '\0');
ocfs2_leave_group(group);
/* cluster_disconnect() was called with hangup_pending==1 */
ocfs2_stack_driver_put();
}
EXPORT_SYMBOL_GPL(ocfs2_cluster_hangup);
spin_lock(&ocfs2_stack_lock); if (active_stack) {
ret = snprintf(buf, PAGE_SIZE, "%s\n",
active_stack->sp_name); if (ret >= PAGE_SIZE)
ret = -E2BIG;
}
spin_unlock(&ocfs2_stack_lock);
ocfs2_kset = kset_create_and_add("ocfs2", NULL, fs_kobj); if (!ocfs2_kset) return -ENOMEM;
ret = sysfs_create_group(&ocfs2_kset->kobj, &ocfs2_attr_group); if (ret) goto error;
return 0;
error:
kset_unregister(ocfs2_kset); return ret;
}
/* * Sysctl bits * * The sysctl lives at /proc/sys/fs/ocfs2/nm/hb_ctl_path. The 'nm' doesn't * make as much sense in a multiple cluster stack world, but it's safer * and easier to preserve the name.
*/
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.11Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.