MFC r260988, r261034, r261120, r261235:
ext2fs: Properly the EXT4_EXTENTS and EXT4_INDEX to the inode flags. In order to support Ext4 extents we need to pass the Ext4 inode flags without interfering with the chflags. This is better done by using the i_flag field in the inode and doing proper translation to the linux ext4 equivalents. Solve a potential corruption issue in the dirindex code. The dirindex code can now be renabled as the problems related to it have been solved. Suggested by: bde Tested by: kevlo
This commit is contained in:
parent
c50ca945d8
commit
e570ba73dc
@ -74,7 +74,7 @@ ext2_bmap(struct vop_bmap_args *ap)
|
|||||||
if (ap->a_bnp == NULL)
|
if (ap->a_bnp == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (VTOI(ap->a_vp)->i_flags & EXT4_EXTENTS)
|
if (VTOI(ap->a_vp)->i_flag & IN_E4EXTENTS)
|
||||||
error = ext4_bmapext(ap->a_vp, ap->a_bn, &blkno,
|
error = ext4_bmapext(ap->a_vp, ap->a_bn, &blkno,
|
||||||
ap->a_runp, ap->a_runb);
|
ap->a_runp, ap->a_runb);
|
||||||
else
|
else
|
||||||
|
@ -50,22 +50,24 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Inode flags
|
* Inode flags
|
||||||
* The current implementation uses only EXT2_IMMUTABLE and EXT2_APPEND flags
|
* The system supports EXT2_IMMUTABLE, EXT2_APPEND and EXT2_NODUMP flags.
|
||||||
|
* The current implementation also uses EXT4_INDEX, EXT4_EXTENTS and
|
||||||
|
* EXT4_HUGE_FILE with some restrictions, imposed the lack of write
|
||||||
|
* support.
|
||||||
*/
|
*/
|
||||||
#define EXT2_SECRM 0x00000001 /* Secure deletion */
|
#define EXT2_SECRM 0x00000001 /* Secure deletion */
|
||||||
#define EXT2_UNRM 0x00000002 /* Undelete */
|
#define EXT2_UNRM 0x00000002 /* Undelete */
|
||||||
#define EXT2_COMPR 0x00000004 /* Compress file */
|
#define EXT2_COMPR 0x00000004 /* Compress file */
|
||||||
#define EXT2_SYNC 0x00000008 /* Synchronous updates */
|
#define EXT2_SYNC 0x00000008 /* Synchronous updates */
|
||||||
#define EXT2_IMMUTABLE 0x00000010 /* Immutable file */
|
#define EXT2_IMMUTABLE 0x00000010 /* Immutable file */
|
||||||
#define EXT2_APPEND 0x00000020 /* writes to file may only append */
|
#define EXT2_APPEND 0x00000020 /* Writes to file may only append */
|
||||||
#define EXT2_NODUMP 0x00000040 /* do not dump file */
|
#define EXT2_NODUMP 0x00000040 /* Do not dump file */
|
||||||
#define EXT2_NOATIME 0x00000080 /* do not update atime */
|
#define EXT2_NOATIME 0x00000080 /* Do not update atime */
|
||||||
|
#define EXT4_INDEX 0x00001000 /* Hash-indexed directory */
|
||||||
#define EXT4_INDEX 0x00001000 /* hash-indexed directory */
|
|
||||||
#define EXT4_IMAGIC 0x00002000 /* AFS directory */
|
#define EXT4_IMAGIC 0x00002000 /* AFS directory */
|
||||||
#define EXT4_JOURNAL_DATA 0x00004000 /* file data should be journaled */
|
#define EXT4_JOURNAL_DATA 0x00004000 /* File data should be journaled */
|
||||||
#define EXT4_NOTAIL 0x00008000 /* file tail should not be merged */
|
#define EXT4_NOTAIL 0x00008000 /* File tail should not be merged */
|
||||||
#define EXT4_DIRSYNC 0x00010000 /* dirsync behaviour */
|
#define EXT4_DIRSYNC 0x00010000 /* Dirsync behaviour */
|
||||||
#define EXT4_TOPDIR 0x00020000 /* Top of directory hierarchies*/
|
#define EXT4_TOPDIR 0x00020000 /* Top of directory hierarchies*/
|
||||||
#define EXT4_HUGE_FILE 0x00040000 /* Set to each huge file */
|
#define EXT4_HUGE_FILE 0x00040000 /* Set to each huge file */
|
||||||
#define EXT4_EXTENTS 0x00080000 /* Inode uses extents */
|
#define EXT4_EXTENTS 0x00080000 /* Inode uses extents */
|
||||||
|
@ -89,12 +89,10 @@ static int ext2_htree_writebuf(struct ext2fs_htree_lookup_info *info);
|
|||||||
int
|
int
|
||||||
ext2_htree_has_idx(struct inode *ip)
|
ext2_htree_has_idx(struct inode *ip)
|
||||||
{
|
{
|
||||||
#ifdef EXT2FS_HTREE
|
|
||||||
if (EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_DIRHASHINDEX) &&
|
if (EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_DIRHASHINDEX) &&
|
||||||
ip->i_flags & EXT4_INDEX)
|
ip->i_flag & IN_E4INDEX)
|
||||||
return (1);
|
return (1);
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,7 +654,7 @@ ext2_htree_create_index(struct vnode *vp, struct componentname *cnp,
|
|||||||
((char *)ep + ep->e2d_reclen);
|
((char *)ep + ep->e2d_reclen);
|
||||||
ep->e2d_reclen = buf1 + blksize - (char *)ep;
|
ep->e2d_reclen = buf1 + blksize - (char *)ep;
|
||||||
|
|
||||||
dp->i_flags |= EXT4_INDEX;
|
dp->i_flag |= IN_E4INDEX;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize index root.
|
* Initialize index root.
|
||||||
|
@ -108,6 +108,8 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
|
|||||||
ip->i_flags |= (ei->e2di_flags & EXT2_APPEND) ? SF_APPEND : 0;
|
ip->i_flags |= (ei->e2di_flags & EXT2_APPEND) ? SF_APPEND : 0;
|
||||||
ip->i_flags |= (ei->e2di_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0;
|
ip->i_flags |= (ei->e2di_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0;
|
||||||
ip->i_flags |= (ei->e2di_flags & EXT2_NODUMP) ? UF_NODUMP : 0;
|
ip->i_flags |= (ei->e2di_flags & EXT2_NODUMP) ? UF_NODUMP : 0;
|
||||||
|
ip->i_flag |= (ei->e2di_flags & EXT4_INDEX) ? IN_E4INDEX : 0;
|
||||||
|
ip->i_flag |= (ei->e2di_flags & EXT4_EXTENTS) ? IN_E4EXTENTS : 0;
|
||||||
ip->i_blocks = ei->e2di_nblock;
|
ip->i_blocks = ei->e2di_nblock;
|
||||||
if (E2DI_HAS_HUGE_FILE(ip)) {
|
if (E2DI_HAS_HUGE_FILE(ip)) {
|
||||||
ip->i_blocks |= (uint64_t)ei->e2di_nblock_high << 32;
|
ip->i_blocks |= (uint64_t)ei->e2di_nblock_high << 32;
|
||||||
@ -156,6 +158,8 @@ ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei)
|
|||||||
ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0;
|
ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0;
|
||||||
ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
|
ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
|
||||||
ei->e2di_flags |= (ip->i_flags & UF_NODUMP) ? EXT2_NODUMP: 0;
|
ei->e2di_flags |= (ip->i_flags & UF_NODUMP) ? EXT2_NODUMP: 0;
|
||||||
|
ei->e2di_flags |= (ip->i_flag & IN_E4INDEX) ? EXT4_INDEX: 0;
|
||||||
|
ei->e2di_flags |= (ip->i_flag & IN_E4EXTENTS) ? EXT4_EXTENTS: 0;
|
||||||
ei->e2di_nblock = ip->i_blocks & 0xffffffff;
|
ei->e2di_nblock = ip->i_blocks & 0xffffffff;
|
||||||
ei->e2di_nblock_high = ip->i_blocks >> 32 & 0xffff;
|
ei->e2di_nblock_high = ip->i_blocks >> 32 & 0xffff;
|
||||||
ei->e2di_gen = ip->i_gen;
|
ei->e2di_gen = ip->i_gen;
|
||||||
|
@ -884,12 +884,11 @@ ext2_direnter(struct inode *ip, struct vnode *dvp, struct componentname *cnp)
|
|||||||
bcopy(cnp->cn_nameptr, newdir.e2d_name, (unsigned)cnp->cn_namelen + 1);
|
bcopy(cnp->cn_nameptr, newdir.e2d_name, (unsigned)cnp->cn_namelen + 1);
|
||||||
newentrysize = EXT2_DIR_REC_LEN(newdir.e2d_namlen);
|
newentrysize = EXT2_DIR_REC_LEN(newdir.e2d_namlen);
|
||||||
|
|
||||||
#ifdef EXT2FS_HTREE
|
|
||||||
if (ext2_htree_has_idx(dp)) {
|
if (ext2_htree_has_idx(dp)) {
|
||||||
error = ext2_htree_add_entry(dvp, &newdir, cnp);
|
error = ext2_htree_add_entry(dvp, &newdir, cnp);
|
||||||
if (error) {
|
if (error) {
|
||||||
dp->i_flags &= ~EXT4_INDEX;
|
dp->i_flag &= ~IN_E4INDEX;
|
||||||
dp->i_flags |= IN_CHANGE | IN_UPDATE;
|
dp->i_flag |= IN_CHANGE | IN_UPDATE;
|
||||||
}
|
}
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -905,7 +904,6 @@ ext2_direnter(struct inode *ip, struct vnode *dvp, struct componentname *cnp)
|
|||||||
return ext2_htree_create_index(dvp, cnp, &newdir);
|
return ext2_htree_create_index(dvp, cnp, &newdir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* EXT2FS_HTREE */
|
|
||||||
|
|
||||||
if (dp->i_count == 0) {
|
if (dp->i_count == 0) {
|
||||||
/*
|
/*
|
||||||
|
@ -82,10 +82,10 @@ ext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp)
|
|||||||
*bpp = NULL;
|
*bpp = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The EXT4_EXTENTS requires special treatment, otherwise we can
|
* IN_E4EXTENTS requires special treatment as we can otherwise fall
|
||||||
* fall back to the normal path.
|
* back to the normal path.
|
||||||
*/
|
*/
|
||||||
if (!(ip->i_flags & EXT4_EXTENTS))
|
if (!(ip->i_flag & IN_E4EXTENTS))
|
||||||
goto normal;
|
goto normal;
|
||||||
|
|
||||||
memset(&path, 0, sizeof(path));
|
memset(&path, 0, sizeof(path));
|
||||||
@ -110,7 +110,7 @@ ext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp)
|
|||||||
if (res)
|
if (res)
|
||||||
*res = (char *)bp->b_data + blkoff(fs, offset);
|
*res = (char *)bp->b_data + blkoff(fs, offset);
|
||||||
/*
|
/*
|
||||||
* If EXT4_EXTENTS is enabled we would get a wrong offset so
|
* If IN_E4EXTENTS is enabled we would get a wrong offset so
|
||||||
* reset b_offset here.
|
* reset b_offset here.
|
||||||
*/
|
*/
|
||||||
bp->b_offset = lbn * bsize;
|
bp->b_offset = lbn * bsize;
|
||||||
|
@ -964,10 +964,10 @@ ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
|
|||||||
* blocks are zeroed out - ext2_balloc depends on this
|
* blocks are zeroed out - ext2_balloc depends on this
|
||||||
* although for regular files and directories only
|
* although for regular files and directories only
|
||||||
*
|
*
|
||||||
* If EXT4_EXTENTS flag is enabled, unused blocks aren't
|
* If IN_E4EXTENTS is enabled, unused blocks are not zeroed
|
||||||
* zeroed out because we could corrupt the extent tree.
|
* out because we could corrupt the extent tree.
|
||||||
*/
|
*/
|
||||||
if (!(ip->i_flags & EXT4_EXTENTS) &&
|
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 = (ip->i_size+fs->e2fs_bsize-1) / fs->e2fs_bsize;
|
used_blocks = (ip->i_size+fs->e2fs_bsize-1) / fs->e2fs_bsize;
|
||||||
for (i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
|
for (i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
|
||||||
|
@ -1615,7 +1615,7 @@ ext2_read(struct vop_read_args *ap)
|
|||||||
ip = VTOI(vp);
|
ip = VTOI(vp);
|
||||||
|
|
||||||
/*EXT4_EXT_LOCK(ip);*/
|
/*EXT4_EXT_LOCK(ip);*/
|
||||||
if (ip->i_flags & EXT4_EXTENTS)
|
if (ip->i_flag & IN_E4EXTENTS)
|
||||||
error = ext4_ext_read(ap);
|
error = ext4_ext_read(ap);
|
||||||
else
|
else
|
||||||
error = ext2_ind_read(ap);
|
error = ext2_ind_read(ap);
|
||||||
|
@ -153,6 +153,13 @@ struct inode {
|
|||||||
#define IN_LAZYACCESS 0x0100 /* Process IN_ACCESS after the
|
#define IN_LAZYACCESS 0x0100 /* Process IN_ACCESS after the
|
||||||
suspension finished */
|
suspension finished */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are translation flags for some attributes that Ext4
|
||||||
|
* passes as inode flags but that we cannot pass directly.
|
||||||
|
*/
|
||||||
|
#define IN_E4INDEX 0x010000
|
||||||
|
#define IN_E4EXTENTS 0x020000
|
||||||
|
|
||||||
#define i_devvp i_ump->um_devvp
|
#define i_devvp i_ump->um_devvp
|
||||||
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
|
Loading…
Reference in New Issue
Block a user