vinumioctl.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 784 行 · 第 1/2 页

C
784
字号
/* * XXX replace all the checks on object validity with * calls to valid<object> *//*- * Copyright (c) 1997, 1998 *	Nan Yang Computer Services Limited.  All rights reserved. * *  This software is distributed under the so-called ``Berkeley *  License'': * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Nan Yang Computer *      Services Limited. * 4. Neither the name of the Company nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * This software is provided ``as is'', and any express or implied * warranties, including, but not limited to, the implied warranties of * merchantability and fitness for a particular purpose are disclaimed. * In no event shall the company or contributors be liable for any * direct, indirect, incidental, special, exemplary, or consequential * damages (including, but not limited to, procurement of substitute * goods or services; loss of use, data, or profits; or business * interruption) however caused and on any theory of liability, whether * in contract, strict liability, or tort (including negligence or * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. * * $Id: vinumioctl.c,v 1.6.2.3 1999/04/06 09:05:57 grog Exp $ */#define STATIC						    /* nothing while we're testing XXX */#define REALLYKERNEL#include "opt_vinum.h"#include <dev/vinum/vinumhdr.h>#include <dev/vinum/request.h>#include <sys/sysproto.h>				    /* for sync(2) */#ifdef VINUMDEBUG#include <sys/reboot.h>#endifvoid attachobject(struct vinum_ioctl_msg *);void detachobject(struct vinum_ioctl_msg *);void renameobject(struct vinum_rename_msg *);void replaceobject(struct vinum_ioctl_msg *);/* ioctl routine */int vinumioctl(dev_t dev,    u_long cmd,    caddr_t data,    int flag,    struct proc *p){    unsigned int objno;    int error = 0;    struct volume *vol;    unsigned int index;					    /* for transferring config info */    unsigned int sdno;					    /* for transferring config info */    int fe;						    /* free list element number */    struct _ioctl_reply *ioctl_reply = (struct _ioctl_reply *) data; /* struct to return */    struct devcode *device = (struct devcode *) &dev;    /* First, decide what we're looking at */    switch (device->type) {    case VINUM_SUPERDEV_TYPE:				    /* ordinary super device */	ioctl_reply = (struct _ioctl_reply *) data;	    /* save the address to reply to */	error = setjmp(command_fail);			    /* come back here on error */	if (error)					    /* bombed out */	    return 0;					    /* the reply will contain meaningful info */	switch (cmd) {#ifdef VINUMDEBUG	case VINUM_DEBUG:	    if (((struct debuginfo *) data)->changeit)	    /* change debug settings */		debug = (((struct debuginfo *) data)->param);	    else {		if (debug & DEBUG_REMOTEGDB)		    boothowto |= RB_GDB;		    /* serial debug line */		else		    boothowto &= ~RB_GDB;		    /* local ddb */		Debugger("vinum debug");	    }	    ioctl_reply = (struct _ioctl_reply *) data;	    /* reinstate the address to reply to */	    ioctl_reply->error = 0;	    return 0;#endif	case VINUM_CREATE:				    /* create a vinum object */	    error = lock_config();			    /* get the config for us alone */	    if (error)					    /* can't do it, */		return error;				    /* give up */	    error = setjmp(command_fail);		    /* come back here on error */	    if (error == 0)				    /* first time, */		ioctl_reply->error = parse_user_config((char *) data, /* update the config */		    &keyword_set);	    else if (ioctl_reply->error == 0) {		    /* longjmp, but no error status */		ioctl_reply->error = EINVAL;		    /* note that something's up */		ioctl_reply->msg[0] = '\0';		    /* no message? */	    }	    unlock_config();	    return 0;					    /* must be 0 to return the real error info */	case VINUM_GETCONFIG:				    /* get the configuration information */	    bcopy(&vinum_conf, data, sizeof(vinum_conf));	    return 0;	    /* start configuring the subsystem */	case VINUM_STARTCONFIG:	    return start_config(*(int *) data);		    /* just lock it.  Parameter is 'force' */	    /*	     * Move the individual parts of the config to user space.	     *	     * Specify the index of the object in the first word of data,	     * and return the object there	     */	case VINUM_DRIVECONFIG:	    index = *(int *) data;			    /* get the index */	    if (index >= (unsigned) vinum_conf.drives_allocated) /* can't do it */		return ENXIO;				    /* bang */	    bcopy(&DRIVE[index], data, sizeof(struct drive)); /* copy the config item out */	    return 0;	case VINUM_SDCONFIG:	    index = *(int *) data;			    /* get the index */	    if (index >= (unsigned) vinum_conf.subdisks_allocated) /* can't do it */		return ENXIO;				    /* bang */	    bcopy(&SD[index], data, sizeof(struct sd));	    /* copy the config item out */	    return 0;	case VINUM_PLEXCONFIG:	    index = *(int *) data;			    /* get the index */	    if (index >= (unsigned) vinum_conf.plexes_allocated) /* can't do it */		return ENXIO;				    /* bang */	    bcopy(&PLEX[index], data, sizeof(struct plex)); /* copy the config item out */	    return 0;	case VINUM_VOLCONFIG:	    index = *(int *) data;			    /* get the index */	    if (index >= (unsigned) vinum_conf.volumes_allocated) /* can't do it */		return ENXIO;				    /* bang */	    bcopy(&VOL[index], data, sizeof(struct volume)); /* copy the config item out */	    return 0;	case VINUM_PLEXSDCONFIG:	    index = *(int *) data;			    /* get the plex index */	    sdno = ((int *) data)[1];			    /* and the sd index */	    if ((index >= (unsigned) vinum_conf.plexes_allocated) /* plex doesn't exist */	    ||(sdno >= PLEX[index].subdisks))		    /* or it doesn't have this many subdisks */		return ENXIO;				    /* bang */	    bcopy(&SD[PLEX[index].sdnos[sdno]],		    /* copy the config item out */		data,		sizeof(struct sd));	    return 0;	    /*	     * We get called in two places: one from the	     * userland config routines, which call us	     * to complete the config and save it.  This	     * call supplies the value 0 as a parameter.	     *	     * The other place is from the user "saveconfig"	     * routine, which can only work if we're *not*	     * configuring.  In this case, supply parameter 1.	     */	case VINUM_SAVECONFIG:	    if (VFLAGS & VF_CONFIGURING) {		    /* must be us, the others are asleep */		if (*(int *) data == 0)			    /* finish config */		    finish_config(1);			    /* finish the configuration and update it */		else		    return EBUSY;			    /* can't do it now */	    }	    save_config();				    /* save configuration to disk */	    return 0;	case VINUM_RELEASECONFIG:			    /* release the config */	    if (VFLAGS & VF_CONFIGURING) {		    /* must be us, the others are asleep */		finish_config(0);			    /* finish the configuration, don't change it */		save_config();				    /* save configuration to disk */	    } else		error = EINVAL;				    /* release what config? */	    return error;	case VINUM_INIT:	    ioctl_reply = (struct _ioctl_reply *) data;	    /* reinstate the address to reply to */	    ioctl_reply->error = 0;	    return 0;	case VINUM_RESETCONFIG:	    if (vinum_inactive(0)) {			    /* if the volumes are not active */		/*		 * Note the open count.  We may be called from v, so we'll be open.		 * Keep the count so we don't underflow		 */		free_vinum(1);				    /* clean up everything */		log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n");		ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */		ioctl_reply->error = 0;		return 0;	    }	    return EBUSY;	case VINUM_SETSTATE:	    setstate((struct vinum_ioctl_msg *) data);	    /* set an object state */	    return 0;#ifdef VINUMDEBUG	case VINUM_MEMINFO:	    vinum_meminfo(data);	    return 0;	case VINUM_MALLOCINFO:	    return vinum_mallocinfo(data);	case VINUM_RQINFO:	    return vinum_rqinfo(data);#endif	case VINUM_LABEL:				    /* label a volume */	    ioctl_reply->error = write_volume_label(*(int *) data); /* index of the volume to label */	    ioctl_reply->msg[0] = '\0';			    /* no message */	    return 0;	case VINUM_REMOVE:	    remove((struct vinum_ioctl_msg *) data);	    /* remove an object */	    return 0;	case VINUM_GETFREELIST:				    /* get a drive free list element */	    index = *(int *) data;			    /* get the drive index */	    fe = ((int *) data)[1];			    /* and the free list element */	    if ((index >= (unsigned) vinum_conf.drives_allocated) /* plex doesn't exist */	    ||(DRIVE[index].state == drive_unallocated))		return ENODEV;	    if (fe >= DRIVE[index].freelist_entries)	    /* no such entry */		return ENOENT;	    bcopy(&DRIVE[index].freelist[fe],		data,		sizeof(struct drive_freelist));	    return 0;	case VINUM_RESETSTATS:	    resetstats((struct vinum_ioctl_msg *) data);    /* reset object stats */	    return 0;	    /* attach an object to a superordinate object */	case VINUM_ATTACH:	    attachobject((struct vinum_ioctl_msg *) data);	    return 0;	    /* detach an object from a superordinate object */	case VINUM_DETACH:	    detachobject((struct vinum_ioctl_msg *) data);	    return 0;	    /* rename an object */	case VINUM_RENAME:	    renameobject((struct vinum_rename_msg *) data);	    return 0;	    /* replace an object */	case VINUM_REPLACE:	    replaceobject((struct vinum_ioctl_msg *) data);	    return 0;	case VINUM_DAEMON:	    vinum_daemon();				    /* perform the daemon */	    return 0;	case VINUM_FINDDAEMON:				    /* check for presence of daemon */	    return vinum_finddaemon();	    return 0;	case VINUM_SETDAEMON:				    /* set daemon flags */	    return vinum_setdaemonopts(*(int *) data);	case VINUM_GETDAEMON:				    /* get daemon flags */	    *(int *) data = daemon_options;	    return 0;	default:	    /* FALLTHROUGH */	}    default:	log(LOG_WARNING,	    "vinumioctl: invalid ioctl from process %d (%s): %lx\n",	    curproc->p_pid,	    curproc->p_comm,	    cmd);	return EINVAL;    case VINUM_DRIVE_TYPE:    case VINUM_PLEX_TYPE:	return EAGAIN;					    /* try again next week */    case VINUM_SD_TYPE:	objno = Sdno(dev);	switch (cmd) {	case VINUM_INITSD:				    /* initialize subdisk */	    return initsd(objno);	default:	    return EINVAL;	}	break;    case VINUM_VOLUME_TYPE:	objno = Volno(dev);	if ((unsigned) objno >= (unsigned) vinum_conf.volumes_allocated) /* not a valid volume */	    return ENXIO;	vol = &VOL[objno];	if (vol->state != volume_up)			    /* not up, */	    return EIO;					    /* I/O error */	switch (cmd) {	case DIOCGDINFO:				    /* get disk label */	    get_volume_label(vol, (struct disklabel *) data);	    break;	    /*	     * Care!  DIOCGPART returns *pointers* to	     * the caller, so we need to store this crap as well.	     * And yes, we need it.	     */	case DIOCGPART:					    /* get partition information */	    get_volume_label(vol, &vol->label);	    ((struct partinfo *) data)->disklab = &vol->label;	    ((struct partinfo *) data)->part = &vol->label.d_partitions[0];	    break;	    /*	     * We don't have this stuff on hardware,	     * so just pretend to do it so that	     * utilities don't get upset.	     */	case DIOCWDINFO:				    /* write partition info */	case DIOCSDINFO:				    /* set partition info */	    return 0;					    /* not a titty */	case DIOCWLABEL:				    /* set or reset label writeable */	    if ((flag & FWRITE) == 0)			    /* not writeable? */		return EACCES;				    /* no, die */	    if (*(int *) data != 0)			    /* set it? */		vol->flags |= VF_WLABEL;		    /* yes */	    else		vol->flags &= ~VF_WLABEL;		    /* no, reset */	    break;	default:	    return ENOTTY;				    /* not my kind of ioctl */	}	break;    }    return 0;						    /* XXX */}/* * The following four functions check the supplied * object index and return a pointer to the object * if it exists.  Otherwise they longjump out via * throw_rude_remark. */struct drive *validdrive(int driveno, struct _ioctl_reply *reply){    if ((driveno < vinum_conf.drives_allocated)	&& (DRIVE[driveno].state > drive_referenced))	return &DRIVE[driveno];    strcpy(reply->msg, "No such drive");    reply->error = ENOENT;    return NULL;}struct sd *validsd(int sdno, struct _ioctl_reply *reply){    if ((sdno < vinum_conf.subdisks_allocated)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?