svn commit: r185588 - head/sbin/newfs
Paul Saab
ps at mu.org
Mon Dec 8 23:42:52 PST 2008
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 at 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 *);
>
More information about the svn-src-all
mailing list