]>
Commit | Line | Data |
---|---|---|
8adf0536 JB |
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 | ||
20 | #include <linux/module.h> | |
6427a727 JB |
21 | #include <linux/fs.h> |
22 | #include <linux/miscdevice.h> | |
23 | #include <linux/mutex.h> | |
24 | #include <linux/reboot.h> | |
8adf0536 JB |
25 | |
26 | #include "stackglue.h" | |
27 | ||
28 | ||
6427a727 JB |
29 | /* |
30 | * The control protocol starts with a handshake. Until the handshake | |
31 | * is complete, the control device will fail all write(2)s. | |
32 | * | |
33 | * The handshake is simple. First, the client reads until EOF. Each line | |
34 | * of output is a supported protocol tag. All protocol tags are a single | |
35 | * character followed by a two hex digit version number. Currently the | |
36 | * only things supported is T01, for "Text-base version 0x01". Next, the | |
37 | * client writes the version they would like to use. If the version tag | |
38 | * written is unknown, -EINVAL is returned. Once the negotiation is | |
39 | * complete, the client can start sending messages. | |
40 | */ | |
41 | ||
42 | /* | |
43 | * ocfs2_live_connection is refcounted because the filesystem and | |
44 | * miscdevice sides can detach in different order. Let's just be safe. | |
45 | */ | |
46 | struct ocfs2_live_connection { | |
47 | struct list_head oc_list; | |
48 | struct ocfs2_cluster_connection *oc_conn; | |
49 | }; | |
50 | ||
51 | static atomic_t ocfs2_control_opened; | |
52 | ||
53 | static LIST_HEAD(ocfs2_live_connection_list); | |
54 | static DEFINE_MUTEX(ocfs2_control_lock); | |
55 | ||
56 | static struct ocfs2_live_connection *ocfs2_connection_find(const char *name) | |
57 | { | |
58 | size_t len = strlen(name); | |
59 | struct ocfs2_live_connection *c; | |
60 | ||
61 | BUG_ON(!mutex_is_locked(&ocfs2_control_lock)); | |
62 | ||
63 | list_for_each_entry(c, &ocfs2_live_connection_list, oc_list) { | |
64 | if ((c->oc_conn->cc_namelen == len) && | |
65 | !strncmp(c->oc_conn->cc_name, name, len)) | |
66 | return c; | |
67 | } | |
68 | ||
69 | return c; | |
70 | } | |
71 | ||
72 | /* | |
73 | * ocfs2_live_connection structures are created underneath the ocfs2 | |
74 | * mount path. Since the VFS prevents multiple calls to | |
75 | * fill_super(), we can't get dupes here. | |
76 | */ | |
77 | static int ocfs2_live_connection_new(struct ocfs2_cluster_connection *conn, | |
78 | struct ocfs2_live_connection **c_ret) | |
79 | { | |
80 | int rc = 0; | |
81 | struct ocfs2_live_connection *c; | |
82 | ||
83 | c = kzalloc(sizeof(struct ocfs2_live_connection), GFP_KERNEL); | |
84 | if (!c) | |
85 | return -ENOMEM; | |
86 | ||
87 | mutex_lock(&ocfs2_control_lock); | |
88 | c->oc_conn = conn; | |
89 | ||
90 | if (atomic_read(&ocfs2_control_opened)) | |
91 | list_add(&c->oc_list, &ocfs2_live_connection_list); | |
92 | else { | |
93 | printk(KERN_ERR | |
94 | "ocfs2: Userspace control daemon is not present\n"); | |
95 | rc = -ESRCH; | |
96 | } | |
97 | ||
98 | mutex_unlock(&ocfs2_control_lock); | |
99 | ||
100 | if (!rc) | |
101 | *c_ret = c; | |
102 | else | |
103 | kfree(c); | |
104 | ||
105 | return rc; | |
106 | } | |
107 | ||
108 | /* | |
109 | * This function disconnects the cluster connection from ocfs2_control. | |
110 | * Afterwards, userspace can't affect the cluster connection. | |
111 | */ | |
112 | static void ocfs2_live_connection_drop(struct ocfs2_live_connection *c) | |
113 | { | |
114 | mutex_lock(&ocfs2_control_lock); | |
115 | list_del_init(&c->oc_list); | |
116 | c->oc_conn = NULL; | |
117 | mutex_unlock(&ocfs2_control_lock); | |
118 | ||
119 | kfree(c); | |
120 | } | |
121 | ||
122 | ||
123 | static ssize_t ocfs2_control_write(struct file *file, | |
124 | const char __user *buf, | |
125 | size_t count, | |
126 | loff_t *ppos) | |
8adf0536 JB |
127 | { |
128 | return 0; | |
129 | } | |
130 | ||
6427a727 JB |
131 | static ssize_t ocfs2_control_read(struct file *file, |
132 | char __user *buf, | |
133 | size_t count, | |
134 | loff_t *ppos) | |
135 | { | |
136 | return 0; | |
137 | } | |
138 | ||
139 | static int ocfs2_control_release(struct inode *inode, struct file *file) | |
140 | { | |
141 | if (atomic_dec_and_test(&ocfs2_control_opened)) { | |
142 | mutex_lock(&ocfs2_control_lock); | |
143 | if (!list_empty(&ocfs2_live_connection_list)) { | |
144 | /* XXX: Do bad things! */ | |
145 | printk(KERN_ERR | |
146 | "ocfs2: Unexpected release of ocfs2_control!\n" | |
147 | " Loss of cluster connection requires " | |
148 | "an emergency restart!\n"); | |
149 | emergency_restart(); | |
150 | } | |
151 | mutex_unlock(&ocfs2_control_lock); | |
152 | } | |
153 | ||
154 | return 0; | |
155 | } | |
156 | ||
157 | static int ocfs2_control_open(struct inode *inode, struct file *file) | |
158 | { | |
159 | atomic_inc(&ocfs2_control_opened); | |
160 | ||
161 | return 0; | |
162 | } | |
163 | ||
164 | static const struct file_operations ocfs2_control_fops = { | |
165 | .open = ocfs2_control_open, | |
166 | .release = ocfs2_control_release, | |
167 | .read = ocfs2_control_read, | |
168 | .write = ocfs2_control_write, | |
169 | .owner = THIS_MODULE, | |
170 | }; | |
171 | ||
172 | struct miscdevice ocfs2_control_device = { | |
173 | .minor = MISC_DYNAMIC_MINOR, | |
174 | .name = "ocfs2_control", | |
175 | .fops = &ocfs2_control_fops, | |
176 | }; | |
177 | ||
178 | static int ocfs2_control_init(void) | |
179 | { | |
180 | int rc; | |
181 | ||
182 | atomic_set(&ocfs2_control_opened, 0); | |
183 | ||
184 | rc = misc_register(&ocfs2_control_device); | |
185 | if (rc) | |
186 | printk(KERN_ERR | |
187 | "ocfs2: Unable to register ocfs2_control device " | |
188 | "(errno %d)\n", | |
189 | -rc); | |
190 | ||
191 | return rc; | |
192 | } | |
193 | ||
194 | static void ocfs2_control_exit(void) | |
195 | { | |
196 | int rc; | |
197 | ||
198 | rc = misc_deregister(&ocfs2_control_device); | |
199 | if (rc) | |
200 | printk(KERN_ERR | |
201 | "ocfs2: Unable to deregister ocfs2_control device " | |
202 | "(errno %d)\n", | |
203 | -rc); | |
204 | } | |
205 | ||
206 | static int __init user_stack_init(void) | |
207 | { | |
208 | return ocfs2_control_init(); | |
209 | } | |
210 | ||
8adf0536 JB |
211 | static void __exit user_stack_exit(void) |
212 | { | |
6427a727 | 213 | ocfs2_control_exit(); |
8adf0536 JB |
214 | } |
215 | ||
216 | MODULE_AUTHOR("Oracle"); | |
217 | MODULE_DESCRIPTION("ocfs2 driver for userspace cluster stacks"); | |
218 | MODULE_LICENSE("GPL"); | |
219 | module_init(user_stack_init); | |
220 | module_exit(user_stack_exit); |