dlmfs.c 16.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
/* -*- mode: c; c-basic-offset: 8; -*-
 * vim: noexpandtab sw=8 ts=8 sts=0:
 *
 * dlmfs.c
 *
 * Code which implements the kernel side of a minimal userspace
 * interface to our DLM. This file handles the virtual file system
 * used for communication with userspace. Credit should go to ramfs,
 * which was a template for the fs side of this module.
 *
 * Copyright (C) 2003, 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 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.
 */

/* Simple VFS hooks based on: */
/*
 * Resizable simple ram filesystem for Linux.
 *
 * Copyright (C) 2000 Linus Torvalds.
 *               2000 Transmeta Corp.
 */

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/backing-dev.h>
46
#include <linux/poll.h>
47 48 49

#include <asm/uaccess.h>

Joel Becker's avatar
Joel Becker committed
50
#include "stackglue.h"
51 52 53 54 55 56
#include "userdlm.h"
#include "dlmfsver.h"

#define MLOG_MASK_PREFIX ML_DLMFS
#include "cluster/masklog.h"

57

58
static const struct super_operations dlmfs_ops;
59
static const struct file_operations dlmfs_file_operations;
60 61 62
static const struct inode_operations dlmfs_dir_inode_operations;
static const struct inode_operations dlmfs_root_inode_operations;
static const struct inode_operations dlmfs_file_inode_operations;
63
static struct kmem_cache *dlmfs_inode_cache;
64 65 66

struct workqueue_struct *user_dlm_worker;

67

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

/*
 * These are the ABI capabilities of dlmfs.
 *
 * Over time, dlmfs has added some features that were not part of the
 * initial ABI.  Unfortunately, some of these features are not detectable
 * via standard usage.  For example, Linux's default poll always returns
 * POLLIN, so there is no way for a caller of poll(2) to know when dlmfs
 * added poll support.  Instead, we provide this list of new capabilities.
 *
 * Capabilities is a read-only attribute.  We do it as a module parameter
 * so we can discover it whether dlmfs is built in, loaded, or even not
 * loaded.
 *
 * The ABI features are local to this machine's dlmfs mount.  This is
 * distinct from the locking protocol, which is concerned with inter-node
 * interaction.
85 86 87 88
 *
 * Capabilities:
 * - bast	: POLLIN against the file descriptor of a held lock
 *		  signifies a bast fired on the lock.
89
 */
90
#define DLMFS_CAPABILITIES "bast stackglue"
91
static int param_set_dlmfs_capabilities(const char *val,
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
					struct kernel_param *kp)
{
	printk(KERN_ERR "%s: readonly parameter\n", kp->name);
	return -EINVAL;
}
static int param_get_dlmfs_capabilities(char *buffer,
					struct kernel_param *kp)
{
	return strlcpy(buffer, DLMFS_CAPABILITIES,
		       strlen(DLMFS_CAPABILITIES) + 1);
}
module_param_call(capabilities, param_set_dlmfs_capabilities,
		  param_get_dlmfs_capabilities, NULL, 0444);
MODULE_PARM_DESC(capabilities, DLMFS_CAPABILITIES);


108 109 110 111 112 113 114
/*
 * decodes a set of open flags into a valid lock level and a set of flags.
 * returns < 0 if we have invalid flags
 * flags which mean something to us:
 * O_RDONLY -> PRMODE level
 * O_WRONLY -> EXMODE level
 *
115
 * O_NONBLOCK -> NOQUEUE
116 117 118 119 120 121
 */
static int dlmfs_decode_open_flags(int open_flags,
				   int *level,
				   int *flags)
{
	if (open_flags & (O_WRONLY|O_RDWR))
122
		*level = DLM_LOCK_EX;
123
	else
124
		*level = DLM_LOCK_PR;
125 126 127

	*flags = 0;
	if (open_flags & O_NONBLOCK)
128
		*flags |= DLM_LKF_NOQUEUE;
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

	return 0;
}

