orangefs-mod.c 8.2 KB
Newer Older
M
Mike Marshall 已提交
1 2 3 4 5 6 7 8 9 10
/*
 * (C) 2001 Clemson University and The University of Chicago
 *
 * Changes by Acxiom Corporation to add proc file handler for pvfs2 client
 * parameters, Copyright Acxiom Corporation, 2005.
 *
 * See COPYING in top-level directory.
 */

#include "protocol.h"
11 12 13
#include "orangefs-kernel.h"
#include "orangefs-debugfs.h"
#include "orangefs-sysfs.h"
M
Mike Marshall 已提交
14

15 16
/* ORANGEFS_VERSION is a ./configure define */
#ifndef ORANGEFS_VERSION
17
#define ORANGEFS_VERSION "upstream"
M
Mike Marshall 已提交
18 19 20 21 22 23 24 25 26 27
#endif

/*
 * global variables declared here
 */

/* array of client debug keyword/mask values */
struct client_debug_mask *cdm_array;
int cdm_element_count;

28 29 30
char kernel_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN] = "none";
char client_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN];
char client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN];
M
Mike Marshall 已提交
31 32 33 34 35 36 37 38

char *debug_help_string;
int help_string_initialized;
struct dentry *help_file_dentry;
struct dentry *client_debug_dentry;
struct dentry *debug_dir;
int client_verbose_index;
int client_all_index;
39
struct orangefs_stats g_orangefs_stats;
M
Mike Marshall 已提交
40 41 42 43 44 45 46 47

/* the size of the hash tables for ops in progress */
int hash_table_size = 509;

static ulong module_parm_debug_mask;
__u64 gossip_debug_mask;
struct client_debug_mask client_debug_mask = { NULL, 0, 0 };
unsigned int kernel_mask_set_mod_init; /* implicitly false */
48 49
int op_timeout_secs = ORANGEFS_DEFAULT_OP_TIMEOUT_SECS;
int slot_timeout_secs = ORANGEFS_DEFAULT_SLOT_TIMEOUT_SECS;
M
Mike Marshall 已提交
50 51

MODULE_LICENSE("GPL");
52 53 54
MODULE_AUTHOR("ORANGEFS Development Team");
MODULE_DESCRIPTION("The Linux Kernel VFS interface to ORANGEFS");
MODULE_PARM_DESC(module_parm_debug_mask, "debugging level (see orangefs-debug.h for values)");
M
Mike Marshall 已提交
55 56 57 58 59
MODULE_PARM_DESC(op_timeout_secs, "Operation timeout in seconds");
MODULE_PARM_DESC(slot_timeout_secs, "Slot timeout in seconds");
MODULE_PARM_DESC(hash_table_size,
		 "size of hash table for operations in progress");

60
static struct file_system_type orangefs_fs_type = {
M
Mike Marshall 已提交
61
	.name = "pvfs2",
62 63
	.mount = orangefs_mount,
	.kill_sb = orangefs_kill_sb,
M
Mike Marshall 已提交
64 65 66 67
	.owner = THIS_MODULE,
};

module_param(hash_table_size, int, 0);
68
module_param(module_parm_debug_mask, ulong, 0644);
M
Mike Marshall 已提交
69 70 71 72 73 74 75
module_param(op_timeout_secs, int, 0);
module_param(slot_timeout_secs, int, 0);

/* synchronizes the request device file */
struct mutex devreq_mutex;

/*
76 77 78 79 80
 * Blocks non-priority requests from being queued for servicing.  This
 * could be used for protecting the request list data structure, but
 * for now it's only being used to stall the op addition to the request
 * list
 */
M
Mike Marshall 已提交
81 82 83 84 85 86 87
struct mutex request_mutex;

/* hash table for storing operations waiting for matching downcall */
struct list_head *htable_ops_in_progress;
DEFINE_SPINLOCK(htable_ops_in_progress_lock);

/* list for queueing upcall operations */
88
LIST_HEAD(orangefs_request_list);
M
Mike Marshall 已提交
89

90 91
/* used to protect the above orangefs_request_list */
DEFINE_SPINLOCK(orangefs_request_list_lock);
M
Mike Marshall 已提交
92 93

