[Ocfs2-tools-commits] mfasheh commits r577 - in trunk: . libo2dlm
libo2dlm/include
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Tue Jan 25 15:57:24 CST 2005
Author: mfasheh
Date: 2005-01-25 15:57:22 -0600 (Tue, 25 Jan 2005)
New Revision: 577
Added:
trunk/libo2dlm/
trunk/libo2dlm/Makefile
trunk/libo2dlm/include/
trunk/libo2dlm/include/kernel-list.h
trunk/libo2dlm/include/o2dlm.h
trunk/libo2dlm/o2dlm.c
trunk/libo2dlm/o2dlm_err.et.in
Modified:
trunk/Makefile
trunk/configure.in
Log:
* commit libo2dlm, a small userspace library to facilitate communication
with ocfs2_dlmfs. This needs testing.
Modified: trunk/Makefile
===================================================================
--- trunk/Makefile 2005-01-25 21:51:12 UTC (rev 576)
+++ trunk/Makefile 2005-01-25 21:57:22 UTC (rev 577)
@@ -22,7 +22,7 @@
$(error could not detect architecture for tools)
endif
-SUBDIRS = libocfs2 libo2cb fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 clusterbo mount.ocfs2 listuuid sizetest extras patches
+SUBDIRS = libocfs2 libo2cb libo2dlm fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 clusterbo mount.ocfs2 listuuid sizetest extras patches
ifdef BUILD_OCFS2CDSL
SUBDIRS += ocfs2cdsl
Modified: trunk/configure.in
===================================================================
--- trunk/configure.in 2005-01-25 21:51:12 UTC (rev 576)
+++ trunk/configure.in 2005-01-25 21:57:22 UTC (rev 577)
@@ -193,6 +193,7 @@
Config.make
libocfs2/ocfs2_err.et
libo2cb/o2cb_err.et
+libo2dlm/o2dlm_err.et
debugfs.ocfs2/debugfs.ocfs2.8
mkfs.ocfs2/mkfs.ocfs2.8
fsck.ocfs2/fsck.ocfs2.8
Added: trunk/libo2dlm/Makefile
===================================================================
--- trunk/libo2dlm/Makefile 2005-01-25 21:51:12 UTC (rev 576)
+++ trunk/libo2dlm/Makefile 2005-01-25 21:57:22 UTC (rev 577)
@@ -0,0 +1,77 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+WARNINGS = -Wall -Wstrict-prototypes -Wmissing-prototypes \
+ -Wmissing-declarations
+
+ifdef OCFS_DEBUG
+OPTS += -ggdb
+else
+OPTS += -O2
+endif
+
+INCLUDES = -Iinclude
+
+LIBRARIES = libo2dlm.a
+
+CFLAGS = $(OPTS) $(WARNINGS) -fPIC
+CPPFLAGS += -DO2DLM_FLAT_INCLUDES
+
+ifneq ($(OCFS2_DEBUG_EXE),)
+DEBUG_EXE_FILES = $(shell awk '/DEBUG_EXE/{if (k[FILENAME] == 0) {print FILENAME; k[FILENAME] = 1;}}' $(CFILES))
+DEBUG_EXE_PROGRAMS = $(addprefix debug_,$(subst .c,,$(DEBUG_EXE_FILES)))
+
+.SECONDARY:
+
+UNINST_PROGRAMS += $(DEBUG_EXE_PROGRAMS)
+
+debug_%.o : %.c
+ $(CC) $(CFLAGS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(LOCAL_CPPFLAGS) \
+ $(INCLUDES) $(DEFINES) \
+ -DDEBUG_EXE -o $@ -c $<
+
+debug_%: debug_%.o libo2dlm.a
+ $(LINK) $(COM_ERR_LIBS)
+
+endif
+
+CFILES = o2dlm.c
+
+HFILES = include/o2dlm.h
+
+HFILES_GEN = \
+ include/o2dlm_err.h
+
+$(CFILES): $(HFILES_GEN)
+
+OBJS = $(subst .c,.o,$(CFILES)) \
+ o2dlm_err.o
+
+o2dlm_err.et: o2dlm_err.et.in
+ cd $(TOPDIR) && ./config.status
+
+include/o2dlm_err.h: o2dlm_err.h
+ cp $< $@
+
+o2dlm_err.c o2dlm_err.h: o2dlm_err.et
+ compile_et o2dlm_err.et
+
+libo2dlm.a: $(OBJS)
+ rm -f $@
+ $(AR) r $@ $^
+ $(RANLIB) $@
+
+DIST_FILES = $(CFILES) $(HFILES) o2dlm_err.et.in
+
+DIST_RULES = dist-subdircreate
+
+dist-subdircreate:
+ $(TOPDIR)/mkinstalldirs $(DIST_DIR)/include
+
+CLEAN_RULES = clean-err
+
+clean-err:
+ rm -f o2dlm_err.c o2dlm_err.h include/o2dlm_err.h
+
+include $(TOPDIR)/Postamble.make
Added: trunk/libo2dlm/include/kernel-list.h
===================================================================
--- trunk/libo2dlm/include/kernel-list.h 2005-01-25 21:51:12 UTC (rev 576)
+++ trunk/libo2dlm/include/kernel-list.h 2005-01-25 21:57:22 UTC (rev 577)
@@ -0,0 +1,116 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = { &name, &name }
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+#if (!defined(__GNUC__) && !defined(__WATCOMC__))
+#define __inline__
+#endif
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head * new,
+ struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/*
+ * Insert a new entry after the specified head..
+ */
+static __inline__ void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/*
+ * Insert a new entry at the tail
+ */
+static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+static __inline__ void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static __inline__ int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/*
+ * Splice in "list" into "head"
+ */
+static __inline__ void list_splice(struct list_head *list, struct list_head *head)
+{
+ struct list_head *first = list->next;
+
+ if (first != list) {
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+ }
+}
+
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+#endif
Added: trunk/libo2dlm/include/o2dlm.h
===================================================================
--- trunk/libo2dlm/include/o2dlm.h 2005-01-25 21:51:12 UTC (rev 576)
+++ trunk/libo2dlm/include/o2dlm.h 2005-01-25 21:57:22 UTC (rev 577)
@@ -0,0 +1,105 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * o2dlm.h
+ *
+ * Defines the userspace locking api
+ *
+ * Copyright (C) 2004 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, version 2, as published by the Free Software Foundation.
+ *
+ * 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 _O2DLM_H_
+#define _O2DLM_H_
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <kernel-list.h>
+
+#include <et/com_err.h>
+
+#if O2DLM_FLAT_INCLUDES
+#include "o2dlm_err.h"
+#else
+#include <o2dlm/o2dlm_err.h>
+#endif
+
+#define O2DLM_LOCK_ID_MAX_LEN 32
+#define O2DLM_DOMAIN_MAX_LEN 255
+
+/* + null pointer */
+#define O2DLM_MAX_FULL_DOMAIN_PATH (PATH_MAX + 1)
+
+/* valid lock flags */
+#define O2DLM_TRYLOCK 0x01
+#define O2DLM_VALID_FLAGS (O2DLM_TRYLOCK)
+
+/* valid lock levels */
+enum o2dlm_lock_level
+{
+ O2DLM_LEVEL_PRMODE,
+ O2DLM_LEVEL_EXMODE
+};
+
+struct o2dlm_lock_res
+{
+ struct list_head l_list; /* to hang us off the locks list */
+ char l_id[O2DLM_LOCK_ID_MAX_LEN]; /* 32 byte,
+ * null
+ * terminated
+ * string */
+ int l_flags; /* limited set of flags */
+ enum o2dlm_lock_level l_level; /* either PR or EX */
+ int l_fd; /* the fd returned by the open call */
+};
+
+struct o2dlm_ctxt
+{
+ struct list_head ct_locks; /* the list of locks */
+ char ct_domain_path[O2DLM_MAX_FULL_DOMAIN_PATH]; /* domain
+ * dir */
+ char ct_ctxt_lock_name[O2DLM_LOCK_ID_MAX_LEN];
+};
+
+/* Expects to be given a path to the root of a valid ocfs2_dlmfs file
+ * system and a domain identifier of length <= 255 characters including
+ * the '\0' */
+errcode_t o2dlm_initialize(const char *dlmfs_path,
+ const char *domain_name,
+ struct o2dlm_ctxt **ctxt);
+
+/*
+ * lock_name, is a valid lock name -- 32 bytes long including the null
+ * character
+ *
+ * Returns: 0 if we got the lock we wanted
+ */
+errcode_t o2dlm_lock(struct o2dlm_ctxt *ctxt,
+ const char *lockid,
+ int flags,
+ enum o2dlm_lock_level level);
+
+/* returns 0 on success */
+errcode_t o2dlm_unlock(struct o2dlm_ctxt *ctxt,
+ char *lockid);
+
+/*
+ * Unlocks all pending locks and frees the lock context.
+ */
+errcode_t o2dlm_destroy(struct o2dlm_ctxt *ctxt);
+#endif /* _O2DLM_H_ */
Added: trunk/libo2dlm/o2dlm.c
===================================================================
--- trunk/libo2dlm/o2dlm.c 2005-01-25 21:51:12 UTC (rev 576)
+++ trunk/libo2dlm/o2dlm.c 2005-01-25 21:57:22 UTC (rev 577)
@@ -0,0 +1,494 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * o2dlm.c
+ *
+ * Defines the userspace locking api
+ *
+ * Copyright (C) 2004 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, version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <sys/statfs.h>
+#include <string.h>
+
+#include <kernel-list.h>
+
+#include <o2dlm.h>
+
+#define USER_DLMFS_MAGIC 0x76a9f425
+
+static errcode_t o2dlm_generate_random_value(int64_t *value)
+{
+ int randfd = 0;
+ int readlen = sizeof(*value);
+
+ if ((randfd = open("/dev/urandom", O_RDONLY)) == -1)
+ return O2DLM_ET_RANDOM;
+
+ if (read(randfd, value, readlen) != readlen)
+ return O2DLM_ET_RANDOM;
+
+ close(randfd);
+
+ return 0;
+}
+
+static errcode_t o2dlm_alloc_ctxt(const char *mnt_path,
+ const char *dirname,
+ struct o2dlm_ctxt **dlm_ctxt)
+{
+ errcode_t err;
+ struct o2dlm_ctxt *ctxt;
+ int64_t rand;
+ int len;
+
+ err = o2dlm_generate_random_value(&rand);
+ if (err)
+ return err;
+
+ ctxt = malloc(sizeof(*ctxt));
+ if (!ctxt)
+ return O2DLM_ET_NO_MEMORY;
+
+ len = snprintf(ctxt->ct_ctxt_lock_name, O2DLM_LOCK_ID_MAX_LEN,
+ ".%016"PRIx64, rand);
+ if (len == O2DLM_LOCK_ID_MAX_LEN) {
+ err = O2DLM_ET_NAME_TOO_LONG;
+ goto exit_and_free;
+ } else if (len < 0) {
+ err = O2DLM_ET_OUTPUT_ERROR;
+ goto exit_and_free;
+ }
+
+ INIT_LIST_HEAD(&ctxt->ct_locks);
+
+ len = snprintf(ctxt->ct_domain_path, PATH_MAX + 1, "%s/%s",
+ mnt_path, dirname);
+ if (len == (PATH_MAX + 1)) {
+ err = O2DLM_ET_BAD_DOMAIN_DIR;
+ goto exit_and_free;
+ } else if (len < 0) {
+ err = O2DLM_ET_OUTPUT_ERROR;
+ goto exit_and_free;
+ }
+
+ *dlm_ctxt = ctxt;
+ err = 0;
+exit_and_free:
+ if (err)
+ free(ctxt);
+ return err;
+}
+
+static void o2dlm_free_ctxt(struct o2dlm_ctxt *ctxt)
+{
+ free(ctxt);
+}
+
+static errcode_t o2dlm_check_user_dlmfs(const char *dlmfs_path)
+{
+ struct statfs stat;
+ int ret;
+
+ ret = statfs(dlmfs_path, &stat);
+ if (ret)
+ return O2DLM_ET_STATFS;
+
+ if (stat.f_type != USER_DLMFS_MAGIC)
+ return O2DLM_ET_NO_FS;
+
+ return 0;
+}
+
+static errcode_t o2dlm_check_domain_dir(struct o2dlm_ctxt *ctxt)
+{
+ int status;
+ char *dirpath = ctxt->ct_domain_path;
+ struct stat st;
+
+ status = stat(dirpath, &st);
+ if (status) {
+ if (errno == ENOENT)
+ return O2DLM_ET_NO_DOMAIN_DIR;
+ return O2DLM_ET_BAD_DOMAIN_DIR;
+ }
+
+ if (!S_ISDIR(st.st_mode))
+ return O2DLM_ET_BAD_DOMAIN_DIR;
+
+ return 0;
+}
+
+#define O2DLM_DOMAIN_DIR_MODE 0755
+
+static errcode_t o2dlm_create_domain(struct o2dlm_ctxt *ctxt)
+{
+ int status;
+ char *dirpath = ctxt->ct_domain_path;
+
+ status = mkdir(dirpath, O2DLM_DOMAIN_DIR_MODE);
+ if (status)
+ return O2DLM_ET_DOMAIN_CREATE;
+ return 0;
+}
+
+static errcode_t o2dlm_delete_domain_dir(struct o2dlm_ctxt *ctxt)
+{
+ int ret;
+
+ ret = rmdir(ctxt->ct_domain_path);
+ if (ret) {
+ if (errno == ENOTEMPTY)
+ return O2DLM_ET_BUSY_DOMAIN_DIR;
+ return O2DLM_ET_DOMAIN_DESTROY;
+ }
+ return 0;
+}
+
+errcode_t o2dlm_initialize(const char *dlmfs_path,
+ const char *domain_name,
+ struct o2dlm_ctxt **dlm_ctxt)
+{
+ errcode_t ret, dir_created = 0;
+ struct o2dlm_ctxt *ctxt;
+
+ if (strlen(domain_name) >= O2DLM_DOMAIN_MAX_LEN)
+ return O2DLM_ET_NAME_TOO_LONG;
+
+ if ((strlen(dlmfs_path) + strlen(domain_name)) >
+ O2DLM_MAX_FULL_DOMAIN_PATH)
+ return O2DLM_ET_NAME_TOO_LONG;
+
+ ret = o2dlm_check_user_dlmfs(dlmfs_path);
+ if (ret)
+ return ret;
+
+ ret = o2dlm_alloc_ctxt(dlmfs_path, domain_name, &ctxt);
+ if (ret)
+ return ret;
+
+ ret = o2dlm_check_domain_dir(ctxt);
+ if (ret) {
+ if (ret != O2DLM_ET_NO_DOMAIN_DIR) {
+ o2dlm_free_ctxt(ctxt);
+ return ret;
+ }
+
+ /* the domain does not yet exist - create it ourselves. */
+ ret = o2dlm_create_domain(ctxt);
+ if (ret) {
+ o2dlm_free_ctxt(ctxt);
+ return ret;
+ }
+ dir_created = 1;
+ }
+
+ /* What we want to do here is create a lock which we'll hold
+ * open for the duration of this context. This way if another
+ * process won't be able to shut down this domain underneath
+ * us. */
+ ret = o2dlm_lock(ctxt, ctxt->ct_ctxt_lock_name, 0, O2DLM_LEVEL_PRMODE);
+ if (ret) {
+ if (dir_created)
+ o2dlm_delete_domain_dir(ctxt); /* best effort
+ * cleanup. */
+ o2dlm_free_ctxt(ctxt);
+ return ret;
+ }
+
+ *dlm_ctxt = ctxt;
+ return 0;
+}
+
+static errcode_t o2dlm_full_path(char *path,
+ struct o2dlm_ctxt *ctxt,
+ const char *filename)
+{
+ int ret;
+ int len = PATH_MAX + 1;
+
+ ret = snprintf(path, len, "%s/%s", ctxt->ct_domain_path, filename);
+ if (ret == len)
+ return O2DLM_ET_NAME_TOO_LONG;
+ else if (ret < 0)
+ return O2DLM_ET_OUTPUT_ERROR;
+ return 0;
+}
+
+static struct o2dlm_lock_res *o2dlm_find_lock_res(struct o2dlm_ctxt *ctxt,
+ const char *lockid)
+{
+ struct o2dlm_lock_res *lockres = NULL;
+ struct list_head *p;
+
+ list_for_each(p, &ctxt->ct_locks) {
+ lockres = list_entry(p, struct o2dlm_lock_res, l_list);
+ if (!strcmp(lockid, lockres->l_id))
+ break;
+ }
+ return lockres;
+}
+
+static int o2dlm_translate_lock_flags(enum o2dlm_lock_level level,
+ int lockflags)
+{
+ int flags;
+
+ switch (level) {
+ case O2DLM_LEVEL_PRMODE:
+ flags = O_RDONLY;
+ break;
+ case O2DLM_LEVEL_EXMODE:
+ flags = O_WRONLY;
+ break;
+ default:
+ flags = 0;
+ }
+
+ if (lockflags & O2DLM_TRYLOCK)
+ flags |= O_NONBLOCK;
+
+ return flags;
+}
+
+static struct o2dlm_lock_res *o2dlm_new_lock_res(const char *id,
+ enum o2dlm_lock_level level,
+ int flags)
+{
+ struct o2dlm_lock_res *lockres;
+
+ lockres = malloc(sizeof(*lockres));
+ if (lockres) {
+ memset(lockres, 0, sizeof(*lockres));
+
+ INIT_LIST_HEAD(&lockres->l_list);
+
+ strncpy(lockres->l_id, id, O2DLM_LOCK_ID_MAX_LEN);
+
+ lockres->l_flags = flags;
+ lockres->l_level = level;
+ lockres->l_fd = -1;
+ }
+ return lockres;
+}
+
+#define O2DLM_OPEN_MODE 0664
+
+errcode_t o2dlm_lock(struct o2dlm_ctxt *ctxt,
+ const char *lockid,
+ int lockflags,
+ enum o2dlm_lock_level level)
+{
+ int ret, flags, fd;
+ char *path;
+ struct o2dlm_lock_res *lockres;
+
+ /* names starting with '.' are reserved. */
+ if (lockid[0] == '.')
+ return O2DLM_ET_INVALID_LOCK_NAME;
+
+ if (strlen(lockid) >= O2DLM_LOCK_ID_MAX_LEN)
+ return O2DLM_ET_INVALID_LOCK_NAME;
+
+ if (level != O2DLM_LEVEL_PRMODE && level != O2DLM_LEVEL_EXMODE)
+ return O2DLM_ET_INVALID_LOCK_LEVEL;
+
+ lockres = o2dlm_find_lock_res(ctxt, lockid);
+ if (lockres)
+ return O2DLM_ET_RECURSIVE_LOCK;
+
+ path = malloc(PATH_MAX + 1);
+ if (!path)
+ return O2DLM_ET_NO_MEMORY;
+
+ ret = o2dlm_full_path(path, ctxt, lockid);
+ if (ret) {
+ free(path);
+ return ret;
+ }
+
+ lockflags &= O2DLM_VALID_FLAGS;
+ flags = o2dlm_translate_lock_flags(level, lockflags);
+
+ lockres = o2dlm_new_lock_res(lockid, level, flags);
+ if (!lockres) {
+ free(path);
+ return O2DLM_ET_NO_MEMORY;
+ }
+
+ fd = open(path, flags|O_CREAT, O2DLM_OPEN_MODE);
+ if (fd < 0) {
+ free(path);
+ free(lockres);
+ return O2DLM_ET_LOCKING;
+ }
+
+ lockres->l_flags = lockflags;
+ lockres->l_fd = fd;
+
+ list_add_tail(&lockres->l_list, &ctxt->ct_locks);
+
+ free(path);
+
+ return 0;
+}
+
+static errcode_t o2dlm_unlock_lock_res(struct o2dlm_ctxt *ctxt,
+ struct o2dlm_lock_res *lockres)
+{
+ int ret, len = PATH_MAX + 1;
+ char *path;
+
+ /* This does the actual unlock. */
+ close(lockres->l_fd);
+
+ /* From here on down, we're trying to unlink the lockres file
+ * from the dlm file system. Note that EBUSY from unlink is
+ * not a fatal error here -- it simply means that the lock is
+ * in use by some other process. */
+ path = malloc(len);
+ if (!path)
+ return O2DLM_ET_NO_MEMORY;
+
+ ret = o2dlm_full_path(path, ctxt, lockres->l_id);
+ if (ret) {
+ free(path);
+ return ret;
+ }
+
+ ret = unlink(path);
+ free (path);
+ if (ret) {
+ if (errno == EBUSY)
+ return O2DLM_ET_BUSY_LOCK;
+ return O2DLM_ET_UNLINK;
+ }
+ return 0;
+}
+
+errcode_t o2dlm_unlock(struct o2dlm_ctxt *ctxt,
+ char *lockid)
+{
+ int ret;
+ struct o2dlm_lock_res *lockres = NULL;
+
+ lockres = o2dlm_find_lock_res(ctxt, lockid);
+ if (!lockres)
+ return O2DLM_ET_UNKNOWN_LOCK;
+
+ list_del(&lockres->l_list);
+
+ ret = o2dlm_unlock_lock_res(ctxt, lockres);
+
+ free(lockres);
+
+ if (ret && (ret != O2DLM_ET_BUSY_LOCK))
+ return ret;
+ return 0;
+}
+
+static errcode_t o2dlm_unlink_all(struct o2dlm_ctxt *ctxt)
+{
+ int ret;
+ char *name;
+ DIR *dir;
+ struct dirent *de;
+
+ name = malloc(PATH_MAX + 1);
+ if (!name)
+ return O2DLM_ET_NO_MEMORY;
+
+ dir = opendir(ctxt->ct_domain_path);
+ if (!dir) {
+ free(name);
+ return O2DLM_ET_DOMAIN_DIR;
+ }
+
+ de = readdir(dir);
+ while(de) {
+ if ((strlen(de->d_name) == 1) &&
+ (de->d_name[0] == '.'))
+ continue;
+ if ((strlen(de->d_name) == 2) &&
+ (de->d_name[0] == '.') &&
+ (de->d_name[1] == '.'))
+ continue;
+
+ ret = o2dlm_full_path(name, ctxt, de->d_name);
+ if (ret)
+ goto close_and_free;
+
+ ret = unlink(name);
+ if (ret) {
+ if (errno != EBUSY) {
+ ret = O2DLM_ET_UNLINK;
+ goto close_and_free;
+ }
+ }
+ de = readdir(dir);
+ }
+
+ ret = 0;
+close_and_free:
+ closedir(dir);
+ free(name);
+ return ret;
+}
+
+errcode_t o2dlm_destroy(struct o2dlm_ctxt *ctxt)
+{
+ int ret;
+ int error = 0;
+ struct o2dlm_lock_res *lockres;
+ struct list_head *p, *n;
+
+ list_for_each_safe(p, n, &ctxt->ct_locks) {
+ lockres = list_entry(p, struct o2dlm_lock_res, l_list);
+ list_del(&lockres->l_list);
+
+ ret = o2dlm_unlock_lock_res(ctxt, lockres);
+ if (ret && (ret != O2DLM_ET_BUSY_LOCK))
+ error = O2DLM_ET_FAILED_UNLOCKS;
+ free(lockres);
+ }
+ if (error)
+ goto free_and_exit;
+
+ ret = o2dlm_unlink_all(ctxt);
+ if (ret && ret != O2DLM_ET_BUSY_LOCK) {
+ error = ret;
+ goto free_and_exit;
+ }
+
+ ret = o2dlm_delete_domain_dir(ctxt);
+ if (ret && ret != O2DLM_ET_BUSY_DOMAIN_DIR)
+ error = ret;
+
+free_and_exit:
+ o2dlm_free_ctxt(ctxt);
+ return error;
+}
Added: trunk/libo2dlm/o2dlm_err.et.in
===================================================================
--- trunk/libo2dlm/o2dlm_err.et.in 2005-01-25 21:51:12 UTC (rev 576)
+++ trunk/libo2dlm/o2dlm_err.et.in 2005-01-25 21:57:22 UTC (rev 577)
@@ -0,0 +1,93 @@
+#
+# o2dlm_err.et.in
+#
+# Error codes for the O2DLM library.
+#
+# Copyright (C) 2005 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, version 2, as published by the Free Software Foundation.
+#
+# 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.
+#
+ error_table o2dl
+
+ec O2DLM_ET_BASE,
+ "O2DLM Library version @VERSION@"
+
+ec O2DLM_ET_NO_MEMORY,
+ "Memory allocation failed"
+
+ec O2DLM_ET_SERVICE_UNAVAILABLE,
+ "Unable to access cluster service"
+
+ec O2DLM_ET_INVALID_LOCK_NAME,
+ "Invalid name for a lock"
+
+ec O2DLM_ET_INVALID_LOCK_LEVEL,
+ "Invalid locking level"
+
+ec O2DLM_ET_INTERNAL_FAILURE,
+ "Internal logic failure"
+
+ec O2DLM_ET_NAME_TOO_LONG,
+ "Name too long"
+
+ec O2DLM_ET_STATFS,
+ "Could not stat user_dlmfs mountpoint"
+
+ec O2DLM_ET_NO_FS,
+ "ocfs2_dlmfs file system was not found"
+
+ec O2DLM_ET_NO_DOMAIN_DIR,
+ "No directory for domain was found"
+
+ec O2DLM_ET_BAD_DOMAIN_DIR,
+ "Could not stat domain directory"
+
+ec O2DLM_ET_BUSY_DOMAIN_DIR,
+ "Domain directory has active locks"
+
+ec O2DLM_ET_DOMAIN_DIR,
+ "Could not read domain dir"
+
+ec O2DLM_ET_DOMAIN_DESTROY,
+ "Could not destroy domain"
+
+ec O2DLM_ET_DOMAIN_CREATE,
+ "Could not create domain"
+
+ec O2DLM_ET_RANDOM,
+ "Could not generate random value"
+
+ec O2DLM_ET_BUSY_LOCK,
+ "Lock resource is in use by another process"
+
+ec O2DLM_ET_OUTPUT_ERROR,
+ "Output Error"
+
+ec O2DLM_ET_UNLINK,
+ "Error unlinking lock resource"
+
+ec O2DLM_ET_UNKNOWN_LOCK,
+ "Could not find lock resource"
+
+ec O2DLM_ET_RECURSIVE_LOCK,
+ "Already have a lock on this resource"
+
+ec O2DLM_ET_LOCKING,
+ "Could not take lock"
+
+ec O2DLM_ET_FAILED_UNLOCKS,
+ "Could not drop all locks"
+
+ end
More information about the Ocfs2-tools-commits
mailing list