static int dlmfs_file_open(struct inode *inode,
			   struct file *file)
{
	int status, level, flags;
	struct dlmfs_filp_private *fp = NULL;
	struct dlmfs_inode_private *ip;

	if (S_ISDIR(inode->i_mode))
		BUG();

	mlog(0, "open called on inode %lu, flags 0x%x\n", inode->i_ino,
		file->f_flags);

	status = dlmfs_decode_open_flags(file->f_flags, &level, &flags);
	if (status < 0)
		goto bail;

	/* We don't want to honor O_APPEND at read/write time as it
	 * doesn't make sense for LVB writes. */
	file->f_flags &= ~O_APPEND;

154
	fp = kmalloc(sizeof(*fp), GFP_NOFS);
155 156 157 158 159 160 161 162 163 164 165 166 167 168
	if (!fp) {
		status = -ENOMEM;
		goto bail;
	}
	fp->fp_lock_level = level;

	ip = DLMFS_I(inode);

	status = user_dlm_cluster_lock(&ip->ip_lockres, level, flags);
	if (status < 0) {
		/* this is a strange error to return here but I want
		 * to be able userspace to be able to distinguish a
		 * valid lock request from one that simply couldn't be
		 * granted. */
169
		if (flags & DLM_LKF_NOQUEUE && status == -EAGAIN)
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
			status = -ETXTBSY;
		kfree(fp);
		goto bail;
	}

	file->private_data = fp;
bail:
	return status;
}

static int dlmfs_file_release(struct inode *inode,
			      struct file *file)
{
	int level, status;
	struct dlmfs_inode_private *ip = DLMFS_I(inode);
185
	struct dlmfs_filp_private *fp = file->private_data;
186 187 188 189 190 191 192 193 194

	if (S_ISDIR(inode->i_mode))
		BUG();

	mlog(0, "close called on inode %lu\n", inode->i_ino);

	status = 0;
	if (fp) {
		level = fp->fp_lock_level;
195
		if (level != DLM_LOCK_IV)
196 197 198 199 200 201 202 203 204
			user_dlm_cluster_unlock(&ip->ip_lockres, level);

		kfree(fp);
		file->private_data = NULL;
	}

	return 0;
}

205 206 207 208 209 210 211 212 213 214 215
/*
 * We do ->setattr() just to override size changes.  Our size is the size
 * of the LVB and nothing else.
 */
static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr)
{
	int error;
	struct inode *inode = dentry->d_inode;

	attr->ia_valid &= ~ATTR_SIZE;
	error = inode_change_ok(inode, attr);
Christoph Hellwig's avatar
Christoph Hellwig committed
216 217
	if (error)
		return error;
218

Christoph Hellwig's avatar
Christoph Hellwig committed
219 220 221
	setattr_copy(inode, attr);
	mark_inode_dirty(inode);
	return 0;
222 223
}

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
static unsigned int dlmfs_file_poll(struct file *file, poll_table *wait)
{
	int event = 0;
	struct inode *inode = file->f_path.dentry->d_inode;
	struct dlmfs_inode_private *ip = DLMFS_I(inode);

	poll_wait(file, &ip->ip_lockres.l_event, wait);

	spin_lock(&ip->ip_lockres.l_lock);
	if (ip->ip_lockres.l_flags & USER_LOCK_BLOCKED)
		event = POLLIN | POLLRDNORM;
	spin_unlock(&ip->ip_lockres.l_lock);

	return event;
}

240 241 242 243 244 245
static ssize_t dlmfs_file_read(struct file *filp,
			       char __user *buf,
			       size_t count,
			       loff_t *ppos)
{
	int bytes_left;
Joel Becker's avatar
Joel Becker committed
246
	ssize_t readlen, got;
247
	char *lvb_buf;
248
	struct inode *inode = filp->f_path.dentry->d_inode;
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265

	mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
		inode->i_ino, count, *ppos);

	if (*ppos >= i_size_read(inode))
		return 0;

	if (!count)
		return 0;

	if (!access_ok(VERIFY_WRITE, buf, count))
		return -EFAULT;

	/* don't read past the lvb */
	if ((count + *ppos) > i_size_read(inode))
		readlen = i_size_read(inode) - *ppos;
	else
