Date: Mon, 8 Dec 2008 23:17:09 -0800 From: "Paul Saab" <ps@mu.org> To: "Luigi Rizzo" <luigi@freebsd.org> Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org Subject: Re: svn commit: r185588 - head/sbin/newfs Message-ID: <5c0ff6a70812082317t15368b3aibcd6df8d13fcab3e@mail.gmail.com> In-Reply-To: <200812031837.mB3Ib0pb098329@svn.freebsd.org> References: <200812031837.mB3Ib0pb098329@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
This requires all devices end in 'a' - 'h'. This breaks newfsing zfs volumes with arbitrary names, On Wed, Dec 3, 2008 at 10:37 AM, Luigi Rizzo <luigi@freebsd.org> wrote: > Author: luigi > Date: Wed Dec 3 18:36:59 2008 > New Revision: 185588 > URL: http://svn.freebsd.org/changeset/base/185588 > > Log: > Enable operation of newfs on plain files, which is useful when you > want to prepare disk images for emulators (though 'makefs' in port > can do something similar). > > This relies on: > + minor changes to pass the consistency checks even when working on a > file; > > + an additional option, '-p partition' , to specify the disk partition to > initialize; > > + some changes on the I/O routines to deal with partition offsets. > > The latter was a bit tricky to implement, see the details in newfs.h: > in newfs, I/O is done through libufs which assumes that the file > descriptor refers to the whole partition. Introducing support for > the offset in libufs would require a non-backward compatible change > in the library, to be dealt with a version bump or with symbol > versioning. > > I felt both approaches to be overkill for this specific application, > especially because there might be other changes to libufs that might > become necessary in the near future. > > So I used the following trick: > - read access is always done by calling bread() directly, so we just add > the offset in the (few) places that call bread(); > - write access is done through bwrite() and sbwrite(), which in turn > calls bwrite(). To avoid rewriting sbwrite(), we supply our own version > of bwrite() here, which takes precedence over the version in libufs. > > MFC after: 4 weeks > > Modified: > head/sbin/newfs/Makefile > head/sbin/newfs/mkfs.c > head/sbin/newfs/newfs.8 > head/sbin/newfs/newfs.c > head/sbin/newfs/newfs.h > > Modified: head/sbin/newfs/Makefile > > ============================================================================== > --- head/sbin/newfs/Makefile Wed Dec 3 18:22:36 2008 (r185587) > +++ head/sbin/newfs/Makefile Wed Dec 3 18:36:59 2008 (r185588) > @@ -1,10 +1,13 @@ > # @(#)Makefile 8.2 (Berkeley) 3/27/94 > # $FreeBSD$ > > +.PATH: ${.CURDIR}/../../sys/geom > + > PROG= newfs > DPADD= ${LIBUFS} > LDADD= -lufs > -SRCS= newfs.c mkfs.c > +SRCS= newfs.c mkfs.c geom_bsd_enc.c > + > WARNS?= 2 > MAN= newfs.8 > > > Modified: head/sbin/newfs/mkfs.c > > ============================================================================== > --- head/sbin/newfs/mkfs.c Wed Dec 3 18:22:36 2008 (r185587) > +++ head/sbin/newfs/mkfs.c Wed Dec 3 18:36:59 2008 (r185588) > @@ -459,7 +459,7 @@ mkfs(struct partition *pp, char *fsys) > * Wipe out old UFS1 superblock(s) if necessary. > */ > if (!Nflag && Oflag != 1) { > - i = bread(&disk, SBLOCK_UFS1 / disk.d_bsize, chdummy, > SBLOCKSIZE); > + i = bread(&disk, part_ofs + SBLOCK_UFS1 / disk.d_bsize, > chdummy, SBLOCKSIZE); > if (i == -1) > err(1, "can't read old UFS1 superblock: %s", > disk.d_error); > > @@ -872,7 +872,7 @@ alloc(int size, int mode) > { > int i, d, blkno, frag; > > - bread(&disk, fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg, > + bread(&disk, part_ofs + fsbtodb(&sblock, cgtod(&sblock, 0)), (char > *)&acg, > sblock.fs_cgsize); > if (acg.cg_magic != CG_MAGIC) { > printf("cg 0: bad magic number\n"); > @@ -925,7 +925,7 @@ iput(union dinode *ip, ino_t ino) > int c; > > c = ino_to_cg(&sblock, ino); > - bread(&disk, fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg, > + bread(&disk, part_ofs + fsbtodb(&sblock, cgtod(&sblock, 0)), (char > *)&acg, > sblock.fs_cgsize); > if (acg.cg_magic != CG_MAGIC) { > printf("cg 0: bad magic number\n"); > @@ -942,7 +942,7 @@ iput(union dinode *ip, ino_t ino) > exit(32); > } > d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); > - bread(&disk, d, (char *)iobuf, sblock.fs_bsize); > + bread(&disk, part_ofs + d, (char *)iobuf, sblock.fs_bsize); > if (sblock.fs_magic == FS_UFS1_MAGIC) > ((struct ufs1_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] = > ip->dp1; > > Modified: head/sbin/newfs/newfs.8 > > ============================================================================== > --- head/sbin/newfs/newfs.8 Wed Dec 3 18:22:36 2008 (r185587) > +++ head/sbin/newfs/newfs.8 Wed Dec 3 18:36:59 2008 (r185588) > @@ -52,6 +52,7 @@ > .Op Fl i Ar bytes > .Op Fl m Ar free-space > .Op Fl o Ar optimization > +.Op Fl p Ar partition > .Op Fl r Ar reserved > .Op Fl s Ar size > .Ar special > @@ -201,6 +202,17 @@ the default is to optimize for > See > .Xr tunefs 8 > for more details on how to set this option. > +.It Fl p Ar partition > +The partition name (a..h) you want to use in case the underlying image > +is a file, so you don't have access to individual partitions through the > +filesystem. > +Can also be used with a device, e.g. > +.Nm > +.Fl p Ar f > +.Ar /dev/da1s3 > +is equivalent to > +.Nm > +.Ar /dev/da1s3f . > .It Fl r Ar reserved > The size, in sectors, of reserved space > at the end of the partition specified in > > Modified: head/sbin/newfs/newfs.c > > ============================================================================== > --- head/sbin/newfs/newfs.c Wed Dec 3 18:22:36 2008 (r185587) > +++ head/sbin/newfs/newfs.c Wed Dec 3 18:36:59 2008 (r185588) > @@ -139,6 +139,9 @@ u_char *volumelabel = NULL; /* volume la > struct uufsd disk; /* libufs disk structure */ > > static char device[MAXPATHLEN]; > +static u_char bootarea[BBSIZE]; > +static int is_file; /* work on a file, not a device */ > +static char *dkname; > static char *disktype; > static int unlabeled; > > @@ -147,6 +150,18 @@ static struct disklabel *getdisklabel(ch > static void rewritelabel(char *s, struct disklabel *lp); > static void usage(void); > > +ufs2_daddr_t part_ofs; /* partition offset in blocks, used with files */ > + > +/* > + * need to replace the library's bwrite so that sbwrite uses this one > + */ > +ssize_t > +bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t > size) > +{ > + return pwrite(disk->d_fd, data, size, > + (off_t)((part_ofs + blockno) * disk->d_bsize)); > +} > + > int > main(int argc, char *argv[]) > { > @@ -158,7 +173,9 @@ main(int argc, char *argv[]) > intmax_t reserved; > int ch, i; > off_t mediasize; > + char part_name; /* partition name, default to full disk */ > > + part_name = 'c'; > reserved = 0; > while ((ch = getopt(argc, argv, > "EJL:NO:RS:T:UXa:b:c:d:e:f:g:h:i:lm:no:r:s:")) != -1) > @@ -276,6 +293,11 @@ main(int argc, char *argv[]) > *cp != '\0' || reserved < 0) > errx(1, "%s: bad reserved size", optarg); > break; > + case 'p': > + is_file = 1; > + part_name = optarg[0]; > + break; > + > case 's': > errno = 0; > fssize = strtoimax(optarg, &cp, 0); > @@ -294,6 +316,8 @@ main(int argc, char *argv[]) > usage(); > > special = argv[0]; > + if (!special[0]) > + err(1, "empty file/special name"); > cp = strrchr(special, '/'); > if (cp == 0) { > /* > @@ -303,7 +327,16 @@ main(int argc, char *argv[]) > special = device; > } > > - if (ufs_disk_fillout_blank(&disk, special) == -1 || > + if (is_file) { > + /* bypass ufs_disk_fillout_blank */ > + bzero( &disk, sizeof(disk)); > + disk.d_bsize = 1; > + disk.d_name = special; > + disk.d_fd = open(special, O_RDONLY); > + if (disk.d_fd < 0 || > + (!Nflag && ufs_disk_write(&disk) == -1)) > + errx(1, "%s: ", special); > + } else if (ufs_disk_fillout_blank(&disk, special) == -1 || > (!Nflag && ufs_disk_write(&disk) == -1)) { > if (disk.d_error != NULL) > errx(1, "%s: %s", special, disk.d_error); > @@ -312,22 +345,30 @@ main(int argc, char *argv[]) > } > if (fstat(disk.d_fd, &st) < 0) > err(1, "%s", special); > - if ((st.st_mode & S_IFMT) != S_IFCHR) > - errx(1, "%s: not a character-special device", special); > + if ((st.st_mode & S_IFMT) != S_IFCHR) { > + warn("%s: not a character-special device", special); > + is_file = 1; /* assume it is a file */ > + dkname = special; > + if (sectorsize == 0) > + sectorsize = 512; > + mediasize = st.st_size; > + /* set fssize from the partition */ > + } else { > + part_name = special[strlen(special) - 1]; > + if ((part_name < 'a' || part_name > 'h') && > !isdigit(part_name)) > + errx(1, "%s: can't figure out file system partition", > + special); > > - if (sectorsize == 0) > + if (sectorsize == 0) > if (ioctl(disk.d_fd, DIOCGSECTORSIZE, §orsize) == -1) > - sectorsize = 0; /* back out on error for safety */ > - if (sectorsize && ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize) != > -1) > + sectorsize = 0; /* back out on error for safety */ > + if (sectorsize && ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize) > != -1) > getfssize(&fssize, special, mediasize / sectorsize, > reserved); > + } > pp = NULL; > lp = getdisklabel(special); > if (lp != NULL) { > - cp = strchr(special, '\0'); > - cp--; > - if ((*cp < 'a' || *cp > 'h') && !isdigit(*cp)) > - errx(1, "%s: can't figure out file system > partition", > - special); > + cp = &part_name; > if (isdigit(*cp)) > pp = &lp->d_partitions[RAW_PART]; > else > @@ -346,6 +387,8 @@ main(int argc, char *argv[]) > fsize = pp->p_fsize; > if (bsize == 0) > bsize = pp->p_frag * pp->p_fsize; > + if (is_file) > + part_ofs = pp->p_offset; > } > if (sectorsize <= 0) > errx(1, "%s: no default sector size", special); > @@ -414,6 +457,19 @@ getdisklabel(char *s) > static struct disklabel lab; > struct disklabel *lp; > > + if (is_file) { > + if (read(disk.d_fd, bootarea, BBSIZE) != BBSIZE) > + err(4, "cannot read bootarea"); > + if (bsd_disklabel_le_dec( > + bootarea + (0 /* labeloffset */ + > + 1 /* labelsoffset */ * sectorsize), > + &lab, MAXPARTITIONS)) > + errx(1, "no valid label found"); > + > + lp = &lab; > + return &lab; > + } > + > if (ioctl(disk.d_fd, DIOCGDINFO, (char *)&lab) != -1) > return (&lab); > unlabeled++; > @@ -432,6 +488,14 @@ rewritelabel(char *s, struct disklabel * > 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); > } > @@ -467,6 +531,7 @@ usage() > fprintf(stderr, "\t-n do not create .snap directory\n"); > fprintf(stderr, "\t-m minimum free space %%\n"); > fprintf(stderr, "\t-o optimization preference (`space' or > `time')\n"); > + fprintf(stderr, "\t-p partition name (a..h)\n"); > fprintf(stderr, "\t-r reserved sectors at the end of device\n"); > fprintf(stderr, "\t-s file system size (sectors)\n"); > exit(1); > > Modified: head/sbin/newfs/newfs.h > > ============================================================================== > --- head/sbin/newfs/newfs.h Wed Dec 3 18:22:36 2008 (r185587) > +++ head/sbin/newfs/newfs.h Wed Dec 3 18:36:59 2008 (r185588) > @@ -70,4 +70,20 @@ extern int avgfilesperdir; /* expected n > extern u_char *volumelabel; /* volume label for filesystem */ > extern struct uufsd disk; /* libufs disk structure */ > > +/* > + * To override a limitation in libufs, export the offset (in sectors) of > the > + * partition on the underlying media (file or disk). The value is used as > + * an offset for all accesses to the media through bread(), which is only > + * invoked directly in this program. > + * For bwrite() we need a different approach, namely override the library > + * version with one defined here. This is because bwrite() is called also > + * by the library function sbwrite() which we cannot intercept nor want to > + * rewrite. As a consequence, the internal version of bwrite() adds the > + * partition offset itself when calling the underlying function, pwrite(). > + * > + * XXX This info really ought to go into the struct uufsd, at which point > + * we can remove the above hack. > + */ > +extern ufs2_daddr_t part_ofs; /* partition offset in blocks */ > + > void mkfs (struct partition *, char *); >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5c0ff6a70812082317t15368b3aibcd6df8d13fcab3e>