lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAFZ0FUXAdY7CsTfC_CqPZd-hqS2C6MGEbC5oyUGMCR2-ay1g+Q@mail.gmail.com>
Date:	Thu, 16 Feb 2012 18:51:42 +0800
From:	Robin Dong <hao.bigrat@...il.com>
To:	Ext4 Developers List <linux-ext4@...r.kernel.org>
Cc:	"Ted Ts'o" <tytso@....edu>, Andreas Dilger <adilger@...ger.ca>
Subject: [RFC] new infrastructure for manipulating different extent format

Hi Ted, Andreas and the list,

After the bigalloc-feature is completed in ext4, we could have much
more big size of block-group (also bigger continuous space), so larger
extent size which is above 128MB is necessary, such as:

struct ext4_extent_large {
       __le64  ee_block;       /* first logical block extent covers */
       __le64  ee_start;       /* starting physical block */
       __le32  ee_len;         /* number of blocks covered by extent */
       __le32  ee_flags;       /* flags and future extension */
};

On the other hand, people who use ext4 in desktop environment may need
more compact format like:

struct ext4_extent_packed {
       __le32  ee_start_lo;
       __le16  ee_start_hi;
       __le16  ee_len;
};

which they can fit 6 extents in the inode.

Therefore, supporting multiple extent formats is the solution which
satisfied both.

My Plan:

First, abstracting the operation on disk extent format out:

struct ext4_ext_operation {
        __u16           (*ext_size) (void);
 /* the size of struct ext4_extent_### */
        ext4_fsblk_t    (*ext_pblock) (void *extent);
        void            (*ext_store_pblock) (void *extent, __u64 pb);
        ext4_lblk_t     (*ext_lblock) (void *extent);
        ext4_lblk_t     (*ext_len) (void *extent);
        int             (*is_uninit) (void *extent);
        void            (*mark_uninit) (void *extent);
        void            (*mark_init) (void *extent);

        __u16           (*idx_size) (void);
        ext4_fsblk_t    (*idx_pblock) (void *idx);
        void            (*idx_store_pblock) (void *idx, __u64 pb);
        ext4_lblk_t     (*idx_lblock) (void *idx);
};

We can use this single entry to handle different extent format through
different implementation of ext4_ext_operation (choosing different
implementation by different eh_magic number),
and the extent format which is used now could be implemented like:

static const struct ext4_ext_operation ext4_normal_eops= {
        .ext_size               = ext4_ext_size,
        .ext_pblock             = ext4_ext_pblock,
        .ext_store_pblock       = ext4_ext_store_pblock,
        .ext_lblock             = ext4_ext_lblock,
        .ext_len                = ext4_ext_get_actual_len,
        .is_uninit              = ext4_ext_is_uninitialized,
        .mark_uninit            = ext4_ext_mark_uninitialized,
        .mark_init              = ext4_ext_mark_initialized,

        .idx_size               = ext4_idx_size,
        .idx_pblock             = ext4_idx_pblock,
        .idx_store_pblock       = ext4_idx_store_pblock,
        .idx_lblock             = ext4_idx_lblock,
};

For instance, the function ext4_ext_binsearch_idx() may look like:

static void ext4_ext_binsearch_idx(struct inode *inode,
                        struct ext4_ext_path *path, ext4_lblk_t block)
{
        struct ext4_extent_header *eh = path->p_hdr;
        struct void *r, *l, *m;
        struct ext4_ext_operation *op = (struct
ext4_ext_operation*)inode->private;

        l = (char *) (eh) + sizeof(struct ext4_extent_header) +
op->idx_size();
        r = l + (le16_to_cpu(eh)->eh_entries) * op->idx_size();
        while (l <= r) {
                m = l + op->idx_size() * ((r - l) / op->idx_size())/
2;
                if (block < op->idx_lblock(m))
                        r = m - op->idx_size();
                else
                        l = m + op->idx_size();
	}
	path->p_idx = l - op->idx_size();
}

The only problem is the performance regression caused by frequent
function calls.

Any suggestions will be appreciated.

-- 
--
Best Regard
Robin Dong
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