Tizen 2.1 base
[external/device-mapper.git] / daemons / clvmd / clvmd-command.c
1 /*
2  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
3  * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
4  *
5  * This file is part of LVM2.
6  *
7  * This copyrighted material is made available to anyone wishing to use,
8  * modify, copy, or redistribute it subject to the terms and conditions
9  * of the GNU General Public License v.2.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program; if not, write to the Free Software Foundation,
13  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14  */
15
16 /*
17
18   CLVMD Cluster LVM daemon command processor.
19
20   To add commands to the daemon simply add a processor in do_command and return
21   and messages back in buf and the length in *retlen. The initial value of
22   buflen is the maximum size of the buffer. if buf is not large enough then it
23   may be reallocated by the functions in here to a suitable size bearing in
24   mind that anything larger than the passed-in size will have to be returned
25   using the system LV and so performance will suffer.
26
27   The status return will be negated and passed back to the originating node.
28
29   pre- and post- command routines are called only on the local node. The
30   purpose is primarily to get and release locks, though the pre- routine should
31   also do any other local setups required by the command (if any) and can
32   return a failure code that prevents the command from being distributed around
33   the cluster
34
35   The pre- and post- routines are run in their own thread so can block as long
36   they like, do_command is run in the main clvmd thread so should not block for
37   too long. If the pre-command returns an error code (!=0) then the command
38   will not be propogated around the cluster but the post-command WILL be called
39
40   Also note that the pre and post routine are *always* called on the local
41   node, even if the command to be executed was only requested to run on a
42   remote node. It may peek inside the client structure to check the status of
43   the command.
44
45   The clients of the daemon must, naturally, understand the return messages and
46   codes.
47
48   Routines in here may only READ the values in the client structure passed in
49   apart from client->private which they are free to do what they like with.
50
51 */
52
53 #include "clvmd-common.h"
54
55 #include <pthread.h>
56
57 #include "clvmd-comms.h"
58 #include "clvm.h"
59 #include "clvmd.h"
60 #include "lvm-functions.h"
61
62 #include "locking.h"
63
64 #include <sys/utsname.h>
65
66 extern debug_t debug;
67 extern struct cluster_ops *clops;
68 static int restart_clvmd(void);
69
70 /* This is where all the real work happens:
71    NOTE: client will be NULL when this is executed on a remote node */
72 int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
73                char **buf, int buflen, int *retlen)
74 {
75         char *args = msg->node + strlen(msg->node) + 1;
76         int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
77         int status = 0;
78         char *lockname;
79         const char *locktype;
80         struct utsname nodeinfo;
81         unsigned char lock_cmd;
82         unsigned char lock_flags;
83
84         /* Do the command */
85         switch (msg->cmd) {
86                 /* Just a test message */
87         case CLVMD_CMD_TEST:
88                 if (arglen > buflen) {
89                         char *new_buf;
90                         buflen = arglen + 200;
91                         new_buf = realloc(*buf, buflen);
92                         if (new_buf == NULL) {
93                                 status = errno;
94                                 free (*buf);
95                         }
96                         *buf = new_buf;
97                 }
98                 if (*buf) {
99                         uname(&nodeinfo);
100                         *retlen = 1 + dm_snprintf(*buf, buflen,
101                                                   "TEST from %s: %s v%s",
102                                                   nodeinfo.nodename, args,
103                                                   nodeinfo.release);
104                 }
105                 break;
106
107         case CLVMD_CMD_LOCK_VG:
108                 lock_cmd = args[0];
109                 lock_flags = args[1];
110                 lockname = &args[2];
111                 /* Check to see if the VG is in use by LVM1 */
112                 status = do_check_lvm1(lockname);
113                 do_lock_vg(lock_cmd, lock_flags, lockname);
114                 break;
115
116         case CLVMD_CMD_LOCK_LV:
117                 /* This is the biggie */
118                 lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
119                 lock_flags = args[1];
120                 lockname = &args[2];
121                 status = do_lock_lv(lock_cmd, lock_flags, lockname);
122                 /* Replace EIO with something less scary */
123                 if (status == EIO) {
124                         *retlen = 1 + dm_snprintf(*buf, buflen, "%s",
125                                                   get_last_lvm_error());
126                         return EIO;
127                 }
128                 break;
129
130         case CLVMD_CMD_LOCK_QUERY:
131                 lockname = &args[2];
132                 if (buflen < 3)
133                         return EIO;
134                 if ((locktype = do_lock_query(lockname)))
135                         *retlen = 1 + dm_snprintf(*buf, buflen, "%s", locktype);
136                 break;
137
138         case CLVMD_CMD_REFRESH:
139                 do_refresh_cache();
140                 break;
141
142         case CLVMD_CMD_SET_DEBUG:
143                 debug = args[0];
144                 break;
145
146         case CLVMD_CMD_RESTART:
147                 restart_clvmd();
148                 break;
149
150         case CLVMD_CMD_GET_CLUSTERNAME:
151                 status = clops->get_cluster_name(*buf, buflen);
152                 if (!status)
153                         *retlen = strlen(*buf)+1;
154                 break;
155
156         case CLVMD_CMD_VG_BACKUP:
157                 /*
158                  * Do not run backup on local node, caller should do that.
159                  */
160                 if (!client)
161                         lvm_do_backup(&args[2]);
162                 break;
163
164         default:
165                 /* Won't get here because command is validated in pre_command */
166                 break;
167         }
168
169         /* Check the status of the command and return the error text */
170         if (status) {
171                 *retlen = 1 + ((*buf) ? dm_snprintf(*buf, buflen, "%s",
172                                                     strerror(status)) : -1);
173         }
174
175         return status;
176
177 }
178
179 static int lock_vg(struct local_client *client)
180 {
181     struct dm_hash_table *lock_hash;
182     struct clvm_header *header =
183         (struct clvm_header *) client->bits.localsock.cmd;
184     unsigned char lock_cmd;
185     unsigned char lock_flags;
186     int lock_mode;
187     char *args = header->node + strlen(header->node) + 1;
188     int lkid;
189     int status = 0;
190     char *lockname;
191
192     /* Keep a track of VG locks in our own hash table. In current
193        practice there should only ever be more than two VGs locked
194        if a user tries to merge lots of them at once */
195     if (client->bits.localsock.private) {
196         lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
197     }
198     else {
199         lock_hash = dm_hash_create(3);
200         if (!lock_hash)
201             return ENOMEM;
202         client->bits.localsock.private = (void *)lock_hash;
203     }
204
205     lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
206     lock_mode = ((int)lock_cmd & LCK_TYPE_MASK);
207     lock_flags = args[1];
208     lockname = &args[2];
209     DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
210
211     if (lock_mode == LCK_UNLOCK) {
212
213         lkid = (int)(long)dm_hash_lookup(lock_hash, lockname);
214         if (lkid == 0)
215             return EINVAL;
216
217         status = sync_unlock(lockname, lkid);
218         if (status)
219             status = errno;
220         else
221             dm_hash_remove(lock_hash, lockname);
222     }
223     else {
224         /* Read locks need to be PR; other modes get passed through */
225         if (lock_mode == LCK_READ)
226             lock_mode = LCK_PREAD;
227         status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LCKF_NOQUEUE : 0, &lkid);
228         if (status)
229             status = errno;
230         else
231             dm_hash_insert(lock_hash, lockname, (void *)(long)lkid);
232     }
233
234     return status;
235 }
236
237
238 /* Pre-command is a good place to get locks that are needed only for the duration
239    of the commands around the cluster (don't forget to free them in post-command),
240    and to sanity check the command arguments */
241 int do_pre_command(struct local_client *client)
242 {
243         struct clvm_header *header =
244             (struct clvm_header *) client->bits.localsock.cmd;
245         unsigned char lock_cmd;
246         unsigned char lock_flags;
247         char *args = header->node + strlen(header->node) + 1;
248         int lockid;
249         int status = 0;
250         char *lockname;
251
252         switch (header->cmd) {
253         case CLVMD_CMD_TEST:
254                 status = sync_lock("CLVMD_TEST", LCK_EXCL, 0, &lockid);
255                 client->bits.localsock.private = (void *)(long)lockid;
256                 break;
257
258         case CLVMD_CMD_LOCK_VG:
259                 lockname = &args[2];
260                 /* We take out a real lock unless LCK_CACHE was set */
261                 if (!strncmp(lockname, "V_", 2) ||
262                     !strncmp(lockname, "P_#", 3))
263                         status = lock_vg(client);
264                 break;
265
266         case CLVMD_CMD_LOCK_LV:
267                 lock_cmd = args[0];
268                 lock_flags = args[1];
269                 lockname = &args[2];
270                 status = pre_lock_lv(lock_cmd, lock_flags, lockname);
271                 break;
272
273         case CLVMD_CMD_REFRESH:
274         case CLVMD_CMD_GET_CLUSTERNAME:
275         case CLVMD_CMD_SET_DEBUG:
276         case CLVMD_CMD_VG_BACKUP:
277         case CLVMD_CMD_LOCK_QUERY:
278         case CLVMD_CMD_RESTART:
279                 break;
280
281         default:
282                 log_error("Unknown command %d received\n", header->cmd);
283                 status = EINVAL;
284         }
285         return status;
286 }
287
288 /* Note that the post-command routine is called even if the pre-command or the real command
289    failed */
290 int do_post_command(struct local_client *client)
291 {
292         struct clvm_header *header =
293             (struct clvm_header *) client->bits.localsock.cmd;
294         int status = 0;
295         unsigned char lock_cmd;
296         unsigned char lock_flags;
297         char *args = header->node + strlen(header->node) + 1;
298         char *lockname;
299
300         switch (header->cmd) {
301         case CLVMD_CMD_TEST:
302                 status =
303                     sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
304                 client->bits.localsock.private = 0;
305                 break;
306
307         case CLVMD_CMD_LOCK_VG:
308         case CLVMD_CMD_VG_BACKUP:
309         case CLVMD_CMD_LOCK_QUERY:
310                 /* Nothing to do here */
311                 break;
312
313         case CLVMD_CMD_LOCK_LV:
314                 lock_cmd = args[0];
315                 lock_flags = args[1];
316                 lockname = &args[2];
317                 status = post_lock_lv(lock_cmd, lock_flags, lockname);
318                 break;
319         }
320         return status;
321 }
322
323
324 /* Called when the client is about to be deleted */
325 void cmd_client_cleanup(struct local_client *client)
326 {
327     if (client->bits.localsock.private) {
328
329         struct dm_hash_node *v;
330         struct dm_hash_table *lock_hash =
331             (struct dm_hash_table *)client->bits.localsock.private;
332
333         dm_hash_iterate(v, lock_hash) {
334                 int lkid = (int)(long)dm_hash_get_data(lock_hash, v);
335                 char *lockname = dm_hash_get_key(lock_hash, v);
336
337                 DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
338                 sync_unlock(lockname, lkid);
339         }
340
341         dm_hash_destroy(lock_hash);
342         client->bits.localsock.private = 0;
343     }
344 }
345
346
347 static int restart_clvmd(void)
348 {
349         char **argv = NULL;
350         char *debug_arg = NULL, *lv_name;
351         int i, argc = 0, max_locks = 0;
352         struct dm_hash_node *hn = NULL;
353
354         DEBUGLOG("clvmd restart requested\n");
355
356         /* Count exclusively-open LVs */
357         hn = NULL;
358         do {
359                 hn = get_next_excl_lock(hn, &lv_name);
360                 if (lv_name)
361                         max_locks++;
362         } while (hn && *lv_name);
363
364         /* clvmd + locks (-E uuid) + debug (-d X) + NULL */
365         argv = malloc((max_locks * 2 + 4) * sizeof(*argv));
366         if (!argv)
367                 goto_out;
368
369         /*
370          * Build the command-line
371          */
372         argv[argc++] = strdup("clvmd");
373         if (!argv[0])
374                 goto_out;
375
376         /* Propogate debug options */
377         if (debug) {
378                 if (!(debug_arg = malloc(16)) ||
379                     dm_snprintf(debug_arg, 16, "-d%d", (int)debug) < 0)
380                         goto_out;
381                 argv[argc++] = debug_arg;
382         }
383
384         /* Now add the exclusively-open LVs */
385         do {
386                 hn = get_next_excl_lock(hn, &lv_name);
387                 if (lv_name) {
388                         argv[argc] = strdup("-E");
389                         if (!argv[argc++])
390                                 goto_out;
391                         argv[argc] = strdup(lv_name);
392                         if (!argv[argc++])
393                                 goto_out;
394
395                         DEBUGLOG("excl lock: %s\n", lv_name);
396                         hn = get_next_excl_lock(hn, &lv_name);
397                 }
398         } while (hn && *lv_name);
399         argv[argc++] = NULL;
400
401         /* Exec new clvmd */
402         /* NOTE: This will fail when downgrading! */
403         execve(CLVMD_PATH, argv, NULL);
404 out:
405         /* We failed */
406         DEBUGLOG("Restart of clvmd failed.\n");
407
408         for (i = 0; i < argc && argv[i]; i++)
409                 free(argv[i]);
410         free(argv);
411
412         return 0;
413 }