vinumio.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,103 行 · 第 1/3 页
C
1,103 行
if (error) { brelse(bp); return error; } error = uiomove((char *) bp->b_data + blockoff, count, &uio); /* move the data */ brelse(bp); } while (error == 0 && uio.uio_resid > 0 && count != 0); return error;}/* * Write data to a drive * * Return error number */int write_drive(struct drive *drive, void *buf, size_t length, off_t offset){ int error; struct buf *bp; struct uio uio; struct iovec iov; daddr_t blocknum; /* block number */ int blockoff; /* offset in block */ int count; /* amount to transfer */ int blockshift; if (drive->state == drive_down) /* currently down */ return 0; /* ignore */ if (drive->vp == NULL) { drive->lasterror = ENODEV; return ENODEV; /* not configured yet */ } iov.iov_base = buf; iov.iov_len = length; uio.uio_iov = &iov; uio.uio_iovcnt = length; uio.uio_offset = offset; uio.uio_resid = length; uio.uio_segflg = UIO_SYSSPACE; uio.uio_rw = UIO_WRITE; uio.uio_procp = curproc; error = 0; blockshift = btodb(drive->blocksize) - 1; /* amount to shift block number * to get sector number */ do { blocknum = btodb(uio.uio_offset) & ~blockshift; /* get the block number */ blockoff = uio.uio_offset % drive->blocksize; /* offset in block */ count = min((unsigned) (drive->blocksize - blockoff), /* amount to transfer in this block */ uio.uio_resid); if (count == drive->blocksize) /* the whole block */ bp = getblk(drive->vp, blocknum, drive->blocksize, 0, 0); /* just transfer it */ else /* partial block: */ error = bread(drive->vp, /* read it first */ blocknum, drive->blocksize, NOCRED, &bp); count = min(count, drive->blocksize - bp->b_resid); /* how much will we transfer now? */ if (error == 0) error = uiomove((char *) bp->b_data + blockoff, /* move the data to the block */ count, &uio); if (error) { brelse(bp); drive->lasterror = error; switch (error) { case EIO: set_drive_state(drive->driveno, drive_down, setstate_force); break; /* XXX Add other possibilities here */ default: } return error; } if (count + blockoff == drive->blocksize) /* * The transfer goes to the end of the block. There's * no need to wait for any more data to arrive. */ bawrite(bp); /* start the write now */ else bdwrite(bp); /* do a delayed write */ } while (error == 0 && uio.uio_resid > 0 && count != 0); if (error) drive->lasterror = error; return error; /* OK */}/* Wake up on completion */void drive_io_done(struct buf *bp){ wakeup((caddr_t) bp); /* Wachet auf! */ bp->b_flags &= ~B_CALL; /* don't do this again */}/* * Check a drive for a vinum header. If found, * update the drive information. We come here * with a partially populated drive structure * which includes the device name. * * Return information on what we found. * * This function is called from two places: check_drive, * which wants to find out whether the drive is a * Vinum drive, and config_drive, which asserts that * it is a vinum drive. In the first case, we don't * print error messages (verbose==0), in the second * we do (verbose==1). */enum drive_label_info read_drive_label(struct drive *drive, int verbose){ int error; int result; /* result of our search */ struct vinum_hdr *vhdr; /* and as header */ error = init_drive(drive, 0); /* find the drive */ if (error) /* find the drive */ return DL_CANT_OPEN; /* not ours */ vhdr = (struct vinum_hdr *) Malloc(VINUMHEADERLEN); /* allocate buffers */ CHECKALLOC(vhdr, "Can't allocate memory"); error = read_drive(drive, (void *) vhdr, VINUMHEADERLEN, VINUM_LABEL_OFFSET); if (vhdr->magic == VINUM_MAGIC) { /* ours! */ if (drive->label.name[0] /* we have a name for this drive */ &&(strcmp(drive->label.name, vhdr->label.name))) { /* but it doesn't match the real name */ drive->lasterror = EINVAL; result = DL_WRONG_DRIVE; /* it's the wrong drive */ } else { drive->state = drive_up; /* it's OK by us */ result = DL_OURS; } /* * We copy the drive anyway so that we have * the correct name in the drive info. This * may not be the name specified */ drive->label = vhdr->label; /* put in the label information */ } else if (vhdr->magic == VINUM_NOMAGIC) /* was ours, but we gave it away */ result = DL_DELETED_LABEL; /* and return the info */ else result = DL_NOT_OURS; /* we could have it, but we don't yet */ Free(vhdr); /* that's all. */ return result;}/* * Check a drive for a vinum header. If found, * read configuration information from the drive and * incorporate the data into the configuration. * * Return drive number. */struct drive *check_drive(char *devicename){ int driveno; int i; struct drive *drive; driveno = find_drive_by_dev(devicename, 1); /* if entry doesn't exist, create it */ drive = &vinum_conf.drive[driveno]; /* and get a pointer */ if (read_drive_label(drive, 0) == DL_OURS) { /* not ours */ for (i = 0; i < vinum_conf.drives_allocated; i++) { /* see if the name already exists */ if ((i != driveno) /* not this drive */&&(DRIVE[i].state != drive_unallocated) /* and it's allocated */ &&(strcmp(DRIVE[i].label.name, DRIVE[driveno].label.name) == 0)) { /* and it has the same name */ struct drive *mydrive = &DRIVE[i]; if (mydrive->devicename[0] == '/') { /* we know a device name for it */ /* * set an error, but don't take the drive down: * that would cause unneeded error messages. */ drive->lasterror = EEXIST; break; } else { /* it's just a place holder, */ int sdno; for (sdno = 0; sdno < vinum_conf.subdisks_allocated; sdno++) { /* look at each subdisk */ if ((SD[sdno].driveno == i) /* it's pointing to this one, */ &&(SD[sdno].state != sd_unallocated)) { /* and it's a real subdisk */ SD[sdno].driveno = drive->driveno; /* point to the one we found */ update_sd_state(sdno); /* and update its state */ } } bzero(mydrive, sizeof(struct drive)); /* don't deallocate it, just remove it */ } } } } else { if (drive->lasterror == 0) drive->lasterror = ENODEV; set_drive_state(drive->driveno, drive_down, setstate_force); } return drive;}static char *sappend(char *txt, char *s){ while ((*s++ = *txt++) != 0); return s - 1;}/* Kludge: kernel printf doesn't handle quads correctly XXX */static char *lltoa(long long l, char *s);static char *lltoa(long long l, char *s){ if (l < 0) { *s++ = '-'; l = -l; } if (l > 9) { s = lltoa(l / 10, s); l %= 10; } *s++ = l + '0'; return s;}/* * Format the configuration in text form into the buffer * at config. Don't go beyond len bytes * XXX this stinks. Fix soon. */void format_config(char *config, int len){ int i; int j; char *s = config; bzero(config, len); /* First, the volume configuration */ for (i = 0; i < vinum_conf.volumes_allocated; i++) { struct volume *vol; vol = &vinum_conf.volume[i]; if ((vol->state > volume_uninit) && (vol->name[0] != '\0')) { /* paranoia */ if (vol->preferred_plex >= 0) /* preferences, */ sprintf(s, "volume %s state %s readpol prefer %s", vol->name, volume_state(vol->state), vinum_conf.plex[vol->preferred_plex].name); else /* default round-robin */ sprintf(s, "volume %s state %s", vol->name, volume_state(vol->state)); while (*s) s++; /* find the end */ s = sappend("\n", s); if (s > &config[len - 80]) { log(LOG_ERR, "vinum: configuration data overflow\n"); return; } } } /* Then the plex configuration */ for (i = 0; i < vinum_conf.plexes_allocated; i++) { struct plex *plex; plex = &vinum_conf.plex[i]; if ((plex->state != plex_referenced) && (plex->name[0] != '\0')) { /* paranoia */ sprintf(s, "plex name %s state %s org %s ", plex->name, plex_state(plex->state), plex_org(plex->organization)); while (*s) s++; /* find the end */ if ((plex->organization == plex_striped) || (plex->organization == plex_raid5)) { sprintf(s, "%db ", (int) plex->stripesize); while (*s) s++; /* find the end */ } if (plex->volno >= 0) /* we have a volume */ sprintf(s, "vol %s ", vinum_conf.volume[plex->volno].name); while (*s) s++; /* find the end */ for (j = 0; j < plex->subdisks; j++) { sprintf(s, " sd %s", vinum_conf.sd[plex->sdnos[j]].name); } s = sappend("\n", s); if (s > &config[len - 80]) { log(LOG_ERR, "vinum: configuration data overflow\n"); return; } } } /* And finally the subdisk configuration */ for (i = 0; i < vinum_conf.subdisks_allocated; i++) { struct sd *sd; sd = &SD[i]; if ((sd->state != sd_referenced) && (sd->name[0] != '\0')) { /* paranoia */ sprintf(s, "sd name %s drive %s plex %s state %s len ", sd->name, vinum_conf.drive[sd->driveno].label.name, vinum_conf.plex[sd->plexno].name, sd_state(sd->state)); while (*s) s++; /* find the end */ s = lltoa(sd->sectors, s); s = sappend("b driveoffset ", s); s = lltoa(sd->driveoffset, s); s = sappend("b plexoffset ", s); s = lltoa(sd->plexoffset, s); s = sappend("b\n", s); if (s > &config[len - 80]) { log(LOG_ERR, "vinum: configuration data overflow\n"); return; } } }}/* * issue a save config request to the d鎚on. The actual work * is done in process context by daemon_save_config */void save_config(void){ queue_daemon_request(daemonrq_saveconfig, (union daemoninfo) NULL);}/* * Write the configuration to all vinum slices. This * is performed by the d鎚on only */void daemon_save_config(void){ int error; int written_config; /* set when we first write the config to disk */ int driveno; struct drive *drive; /* point to current drive info */ struct vinum_hdr *vhdr; /* and as header */ char *config; /* point to config data */ int wlabel_on; /* to set writing label on/off */ /* don't save the configuration while we're still working on it */ if (vinum_conf.flags & VF_CONFIGURING) return; written_config = 0; /* no config written yet */ /* Build a volume header */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?