Write support for the Ext4 Read-only Compatible Feature "huge_file".

Primarily, this feature extends the inode block count field to 48 bits.
Additionally, this feature allows this field to be represented in file
system block size units rather than DEV_BSIZE units.
This commit is contained in:
jakllsch 2012-11-21 23:11:23 +00:00
parent cde2f36932
commit 4ca1f26828
8 changed files with 77 additions and 23 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs.h,v 1.32 2012/11/21 20:45:35 jakllsch Exp $ */
/* $NetBSD: ext2fs.h,v 1.33 2012/11/21 23:11:23 jakllsch Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@ -265,7 +265,8 @@ struct m_ext2fs {
*/
#define EXT2F_COMPAT_SUPP 0x0000
#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER \
| EXT2F_ROCOMPAT_LARGEFILE)
| EXT2F_ROCOMPAT_LARGEFILE \
| EXT2F_ROCOMPAT_HUGE_FILE)
#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_alloc.c,v 1.42 2011/03/06 04:46:26 rmind Exp $ */
/* $NetBSD: ext2fs_alloc.c,v 1.43 2012/11/21 23:11:23 jakllsch Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.42 2011/03/06 04:46:26 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.43 2012/11/21 23:11:23 jakllsch Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -135,7 +135,7 @@ ext2fs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref,
bno = (daddr_t)ext2fs_hashalloc(ip, cg, bpref, fs->e2fs_bsize,
ext2fs_alloccg);
if (bno > 0) {
ip->i_e2fs_nblock += btodb(fs->e2fs_bsize);
ext2fs_setnblock(ip, ext2fs_nblock(ip) + btodb(fs->e2fs_bsize));
ip->i_flag |= IN_CHANGE | IN_UPDATE;
*bnp = bno;
return (0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_balloc.c,v 1.34 2009/10/19 18:41:17 bouyer Exp $ */
/* $NetBSD: ext2fs_balloc.c,v 1.35 2012/11/21 23:11:23 jakllsch Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_balloc.c,v 1.34 2009/10/19 18:41:17 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: ext2fs_balloc.c,v 1.35 2012/11/21 23:11:23 jakllsch Exp $");
#if defined(_KERNEL_OPT)
#include "opt_uvmhist.h"
@ -343,7 +343,7 @@ fail:
}
}
if (deallocated) {
ip->i_e2fs_nblock -= btodb(deallocated);
ext2fs_setnblock(ip, ext2fs_nblock(ip) - btodb(deallocated));
ip->i_e2fs_flags |= IN_CHANGE | IN_UPDATE;
}
return error;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_extern.h,v 1.45 2012/11/17 16:03:48 jakllsch Exp $ */
/* $NetBSD: ext2fs_extern.h,v 1.46 2012/11/21 23:11:23 jakllsch Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -110,6 +110,8 @@ int ext2fs_bmap(void *);
/* ext2fs_inode.c */
uint64_t ext2fs_size(struct inode *);
int ext2fs_setsize(struct inode *, uint64_t);
uint64_t ext2fs_nblock(struct inode *);
int ext2fs_setnblock(struct inode *, uint64_t);
int ext2fs_update(struct vnode *, const struct timespec *,
const struct timespec *, int);
int ext2fs_truncate(struct vnode *, off_t, int, kauth_cred_t);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_inode.c,v 1.75 2012/01/27 19:22:48 para Exp $ */
/* $NetBSD: ext2fs_inode.c,v 1.76 2012/11/21 23:11:23 jakllsch Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.75 2012/01/27 19:22:48 para Exp $");
__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.76 2012/11/21 23:11:23 jakllsch Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -128,6 +128,54 @@ ext2fs_setsize(struct inode *ip, uint64_t size)
return 0;
}
uint64_t
ext2fs_nblock(struct inode *ip)
{
uint64_t nblock = ip->i_e2fs_nblock;
struct m_ext2fs * const fs = ip->i_e2fs;
if (fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_HUGE_FILE) {
nblock |= (uint64_t)ip->i_e2fs_nblock_high << 32;
if ((ip->i_e2fs_flags & EXT2_HUGE_FILE)) {
nblock = fsbtodb(fs, nblock);
}
}
return nblock;
}
int
ext2fs_setnblock(struct inode *ip, uint64_t nblock)
{
struct m_ext2fs * const fs = ip->i_e2fs;
if (nblock <= 0xffffffffULL) {
CLR(ip->i_e2fs_flags, EXT2_HUGE_FILE);
ip->i_e2fs_nblock = nblock;
return 0;
}
if (!ISSET(fs->e2fs.e2fs_features_rocompat, EXT2F_ROCOMPAT_HUGE_FILE))
return EFBIG;
if (nblock <= 0xffffffffffffULL) {
CLR(ip->i_e2fs_flags, EXT2_HUGE_FILE);
ip->i_e2fs_nblock = nblock & 0xffffffff;
ip->i_e2fs_nblock_high = (nblock >> 32) & 0xffff;
return 0;
}
if (dbtofsb(fs, nblock) <= 0xffffffffffffULL) {
SET(ip->i_e2fs_flags, EXT2_HUGE_FILE);
ip->i_e2fs_nblock = dbtofsb(fs, nblock) & 0xffffffff;
ip->i_e2fs_nblock_high = (dbtofsb(fs, nblock) >> 32) & 0xffff;
return 0;
}
return EFBIG;
}
/*
* Last reference to an inode. If necessary, write or delete it.
*/
@ -260,7 +308,7 @@ ext2fs_truncate(struct vnode *ovp, off_t length, int ioflag,
if (ovp->v_type == VLNK &&
(ext2fs_size(oip) < ump->um_maxsymlinklen ||
(ump->um_maxsymlinklen == 0 && oip->i_e2fs_nblock == 0))) {
(ump->um_maxsymlinklen == 0 && ext2fs_nblock(oip) == 0))) {
KDASSERT(length == 0);
memset((char *)&oip->i_din.e2fs_din->e2di_shortlink, 0,
(u_int)ext2fs_size(oip));
@ -425,7 +473,9 @@ done:
* Put back the real size.
*/
(void)ext2fs_setsize(oip, length);
oip->i_e2fs_nblock -= blocksreleased;
error = ext2fs_setnblock(oip, ext2fs_nblock(oip) - blocksreleased);
if (error != 0)
allerror = error;
oip->i_flag |= IN_CHANGE;
KASSERT(ovp->v_type != VREG || ovp->v_size == ext2fs_size(oip));
return (allerror);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_readwrite.c,v 1.61 2012/04/29 22:54:00 chs Exp $ */
/* $NetBSD: ext2fs_readwrite.c,v 1.62 2012/11/21 23:11:23 jakllsch Exp $ */
/*-
* Copyright (c) 1993
@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_readwrite.c,v 1.61 2012/04/29 22:54:00 chs Exp $");
__KERNEL_RCSID(0, "$NetBSD: ext2fs_readwrite.c,v 1.62 2012/11/21 23:11:23 jakllsch Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -123,7 +123,7 @@ ext2fs_read(void *v)
if (vp->v_type == VLNK) {
if (ext2fs_size(ip) < ump->um_maxsymlinklen ||
(ump->um_maxsymlinklen == 0 && ip->i_e2fs_nblock == 0))
(ump->um_maxsymlinklen == 0 && ext2fs_nblock(ip) == 0))
panic("%s: short symlink", "ext2fs_read");
} else if (vp->v_type != VREG && vp->v_type != VDIR)
panic("%s: type %d", "ext2fs_read", vp->v_type);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_vfsops.c,v 1.166 2012/09/01 17:01:24 christos Exp $ */
/* $NetBSD: ext2fs_vfsops.c,v 1.167 2012/11/21 23:11:23 jakllsch Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1994
@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.166 2012/09/01 17:01:24 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.167 2012/11/21 23:11:23 jakllsch Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@ -1075,8 +1075,9 @@ retry:
/* If the inode was deleted, reset all fields */
if (ip->i_e2fs_dtime != 0) {
ip->i_e2fs_mode = ip->i_e2fs_nblock = 0;
ip->i_e2fs_mode = 0;
(void)ext2fs_setsize(ip, 0);
(void)ext2fs_setnblock(ip, 0);
memset(ip->i_e2fs_blocks, 0, sizeof(ip->i_e2fs_blocks));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_vnops.c,v 1.104 2012/05/09 00:21:18 riastradh Exp $ */
/* $NetBSD: ext2fs_vnops.c,v 1.105 2012/11/21 23:11:23 jakllsch Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.104 2012/05/09 00:21:18 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.105 2012/11/21 23:11:23 jakllsch Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -326,7 +326,7 @@ ext2fs_getattr(void *v)
vap->va_blocksize = MAXBSIZE;
else
vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
vap->va_bytes = dbtob((u_quad_t)ip->i_e2fs_nblock);
vap->va_bytes = dbtob(ext2fs_nblock(ip));
vap->va_type = vp->v_type;
vap->va_filerev = ip->i_modrev;
return (0);
@ -922,7 +922,7 @@ ext2fs_readlink(void *v)
isize = ext2fs_size(ip);
if (isize < ump->um_maxsymlinklen ||
(ump->um_maxsymlinklen == 0 && ip->i_e2fs_nblock == 0)) {
(ump->um_maxsymlinklen == 0 && ext2fs_nblock(ip) == 0)) {
uiomove((char *)ip->i_din.e2fs_din->e2di_shortlink, isize, ap->a_uio);
return (0);
}