266
		readlen = count;
267

268
	lvb_buf = kmalloc(readlen, GFP_NOFS);
269 270 271
	if (!lvb_buf)
		return -ENOMEM;

Joel Becker's avatar
Joel Becker committed
272 273 274 275 276 277 278
	got = user_dlm_read_lvb(inode, lvb_buf, readlen);
	if (got) {
		BUG_ON(got != readlen);
		bytes_left = __copy_to_user(buf, lvb_buf, readlen);
		readlen -= bytes_left;
	} else
		readlen = 0;
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295

	kfree(lvb_buf);

	*ppos = *ppos + readlen;

	mlog(0, "read %zd bytes\n", readlen);
	return readlen;
}

static ssize_t dlmfs_file_write(struct file *filp,
				const char __user *buf,
				size_t count,
				loff_t *ppos)
{
	int bytes_left;
	ssize_t writelen;
	char *lvb_buf;
296
	struct inode *inode = filp->f_path.dentry->d_inode;
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

	mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
		inode->i_ino, count, *ppos);

	if (*ppos >= i_size_read(inode))
		return -ENOSPC;

	if (!count)
		return 0;

	if (!access_ok(VERIFY_READ, buf, count))
		return -EFAULT;

	/* don't write past the lvb */
	if ((count + *ppos) > i_size_read(inode))
		writelen = i_size_read(inode) - *ppos;
	else
		writelen = count - *ppos;

316
	lvb_buf = kmalloc(writelen, GFP_NOFS);
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
	if (!lvb_buf)
		return -ENOMEM;

	bytes_left = copy_from_user(lvb_buf, buf, writelen);
	writelen -= bytes_left;
	if (writelen)
		user_dlm_write_lvb(inode, lvb_buf, writelen);

	kfree(lvb_buf);

	*ppos = *ppos + writelen;
	mlog(0, "wrote %zd bytes\n", writelen);
	return writelen;
}

332
static void dlmfs_init_once(void *foo)
333 334 335 336
{
	struct dlmfs_inode_private *ip =
		(struct dlmfs_inode_private *) foo;

Joel Becker's avatar
Joel Becker committed
337
	ip->ip_conn = NULL;
338
	ip->ip_parent = NULL;
339

340
	inode_init_once(&ip->ip_vfs_inode);
341 342 343 344 345 346
}

static struct inode *dlmfs_alloc_inode(struct super_block *sb)
{
	struct dlmfs_inode_private *ip;

347
	ip = kmem_cache_alloc(dlmfs_inode_cache, GFP_NOFS);
348 349 350 351 352 353
	if (!ip)
		return NULL;

	return &ip->ip_vfs_inode;
}

Nick Piggin's avatar
Nick Piggin committed
354
static void dlmfs_i_callback(struct rcu_head *head)
355
{
Nick Piggin's avatar
Nick Piggin committed
356
	struct inode *inode = container_of(head, struct inode, i_rcu);
357 358 359
	kmem_cache_free(dlmfs_inode_cache, DLMFS_I(inode));
}

Nick Piggin's avatar
Nick Piggin committed
360 361 362 363 364
static void dlmfs_destroy_inode(struct inode *inode)
{
	call_rcu(&inode->i_rcu, dlmfs_i_callback);
}

