stack_user.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. /* -*- mode: c; c-basic-offset: 8; -*-
  2. * vim: noexpandtab sw=8 ts=8 sts=0:
  3. *
  4. * stack_user.c
  5. *
  6. * Code which interfaces ocfs2 with fs/dlm and a userspace stack.
  7. *
  8. * Copyright (C) 2007 Oracle. All rights reserved.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public
  12. * License as published by the Free Software Foundation, version 2.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. */
  19. #include <linux/module.h>
  20. #include <linux/fs.h>
  21. #include <linux/miscdevice.h>
  22. #include <linux/mutex.h>
  23. #include <linux/reboot.h>
  24. #include <asm/uaccess.h>
  25. #include "stackglue.h"
  26. /*
  27. * The control protocol starts with a handshake. Until the handshake
  28. * is complete, the control device will fail all write(2)s.
  29. *
  30. * The handshake is simple. First, the client reads until EOF. Each line
  31. * of output is a supported protocol tag. All protocol tags are a single
  32. * character followed by a two hex digit version number. Currently the
  33. * only things supported is T01, for "Text-base version 0x01". Next, the
  34. * client writes the version they would like to use, including the newline.
  35. * Thus, the protocol tag is 'T01\n'. If the version tag written is
  36. * unknown, -EINVAL is returned. Once the negotiation is complete, the
  37. * client can start sending messages.
  38. *
  39. * The T01 protocol has three messages. First is the "SETN" message.
  40. * It has the following syntax:
  41. *
  42. * SETN<space><8-char-hex-nodenum><newline>
  43. *
  44. * This is 14 characters.
  45. *
  46. * The "SETN" message must be the first message following the protocol.
  47. * It tells ocfs2_control the local node number.
  48. *
  49. * Next comes the "SETV" message. It has the following syntax:
  50. *
  51. * SETV<space><2-char-hex-major><space><2-char-hex-minor><newline>
  52. *
  53. * This is 11 characters.
  54. *
  55. * The "SETV" message sets the filesystem locking protocol version as
  56. * negotiated by the client. The client negotiates based on the maximum
  57. * version advertised in /sys/fs/ocfs2/max_locking_protocol. The major
  58. * number from the "SETV" message must match
  59. * user_stack.sp_proto->lp_max_version.pv_major, and the minor number
  60. * must be less than or equal to ...->lp_max_version.pv_minor.
  61. *
  62. * Once this information has been set, mounts will be allowed. From this
  63. * point on, the "DOWN" message can be sent for node down notification.
  64. * It has the following syntax:
  65. *
  66. * DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline>
  67. *
  68. * eg:
  69. *
  70. * DOWN 632A924FDD844190BDA93C0DF6B94899 00000001\n
  71. *
  72. * This is 47 characters.
  73. */
  74. /*
  75. * Whether or not the client has done the handshake.
  76. * For now, we have just one protocol version.
  77. */
  78. #define OCFS2_CONTROL_PROTO "T01\n"
  79. #define OCFS2_CONTROL_PROTO_LEN 4
  80. /* Handshake states */
  81. #define OCFS2_CONTROL_HANDSHAKE_INVALID (0)
  82. #define OCFS2_CONTROL_HANDSHAKE_READ (1)
  83. #define OCFS2_CONTROL_HANDSHAKE_PROTOCOL (2)
  84. #define OCFS2_CONTROL_HANDSHAKE_VALID (3)
  85. /* Messages */
  86. #define OCFS2_CONTROL_MESSAGE_OP_LEN 4
  87. #define OCFS2_CONTROL_MESSAGE_SETNODE_OP "SETN"
  88. #define OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN 14
  89. #define OCFS2_CONTROL_MESSAGE_SETVERSION_OP "SETV"
  90. #define OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN 11
  91. #define OCFS2_CONTROL_MESSAGE_DOWN_OP "DOWN"
  92. #define OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN 47
  93. #define OCFS2_TEXT_UUID_LEN 32
  94. #define OCFS2_CONTROL_MESSAGE_VERNUM_LEN 2
  95. #define OCFS2_CONTROL_MESSAGE_NODENUM_LEN 8
  96. /*
  97. * ocfs2_live_connection is refcounted because the filesystem and
  98. * miscdevice sides can detach in different order. Let's just be safe.
  99. */
  100. struct ocfs2_live_connection {
  101. struct list_head oc_list;
  102. struct ocfs2_cluster_connection *oc_conn;
  103. };
  104. struct ocfs2_control_private {
  105. struct list_head op_list;
  106. int op_state;
  107. int op_this_node;
  108. struct ocfs2_protocol_version op_proto;
  109. };
  110. /* SETN<space><8-char-hex-nodenum><newline> */
  111. struct ocfs2_control_message_setn {
  112. char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
  113. char space;
  114. char nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
  115. char newline;
  116. };
  117. /* SETV<space><2-char-hex-major><space><2-char-hex-minor><newline> */
  118. struct ocfs2_control_message_setv {
  119. char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
  120. char space1;
  121. char major[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
  122. char space2;
  123. char minor[OCFS2_CONTROL_MESSAGE_VERNUM_LEN];
  124. char newline;
  125. };
  126. /* DOWN<space><32-char-cap-hex-uuid><space><8-char-hex-nodenum><newline> */
  127. struct ocfs2_control_message_down {
  128. char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
  129. char space1;
  130. char uuid[OCFS2_TEXT_UUID_LEN];
  131. char space2;
  132. char nodestr[OCFS2_CONTROL_MESSAGE_NODENUM_LEN];
  133. char newline;
  134. };
  135. union ocfs2_control_message {
  136. char tag[OCFS2_CONTROL_MESSAGE_OP_LEN];
  137. struct ocfs2_control_message_setn u_setn;
  138. struct ocfs2_control_message_setv u_setv;
  139. struct ocfs2_control_message_down u_down;
  140. };
  141. static atomic_t ocfs2_control_opened;
  142. static int ocfs2_control_this_node = -1;
  143. static struct ocfs2_protocol_version running_proto;
  144. static LIST_HEAD(ocfs2_live_connection_list);
  145. static LIST_HEAD(ocfs2_control_private_list);
  146. static DEFINE_MUTEX(ocfs2_control_lock);
  147. static inline void ocfs2_control_set_handshake_state(struct file *file,
  148. int state)
  149. {
  150. struct ocfs2_control_private *p = file->private_data;
  151. p->op_state = state;
  152. }
  153. static inline int ocfs2_control_get_handshake_state(struct file *file)
  154. {
  155. struct ocfs2_control_private *p = file->private_data;
  156. return p->op_state;
  157. }
  158. static struct ocfs2_live_connection *ocfs2_connection_find(const char *name)
  159. {
  160. size_t len = strlen(name);
  161. struct ocfs2_live_connection *c;
  162. BUG_ON(!mutex_is_locked(&ocfs2_control_lock));
  163. list_for_each_entry(c, &ocfs2_live_connection_list, oc_list) {
  164. if ((c->oc_conn->cc_namelen == len) &&
  165. !strncmp(c->oc_conn->cc_name, name, len))
  166. return c;
  167. }
  168. return c;
  169. }
  170. /*
  171. * ocfs2_live_connection structures are created underneath the ocfs2
  172. * mount path. Since the VFS prevents multiple calls to
  173. * fill_super(), we can't get dupes here.
  174. */
  175. static int ocfs2_live_connection_new(struct ocfs2_cluster_connection *conn,
  176. struct ocfs2_live_connection **c_ret)
  177. {
  178. int rc = 0;
  179. struct ocfs2_live_connection *c;
  180. c = kzalloc(sizeof(struct ocfs2_live_connection), GFP_KERNEL);
  181. if (!c)
  182. return -ENOMEM;
  183. mutex_lock(&ocfs2_control_lock);
  184. c->oc_conn = conn;
  185. if (atomic_read(&ocfs2_control_opened))
  186. list_add(&c->oc_list, &ocfs2_live_connection_list);
  187. else {
  188. printk(KERN_ERR
  189. "ocfs2: Userspace control daemon is not present\n");
  190. rc = -ESRCH;
  191. }
  192. mutex_unlock(&ocfs2_control_lock);
  193. if (!rc)
  194. *c_ret = c;
  195. else
  196. kfree(c);
  197. return rc;
  198. }
  199. /*
  200. * This function disconnects the cluster connection from ocfs2_control.
  201. * Afterwards, userspace can't affect the cluster connection.
  202. */
  203. static void ocfs2_live_connection_drop(struct ocfs2_live_connection *c)
  204. {
  205. mutex_lock(&ocfs2_control_lock);
  206. list_del_init(&c->oc_list);
  207. c->oc_conn = NULL;
  208. mutex_unlock(&ocfs2_control_lock);
  209. kfree(c);
  210. }
  211. static int ocfs2_control_cfu(void *target, size_t target_len,
  212. const char __user *buf, size_t count)
  213. {
  214. /* The T01 expects write(2) calls to have exactly one command */
  215. if ((count != target_len) ||
  216. (count > sizeof(union ocfs2_control_message)))
  217. return -EINVAL;
  218. if (copy_from_user(target, buf, target_len))
  219. return -EFAULT;
  220. return 0;
  221. }
  222. static ssize_t ocfs2_control_validate_protocol(struct file *file,
  223. const char __user *buf,
  224. size_t count)
  225. {
  226. ssize_t ret;
  227. char kbuf[OCFS2_CONTROL_PROTO_LEN];
  228. ret = ocfs2_control_cfu(kbuf, OCFS2_CONTROL_PROTO_LEN,
  229. buf, count);
  230. if (ret)
  231. return ret;
  232. if (strncmp(kbuf, OCFS2_CONTROL_PROTO, OCFS2_CONTROL_PROTO_LEN))
  233. return -EINVAL;
  234. ocfs2_control_set_handshake_state(file,
  235. OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
  236. return count;
  237. }
  238. static void ocfs2_control_send_down(const char *uuid,
  239. int nodenum)
  240. {
  241. struct ocfs2_live_connection *c;
  242. mutex_lock(&ocfs2_control_lock);
  243. c = ocfs2_connection_find(uuid);
  244. if (c) {
  245. BUG_ON(c->oc_conn == NULL);
  246. c->oc_conn->cc_recovery_handler(nodenum,
  247. c->oc_conn->cc_recovery_data);
  248. }
  249. mutex_unlock(&ocfs2_control_lock);
  250. }
  251. /*
  252. * Called whenever configuration elements are sent to /dev/ocfs2_control.
  253. * If all configuration elements are present, try to set the global
  254. * values. If there is a problem, return an error. Skip any missing
  255. * elements, and only bump ocfs2_control_opened when we have all elements
  256. * and are successful.
  257. */
  258. static int ocfs2_control_install_private(struct file *file)
  259. {
  260. int rc = 0;
  261. int set_p = 1;
  262. struct ocfs2_control_private *p = file->private_data;
  263. BUG_ON(p->op_state != OCFS2_CONTROL_HANDSHAKE_PROTOCOL);
  264. mutex_lock(&ocfs2_control_lock);
  265. if (p->op_this_node < 0) {
  266. set_p = 0;
  267. } else if ((ocfs2_control_this_node >= 0) &&
  268. (ocfs2_control_this_node != p->op_this_node)) {
  269. rc = -EINVAL;
  270. goto out_unlock;
  271. }
  272. if (!p->op_proto.pv_major) {
  273. set_p = 0;
  274. } else if (!list_empty(&ocfs2_live_connection_list) &&
  275. ((running_proto.pv_major != p->op_proto.pv_major) ||
  276. (running_proto.pv_minor != p->op_proto.pv_minor))) {
  277. rc = -EINVAL;
  278. goto out_unlock;
  279. }
  280. if (set_p) {
  281. ocfs2_control_this_node = p->op_this_node;
  282. running_proto.pv_major = p->op_proto.pv_major;
  283. running_proto.pv_minor = p->op_proto.pv_minor;
  284. }
  285. out_unlock:
  286. mutex_unlock(&ocfs2_control_lock);
  287. if (!rc && set_p) {
  288. /* We set the global values successfully */
  289. atomic_inc(&ocfs2_control_opened);
  290. ocfs2_control_set_handshake_state(file,
  291. OCFS2_CONTROL_HANDSHAKE_VALID);
  292. }
  293. return rc;
  294. }
  295. static int ocfs2_control_do_setnode_msg(struct file *file,
  296. struct ocfs2_control_message_setn *msg)
  297. {
  298. long nodenum;
  299. char *ptr = NULL;
  300. struct ocfs2_control_private *p = file->private_data;
  301. if (ocfs2_control_get_handshake_state(file) !=
  302. OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
  303. return -EINVAL;
  304. if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
  305. OCFS2_CONTROL_MESSAGE_OP_LEN))
  306. return -EINVAL;
  307. if ((msg->space != ' ') || (msg->newline != '\n'))
  308. return -EINVAL;
  309. msg->space = msg->newline = '\0';
  310. nodenum = simple_strtol(msg->nodestr, &ptr, 16);
  311. if (!ptr || *ptr)
  312. return -EINVAL;
  313. if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
  314. (nodenum > INT_MAX) || (nodenum < 0))
  315. return -ERANGE;
  316. p->op_this_node = nodenum;
  317. return ocfs2_control_install_private(file);
  318. }
  319. static int ocfs2_control_do_setversion_msg(struct file *file,
  320. struct ocfs2_control_message_setv *msg)
  321. {
  322. long major, minor;
  323. char *ptr = NULL;
  324. struct ocfs2_control_private *p = file->private_data;
  325. struct ocfs2_protocol_version *max =
  326. &user_stack.sp_proto->lp_max_version;
  327. if (ocfs2_control_get_handshake_state(file) !=
  328. OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
  329. return -EINVAL;
  330. if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
  331. OCFS2_CONTROL_MESSAGE_OP_LEN))
  332. return -EINVAL;
  333. if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
  334. (msg->newline != '\n'))
  335. return -EINVAL;
  336. msg->space1 = msg->space2 = msg->newline = '\0';
  337. major = simple_strtol(msg->major, &ptr, 16);
  338. if (!ptr || *ptr)
  339. return -EINVAL;
  340. minor = simple_strtol(msg->minor, &ptr, 16);
  341. if (!ptr || *ptr)
  342. return -EINVAL;
  343. /*
  344. * The major must be between 1 and 255, inclusive. The minor
  345. * must be between 0 and 255, inclusive. The version passed in
  346. * must be within the maximum version supported by the filesystem.
  347. */
  348. if ((major == LONG_MIN) || (major == LONG_MAX) ||
  349. (major > (u8)-1) || (major < 1))
  350. return -ERANGE;
  351. if ((minor == LONG_MIN) || (minor == LONG_MAX) ||
  352. (minor > (u8)-1) || (minor < 0))
  353. return -ERANGE;
  354. if ((major != max->pv_major) ||
  355. (minor > max->pv_minor))
  356. return -EINVAL;
  357. p->op_proto.pv_major = major;
  358. p->op_proto.pv_minor = minor;
  359. return ocfs2_control_install_private(file);
  360. }
  361. static int ocfs2_control_do_down_msg(struct file *file,
  362. struct ocfs2_control_message_down *msg)
  363. {
  364. long nodenum;
  365. char *p = NULL;
  366. if (ocfs2_control_get_handshake_state(file) !=
  367. OCFS2_CONTROL_HANDSHAKE_VALID)
  368. return -EINVAL;
  369. if (strncmp(msg->tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
  370. OCFS2_CONTROL_MESSAGE_OP_LEN))
  371. return -EINVAL;
  372. if ((msg->space1 != ' ') || (msg->space2 != ' ') ||
  373. (msg->newline != '\n'))
  374. return -EINVAL;
  375. msg->space1 = msg->space2 = msg->newline = '\0';
  376. nodenum = simple_strtol(msg->nodestr, &p, 16);
  377. if (!p || *p)
  378. return -EINVAL;
  379. if ((nodenum == LONG_MIN) || (nodenum == LONG_MAX) ||
  380. (nodenum > INT_MAX) || (nodenum < 0))
  381. return -ERANGE;
  382. ocfs2_control_send_down(msg->uuid, nodenum);
  383. return 0;
  384. }
  385. static ssize_t ocfs2_control_message(struct file *file,
  386. const char __user *buf,
  387. size_t count)
  388. {
  389. ssize_t ret;
  390. union ocfs2_control_message msg;
  391. /* Try to catch padding issues */
  392. WARN_ON(offsetof(struct ocfs2_control_message_down, uuid) !=
  393. (sizeof(msg.u_down.tag) + sizeof(msg.u_down.space1)));
  394. memset(&msg, 0, sizeof(union ocfs2_control_message));
  395. ret = ocfs2_control_cfu(&msg, count, buf, count);
  396. if (ret)
  397. goto out;
  398. if ((count == OCFS2_CONTROL_MESSAGE_SETNODE_TOTAL_LEN) &&
  399. !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETNODE_OP,
  400. OCFS2_CONTROL_MESSAGE_OP_LEN))
  401. ret = ocfs2_control_do_setnode_msg(file, &msg.u_setn);
  402. else if ((count == OCFS2_CONTROL_MESSAGE_SETVERSION_TOTAL_LEN) &&
  403. !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_SETVERSION_OP,
  404. OCFS2_CONTROL_MESSAGE_OP_LEN))
  405. ret = ocfs2_control_do_setversion_msg(file, &msg.u_setv);
  406. else if ((count == OCFS2_CONTROL_MESSAGE_DOWN_TOTAL_LEN) &&
  407. !strncmp(msg.tag, OCFS2_CONTROL_MESSAGE_DOWN_OP,
  408. OCFS2_CONTROL_MESSAGE_OP_LEN))
  409. ret = ocfs2_control_do_down_msg(file, &msg.u_down);
  410. else
  411. ret = -EINVAL;
  412. out:
  413. return ret ? ret : count;
  414. }
  415. static ssize_t ocfs2_control_write(struct file *file,
  416. const char __user *buf,
  417. size_t count,
  418. loff_t *ppos)
  419. {
  420. ssize_t ret;
  421. switch (ocfs2_control_get_handshake_state(file)) {
  422. case OCFS2_CONTROL_HANDSHAKE_INVALID:
  423. ret = -EINVAL;
  424. break;
  425. case OCFS2_CONTROL_HANDSHAKE_READ:
  426. ret = ocfs2_control_validate_protocol(file, buf,
  427. count);
  428. break;
  429. case OCFS2_CONTROL_HANDSHAKE_PROTOCOL:
  430. case OCFS2_CONTROL_HANDSHAKE_VALID:
  431. ret = ocfs2_control_message(file, buf, count);
  432. break;
  433. default:
  434. BUG();
  435. ret = -EIO;
  436. break;
  437. }
  438. return ret;
  439. }
  440. /*
  441. * This is a naive version. If we ever have a new protocol, we'll expand
  442. * it. Probably using seq_file.
  443. */
  444. static ssize_t ocfs2_control_read(struct file *file,
  445. char __user *buf,
  446. size_t count,
  447. loff_t *ppos)
  448. {
  449. char *proto_string = OCFS2_CONTROL_PROTO;
  450. size_t to_write = 0;
  451. if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
  452. return 0;
  453. to_write = OCFS2_CONTROL_PROTO_LEN - *ppos;
  454. if (to_write > count)
  455. to_write = count;
  456. if (copy_to_user(buf, proto_string + *ppos, to_write))
  457. return -EFAULT;
  458. *ppos += to_write;
  459. /* Have we read the whole protocol list? */
  460. if (*ppos >= OCFS2_CONTROL_PROTO_LEN)
  461. ocfs2_control_set_handshake_state(file,
  462. OCFS2_CONTROL_HANDSHAKE_READ);
  463. return to_write;
  464. }
  465. static int ocfs2_control_release(struct inode *inode, struct file *file)
  466. {
  467. struct ocfs2_control_private *p = file->private_data;
  468. mutex_lock(&ocfs2_control_lock);
  469. if (ocfs2_control_get_handshake_state(file) !=
  470. OCFS2_CONTROL_HANDSHAKE_VALID)
  471. goto out;
  472. if (atomic_dec_and_test(&ocfs2_control_opened)) {
  473. if (!list_empty(&ocfs2_live_connection_list)) {
  474. /* XXX: Do bad things! */
  475. printk(KERN_ERR
  476. "ocfs2: Unexpected release of ocfs2_control!\n"
  477. " Loss of cluster connection requires "
  478. "an emergency restart!\n");
  479. emergency_restart();
  480. }
  481. /*
  482. * Last valid close clears the node number and resets
  483. * the locking protocol version
  484. */
  485. ocfs2_control_this_node = -1;
  486. running_proto.pv_major = 0;
  487. running_proto.pv_major = 0;
  488. }
  489. out:
  490. list_del_init(&p->op_list);
  491. file->private_data = NULL;
  492. mutex_unlock(&ocfs2_control_lock);
  493. kfree(p);
  494. return 0;
  495. }
  496. static int ocfs2_control_open(struct inode *inode, struct file *file)
  497. {
  498. struct ocfs2_control_private *p;
  499. p = kzalloc(sizeof(struct ocfs2_control_private), GFP_KERNEL);
  500. if (!p)
  501. return -ENOMEM;
  502. p->op_this_node = -1;
  503. mutex_lock(&ocfs2_control_lock);
  504. file->private_data = p;
  505. list_add(&p->op_list, &ocfs2_control_private_list);
  506. mutex_unlock(&ocfs2_control_lock);
  507. return 0;
  508. }
  509. static const struct file_operations ocfs2_control_fops = {
  510. .open = ocfs2_control_open,
  511. .release = ocfs2_control_release,
  512. .read = ocfs2_control_read,
  513. .write = ocfs2_control_write,
  514. .owner = THIS_MODULE,
  515. };
  516. struct miscdevice ocfs2_control_device = {
  517. .minor = MISC_DYNAMIC_MINOR,
  518. .name = "ocfs2_control",
  519. .fops = &ocfs2_control_fops,
  520. };
  521. static int ocfs2_control_init(void)
  522. {
  523. int rc;
  524. atomic_set(&ocfs2_control_opened, 0);
  525. rc = misc_register(&ocfs2_control_device);
  526. if (rc)
  527. printk(KERN_ERR
  528. "ocfs2: Unable to register ocfs2_control device "
  529. "(errno %d)\n",
  530. -rc);
  531. return rc;
  532. }
  533. static void ocfs2_control_exit(void)
  534. {
  535. int rc;
  536. rc = misc_deregister(&ocfs2_control_device);
  537. if (rc)
  538. printk(KERN_ERR
  539. "ocfs2: Unable to deregister ocfs2_control device "
  540. "(errno %d)\n",
  541. -rc);
  542. }
  543. static int __init user_stack_init(void)
  544. {
  545. return ocfs2_control_init();
  546. }
  547. static void __exit user_stack_exit(void)
  548. {
  549. ocfs2_control_exit();
  550. }
  551. MODULE_AUTHOR("Oracle");
  552. MODULE_DESCRIPTION("ocfs2 driver for userspace cluster stacks");
  553. MODULE_LICENSE("GPL");
  554. module_init(user_stack_init);
  555. module_exit(user_stack_exit);