Remove some emacs variable settings.
[dragonfly.git] / sys / dev / raid / vinum / vinumioctl.c
blob20e43bbc168e099bab84d60b1b8c7e0f0eae434a
1 /*
2 * XXX replace all the checks on object validity with
3 * calls to valid<object>
4 */
5 /*-
6 * Copyright (c) 1997, 1998, 1999
7 * Nan Yang Computer Services Limited. All rights reserved.
9 * Parts copyright (c) 1997, 1998 Cybernet Corporation, NetMAX project.
11 * Written by Greg Lehey
13 * This software is distributed under the so-called ``Berkeley
14 * License'':
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by Nan Yang Computer
27 * Services Limited.
28 * 4. Neither the name of the Company nor the names of its contributors
29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission.
32 * This software is provided ``as is'', and any express or implied
33 * warranties, including, but not limited to, the implied warranties of
34 * merchantability and fitness for a particular purpose are disclaimed.
35 * In no event shall the company or contributors be liable for any
36 * direct, indirect, incidental, special, exemplary, or consequential
37 * damages (including, but not limited to, procurement of substitute
38 * goods or services; loss of use, data, or profits; or business
39 * interruption) however caused and on any theory of liability, whether
40 * in contract, strict liability, or tort (including negligence or
41 * otherwise) arising in any way out of the use of this software, even if
42 * advised of the possibility of such damage.
44 * $Id: vinumioctl.c,v 1.14 2000/10/27 03:07:53 grog Exp grog $
45 * $FreeBSD: src/sys/dev/vinum/vinumioctl.c,v 1.25.2.4 2002/02/03 00:44:19 grog Exp $
48 #include "vinumhdr.h"
49 #include "request.h"
51 #ifdef VINUMDEBUG
52 #include <sys/reboot.h>
53 #endif
55 void attachobject(struct vinum_ioctl_msg *);
56 void detachobject(struct vinum_ioctl_msg *);
57 void renameobject(struct vinum_rename_msg *);
58 void replaceobject(struct vinum_ioctl_msg *);
59 void moveobject(struct vinum_ioctl_msg *);
61 jmp_buf command_fail; /* return on a failed command */
63 /* ioctl routine */
64 int
65 vinumioctl(struct dev_ioctl_args *ap)
67 cdev_t dev = ap->a_head.a_dev;
68 u_long cmd = ap->a_cmd;
69 caddr_t data = ap->a_data;
70 int error;
71 unsigned int index; /* for transferring config info */
72 unsigned int sdno; /* for transferring config info */
73 unsigned int objno;
74 struct volume *vol;
75 struct partinfo *dpart;
76 int fe; /* free list element number */
77 struct _ioctl_reply *ioctl_reply; /* struct to return */
79 error = 0;
81 /* First, decide what we're looking at */
82 switch (DEVTYPE(dev)) {
83 case VINUM_SUPERDEV_TYPE: /* ordinary super device */
84 ioctl_reply = (struct _ioctl_reply *) data; /* save the address to reply to */
85 switch (cmd) {
86 #ifdef VINUMDEBUG
87 case VINUM_DEBUG:
88 if (((struct debuginfo *) data)->changeit) /* change debug settings */
89 debug = (((struct debuginfo *) data)->param);
90 else {
91 if (debug & DEBUG_REMOTEGDB)
92 boothowto |= RB_GDB; /* serial debug line */
93 else
94 boothowto &= ~RB_GDB; /* local ddb */
95 Debugger("vinum debug");
97 ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */
98 ioctl_reply->error = 0;
99 break;
100 #endif
102 case VINUM_CREATE: /* create a vinum object */
103 error = lock_config(); /* get the config for us alone */
104 if (error) /* can't do it, */
105 break;
106 error = setjmp(command_fail); /* come back here on error */
107 if (error == 0) /* first time, */
108 ioctl_reply->error = parse_user_config((char *) data, /* update the config */
109 &keyword_set);
110 else if (ioctl_reply->error == 0) { /* longjmp, but no error status */
111 error = 0;
112 ioctl_reply->error = EINVAL; /* note that something's up */
113 ioctl_reply->msg[0] = '\0'; /* no message? */
115 unlock_config();
116 break;
118 case VINUM_GETCONFIG: /* get the configuration information */
119 bcopy(&vinum_conf, data, sizeof(vinum_conf));
120 break;
122 /* start configuring the subsystem */
123 case VINUM_STARTCONFIG:
124 error = start_config(*(int *) data); /* just lock it. Parameter is 'force' */
125 break;
127 case VINUM_DRIVECONFIG:
129 * Move the individual parts of the config to user space.
131 * Specify the index of the object in the first word of data,
132 * and return the object there
134 index = *(int *) data;
135 if (index >= (unsigned)vinum_conf.drives_allocated) {
136 error = ENXIO;
137 } else {
138 bcopy(&DRIVE[index], data, sizeof(struct drive));
140 break;
142 case VINUM_SDCONFIG:
143 index = *(int *) data;
144 if (index >= (unsigned) vinum_conf.subdisks_allocated) {
145 error = ENXIO;
146 } else {
147 bcopy(&SD[index], data, sizeof(struct sd));
149 break;
151 case VINUM_PLEXCONFIG:
152 index = *(int *) data;
153 if (index >= (unsigned) vinum_conf.plexes_allocated) {
154 error = ENXIO;
155 } else {
156 bcopy(&PLEX[index], data, sizeof(struct plex));
158 break;
160 case VINUM_VOLCONFIG:
161 index = *(int *) data;
162 if (index >= (unsigned) vinum_conf.volumes_allocated) {
163 error = ENXIO;
164 } else {
165 bcopy(&VOL[index], data, sizeof(struct volume));
167 break;
169 case VINUM_PLEXSDCONFIG:
170 index = ((int *)data)[0]; /* get the plex index */
171 sdno = ((int *)data)[1]; /* and the sd index */
172 if ((index >= (unsigned) vinum_conf.plexes_allocated)
173 ||(sdno >= PLEX[index].subdisks)) {
174 error = ENXIO;
175 } else {
176 bcopy(&SD[PLEX[index].sdnos[sdno]], data, sizeof(struct sd));
178 break;
179 case VINUM_SAVECONFIG:
181 * We get called in two places: one from the
182 * userland config routines, which call us
183 * to complete the config and save it. This
184 * call supplies the value 0 as a parameter.
186 * The other place is from the user "saveconfig"
187 * routine, which can only work if we're *not*
188 * configuring. In this case, supply parameter 1.
190 if (VFLAGS & VF_CONFIGURING) { /* must be us, the others are asleep */
191 if (*(int *) data == 0) /* finish config */
192 finish_config(1); /* finish the configuration and update it */
193 else
194 error = EBUSY;
196 if (error == 0)
197 save_config(); /* save configuration to disk */
198 break;
200 case VINUM_RELEASECONFIG: /* release the config */
201 if (VFLAGS & VF_CONFIGURING) { /* must be us, the others are asleep */
202 finish_config(0); /* finish the configuration, don't change it */
203 save_config(); /* save configuration to disk */
204 } else {
205 error = EINVAL; /* release what config? */
207 break;
209 case VINUM_INIT:
210 ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */
211 ioctl_reply->error = 0;
212 break;
214 case VINUM_RESETCONFIG:
215 if (vinum_inactive(0)) { /* if the volumes are not active */
217 * Note the open count. We may be called from v, so we'll be open.
218 * Keep the count so we don't underflow
220 free_vinum(1); /* clean up everything */
221 log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n");
222 ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */
223 ioctl_reply->error = 0;
224 } else {
225 error = EBUSY;
228 case VINUM_SETSTATE:
229 setstate((struct vinum_ioctl_msg *) data); /* set an object state */
230 break;
233 * Set state by force, without changing
234 * anything else.
236 case VINUM_SETSTATE_FORCE:
237 setstate_by_force((struct vinum_ioctl_msg *) data); /* set an object state */
238 break;
240 #ifdef VINUMDEBUG
241 case VINUM_MEMINFO:
242 vinum_meminfo(data);
243 break;
245 case VINUM_MALLOCINFO:
246 error = vinum_mallocinfo(data);
247 break;
249 case VINUM_RQINFO:
250 error = vinum_rqinfo(data);
251 break;
252 #endif
254 case VINUM_REMOVE:
255 remove((struct vinum_ioctl_msg *) data); /* remove an object */
256 break;
258 case VINUM_GETFREELIST: /* get a drive free list element */
259 index = *(int *) data; /* get the drive index */
260 fe = ((int *) data)[1]; /* and the free list element */
261 if ((index >= (unsigned) vinum_conf.drives_allocated) /* plex doesn't exist */
262 ||(DRIVE[index].state == drive_unallocated)) {
263 error = ENODEV;
264 } else if (fe >= DRIVE[index].freelist_entries) {
265 error = ENOENT;
266 } else {
267 bcopy(&DRIVE[index].freelist[fe], data,
268 sizeof(struct drive_freelist));
270 break;
272 case VINUM_RESETSTATS:
273 resetstats((struct vinum_ioctl_msg *) data); /* reset object stats */
274 break;
276 /* attach an object to a superordinate object */
277 case VINUM_ATTACH:
278 attachobject((struct vinum_ioctl_msg *) data);
279 break;
281 /* detach an object from a superordinate object */
282 case VINUM_DETACH:
283 detachobject((struct vinum_ioctl_msg *) data);
284 break;
286 /* rename an object */
287 case VINUM_RENAME:
288 renameobject((struct vinum_rename_msg *) data);
289 break;
291 /* replace an object */
292 case VINUM_REPLACE:
293 replaceobject((struct vinum_ioctl_msg *) data);
294 break;
296 case VINUM_DAEMON:
297 vinum_daemon(); /* perform the daemon */
298 break;
300 case VINUM_FINDDAEMON: /* check for presence of daemon */
301 error = vinum_finddaemon();
302 break;
304 case VINUM_SETDAEMON: /* set daemon flags */
305 error = vinum_setdaemonopts(*(int *) data);
306 break;
308 case VINUM_GETDAEMON: /* get daemon flags */
309 *(int *) data = daemon_options;
310 break;
312 case VINUM_PARITYOP: /* check/rebuild RAID-4/5 parity */
313 parityops((struct vinum_ioctl_msg *) data);
314 break;
316 /* move an object */
317 case VINUM_MOVE:
318 moveobject((struct vinum_ioctl_msg *) data);
319 break;
320 default:
321 error = EINVAL;
322 break;
324 break;
325 case VINUM_LABEL:
326 case VINUM_DRIVE_TYPE:
327 case VINUM_SD_TYPE:
328 case VINUM_RAWSD_TYPE:
329 case VINUM_RAWPLEX_TYPE:
330 case VINUM_PLEX_TYPE:
331 error = EINVAL;
332 break;
333 case VINUM_VOLUME_TYPE:
334 objno = Volno(dev);
336 if (objno >= (unsigned)vinum_conf.volumes_allocated) {
337 error = ENXIO;
338 break;
340 vol = &VOL[objno];
341 if (vol->state != volume_up) {
342 error = EIO;
343 break;
346 switch(cmd) {
347 case DIOCGPART:
348 dpart = (void *)data;
350 bzero(dpart, sizeof(*dpart));
351 dpart->media_offset = 0;
352 dpart->media_size = (u_int64_t)vol->size * DEV_BSIZE;
353 dpart->media_blocks = vol->size;
354 dpart->media_blksize = DEV_BSIZE;
355 dpart->fstype = FS_BSDFFS;
356 break;
357 default:
358 error = EINVAL;
360 break;
361 default:
362 error = EINVAL;
363 break;
365 if (error) {
366 log(LOG_WARNING,
367 "vinumioctl: invalid ioctl from process %d (%s): %lx\n",
368 curproc->p_pid,
369 curproc->p_comm,
370 cmd);
372 return error;
376 * The following four functions check the supplied
377 * object index and return a pointer to the object
378 * if it exists. Otherwise they longjump out via
379 * throw_rude_remark.
381 struct drive *
382 validdrive(int driveno, struct _ioctl_reply *reply)
384 if ((driveno < vinum_conf.drives_allocated)
385 && (DRIVE[driveno].state > drive_referenced))
386 return &DRIVE[driveno];
387 strcpy(reply->msg, "No such drive");
388 reply->error = ENOENT;
389 return NULL;
392 struct sd *
393 validsd(int sdno, struct _ioctl_reply *reply)
395 if ((sdno < vinum_conf.subdisks_allocated)
396 && (SD[sdno].state > sd_referenced))
397 return &SD[sdno];
398 strcpy(reply->msg, "No such subdisk");
399 reply->error = ENOENT;
400 return NULL;
403 struct plex *
404 validplex(int plexno, struct _ioctl_reply *reply)
406 if ((plexno < vinum_conf.plexes_allocated)
407 && (PLEX[plexno].state > plex_referenced))
408 return &PLEX[plexno];
409 strcpy(reply->msg, "No such plex");
410 reply->error = ENOENT;
411 return NULL;
414 struct volume *
415 validvol(int volno, struct _ioctl_reply *reply)
417 if ((volno < vinum_conf.volumes_allocated)
418 && (VOL[volno].state > volume_uninit))
419 return &VOL[volno];
420 strcpy(reply->msg, "No such volume");
421 reply->error = ENOENT;
422 return NULL;
425 /* reset an object's stats */
426 void
427 resetstats(struct vinum_ioctl_msg *msg)
429 struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
431 switch (msg->type) {
432 case drive_object:
433 if (msg->index < vinum_conf.drives_allocated) {
434 struct drive *drive = &DRIVE[msg->index];
435 if (drive->state > drive_referenced) {
436 drive->reads = 0; /* number of reads on this drive */
437 drive->writes = 0; /* number of writes on this drive */
438 drive->bytes_read = 0; /* number of bytes read */
439 drive->bytes_written = 0; /* number of bytes written */
440 reply->error = 0;
441 return;
443 reply->error = EINVAL;
444 return;
446 case sd_object:
447 if (msg->index < vinum_conf.subdisks_allocated) {
448 struct sd *sd = &SD[msg->index];
449 if (sd->state > sd_referenced) {
450 sd->reads = 0; /* number of reads on this subdisk */
451 sd->writes = 0; /* number of writes on this subdisk */
452 sd->bytes_read = 0; /* number of bytes read */
453 sd->bytes_written = 0; /* number of bytes written */
454 reply->error = 0;
455 return;
457 reply->error = EINVAL;
458 return;
460 break;
462 case plex_object:
463 if (msg->index < vinum_conf.plexes_allocated) {
464 struct plex *plex = &PLEX[msg->index];
465 if (plex->state > plex_referenced) {
466 plex->reads = 0;
467 plex->writes = 0; /* number of writes on this plex */
468 plex->bytes_read = 0; /* number of bytes read */
469 plex->bytes_written = 0; /* number of bytes written */
470 plex->recovered_reads = 0; /* number of recovered read operations */
471 plex->degraded_writes = 0; /* number of degraded writes */
472 plex->parityless_writes = 0; /* number of parityless writes */
473 plex->multiblock = 0; /* requests that needed more than one block */
474 plex->multistripe = 0; /* requests that needed more than one stripe */
475 reply->error = 0;
476 return;
478 reply->error = EINVAL;
479 return;
481 break;
483 case volume_object:
484 if (msg->index < vinum_conf.volumes_allocated) {
485 struct volume *vol = &VOL[msg->index];
486 if (vol->state > volume_uninit) {
487 vol->bytes_read = 0; /* number of bytes read */
488 vol->bytes_written = 0; /* number of bytes written */
489 vol->reads = 0; /* number of reads on this volume */
490 vol->writes = 0; /* number of writes on this volume */
491 vol->recovered_reads = 0; /* reads recovered from another plex */
492 reply->error = 0;
493 return;
495 reply->error = EINVAL;
496 return;
498 case invalid_object: /* can't get this */
499 reply->error = EINVAL;
500 return;
504 /* attach an object to a superior object */
505 void
506 attachobject(struct vinum_ioctl_msg *msg)
508 struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
509 int sdno;
510 struct sd *sd;
511 struct plex *plex;
512 struct volume *vol;
514 switch (msg->type) {
515 case drive_object: /* you can't attach a drive to anything */
516 case volume_object: /* nor a volume */
517 case invalid_object: /* "this can't happen" */
518 reply->error = EINVAL;
519 reply->msg[0] = '\0'; /* vinum(8) doesn't do this */
520 return;
522 case sd_object:
523 sd = validsd(msg->index, reply);
524 if (sd == NULL) /* not a valid subdisk */
525 return;
526 plex = validplex(msg->otherobject, reply);
527 if (plex) {
529 * We should be more intelligent about this.
530 * We should be able to reattach a dead
531 * subdisk, but if we want to increase the total
532 * number of subdisks, we have a lot of reshuffling
533 * to do. XXX
535 if ((plex->organization != plex_concat) /* can't attach to striped and RAID-4/5 */
536 &&(!msg->force)) { /* without using force */
537 reply->error = EINVAL; /* no message, the user should check */
538 strcpy(reply->msg, "Can't attach to this plex organization");
539 return;
541 if (sd->plexno >= 0) { /* already belong to a plex */
542 reply->error = EBUSY; /* no message, the user should check */
543 reply->msg[0] = '\0';
544 return;
546 sd->plexoffset = msg->offset; /* this is where we want it */
547 set_sd_state(sd->sdno, sd_stale, setstate_force); /* make sure it's stale */
548 give_sd_to_plex(plex->plexno, sd->sdno); /* and give it to the plex */
549 update_sd_config(sd->sdno, 0);
550 save_config();
552 if (sd->state == sd_reviving)
553 reply->error = EAGAIN; /* need to revive it */
554 else
555 reply->error = 0;
556 break;
558 case plex_object:
559 plex = validplex(msg->index, reply); /* get plex */
560 if (plex == NULL)
561 return;
562 vol = validvol(msg->otherobject, reply); /* and volume information */
563 if (vol) {
564 if ((vol->plexes == MAXPLEX) /* we have too many already */
565 ||(plex->volno >= 0)) { /* or the plex has an owner */
566 reply->error = EINVAL; /* no message, the user should check */
567 reply->msg[0] = '\0';
568 return;
570 for (sdno = 0; sdno < plex->subdisks; sdno++) {
571 sd = &SD[plex->sdnos[sdno]];
573 if (sd->state > sd_down) /* real subdisk, vaguely accessible */
574 set_sd_state(plex->sdnos[sdno], sd_stale, setstate_force); /* make it stale */
576 set_plex_state(plex->plexno, plex_up, setstate_none); /* update plex state */
577 give_plex_to_volume(msg->otherobject, msg->index); /* and give it to the volume */
578 update_plex_config(plex->plexno, 0);
579 save_config();
584 /* detach an object from a superior object */
585 void
586 detachobject(struct vinum_ioctl_msg *msg)
588 struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
589 struct sd *sd;
590 struct plex *plex;
591 struct volume *vol;
592 int sdno;
593 int plexno;
595 switch (msg->type) {
596 case drive_object: /* you can't detach a drive from anything */
597 case volume_object: /* nor a volume */
598 case invalid_object: /* "this can't happen" */
599 reply->error = EINVAL;
600 reply->msg[0] = '\0'; /* vinum(8) doesn't do this */
601 return;
603 case sd_object:
604 sd = validsd(msg->index, reply);
605 if (sd == NULL)
606 return;
607 if (sd->plexno < 0) { /* doesn't belong to a plex */
608 reply->error = ENOENT;
609 strcpy(reply->msg, "Subdisk is not attached");
610 return;
611 } else { /* valid plex number */
612 plex = &PLEX[sd->plexno];
613 if ((!msg->force) /* don't force things */
614 &&((plex->state == plex_up) /* and the plex is up */
615 ||((plex->state == plex_flaky) && sd->state == sd_up))) { /* or flaky with this sd up */
616 reply->error = EBUSY; /* we need this sd */
617 reply->msg[0] = '\0';
618 return;
620 sd->plexno = -1; /* anonymous sd */
621 if (plex->subdisks == 1) { /* this was the only subdisk */
622 Free(plex->sdnos); /* free the subdisk array */
623 plex->sdnos = NULL; /* and note the fact */
624 plex->subdisks_allocated = 0; /* no subdisk space */
625 } else {
626 for (sdno = 0; sdno < plex->subdisks; sdno++) {
627 if (plex->sdnos[sdno] == msg->index) /* found our subdisk */
628 break;
630 if (sdno < (plex->subdisks - 1)) /* not the last one, compact */
631 bcopy(&plex->sdnos[sdno + 1],
632 &plex->sdnos[sdno],
633 (plex->subdisks - 1 - sdno) * sizeof(int));
635 plex->subdisks--;
636 if (!bcmp(plex->name, sd->name, strlen(plex->name) + 1))
637 /* this subdisk is named after the plex */
639 bcopy(sd->name,
640 &sd->name[3],
641 imin(strlen(sd->name) + 1, MAXSDNAME - 3));
642 bcopy("ex-", sd->name, 3);
643 sd->name[MAXSDNAME - 1] = '\0';
645 update_plex_config(plex->plexno, 0);
646 if (isstriped(plex)) /* we've just mutilated our plex, */
647 set_plex_state(plex->plexno,
648 plex_down,
649 setstate_force | setstate_configuring);
650 save_config();
651 reply->error = 0;
653 return;
655 case plex_object:
656 plex = validplex(msg->index, reply); /* get plex */
657 if (plex == NULL)
658 return;
659 if (plex->volno >= 0) {
660 int volno = plex->volno;
662 vol = &VOL[volno];
663 if ((!msg->force) /* don't force things */
664 &&((vol->state == volume_up) /* and the volume is up */
665 &&(vol->plexes == 1))) { /* and this is the last plex */
667 * XXX As elsewhere, check whether we will lose
668 * mapping by removing this plex
670 reply->error = EBUSY; /* we need this plex */
671 reply->msg[0] = '\0';
672 return;
674 plex->volno = -1; /* anonymous plex */
675 for (plexno = 0; plexno < vol->plexes; plexno++) {
676 if (vol->plex[plexno] == msg->index) /* found our plex */
677 break;
679 if (plexno < (vol->plexes - 1)) /* not the last one, compact */
680 bcopy(&vol->plex[plexno + 1],
681 &vol->plex[plexno],
682 (vol->plexes - 1 - plexno) * sizeof(int));
683 vol->plexes--;
684 vol->last_plex_read = 0; /* don't go beyond the end */
685 if (!bcmp(vol->name, plex->name, strlen(vol->name) + 1))
686 /* this plex is named after the volume */
688 /* First, check if the subdisks are the same */
689 if (msg->recurse) {
690 int sdno;
692 for (sdno = 0; sdno < plex->subdisks; sdno++) {
693 struct sd *sd = &SD[plex->sdnos[sdno]];
695 if (!bcmp(plex->name, sd->name, strlen(plex->name) + 1))
696 /* subdisk is named after the plex */
698 bcopy(sd->name,
699 &sd->name[3],
700 imin(strlen(sd->name) + 1, MAXSDNAME - 3));
701 bcopy("ex-", sd->name, 3);
702 sd->name[MAXSDNAME - 1] = '\0';
706 bcopy(plex->name,
707 &plex->name[3],
708 imin(strlen(plex->name) + 1, MAXPLEXNAME - 3));
709 bcopy("ex-", plex->name, 3);
710 plex->name[MAXPLEXNAME - 1] = '\0';
712 update_volume_config(volno, 0);
713 save_config();
714 reply->error = 0;
715 } else {
716 reply->error = ENOENT;
717 strcpy(reply->msg, "Plex is not attached");
722 void
723 renameobject(struct vinum_rename_msg *msg)
725 struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
726 struct drive *drive;
727 struct sd *sd;
728 struct plex *plex;
729 struct volume *vol;
731 switch (msg->type) {
732 case drive_object: /* you can't attach a drive to anything */
733 if (find_drive(msg->newname, 0) >= 0) { /* we have that name already, */
734 reply->error = EEXIST;
735 reply->msg[0] = '\0';
736 return;
738 drive = validdrive(msg->index, reply);
739 if (drive) {
740 bcopy(msg->newname, drive->label.name, MAXDRIVENAME);
741 save_config();
742 reply->error = 0;
744 return;
746 case sd_object: /* you can't attach a subdisk to anything */
747 if (find_subdisk(msg->newname, 0) >= 0) { /* we have that name already, */
748 reply->error = EEXIST;
749 reply->msg[0] = '\0';
750 return;
752 sd = validsd(msg->index, reply);
753 if (sd) {
754 bcopy(msg->newname, sd->name, MAXSDNAME);
755 update_sd_config(sd->sdno, 0);
756 save_config();
757 reply->error = 0;
759 return;
761 case plex_object: /* you can't attach a plex to anything */
762 if (find_plex(msg->newname, 0) >= 0) { /* we have that name already, */
763 reply->error = EEXIST;
764 reply->msg[0] = '\0';
765 return;
767 plex = validplex(msg->index, reply);
768 if (plex) {
769 bcopy(msg->newname, plex->name, MAXPLEXNAME);
770 update_plex_config(plex->plexno, 0);
771 save_config();
772 reply->error = 0;
774 return;
776 case volume_object: /* you can't attach a volume to anything */
777 if (find_volume(msg->newname, 0) >= 0) { /* we have that name already, */
778 reply->error = EEXIST;
779 reply->msg[0] = '\0';
780 return;
782 vol = validvol(msg->index, reply);
783 if (vol) {
784 bcopy(msg->newname, vol->name, MAXVOLNAME);
785 update_volume_config(msg->index, 0);
786 save_config();
787 reply->error = 0;
789 return;
791 case invalid_object:
792 reply->error = EINVAL;
793 reply->msg[0] = '\0';
798 * Replace one object with another.
799 * Currently only for drives.
800 * message->index is the drive number of the old drive
801 * message->otherobject is the drive number of the new drive
803 void
804 replaceobject(struct vinum_ioctl_msg *msg)
806 struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
808 reply->error = ENODEV; /* until I know how to do this */
809 strcpy(reply->msg, "replace not implemented yet");
810 /* save_config (); */
813 void
814 moveobject(struct vinum_ioctl_msg *msg)
816 struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
817 struct drive *drive;
818 struct sd *sd;
820 /* Check that our objects are valid (i.e. they exist) */
821 drive = validdrive(msg->index, (struct _ioctl_reply *) msg);
822 if (drive == NULL)
823 return;
824 sd = validsd(msg->otherobject, (struct _ioctl_reply *) msg);
825 if (sd == NULL)
826 return;
827 if (sd->driveno == msg->index) /* sd already belongs to drive */
828 return;
830 if (sd->state > sd_stale)
831 set_sd_state(sd->sdno, sd_stale, setstate_force); /* make the subdisk stale */
832 else
833 sd->state = sd_empty;
834 if (sd->plexno >= 0) /* part of a plex, */
835 update_plex_state(sd->plexno); /* update its state */
837 /* Return the space on the old drive */
838 if ((sd->driveno >= 0) /* we have a drive, */
839 &&(sd->sectors > 0)) /* and some space on it */
840 return_drive_space(sd->driveno, /* return the space */
841 sd->driveoffset,
842 sd->sectors);
844 /* Reassign the old subdisk */
845 sd->driveno = msg->index;
846 sd->driveoffset = -1; /* let the drive decide where to put us */
847 give_sd_to_drive(sd->sdno);
848 reply->error = 0;