Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/ext2fs/ext2_vfsops.c
Show First 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
#include <sys/vnode.h> | #include <sys/vnode.h> | ||||
#include <sys/mount.h> | #include <sys/mount.h> | ||||
#include <sys/bio.h> | #include <sys/bio.h> | ||||
#include <sys/buf.h> | #include <sys/buf.h> | ||||
#include <sys/conf.h> | #include <sys/conf.h> | ||||
#include <sys/endian.h> | #include <sys/endian.h> | ||||
#include <sys/fcntl.h> | #include <sys/fcntl.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/sdt.h> | |||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <geom/geom.h> | #include <geom/geom.h> | ||||
#include <geom/geom_vfs.h> | #include <geom/geom_vfs.h> | ||||
#include <fs/ext2fs/fs.h> | #include <fs/ext2fs/fs.h> | ||||
#include <fs/ext2fs/ext2_mount.h> | #include <fs/ext2fs/ext2_mount.h> | ||||
#include <fs/ext2fs/inode.h> | #include <fs/ext2fs/inode.h> | ||||
#include <fs/ext2fs/ext2fs.h> | #include <fs/ext2fs/ext2fs.h> | ||||
#include <fs/ext2fs/ext2_dinode.h> | #include <fs/ext2fs/ext2_dinode.h> | ||||
#include <fs/ext2fs/ext2_extern.h> | #include <fs/ext2fs/ext2_extern.h> | ||||
#include <fs/ext2fs/ext2_extents.h> | #include <fs/ext2fs/ext2_extents.h> | ||||
SDT_PROVIDER_DECLARE(ext2fs); | |||||
/* | |||||
* ext2fs trace probe: | |||||
* arg0: verbosity. Higher numbers give more verbose messages | |||||
* arg1: Textual message | |||||
*/ | |||||
SDT_PROBE_DEFINE2(ext2fs, , vfsops, trace, "int", "char*"); | |||||
static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td); | static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td); | ||||
static int ext2_mountfs(struct vnode *, struct mount *); | static int ext2_mountfs(struct vnode *, struct mount *); | ||||
static int ext2_reload(struct mount *mp, struct thread *td); | static int ext2_reload(struct mount *mp, struct thread *td); | ||||
static int ext2_sbupdate(struct ext2mount *, int); | static int ext2_sbupdate(struct ext2mount *, int); | ||||
static int ext2_cgupdate(struct ext2mount *, int); | static int ext2_cgupdate(struct ext2mount *, int); | ||||
static vfs_unmount_t ext2_unmount; | static vfs_unmount_t ext2_unmount; | ||||
static vfs_root_t ext2_root; | static vfs_root_t ext2_root; | ||||
static vfs_statfs_t ext2_statfs; | static vfs_statfs_t ext2_statfs; | ||||
▲ Show 20 Lines • Show All 266 Lines • ▼ Show 20 Lines | ext2_cg_location(struct m_ext2fs *fs, int number) | ||||
if (ext2_cg_has_sb(fs, cg)) | if (ext2_cg_has_sb(fs, cg)) | ||||
has_super = 1; | has_super = 1; | ||||
return (has_super + cg * (e4fs_daddr_t)EXT2_BLOCKS_PER_GROUP(fs) + | return (has_super + cg * (e4fs_daddr_t)EXT2_BLOCKS_PER_GROUP(fs) + | ||||
fs->e2fs->e2fs_first_dblock); | fs->e2fs->e2fs_first_dblock); | ||||
} | } | ||||
SDT_PROBE_DEFINE2(ext2fs, , vfsops, ext2_cg_validate_error, "char*", "int"); | |||||
static int | static int | ||||
ext2_cg_validate(struct m_ext2fs *fs) | ext2_cg_validate(struct m_ext2fs *fs) | ||||
{ | { | ||||
uint64_t b_bitmap; | uint64_t b_bitmap; | ||||
uint64_t i_bitmap; | uint64_t i_bitmap; | ||||
uint64_t i_tables; | uint64_t i_tables; | ||||
uint64_t first_block, last_block, last_cg_block; | uint64_t first_block, last_block, last_cg_block; | ||||
struct ext2_gd *gd; | struct ext2_gd *gd; | ||||
Show All 15 Lines | for (i = 0; i < fs->e2fs_gcount; i++) { | ||||
} | } | ||||
if ((cg_count == fs->e2fs_gcount) && | if ((cg_count == fs->e2fs_gcount) && | ||||
!(gd->ext4bgd_flags & EXT2_BG_INODE_ZEROED)) | !(gd->ext4bgd_flags & EXT2_BG_INODE_ZEROED)) | ||||
cg_count = i; | cg_count = i; | ||||
b_bitmap = e2fs_gd_get_b_bitmap(gd); | b_bitmap = e2fs_gd_get_b_bitmap(gd); | ||||
if (b_bitmap == 0) { | if (b_bitmap == 0) { | ||||
printf("ext2fs: cg %u: block bitmap is zero\n", i); | SDT_PROBE2(ext2fs, , vfsops, ext2_cg_validate_error, | ||||
"block bitmap is zero", i); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (b_bitmap <= last_cg_block) { | if (b_bitmap <= last_cg_block) { | ||||
printf("ext2fs: cg %u: block bitmap overlaps gds\n", i); | SDT_PROBE2(ext2fs, , vfsops, ext2_cg_validate_error, | ||||
"block bitmap overlaps gds", i); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (b_bitmap < first_block || b_bitmap > last_block) { | if (b_bitmap < first_block || b_bitmap > last_block) { | ||||
printf("ext2fs: cg %u: block bitmap not in group, blk=%ju\n", | SDT_PROBE2(ext2fs, , vfsops, ext2_cg_validate_error, | ||||
i, b_bitmap); | "block bitmap not in group", i); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
i_bitmap = e2fs_gd_get_i_bitmap(gd); | i_bitmap = e2fs_gd_get_i_bitmap(gd); | ||||
if (i_bitmap == 0) { | if (i_bitmap == 0) { | ||||
printf("ext2fs: cg %u: inode bitmap is zero\n", i); | SDT_PROBE2(ext2fs, , vfsops, ext2_cg_validate_error, | ||||
"inode bitmap is zero", i); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (i_bitmap <= last_cg_block) { | if (i_bitmap <= last_cg_block) { | ||||
printf("ext2fs: cg %u: inode bitmap overlaps gds\n", i); | SDT_PROBE2(ext2fs, , vfsops, ext2_cg_validate_error, | ||||
"inode bitmap overlaps gds", i); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (i_bitmap < first_block || i_bitmap > last_block) { | if (i_bitmap < first_block || i_bitmap > last_block) { | ||||
printf("ext2fs: cg %u: inode bitmap not in group blk=%ju\n", | SDT_PROBE2(ext2fs, , vfsops, ext2_cg_validate_error, | ||||
i, i_bitmap); | "inode bitmap not in group blk", i); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
i_tables = e2fs_gd_get_i_tables(gd); | i_tables = e2fs_gd_get_i_tables(gd); | ||||
if (i_tables == 0) { | if (i_tables == 0) { | ||||
printf("ext2fs: cg %u: inode table is zero\n", i); | SDT_PROBE2(ext2fs, , vfsops, ext2_cg_validate_error, | ||||
"inode table is zero", i); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (i_tables <= last_cg_block) { | if (i_tables <= last_cg_block) { | ||||
printf("ext2fs: cg %u: inode talbes overlaps gds\n", i); | SDT_PROBE2(ext2fs, , vfsops, ext2_cg_validate_error, | ||||
"inode talbes overlaps gds", i); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (i_tables < first_block || | if (i_tables < first_block || | ||||
i_tables + fs->e2fs_itpg - 1 > last_block) { | i_tables + fs->e2fs_itpg - 1 > last_block) { | ||||
printf("ext2fs: cg %u: inode tables not in group blk=%ju\n", | SDT_PROBE2(ext2fs, , vfsops, ext2_cg_validate_error, | ||||
i, i_tables); | "inode tables not in group blk", i); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG)) | if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG)) | ||||
first_block += EXT2_BLOCKS_PER_GROUP(fs); | first_block += EXT2_BLOCKS_PER_GROUP(fs); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
SDT_PROBE_DEFINE1(ext2fs, , vfsops, ext2_compute_sb_data_error, "char*"); | |||||
/* | /* | ||||
* This computes the fields of the m_ext2fs structure from the | * This computes the fields of the m_ext2fs structure from the | ||||
* data in the ext2fs structure read in. | * data in the ext2fs structure read in. | ||||
*/ | */ | ||||
static int | static int | ||||
ext2_compute_sb_data(struct vnode *devvp, struct ext2fs *es, | ext2_compute_sb_data(struct vnode *devvp, struct ext2fs *es, | ||||
struct m_ext2fs *fs) | struct m_ext2fs *fs) | ||||
{ | { | ||||
struct buf *bp; | struct buf *bp; | ||||
uint32_t e2fs_descpb, e2fs_gdbcount_alloc; | uint32_t e2fs_descpb, e2fs_gdbcount_alloc; | ||||
int i, j; | int i, j; | ||||
int g_count = 0; | int g_count = 0; | ||||
int error; | int error; | ||||
/* Check checksum features */ | /* Check checksum features */ | ||||
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) && | if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) && | ||||
EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) { | EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) { | ||||
printf("ext2fs: incorrect checksum features combination\n"); | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
"incorrect checksum features combination"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Precompute checksum seed for all metadata */ | /* Precompute checksum seed for all metadata */ | ||||
ext2_sb_csum_set_seed(fs); | ext2_sb_csum_set_seed(fs); | ||||
/* Verify sb csum if possible */ | /* Verify sb csum if possible */ | ||||
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) { | if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) { | ||||
error = ext2_sb_csum_verify(fs); | error = ext2_sb_csum_verify(fs); | ||||
if (error) { | if (error) { | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
/* Check for block size = 1K|2K|4K */ | /* Check for block size = 1K|2K|4K */ | ||||
if (es->e2fs_log_bsize > 2) { | if (es->e2fs_log_bsize > 2) { | ||||
printf("ext2fs: bad block size: %d\n", es->e2fs_log_bsize); | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
"bad block size"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize; | fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize; | ||||
fs->e2fs_bsize = 1U << fs->e2fs_bshift; | fs->e2fs_bsize = 1U << fs->e2fs_bshift; | ||||
fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1; | fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1; | ||||
fs->e2fs_qbmask = fs->e2fs_bsize - 1; | fs->e2fs_qbmask = fs->e2fs_bsize - 1; | ||||
/* Check for fragment size */ | /* Check for fragment size */ | ||||
if (es->e2fs_log_fsize > | if (es->e2fs_log_fsize > | ||||
(EXT2_MAX_FRAG_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE)) { | (EXT2_MAX_FRAG_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE)) { | ||||
printf("ext2fs: invalid log cluster size: %u\n", | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
es->e2fs_log_fsize); | "invalid log cluster size"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize; | fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize; | ||||
if (fs->e2fs_fsize != fs->e2fs_bsize) { | if (fs->e2fs_fsize != fs->e2fs_bsize) { | ||||
printf("ext2fs: fragment size (%u) != block size %u\n", | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
fs->e2fs_fsize, fs->e2fs_bsize); | "fragment size != block size"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
fs->e2fs_fpb = fs->e2fs_bsize / fs->e2fs_fsize; | fs->e2fs_fpb = fs->e2fs_bsize / fs->e2fs_fsize; | ||||
/* Check reserved gdt blocks for future filesystem expansion */ | /* Check reserved gdt blocks for future filesystem expansion */ | ||||
if (es->e2fs_reserved_ngdb > (fs->e2fs_bsize / 4)) { | if (es->e2fs_reserved_ngdb > (fs->e2fs_bsize / 4)) { | ||||
printf("ext2fs: number of reserved GDT blocks too large: %u\n", | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
es->e2fs_reserved_ngdb); | "number of reserved GDT blocks too large"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (es->e2fs_rev == E2FS_REV0) { | if (es->e2fs_rev == E2FS_REV0) { | ||||
fs->e2fs_isize = E2FS_REV0_INODE_SIZE; | fs->e2fs_isize = E2FS_REV0_INODE_SIZE; | ||||
} else { | } else { | ||||
fs->e2fs_isize = es->e2fs_inode_size; | fs->e2fs_isize = es->e2fs_inode_size; | ||||
/* | /* | ||||
* Check first ino. | * Check first ino. | ||||
*/ | */ | ||||
if (es->e2fs_first_ino < EXT2_FIRSTINO) { | if (es->e2fs_first_ino < EXT2_FIRSTINO) { | ||||
printf("ext2fs: invalid first ino: %u\n", | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
es->e2fs_first_ino); | "invalid first ino"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* | /* | ||||
* Simple sanity check for superblock inode size value. | * Simple sanity check for superblock inode size value. | ||||
*/ | */ | ||||
if (EXT2_INODE_SIZE(fs) < E2FS_REV0_INODE_SIZE || | if (EXT2_INODE_SIZE(fs) < E2FS_REV0_INODE_SIZE || | ||||
EXT2_INODE_SIZE(fs) > fs->e2fs_bsize || | EXT2_INODE_SIZE(fs) > fs->e2fs_bsize || | ||||
(fs->e2fs_isize & (fs->e2fs_isize - 1)) != 0) { | (fs->e2fs_isize & (fs->e2fs_isize - 1)) != 0) { | ||||
printf("ext2fs: invalid inode size %u\n", | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
fs->e2fs_isize); | "invalid inode size"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
} | } | ||||
/* Check group descriptors */ | /* Check group descriptors */ | ||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT) && | if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT) && | ||||
es->e3fs_desc_size != E2FS_64BIT_GD_SIZE) { | es->e3fs_desc_size != E2FS_64BIT_GD_SIZE) { | ||||
printf("ext2fs: unsupported 64bit descriptor size %u\n", | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
es->e3fs_desc_size); | "unsupported 64bit descriptor size"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
fs->e2fs_bpg = es->e2fs_bpg; | fs->e2fs_bpg = es->e2fs_bpg; | ||||
fs->e2fs_fpg = es->e2fs_fpg; | fs->e2fs_fpg = es->e2fs_fpg; | ||||
if (fs->e2fs_bpg == 0 || fs->e2fs_fpg == 0) { | if (fs->e2fs_bpg == 0 || fs->e2fs_fpg == 0) { | ||||
printf("ext2fs: zero blocks/fragments per group\n"); | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
"zero blocks/fragments per group"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (fs->e2fs_bpg != fs->e2fs_bsize * 8) { | if (fs->e2fs_bpg != fs->e2fs_bsize * 8) { | ||||
printf("ext2fs: non-standard group size unsupported %d\n", | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
fs->e2fs_bpg); | "non-standard group size unsupported"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs); | fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs); | ||||
if (fs->e2fs_ipb == 0 || | if (fs->e2fs_ipb == 0 || | ||||
fs->e2fs_ipb > fs->e2fs_bsize / E2FS_REV0_INODE_SIZE) { | fs->e2fs_ipb > fs->e2fs_bsize / E2FS_REV0_INODE_SIZE) { | ||||
printf("ext2fs: bad inodes per block size\n"); | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
"bad inodes per block size"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
fs->e2fs_ipg = es->e2fs_ipg; | fs->e2fs_ipg = es->e2fs_ipg; | ||||
if (fs->e2fs_ipg < fs->e2fs_ipb || fs->e2fs_ipg > fs->e2fs_bsize * 8) { | if (fs->e2fs_ipg < fs->e2fs_ipb || fs->e2fs_ipg > fs->e2fs_bsize * 8) { | ||||
printf("ext2fs: invalid inodes per group: %u\n", fs->e2fs_ipb); | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
"invalid inodes per group"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb; | fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb; | ||||
fs->e2fs_bcount = es->e2fs_bcount; | fs->e2fs_bcount = es->e2fs_bcount; | ||||
fs->e2fs_rbcount = es->e2fs_rbcount; | fs->e2fs_rbcount = es->e2fs_rbcount; | ||||
fs->e2fs_fbcount = es->e2fs_fbcount; | fs->e2fs_fbcount = es->e2fs_fbcount; | ||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) { | if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) { | ||||
fs->e2fs_bcount |= (uint64_t)(es->e4fs_bcount_hi) << 32; | fs->e2fs_bcount |= (uint64_t)(es->e4fs_bcount_hi) << 32; | ||||
fs->e2fs_rbcount |= (uint64_t)(es->e4fs_rbcount_hi) << 32; | fs->e2fs_rbcount |= (uint64_t)(es->e4fs_rbcount_hi) << 32; | ||||
fs->e2fs_fbcount |= (uint64_t)(es->e4fs_fbcount_hi) << 32; | fs->e2fs_fbcount |= (uint64_t)(es->e4fs_fbcount_hi) << 32; | ||||
} | } | ||||
if (fs->e2fs_rbcount > fs->e2fs_bcount || | if (fs->e2fs_rbcount > fs->e2fs_bcount || | ||||
fs->e2fs_fbcount > fs->e2fs_bcount) { | fs->e2fs_fbcount > fs->e2fs_bcount) { | ||||
printf("ext2fs: invalid block count\n"); | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
"invalid block count"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (es->e2fs_first_dblock >= fs->e2fs_bcount) { | if (es->e2fs_first_dblock >= fs->e2fs_bcount) { | ||||
printf("ext2fs: first data block out of range\n"); | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
"first data block out of range"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
fs->e2fs_gcount = howmany(fs->e2fs_bcount - es->e2fs_first_dblock, | fs->e2fs_gcount = howmany(fs->e2fs_bcount - es->e2fs_first_dblock, | ||||
EXT2_BLOCKS_PER_GROUP(fs)); | EXT2_BLOCKS_PER_GROUP(fs)); | ||||
if (fs->e2fs_gcount > ((uint64_t)1 << 32) - EXT2_DESCS_PER_BLOCK(fs)) { | if (fs->e2fs_gcount > ((uint64_t)1 << 32) - EXT2_DESCS_PER_BLOCK(fs)) { | ||||
printf("ext2fs: groups count too large: %u\n", fs->e2fs_gcount); | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
"groups count too large"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Check for extra isize in big inodes. */ | /* Check for extra isize in big inodes. */ | ||||
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_EXTRA_ISIZE) && | if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_EXTRA_ISIZE) && | ||||
EXT2_INODE_SIZE(fs) < sizeof(struct ext2fs_dinode)) { | EXT2_INODE_SIZE(fs) < sizeof(struct ext2fs_dinode)) { | ||||
printf("ext2fs: no space for extra inode timestamps\n"); | SDT_PROBE1(ext2fs, , vfsops, ext2_compute_sb_data_error, | ||||
"no space for extra inode timestamps"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* s_resuid / s_resgid ? */ | /* s_resuid / s_resgid ? */ | ||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) { | if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) { | ||||
e2fs_descpb = fs->e2fs_bsize / E2FS_64BIT_GD_SIZE; | e2fs_descpb = fs->e2fs_bsize / E2FS_64BIT_GD_SIZE; | ||||
e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount, e2fs_descpb); | e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount, e2fs_descpb); | ||||
▲ Show 20 Lines • Show All 489 Lines • ▼ Show 20 Lines | ext2_sync(struct mount *mp, int waitfor) | ||||
struct inode *ip; | struct inode *ip; | ||||
struct ext2mount *ump = VFSTOEXT2(mp); | struct ext2mount *ump = VFSTOEXT2(mp); | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
int error, allerror = 0; | int error, allerror = 0; | ||||
td = curthread; | td = curthread; | ||||
fs = ump->um_e2fs; | fs = ump->um_e2fs; | ||||
if (fs->e2fs_fmod != 0 && fs->e2fs_ronly != 0) { /* XXX */ | if (fs->e2fs_fmod != 0 && fs->e2fs_ronly != 0) { /* XXX */ | ||||
printf("fs = %s\n", fs->e2fs_fsmnt); | panic("ext2_sync: rofs mod fs=%s", fs->e2fs_fsmnt); | ||||
panic("ext2_sync: rofs mod"); | |||||
} | } | ||||
/* | /* | ||||
* Write back each (modified) inode. | * Write back each (modified) inode. | ||||
*/ | */ | ||||
loop: | loop: | ||||
MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { | MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { | ||||
if (vp->v_type == VNON) { | if (vp->v_type == VNON) { | ||||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) | ||||
* out because we could corrupt the extent tree. | * out because we could corrupt the extent tree. | ||||
*/ | */ | ||||
if (!(ip->i_flag & IN_E4EXTENTS) && | if (!(ip->i_flag & IN_E4EXTENTS) && | ||||
(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode))) { | (S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode))) { | ||||
used_blocks = howmany(ip->i_size, fs->e2fs_bsize); | used_blocks = howmany(ip->i_size, fs->e2fs_bsize); | ||||
for (i = used_blocks; i < EXT2_NDIR_BLOCKS; i++) | for (i = used_blocks; i < EXT2_NDIR_BLOCKS; i++) | ||||
ip->i_db[i] = 0; | ip->i_db[i] = 0; | ||||
} | } | ||||
#ifdef EXT2FS_DEBUG | #ifdef EXT2FS_PRINT_EXTENTS | ||||
ext2_print_inode(ip); | ext2_print_inode(ip); | ||||
ext4_ext_print_extent_tree_status(ip); | ext4_ext_print_extent_tree_status(ip); | ||||
#endif | #endif | ||||
bqrelse(bp); | bqrelse(bp); | ||||
/* | /* | ||||
* Initialize the vnode from the inode, check for aliases. | * Initialize the vnode from the inode, check for aliases. | ||||
* Note that the underlying vnode may have changed. | * Note that the underlying vnode may have changed. | ||||
▲ Show 20 Lines • Show All 148 Lines • Show Last 20 Lines |