diff options
Diffstat (limited to 'usr.sbin/makefs')
-rw-r--r-- | usr.sbin/makefs/ffs.c | 94 | ||||
-rw-r--r-- | usr.sbin/makefs/zfs.c | 2 | ||||
-rw-r--r-- | usr.sbin/makefs/zfs/vdev.c | 2 |
3 files changed, 78 insertions, 20 deletions
diff --git a/usr.sbin/makefs/ffs.c b/usr.sbin/makefs/ffs.c index c0fcadf11fba..ed94abb7504f 100644 --- a/usr.sbin/makefs/ffs.c +++ b/usr.sbin/makefs/ffs.c @@ -591,6 +591,75 @@ ffs_create_image(const char *image, fsinfo_t *fsopts) return (fsopts->fd); } +static void +ffs_add_size(fsinfo_t *fsopts, size_t file_len) +{ + ffs_opt_t *ffs_opts = fsopts->fs_specific; + size_t blocks, fs_nindir, overhead; + int indir_level; + + blocks = howmany(file_len, ffs_opts->bsize); + + if (blocks <= UFS_NDADDR) { + /* Count full blocks. */ + fsopts->size += rounddown2(file_len, ffs_opts->bsize); + /* Calculate fragment size needed. */ + overhead = howmany(file_len - + rounddown2(file_len, ffs_opts->bsize), ffs_opts->fsize); + + /* + * A file could have just 1 fragment with size 1/8, 1/4 or 1/2 + * of bsize. + */ + switch (overhead) { + case 0: + break; + case 1: + fsopts->size += ffs_opts->fsize; + break; + case 2: + fsopts->size += 2 * ffs_opts->fsize; + break; + case 3: + case 4: + fsopts->size += 4 * ffs_opts->fsize; + break; + default: + fsopts->size += ffs_opts->bsize; + break; + } + return; + } + + /* File does not fit into direct blocks, count indirect blocks. */ + blocks = howmany(file_len - UFS_NDADDR * (size_t)ffs_opts->bsize, + ffs_opts->bsize); + fs_nindir = (size_t)ffs_opts->bsize / ((ffs_opts->version == 1) ? + sizeof(ufs1_daddr_t) : sizeof(ufs2_daddr_t)); + + indir_level = overhead = 0; + while (blocks > 0 && indir_level < 3) { + /* One indirect block is stored in di_ib[] */ + blocks = howmany(blocks, fs_nindir) - 1; + fsopts->size += ffs_opts->bsize * blocks; + overhead += blocks + 1; + indir_level++; + } + + assert(blocks == 0); + + if ((debug & DEBUG_FS_SIZE_DIR_NODE) != 0) { + printf("ffs_size_dir: size %jd, using %d levels of indirect " + "blocks, overhead %jd blocks\n", (uintmax_t)file_len, + indir_level, (uintmax_t)overhead); + } + + /* + * If the file is big enough to use indirect blocks, + * we allocate bsize block for trailing data. + */ + fsopts->size += roundup2(file_len, ffs_opts->bsize); +} static void ffs_size_dir(fsnode *root, fsinfo_t *fsopts) @@ -622,20 +691,6 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts) e, tmpdir.d_namlen, this, curdirsize); \ } while (0); -#define ADDSIZE(x) do { \ - if ((size_t)(x) < UFS_NDADDR * (size_t)ffs_opts->bsize) { \ - fsopts->size += roundup((x), ffs_opts->fsize); \ - } else { \ - /* Count space consumed by indirecttion blocks. */ \ - fsopts->size += ffs_opts->bsize * \ - (howmany((x), UFS_NDADDR * ffs_opts->bsize) - 1); \ - /* \ - * If the file is big enough to use indirect blocks, \ - * we allocate bsize block for trailing data. \ - */ \ - fsopts->size += roundup((x), ffs_opts->bsize); \ - } \ -} while (0); curdirsize = 0; for (node = root; node != NULL; node = node->next) { @@ -646,13 +701,13 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts) } else if ((node->inode->flags & FI_SIZED) == 0) { /* don't count duplicate names */ node->inode->flags |= FI_SIZED; - if (debug & DEBUG_FS_SIZE_DIR_NODE) + if ((debug & DEBUG_FS_SIZE_DIR_NODE) != 0) printf("ffs_size_dir: `%s' size %lld\n", node->name, (long long)node->inode->st.st_size); fsopts->inodes++; if (node->type == S_IFREG) - ADDSIZE(node->inode->st.st_size); + ffs_add_size(fsopts, node->inode->st.st_size); if (node->type == S_IFLNK) { size_t slen; @@ -660,13 +715,16 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts) if (slen >= (ffs_opts->version == 1 ? UFS1_MAXSYMLINKLEN : UFS2_MAXSYMLINKLEN)) - ADDSIZE(slen); + ffs_add_size(fsopts, slen); } } if (node->type == S_IFDIR) ffs_size_dir(node->child, fsopts); } - ADDSIZE(curdirsize); + ffs_add_size(fsopts, curdirsize); + + /* Round up to full block to account fragment scattering. */ + fsopts->size = roundup2(fsopts->size, ffs_opts->bsize); if (debug & DEBUG_FS_SIZE_DIR) printf("ffs_size_dir: exit: size %lld inodes %lld\n", diff --git a/usr.sbin/makefs/zfs.c b/usr.sbin/makefs/zfs.c index 8d50c450541b..e33a182e5c8f 100644 --- a/usr.sbin/makefs/zfs.c +++ b/usr.sbin/makefs/zfs.c @@ -596,7 +596,7 @@ pool_labels_write(zfs_opt_t *zfs) * checksum is calculated in vdev_label_write(). */ for (size_t uoff = 0; uoff < sizeof(label->vl_uberblock); - uoff += (1 << zfs->ashift)) { + uoff += ASHIFT_UBERBLOCK_SIZE(zfs->ashift)) { ub = (uberblock_t *)(&label->vl_uberblock[0] + uoff); ub->ub_magic = UBERBLOCK_MAGIC; ub->ub_version = SPA_VERSION; diff --git a/usr.sbin/makefs/zfs/vdev.c b/usr.sbin/makefs/zfs/vdev.c index afcce402cb13..a2423e180ca3 100644 --- a/usr.sbin/makefs/zfs/vdev.c +++ b/usr.sbin/makefs/zfs/vdev.c @@ -200,7 +200,7 @@ vdev_label_write(zfs_opt_t *zfs, int ind, const vdev_label_t *labelp) * per sector; for example, with an ashift of 12 we end up with * 128KB/4KB=32 copies of the uberblock in the ring. */ - blksz = 1 << zfs->ashift; + blksz = ASHIFT_UBERBLOCK_SIZE(zfs->ashift); assert(sizeof(label->vl_uberblock) % blksz == 0); for (size_t roff = 0; roff < sizeof(label->vl_uberblock); roff += blksz) { |