/* used for incoming request notification */
94
DECLARE_WAIT_QUEUE_HEAD(orangefs_request_list_waitq);
M
Mike Marshall 已提交
95

96
static int __init orangefs_init(void)
M
Mike Marshall 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
{
	int ret = -1;
	__u32 i = 0;

	/* convert input debug mask to a 64-bit unsigned integer */
	gossip_debug_mask = (unsigned long long) module_parm_debug_mask;

	/*
	 * set the kernel's gossip debug string; invalid mask values will
	 * be ignored.
	 */
	debug_mask_to_string(&gossip_debug_mask, 0);

	/* remove any invalid values from the mask */
	debug_string_to_mask(kernel_debug_string, &gossip_debug_mask, 0);

	/*
	 * if the mask has a non-zero value, then indicate that the mask
115
	 * was set when the kernel module was loaded.  The orangefs dev ioctl
M
Mike Marshall 已提交
116 117 118 119 120 121 122
	 * command will look at this boolean to determine if the kernel's
	 * debug mask should be overwritten when the client-core is started.
	 */
	if (gossip_debug_mask != 0)
		kernel_mask_set_mod_init = true;

	/* print information message to the system log */
123
	pr_info("orangefs: orangefs_init called with debug mask: :%s: :%llx:\n",
M
Mike Marshall 已提交
124 125 126
	       kernel_debug_string,
	       (unsigned long long)gossip_debug_mask);

127
	ret = bdi_init(&orangefs_backing_dev_info);
M
Mike Marshall 已提交
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

	if (ret)
		return ret;

	if (op_timeout_secs < 0)
		op_timeout_secs = 0;

	if (slot_timeout_secs < 0)
		slot_timeout_secs = 0;

	/* initialize global book keeping data structures */
	ret = op_cache_initialize();
	if (ret < 0)
		goto err;

	ret = dev_req_cache_initialize();
	if (ret < 0)
		goto cleanup_op;

147
	ret = orangefs_inode_cache_initialize();
M
Mike Marshall 已提交
148 149 150 151 152 153 154
	if (ret < 0)
		goto cleanup_req;

	ret = kiocb_cache_initialize();
	if (ret  < 0)
		goto cleanup_inode;

155
	/* Initialize the orangefsdev subsystem. */
156
	ret = orangefs_dev_init();
M
Mike Marshall 已提交
157
	if (ret < 0) {
158
		gossip_err("orangefs: could not initialize device subsystem %d!\n",
M
Mike Marshall 已提交
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
			   ret);
		goto cleanup_kiocb;
	}

	mutex_init(&devreq_mutex);
	mutex_init(&request_mutex);

	htable_ops_in_progress =
	    kcalloc(hash_table_size, sizeof(struct list_head), GFP_KERNEL);
	if (!htable_ops_in_progress) {
		gossip_err("Failed to initialize op hashtable");
		ret = -ENOMEM;
		goto cleanup_device;
	}

	/* initialize a doubly linked at each hash table index */
	for (i = 0; i < hash_table_size; i++)
		INIT_LIST_HEAD(&htable_ops_in_progress[i]);

	ret = fsid_key_table_initialize();
	if (ret < 0)
		goto cleanup_progress_table;

	/*
	 * Build the contents of /sys/kernel/debug/orangefs/debug-help
	 * from the keywords in the kernel keyword/mask array.
	 *
	 * The keywords in the client keyword/mask array are
	 * unknown at boot time.
	 *
	 * orangefs_prepare_debugfs_help_string will be used again
	 * later to rebuild the debug-help file after the client starts
	 * and passes along the needed info. The argument signifies
	 * which time orangefs_prepare_debugfs_help_string is being
	 * called.
	 *
	 */
	ret = orangefs_prepare_debugfs_help_string(1);
	if (ret)
		goto out;

200 201
	orangefs_debugfs_init();
	orangefs_kernel_debug_init();
M
Mike Marshall 已提交
202 203
	orangefs_sysfs_init();

204
	ret = register_filesystem(&orangefs_fs_type);
M
Mike Marshall 已提交
205
	if (ret == 0) {
206
		pr_info("orangefs: module version %s loaded\n", ORANGEFS_VERSION);
M
Mike Marshall 已提交
207 208 209
		return 0;
	}

210
	orangefs_debugfs_cleanup();
M
Mike Marshall 已提交
211 212 213 214 215 216 217
	orangefs_sysfs_exit();
	fsid_key_table_finalize();

cleanup_progress_table:
	kfree(htable_ops_in_progress);

cleanup_device:
218
	orangefs_dev_cleanup();
M
Mike Marshall 已提交
219 220 221 222 223

cleanup_kiocb:
	kiocb_cache_finalize();

cleanup_inode:
224
	orangefs_inode_cache_finalize();
M
Mike Marshall 已提交
225 226 227 228 229 230 231 232

cleanup_req:
	dev_req_cache_finalize();

cleanup_op:
	op_cache_finalize();

err:
233
	bdi_destroy(&orangefs_backing_dev_info);
M
Mike Marshall 已提交
234 235 236 237 238

out:
	return ret;
}

