void rewritelabel(char *s, struct disklabel *lp) { if (unlabeled) return; lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); if (is_file) { bsd_disklabel_le_enc(bootarea + 0 /* labeloffset */ + 1 /* labelsoffset */ * sectorsize, lp); lseek(disk.d_fd, 0, SEEK_SET); if (write(disk.d_fd, bootarea, BBSIZE) != BBSIZE) errx(1, "cannot write label"); return; } if (ioctl(disk.d_fd, DIOCWDINFO, (char *)lp) == -1) warn("ioctl (WDINFO): %s: can't rewrite disk label", s); }
static int writelabel(void) { int i, fd, serrno; struct gctl_req *grq; char const *errstr; struct disklabel *lp = &lab; if (disable_write) { warnx("write to disk label suppressed - label was as follows:"); display(stdout, NULL); return (0); } lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); if (installboot) readboot(); for (i = 0; i < lab.d_npartitions; i++) if (lab.d_partitions[i].p_size) lab.d_partitions[i].p_offset += lba_offset; bsd_disklabel_le_enc(bootarea + labeloffset + labelsoffset * lab.d_secsize, lp); fd = open(specname, O_RDWR); if (fd < 0) { if (is_file) { warn("cannot open file %s for writing label", specname); return(1); } else serrno = errno; if (geom_class_available("PART") != 0) { /* * Since we weren't able open provider for * writing, then recommend user to use gpart(8). */ warnc(serrno, "cannot open provider %s for writing label", specname); warnx("Try to use gpart(8)."); return (1); } /* Give up if GEOM_BSD is not available. */ if (geom_class_available("BSD") == 0) { warnc(serrno, "%s", specname); return (1); } grq = gctl_get_handle(); gctl_ro_param(grq, "verb", -1, "write label"); gctl_ro_param(grq, "class", -1, "BSD"); gctl_ro_param(grq, "geom", -1, pname); gctl_ro_param(grq, "label", 148+16*8, bootarea + labeloffset + labelsoffset * lab.d_secsize); errstr = gctl_issue(grq); if (errstr != NULL) { warnx("%s", errstr); gctl_free(grq); return(1); } gctl_free(grq); if (installboot) { grq = gctl_get_handle(); gctl_ro_param(grq, "verb", -1, "write bootcode"); gctl_ro_param(grq, "class", -1, "BSD"); gctl_ro_param(grq, "geom", -1, pname); gctl_ro_param(grq, "bootcode", BBSIZE, bootarea); errstr = gctl_issue(grq); if (errstr != NULL) { warnx("%s", errstr); gctl_free(grq); return (1); } gctl_free(grq); } } else { if (write(fd, bootarea, bbsize) != bbsize) { warn("write %s", specname); close (fd); return (1); } close (fd); } return (0); }
/*- * This start routine is only called for non-trivial requests, all the * trivial ones are handled autonomously by the slice code. * For requests we handle here, we must call the g_io_deliver() on the * bio, and return non-zero to indicate to the slice code that we did so. * This code executes in the "DOWN" I/O path, this means: * * No sleeping. * * Don't grab the topology lock. * * Don't call biowait, g_getattr(), g_setattr() or g_read_data() */ static int g_bsd_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td) { struct g_geom *gp; struct g_bsd_softc *ms; struct g_slicer *gsp; u_char *label; int error; gp = pp->geom; gsp = gp->softc; ms = gsp->softc; switch(cmd) { case DIOCGDINFO: /* Return a copy of the disklabel to userland. */ bsd_disklabel_le_dec(ms->label, data, MAXPARTITIONS); return(0); case DIOCBSDBB: { struct g_consumer *cp; u_char *buf; void *p; int error, i; uint64_t sum; if (!(fflag & FWRITE)) return (EPERM); /* The disklabel to set is the ioctl argument. */ buf = g_malloc(BBSIZE, M_WAITOK); p = *(void **)data; error = copyin(p, buf, BBSIZE); if (!error) { /* XXX: Rude, but supposedly safe */ DROP_GIANT(); g_topology_lock(); /* Validate and modify our slice instance to match. */ error = g_bsd_modify(gp, buf + ms->labeloffset); if (!error) { cp = LIST_FIRST(&gp->consumer); if (ms->labeloffset == ALPHA_LABEL_OFFSET) { sum = 0; for (i = 0; i < 63; i++) sum += le64dec(buf + i * 8); le64enc(buf + 504, sum); } error = g_write_data(cp, 0, buf, BBSIZE); } g_topology_unlock(); PICKUP_GIANT(); } g_free(buf); return (error); } case DIOCSDINFO: case DIOCWDINFO: { if (!(fflag & FWRITE)) return (EPERM); label = g_malloc(LABELSIZE, M_WAITOK); /* The disklabel to set is the ioctl argument. */ bsd_disklabel_le_enc(label, data); DROP_GIANT(); g_topology_lock(); /* Validate and modify our slice instance to match. */ error = g_bsd_modify(gp, label); if (error == 0 && cmd == DIOCWDINFO) error = g_bsd_writelabel(gp, NULL); g_topology_unlock(); PICKUP_GIANT(); g_free(label); return(error); } default: return (ENOIOCTL); } }