365
static void dlmfs_evict_inode(struct inode *inode)
366 367 368 369
{
	int status;
	struct dlmfs_inode_private *ip;

370
	end_writeback(inode);
371 372 373 374 375 376 377 378 379 380 381 382 383

	mlog(0, "inode %lu\n", inode->i_ino);

	ip = DLMFS_I(inode);

	if (S_ISREG(inode->i_mode)) {
		status = user_dlm_destroy_lock(&ip->ip_lockres);
		if (status < 0)
			mlog_errno(status);
		iput(ip->ip_parent);
		goto clear_fields;
	}

Joel Becker's avatar
Joel Becker committed
384
	mlog(0, "we're a directory, ip->ip_conn = 0x%p\n", ip->ip_conn);
385 386
	/* we must be a directory. If required, lets unregister the
	 * dlm context now. */
Joel Becker's avatar
Joel Becker committed
387 388
	if (ip->ip_conn)
		user_dlm_unregister(ip->ip_conn);
389 390
clear_fields:
	ip->ip_parent = NULL;
Joel Becker's avatar
Joel Becker committed
391
	ip->ip_conn = NULL;
392 393 394
}

static struct backing_dev_info dlmfs_backing_dev_info = {
395
	.name		= "ocfs2-dlmfs",
396
	.ra_pages	= 0,	/* No readahead */
397
	.capabilities	= BDI_CAP_NO_ACCT_AND_WRITEBACK,
398 399 400 401 402 403 404 405 406 407 408
};

static struct inode *dlmfs_get_root_inode(struct super_block *sb)
{
	struct inode *inode = new_inode(sb);
	int mode = S_IFDIR | 0755;
	struct dlmfs_inode_private *ip;

	if (inode) {
		ip = DLMFS_I(inode);

409
		inode->i_ino = get_next_ino();
Al Viro's avatar
Al Viro committed
410
		inode_init_owner(inode, NULL, mode);
411 412
		inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
413
		inc_nlink(inode);
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432

		inode->i_fop = &simple_dir_operations;
		inode->i_op = &dlmfs_root_inode_operations;
	}

	return inode;
}

static struct inode *dlmfs_get_inode(struct inode *parent,
				     struct dentry *dentry,
				     int mode)
{
	struct super_block *sb = parent->i_sb;
	struct inode * inode = new_inode(sb);
	struct dlmfs_inode_private *ip;

	if (!inode)
		return NULL;

433
	inode->i_ino = get_next_ino();
Al Viro's avatar
Al Viro committed
434
	inode_init_owner(inode, parent, mode);
435 436 437 438
	inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;

	ip = DLMFS_I(inode);
Joel Becker's avatar
Joel Becker committed
439
	ip->ip_conn = DLMFS_I(parent)->ip_conn;
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467

	switch (mode & S_IFMT) {
	default:
		/* for now we don't support anything other than
		 * directories and regular files. */
		BUG();
		break;
	case S_IFREG:
		inode->i_op = &dlmfs_file_inode_operations;
		inode->i_fop = &dlmfs_file_operations;

		i_size_write(inode,  DLM_LVB_LEN);

		user_dlm_lock_res_init(&ip->ip_lockres, dentry);

		/* released at clear_inode time, this insures that we
		 * get to drop the dlm reference on each lock *before*
		 * we call the unregister code for releasing parent
		 * directories. */
		ip->ip_parent = igrab(parent);
		BUG_ON(!ip->ip_parent);
		break;
	case S_IFDIR:
		inode->i_op = &dlmfs_dir_inode_operations;
		inode->i_fop = &simple_dir_operations;

		/* directory inodes start off with i_nlink ==
		 * 2 (for "." entry) */
468
		inc_nlink(inode);
469 470 471 472 473 474 475 476 477 478 479
		break;
	}
	return inode;
}

/*
 * File creation. Allocate an inode, and we're done..
 */
/* SMP-safe */
static int dlmfs_mkdir(struct inode * dir,
		       struct dentry * dentry,
480
		       umode_t mode)