239
static void __exit orangefs_exit(void)
M
Mike Marshall 已提交
240 241
{
	int i = 0;
242
	struct orangefs_kernel_op_s *cur_op = NULL;
M
Mike Marshall 已提交
243

244
	gossip_debug(GOSSIP_INIT_DEBUG, "orangefs: orangefs_exit called\n");
M
Mike Marshall 已提交
245

246 247
	unregister_filesystem(&orangefs_fs_type);
	orangefs_debugfs_cleanup();
M
Mike Marshall 已提交
248 249
	orangefs_sysfs_exit();
	fsid_key_table_finalize();
250
	orangefs_dev_cleanup();
M
Mike Marshall 已提交
251
	/* clear out all pending upcall op requests */
252 253 254 255
	spin_lock(&orangefs_request_list_lock);
	while (!list_empty(&orangefs_request_list)) {
		cur_op = list_entry(orangefs_request_list.next,
				    struct orangefs_kernel_op_s,
M
Mike Marshall 已提交
256 257 258 259 260 261 262
				    list);
		list_del(&cur_op->list);
		gossip_debug(GOSSIP_INIT_DEBUG,
			     "Freeing unhandled upcall request type %d\n",
			     cur_op->upcall.type);
		op_release(cur_op);
	}
263
	spin_unlock(&orangefs_request_list_lock);
M
Mike Marshall 已提交
264 265 266 267

	for (i = 0; i < hash_table_size; i++)
		while (!list_empty(&htable_ops_in_progress[i])) {
			cur_op = list_entry(htable_ops_in_progress[i].next,
268
					    struct orangefs_kernel_op_s,
M
Mike Marshall 已提交
269 270 271 272 273
					    list);
			op_release(cur_op);
		}

	kiocb_cache_finalize();
274
	orangefs_inode_cache_finalize();
M
Mike Marshall 已提交
275 276 277 278 279
	dev_req_cache_finalize();
	op_cache_finalize();

	kfree(htable_ops_in_progress);

280
	bdi_destroy(&orangefs_backing_dev_info);
M
Mike Marshall 已提交
281

282
	pr_info("orangefs: module version %s unloaded\n", ORANGEFS_VERSION);
M
Mike Marshall 已提交
283 284 285 286 287 288 289 290 291 292 293
}

/*
 * What we do in this function is to walk the list of operations
 * that are in progress in the hash table and mark them as purged as well.
 */
void purge_inprogress_ops(void)
{
	int i;

	for (i = 0; i < hash_table_size; i++) {
294 295
		struct orangefs_kernel_op_s *op;
		struct orangefs_kernel_op_s *next;
M
Mike Marshall 已提交
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313

		list_for_each_entry_safe(op,
					 next,
					 &htable_ops_in_progress[i],
					 list) {
			spin_lock(&op->lock);
			gossip_debug(GOSSIP_INIT_DEBUG,
				"pvfs2-client-core: purging in-progress op tag "
				"%llu %s\n",
				llu(op->tag),
				get_opname_string(op));
			set_op_state_purged(op);
			spin_unlock(&op->lock);
			wake_up_interruptible(&op->waitq);
		}
	}
}

314 315
module_init(orangefs_init);
module_exit(orangefs_exit);