481 482 483 484 485
{
	int status;
	struct inode *inode = NULL;
	struct qstr *domain = &dentry->d_name;
	struct dlmfs_inode_private *ip;
Joel Becker's avatar
Joel Becker committed
486
	struct ocfs2_cluster_connection *conn;
487 488 489 490

	mlog(0, "mkdir %.*s\n", domain->len, domain->name);

	/* verify that we have a proper domain */
Joel Becker's avatar
Joel Becker committed
491
	if (domain->len >= GROUP_NAME_MAX) {
492 493 494 495 496 497 498 499 500 501 502 503 504 505
		status = -EINVAL;
		mlog(ML_ERROR, "invalid domain name for directory.\n");
		goto bail;
	}

	inode = dlmfs_get_inode(dir, dentry, mode | S_IFDIR);
	if (!inode) {
		status = -ENOMEM;
		mlog_errno(status);
		goto bail;
	}

	ip = DLMFS_I(inode);

Joel Becker's avatar
Joel Becker committed
506 507 508
	conn = user_dlm_register(domain);
	if (IS_ERR(conn)) {
		status = PTR_ERR(conn);
509 510 511 512
		mlog(ML_ERROR, "Error %d could not register domain \"%.*s\"\n",
		     status, domain->len, domain->name);
		goto bail;
	}
Joel Becker's avatar
Joel Becker committed
513
	ip->ip_conn = conn;
514

515
	inc_nlink(dir);
516 517 518 519 520 521 522 523 524 525 526 527
	d_instantiate(dentry, inode);
	dget(dentry);	/* Extra count - pin the dentry in core */

	status = 0;
bail:
	if (status < 0)
		iput(inode);
	return status;
}

static int dlmfs_create(struct inode *dir,
			struct dentry *dentry,
Al Viro's avatar
Al Viro committed
528
			umode_t mode,
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
			struct nameidata *nd)
{
	int status = 0;
	struct inode *inode;
	struct qstr *name = &dentry->d_name;

	mlog(0, "create %.*s\n", name->len, name->name);

	/* verify name is valid and doesn't contain any dlm reserved
	 * characters */
	if (name->len >= USER_DLM_LOCK_ID_MAX_LEN ||
	    name->name[0] == '$') {
		status = -EINVAL;
		mlog(ML_ERROR, "invalid lock name, %.*s\n", name->len,
		     name->name);
		goto bail;
	}

	inode = dlmfs_get_inode(dir, dentry, mode | S_IFREG);
	if (!inode) {
		status = -ENOMEM;
		mlog_errno(status);
		goto bail;
	}

	d_instantiate(dentry, inode);
	dget(dentry);	/* Extra count - pin the dentry in core */
bail:
	return status;
}

static int dlmfs_unlink(struct inode *dir,
			struct dentry *dentry)
{
	int status;
	struct inode *inode = dentry->d_inode;

	mlog(0, "unlink inode %lu\n", inode->i_ino);

	/* if there are no current holders, or none that are waiting
	 * to acquire a lock, this basically destroys our lockres. */
	status = user_dlm_destroy_lock(&DLMFS_I(inode)->ip_lockres);
	if (status < 0) {
		mlog(ML_ERROR, "unlink %.*s, error %d from destroy\n",
		     dentry->d_name.len, dentry->d_name.name, status);
		goto bail;
	}
	status = simple_unlink(dir, dentry);
bail:
	return status;
}

static int dlmfs_fill_super(struct super_block * sb,
			    void * data,
			    int silent)
{
	struct inode * inode;
	struct dentry * root;

	sb->s_maxbytes = MAX_LFS_FILESIZE;
	sb->s_blocksize = PAGE_CACHE_SIZE;
	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
	sb->s_magic = DLMFS_MAGIC;
	sb->s_op = &dlmfs_ops;
	inode = dlmfs_get_root_inode(sb);
	if (!inode)
		return -ENOMEM;

	root = d_alloc_root(inode);
	if (!root) {
		iput(inode);
		return -ENOMEM;
	}
	sb->s_root = root;
	return 0;
}

606
static const struct file_operations dlmfs_file_operations = {
607 608
	.open		= dlmfs_file_open,
	.release	= dlmfs_file_release,
609
	.poll		= dlmfs_file_poll,
610 611
	.read		= dlmfs_file_read,
	.write		= dlmfs_file_write,
612
	.llseek		= default_llseek,
613 614
};

615
static const struct inode_operations dlmfs_dir_inode_operations = {
616 617 618 619 620 621
	.create		= dlmfs_create,
	.lookup		= simple_lookup,
	.unlink		= dlmfs_unlink,
};

/* this way we can restrict mkdir to only the toplevel of the fs. */
622
static const struct inode_operations dlmfs_root_inode_operations = {
623 624 625 626 627
	.lookup		= simple_lookup,
	.mkdir		= dlmfs_mkdir,
	.rmdir		= simple_rmdir,
};

628
static const struct super_operations dlmfs_ops = {
629 630 631
	.statfs		= simple_statfs,
	.alloc_inode	= dlmfs_alloc_inode,
	.destroy_inode	= dlmfs_destroy_inode,
632
	.evict_inode	= dlmfs_evict_inode,
633 634 635
	.drop_inode	= generic_delete_inode,
};

636
static const struct inode_operations dlmfs_file_inode_operations = {
637
	.getattr	= simple_getattr,
638
	.setattr	= dlmfs_file_setattr,
639 640
};

Al Viro's avatar
Al Viro committed
641 642
static struct dentry *dlmfs_mount(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data)
643
{
Al Viro's avatar
Al Viro committed
644
	return mount_nodev(fs_type, flags, data, dlmfs_fill_super);
645 646 647 648 649
}

static struct file_system_type dlmfs_fs_type = {
	.owner		= THIS_MODULE,
	.name		= "ocfs2_dlmfs",
Al Viro's avatar
Al Viro committed
650
	.mount		= dlmfs_mount,
651 652 653 654 655 656 657 658 659 660
	.kill_sb	= kill_litter_super,
};

static int __init init_dlmfs_fs(void)
{
	int status;
	int cleanup_inode = 0, cleanup_worker = 0;

	dlmfs_print_version();

Peter Zijlstra's avatar
Peter Zijlstra committed
661 662 663 664
	status = bdi_init(&dlmfs_backing_dev_info);
	if (status)
		return status;

665 666
	dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache",
				sizeof(struct dlmfs_inode_private),
667 668
				0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
					SLAB_MEM_SPREAD),
669
				dlmfs_init_once);
670 671
	if (!dlmfs_inode_cache) {
		status = -ENOMEM;
Peter Zijlstra's avatar
Peter Zijlstra committed
672
		goto bail;
673
	}
674 675 676 677 678 679 680 681 682
	cleanup_inode = 1;

	user_dlm_worker = create_singlethread_workqueue("user_dlm");
	if (!user_dlm_worker) {
		status = -ENOMEM;
		goto bail;
	}
	cleanup_worker = 1;

Joel Becker's avatar
Joel Becker committed
683
	user_dlm_set_locking_protocol();
684 685 686 687 688 689 690
	status = register_filesystem(&dlmfs_fs_type);
bail:
	if (status) {
		if (cleanup_inode)
			kmem_cache_destroy(dlmfs_inode_cache);
		if (cleanup_worker)
			destroy_workqueue(user_dlm_worker);
Peter Zijlstra's avatar
Peter Zijlstra committed
691
		bdi_destroy(&dlmfs_backing_dev_info);
692 693 694 695 696 697 698 699 700 701 702 703
	} else
		printk("OCFS2 User DLM kernel interface loaded\n");
	return status;
}

static void __exit exit_dlmfs_fs(void)
{
	unregister_filesystem(&dlmfs_fs_type);

	flush_workqueue(user_dlm_worker);
	destroy_workqueue(user_dlm_worker);

704
	kmem_cache_destroy(dlmfs_inode_cache);
Peter Zijlstra's avatar
Peter Zijlstra committed
705 706

	bdi_destroy(&dlmfs_backing_dev_info);
707 708 709 710 711 712 713
}

MODULE_AUTHOR("Oracle");
MODULE_LICENSE("GPL");

module_init(init_dlmfs_fs)
module_exit(exit_dlmfs_fs)