[Ocfs2-tools-devel] [PATCH] libocfs2: Prevent endian swapping from scribbling over memory.
Tao Ma
tao.ma at oracle.com
Wed Jul 29 23:32:04 PDT 2009
sob.
Joel Becker wrote:
> Some ocfs2 disk structures, such as our btree extent lists, are variable
> in size. They live inside another disk structure, and one of their
> fields describes how big they are. When we read the structure into RAM
> and swap it to the local CPU, we rely on that field to make sure we only
> swap what is necessary.
>
> However, if that field gets corrupted, our endian swapping code will
> happily keep scribbling past the end of the block buffer until it his
> the corrupted limit or segfaults. If you're lucky, it segfaults.
>
> This change modifies all the impacted swapping functions. They now take
> the ocfs2_filesys as an argument so that they know the blocksize. A new
> function, ocfs2_swap_barrier(), is introduced. It uses the
> ocfs2_filesys and the current location in the block buffer to determine
> when the swapping code is about to walk off the end.
>
> Some of our list structures can live inside multiple containing
> blocks. Those swap functions require an additional argument, the
> address of the containing object. That way, ocfs2_swap_barrier() knows
> what address to start at.
>
> This is ocfs2 bugzilla #1109.
>
> Signed-off-by: Joel Becker <joel.becker at oracle.com>
> ---
> debugfs.ocfs2/dump.c | 6 +-
> debugfs.ocfs2/find_block_inode.c | 2 +-
> extras/find_dup_extents.c | 2 +-
> fsck.ocfs2/pass1.c | 2 +-
> include/ocfs2/ocfs2.h | 57 ++++++++++++++---
> libocfs2/extents.c | 31 ++++++---
> libocfs2/inode.c | 55 +++++++++++-----
> libocfs2/openfs.c | 4 +-
> libocfs2/xattr.c | 130 ++++++++++++++++++++++++++++---------
> mkfs.ocfs2/mkfs.c | 13 +++-
> tunefs.ocfs2/libocfs2ne.c | 2 +-
> 11 files changed, 223 insertions(+), 81 deletions(-)
>
> diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
> index 4c1157c..17f58e9 100644
> --- a/debugfs.ocfs2/dump.c
> +++ b/debugfs.ocfs2/dump.c
> @@ -682,14 +682,14 @@ void dump_jbd_metadata (FILE *out, enum dump_block_type type, char *buf,
> switch (type) {
> case DUMP_BLOCK_INODE:
> fprintf(out, "Inode\n");
> - ocfs2_swap_inode_to_cpu((struct ocfs2_dinode *)buf,
> - gbls.fs->fs_blocksize);
> + ocfs2_swap_inode_to_cpu(gbls.fs, (struct ocfs2_dinode *)buf);
> dump_inode (out, (struct ocfs2_dinode *)buf);
> fprintf (out, "\n");
> break;
> case DUMP_BLOCK_EXTENT_BLOCK:
> fprintf(out, "Extent\n");
> - ocfs2_swap_extent_block_to_cpu((struct ocfs2_extent_block *)buf);
> + ocfs2_swap_extent_block_to_cpu(gbls.fs,
> + (struct ocfs2_extent_block *)buf);
> dump_extent_block (out, (struct ocfs2_extent_block *)buf);
> fprintf (out, "\n");
> break;
> diff --git a/debugfs.ocfs2/find_block_inode.c b/debugfs.ocfs2/find_block_inode.c
> index 1291afb..293ce09 100644
> --- a/debugfs.ocfs2/find_block_inode.c
> +++ b/debugfs.ocfs2/find_block_inode.c
> @@ -378,7 +378,7 @@ errcode_t find_block_inode(ocfs2_filesys *fs, uint64_t *blkno, int count,
> strlen(OCFS2_INODE_SIGNATURE)))
> continue;
>
> - ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> + ocfs2_swap_inode_to_cpu(fs, di);
>
> if (di->i_fs_generation != fs->fs_super->i_fs_generation)
> continue;
> diff --git a/extras/find_dup_extents.c b/extras/find_dup_extents.c
> index 9263891..1f8fdcc 100644
> --- a/extras/find_dup_extents.c
> +++ b/extras/find_dup_extents.c
> @@ -184,7 +184,7 @@ static errcode_t run_scan(struct walk_extents *we, int test)
> strlen(OCFS2_INODE_SIGNATURE)))
> continue;
>
> - ocfs2_swap_inode_to_cpu(di, we->fs->fs_blocksize);
> + ocfs2_swap_inode_to_cpu(we->fs, di);
>
> if (!(di->i_flags & OCFS2_VALID_FL))
> continue;
> diff --git a/fsck.ocfs2/pass1.c b/fsck.ocfs2/pass1.c
> index 15880bc..4aeba8c 100644
> --- a/fsck.ocfs2/pass1.c
> +++ b/fsck.ocfs2/pass1.c
> @@ -1377,7 +1377,7 @@ errcode_t o2fsck_pass1(o2fsck_state *ost)
> if (!memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
> strlen(OCFS2_INODE_SIGNATURE))) {
>
> - ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> + ocfs2_swap_inode_to_cpu(fs, di);
>
> /* We only consider inodes whose generations don't
> * match if the user has asked us to */
> diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
> index 4dbbf43..fca35d7 100644
> --- a/include/ocfs2/ocfs2.h
> +++ b/include/ocfs2/ocfs2.h
> @@ -251,8 +251,8 @@ errcode_t ocfs2_flush(ocfs2_filesys *fs);
> errcode_t ocfs2_close(ocfs2_filesys *fs);
> void ocfs2_freefs(ocfs2_filesys *fs);
>
> -void ocfs2_swap_inode_from_cpu(struct ocfs2_dinode *di, size_t blocksize);
> -void ocfs2_swap_inode_to_cpu(struct ocfs2_dinode *di, size_t blocksize);
> +void ocfs2_swap_inode_from_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di);
> +void ocfs2_swap_inode_to_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di);
> errcode_t ocfs2_read_inode(ocfs2_filesys *fs, uint64_t blkno,
> char *inode_buf);
> errcode_t ocfs2_write_inode(ocfs2_filesys *fs, uint64_t blkno,
> @@ -266,8 +266,17 @@ errcode_t ocfs2_write_cached_inode(ocfs2_filesys *fs,
> errcode_t ocfs2_free_cached_inode(ocfs2_filesys *fs,
> ocfs2_cached_inode *cinode);
>
> -void ocfs2_swap_extent_list_from_cpu(struct ocfs2_extent_list *el);
> -void ocfs2_swap_extent_list_to_cpu(struct ocfs2_extent_list *el);
> +/*
> + * obj is the object containing the extent list. eg, if you are swapping
> + * an inode's extent list, you're passing 'di' for the obj and
> + * '&di->id2.i_list' for the el. obj is needed to make sure the
> + * byte swapping code doesn't walk off the end of the buffer in the
> + * presence of corruption.
> + */
> +void ocfs2_swap_extent_list_from_cpu(ocfs2_filesys *fs, void *obj,
> + struct ocfs2_extent_list *el);
> +void ocfs2_swap_extent_list_to_cpu(ocfs2_filesys *fs, void *obj,
> + struct ocfs2_extent_list *el);
> errcode_t ocfs2_extent_map_get_blocks(ocfs2_cached_inode *cinode,
> uint64_t v_blkno, int count,
> uint64_t *p_blkno,
> @@ -298,8 +307,10 @@ extern size_t ocfs2_journal_tag_bytes(journal_superblock_t *jsb);
> extern uint64_t ocfs2_journal_tag_block(journal_block_tag_t *tag,
> size_t tag_bytes);
>
> -void ocfs2_swap_extent_block_to_cpu(struct ocfs2_extent_block *eb);
> -void ocfs2_swap_extent_block_from_cpu(struct ocfs2_extent_block *eb);
> +void ocfs2_swap_extent_block_to_cpu(ocfs2_filesys *fs,
> + struct ocfs2_extent_block *eb);
> +void ocfs2_swap_extent_block_from_cpu(ocfs2_filesys *fs,
> + struct ocfs2_extent_block *eb);
> errcode_t ocfs2_read_extent_block(ocfs2_filesys *fs, uint64_t blkno,
> char *eb_buf);
> errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs, uint64_t blkno,
> @@ -974,6 +985,27 @@ static inline int ocfs2_support_xattr(struct ocfs2_super_block *osb)
> }
>
> /*
> + * When we're swapping some of our disk structures, a garbage count
> + * can send us past the edge of a block buffer. This function guards
> + * against that. It returns true if the element would walk off then end
> + * of the block buffer.
> + */
> +static inline int ocfs2_swap_barrier(ocfs2_filesys *fs, void *block_buffer,
> + void *element, size_t element_size)
> +{
> + char *limit, *end;
> +
> + limit = block_buffer;
> + limit += fs->fs_blocksize;
> +
> + end = element;
> + end += element_size;
> +
> + return end > limit;
> +}
> +
> +
> +/*
> * shamelessly lifted from the kernel
> *
> * min()/max() macros that also do
> @@ -1098,10 +1130,15 @@ int ocfs2_xattr_find_leaf(ocfs2_filesys *fs, struct ocfs2_xattr_block *xb,
> uint32_t cpos, char **leaf_buf);
> uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs);
> uint16_t ocfs2_blocks_per_xattr_bucket(ocfs2_filesys *fs);
> -void ocfs2_swap_xattrs_to_cpu(struct ocfs2_xattr_header *xh);
> -void ocfs2_swap_xattrs_from_cpu(struct ocfs2_xattr_header *xh);
> -void ocfs2_swap_xattr_block_to_cpu(struct ocfs2_xattr_block *xb);
> -void ocfs2_swap_xattr_block_from_cpu(struct ocfs2_xattr_block *xb);
> +/* See ocfs2_swap_extent_list() for a discussion of obj */
> +void ocfs2_swap_xattrs_to_cpu(ocfs2_filesys *fs, void *obj,
> + struct ocfs2_xattr_header *xh);
> +void ocfs2_swap_xattrs_from_cpu(ocfs2_filesys *fs, void *obj,
> + struct ocfs2_xattr_header *xh);
> +void ocfs2_swap_xattr_block_to_cpu(ocfs2_filesys *fs,
> + struct ocfs2_xattr_block *xb);
> +void ocfs2_swap_xattr_block_from_cpu(ocfs2_filesys *fs,
> + struct ocfs2_xattr_block *xb);
> errcode_t ocfs2_read_xattr_block(ocfs2_filesys *fs,
> uint64_t blkno,
> char *xb_buf);
> diff --git a/libocfs2/extents.c b/libocfs2/extents.c
> index 4b6808a..ee7ef93 100644
> --- a/libocfs2/extents.c
> +++ b/libocfs2/extents.c
> @@ -42,13 +42,18 @@ static void ocfs2_swap_extent_list_primary(struct ocfs2_extent_list *el)
> el->l_next_free_rec = bswap_16(el->l_next_free_rec);
> }
>
> -static void ocfs2_swap_extent_list_secondary(struct ocfs2_extent_list *el)
> +static void ocfs2_swap_extent_list_secondary(ocfs2_filesys *fs, void *obj,
> + struct ocfs2_extent_list *el)
> {
> uint16_t i;
>
> for(i = 0; i < el->l_next_free_rec; i++) {
> struct ocfs2_extent_rec *rec = &el->l_recs[i];
>
> + if (ocfs2_swap_barrier(fs, obj, rec,
> + sizeof(struct ocfs2_extent_rec)))
> + break;
> +
> rec->e_cpos = bswap_32(rec->e_cpos);
> if (el->l_tree_depth)
> rec->e_int_clusters = bswap_32(rec->e_int_clusters);
> @@ -58,21 +63,23 @@ static void ocfs2_swap_extent_list_secondary(struct ocfs2_extent_list *el)
> }
> }
>
> -void ocfs2_swap_extent_list_from_cpu(struct ocfs2_extent_list *el)
> +void ocfs2_swap_extent_list_from_cpu(ocfs2_filesys *fs, void *obj,
> + struct ocfs2_extent_list *el)
> {
> if (cpu_is_little_endian)
> return;
>
> - ocfs2_swap_extent_list_secondary(el);
> + ocfs2_swap_extent_list_secondary(fs, obj, el);
> ocfs2_swap_extent_list_primary(el);
> }
> -void ocfs2_swap_extent_list_to_cpu(struct ocfs2_extent_list *el)
> +void ocfs2_swap_extent_list_to_cpu(ocfs2_filesys *fs, void *obj,
> + struct ocfs2_extent_list *el)
> {
> if (cpu_is_little_endian)
> return;
>
> ocfs2_swap_extent_list_primary(el);
> - ocfs2_swap_extent_list_secondary(el);
> + ocfs2_swap_extent_list_secondary(fs, obj, el);
> }
>
> static void ocfs2_swap_extent_block_header(struct ocfs2_extent_block *eb)
> @@ -85,22 +92,24 @@ static void ocfs2_swap_extent_block_header(struct ocfs2_extent_block *eb)
> eb->h_next_leaf_blk = bswap_64(eb->h_next_leaf_blk);
> }
>
> -void ocfs2_swap_extent_block_from_cpu(struct ocfs2_extent_block *eb)
> +void ocfs2_swap_extent_block_from_cpu(ocfs2_filesys *fs,
> + struct ocfs2_extent_block *eb)
> {
> if (cpu_is_little_endian)
> return;
>
> ocfs2_swap_extent_block_header(eb);
> - ocfs2_swap_extent_list_from_cpu(&eb->h_list);
> + ocfs2_swap_extent_list_from_cpu(fs, eb, &eb->h_list);
> }
>
> -void ocfs2_swap_extent_block_to_cpu(struct ocfs2_extent_block *eb)
> +void ocfs2_swap_extent_block_to_cpu(ocfs2_filesys *fs,
> + struct ocfs2_extent_block *eb)
> {
> if (cpu_is_little_endian)
> return;
>
> ocfs2_swap_extent_block_header(eb);
> - ocfs2_swap_extent_list_to_cpu(&eb->h_list);
> + ocfs2_swap_extent_list_to_cpu(fs, eb, &eb->h_list);
> }
>
> errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs,
> @@ -138,7 +147,7 @@ errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs,
> memcpy(eb_buf, blk, fs->fs_blocksize);
>
> eb = (struct ocfs2_extent_block *) eb_buf;
> - ocfs2_swap_extent_block_to_cpu(eb);
> + ocfs2_swap_extent_block_to_cpu(fs, eb);
>
> out:
> ocfs2_free(&blk);
> @@ -182,7 +191,7 @@ errcode_t ocfs2_write_extent_block(ocfs2_filesys *fs, uint64_t blkno,
> memcpy(blk, eb_buf, fs->fs_blocksize);
>
> eb = (struct ocfs2_extent_block *) blk;
> - ocfs2_swap_extent_block_from_cpu(eb);
> + ocfs2_swap_extent_block_from_cpu(fs, eb);
>
> ocfs2_compute_meta_ecc(fs, blk, &eb->h_check);
> ret = io_write_block(fs->fs_io, blkno, 1, blk);
> diff --git a/libocfs2/inode.c b/libocfs2/inode.c
> index e786f5e..1abda69 100644
> --- a/libocfs2/inode.c
> +++ b/libocfs2/inode.c
> @@ -63,7 +63,7 @@ out_buf:
> return ret;
> }
>
> -static void ocfs2_swap_inode_third(struct ocfs2_dinode *di)
> +static void ocfs2_swap_inode_third(ocfs2_filesys *fs, struct ocfs2_dinode *di)
> {
>
> if (di->i_flags & OCFS2_CHAIN_FL) {
> @@ -73,6 +73,10 @@ static void ocfs2_swap_inode_third(struct ocfs2_dinode *di)
> for (i = 0; i < cl->cl_next_free_rec; i++) {
> struct ocfs2_chain_rec *rec = &cl->cl_recs[i];
>
> + if (ocfs2_swap_barrier(fs, di, rec,
> + sizeof(struct ocfs2_chain_rec)))
> + break;
> +
> rec->c_free = bswap_32(rec->c_free);
> rec->c_total = bswap_32(rec->c_total);
> rec->c_blkno = bswap_64(rec->c_blkno);
> @@ -86,6 +90,10 @@ static void ocfs2_swap_inode_third(struct ocfs2_dinode *di)
> struct ocfs2_truncate_rec *rec =
> &tl->tl_recs[i];
>
> + if (ocfs2_swap_barrier(fs, di, rec,
> + sizeof(struct ocfs2_truncate_rec)))
> + break;
> +
> rec->t_start = bswap_32(rec->t_start);
> rec->t_clusters = bswap_32(rec->t_clusters);
> }
> @@ -202,11 +210,22 @@ static int has_extents(struct ocfs2_dinode *di)
> return 1;
> }
>
> -static inline void ocfs2_swap_inline_dir(struct ocfs2_dinode *di,
> - int to_cpu)
> +static inline void ocfs2_swap_inline_dir(ocfs2_filesys *fs,
> + struct ocfs2_dinode *di, int to_cpu)
> {
> void *de_buf = di->id2.i_data.id_data;
> uint64_t bytes = di->id2.i_data.id_count;
> + int max_inline = ocfs2_max_inline_data(fs->fs_blocksize);
> +
> + if (di->i_dyn_features & OCFS2_INLINE_XATTR_FL)
> + max_inline -= di->i_xattr_inline_size;
> +
> + /* Just in case i_xattr_inline_size is garbage */
> + if (max_inline < 0)
> + max_inline = 0;
> +
> + if (bytes > max_inline)
> + bytes = max_inline;
>
> if (to_cpu)
> ocfs2_swap_dir_entries_to_cpu(de_buf, bytes);
> @@ -214,41 +233,43 @@ static inline void ocfs2_swap_inline_dir(struct ocfs2_dinode *di,
> ocfs2_swap_dir_entries_from_cpu(de_buf, bytes);
> }
>
> -void ocfs2_swap_inode_from_cpu(struct ocfs2_dinode *di, size_t blocksize)
> +void ocfs2_swap_inode_from_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di)
> {
> if (cpu_is_little_endian)
> return;
>
> if (di->i_dyn_features & OCFS2_INLINE_XATTR_FL) {
> struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)
> - ((void *)di + blocksize - di->i_xattr_inline_size);
> - ocfs2_swap_xattrs_from_cpu(xh);
> + ((void *)di + fs->fs_blocksize -
> + di->i_xattr_inline_size);
> + ocfs2_swap_xattrs_from_cpu(fs, di, xh);
> }
> if (has_extents(di))
> - ocfs2_swap_extent_list_from_cpu(&di->id2.i_list);
> + ocfs2_swap_extent_list_from_cpu(fs, di, &di->id2.i_list);
> if (di->i_dyn_features & OCFS2_INLINE_DATA_FL && S_ISDIR(di->i_mode))
> - ocfs2_swap_inline_dir(di, 0);
> - ocfs2_swap_inode_third(di);
> + ocfs2_swap_inline_dir(fs, di, 0);
> + ocfs2_swap_inode_third(fs, di);
> ocfs2_swap_inode_second(di);
> ocfs2_swap_inode_first(di);
> }
>
> -void ocfs2_swap_inode_to_cpu(struct ocfs2_dinode *di, size_t blocksize)
> +void ocfs2_swap_inode_to_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di)
> {
> if (cpu_is_little_endian)
> return;
>
> ocfs2_swap_inode_first(di);
> ocfs2_swap_inode_second(di);
> - ocfs2_swap_inode_third(di);
> + ocfs2_swap_inode_third(fs, di);
> if (di->i_dyn_features & OCFS2_INLINE_DATA_FL && S_ISDIR(di->i_mode))
> - ocfs2_swap_inline_dir(di, 1);
> + ocfs2_swap_inline_dir(fs, di, 1);
> if (has_extents(di))
> - ocfs2_swap_extent_list_to_cpu(&di->id2.i_list);
> + ocfs2_swap_extent_list_to_cpu(fs, di, &di->id2.i_list);
> if (di->i_dyn_features & OCFS2_INLINE_XATTR_FL) {
> struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)
> - ((void *)di + blocksize - di->i_xattr_inline_size);
> - ocfs2_swap_xattrs_to_cpu(xh);
> + ((void *)di + fs->fs_blocksize -
> + di->i_xattr_inline_size);
> + ocfs2_swap_xattrs_to_cpu(fs, di, xh);
> }
> }
>
> @@ -284,7 +305,7 @@ errcode_t ocfs2_read_inode(ocfs2_filesys *fs, uint64_t blkno,
> memcpy(inode_buf, blk, fs->fs_blocksize);
>
> di = (struct ocfs2_dinode *) inode_buf;
> - ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> + ocfs2_swap_inode_to_cpu(fs, di);
>
> ret = 0;
> out:
> @@ -314,7 +335,7 @@ errcode_t ocfs2_write_inode(ocfs2_filesys *fs, uint64_t blkno,
> memcpy(blk, inode_buf, fs->fs_blocksize);
>
> di = (struct ocfs2_dinode *)blk;
> - ocfs2_swap_inode_from_cpu(di, fs->fs_blocksize);
> + ocfs2_swap_inode_from_cpu(fs, di);
>
> ocfs2_compute_meta_ecc(fs, blk, &di->i_check);
> ret = io_write_block(fs->fs_io, blkno, 1, blk);
> diff --git a/libocfs2/openfs.c b/libocfs2/openfs.c
> index 538d859..156ea47 100644
> --- a/libocfs2/openfs.c
> +++ b/libocfs2/openfs.c
> @@ -137,7 +137,7 @@ errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb)
> orig_blocksize = fs->fs_blocksize;
> fs->fs_super = (struct ocfs2_dinode *)swapblk;
> fs->fs_blocksize = blocksize;
> - ocfs2_swap_inode_to_cpu(fs->fs_super, fs->fs_blocksize);
> + ocfs2_swap_inode_to_cpu(fs, fs->fs_super);
>
> ret = ocfs2_validate_meta_ecc(fs, blk, &di->i_check);
>
> @@ -148,7 +148,7 @@ errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb)
> if (ret)
> goto out_blk;
>
> - ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> + ocfs2_swap_inode_to_cpu(fs, di);
> if (!sb)
> fs->fs_super = di;
> else {
> diff --git a/libocfs2/xattr.c b/libocfs2/xattr.c
> index bffdfd9..adcf6ad 100644
> --- a/libocfs2/xattr.c
> +++ b/libocfs2/xattr.c
> @@ -106,9 +106,26 @@ static void ocfs2_swap_xattr_header(struct ocfs2_xattr_header *xh)
> xh->xh_num_buckets = bswap_16(xh->xh_num_buckets);
> }
>
> -static void ocfs2_swap_xattr_entries_to_cpu(struct ocfs2_xattr_header *xh)
> +/*
> + * The swap barriers for xattrs are the hardest. The ocfs2_xattr_header
> + * can be at the start of a bucket, inside an xattr block, or at the end
> + * of an inode. Thus, we need to pass obj for the containing object.
> + * On top of that, buckets are always 4K, regardless of blocksize. Thus,
> + * we take objsize as an argument and fake the ocfs2_filesys we pass to
> + * ocfs2_swap_barrier().
> + *
> + * Much of this is internal to xattr.c, thankfully. The callers of the
> + * pubic ocfs2_swap_xattr*() APIs don't have to worry about objsize!
> + */
> +static void ocfs2_swap_xattr_entries_to_cpu(ocfs2_filesys *fs, void *obj,
> + size_t objsize,
> + struct ocfs2_xattr_header *xh)
> {
> uint16_t i;
> + char *value;
> + ocfs2_filesys fake_fs = {
> + .fs_blocksize = objsize,
> + };
>
> if (cpu_is_little_endian)
> return;
> @@ -116,23 +133,41 @@ static void ocfs2_swap_xattr_entries_to_cpu(struct ocfs2_xattr_header *xh)
> for (i = 0; i < xh->xh_count; i++) {
> struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
>
> + if (ocfs2_swap_barrier(&fake_fs, obj, xe,
> + sizeof(struct ocfs2_xattr_entry)))
> + break;
> +
> ocfs2_swap_xattr_entry(xe);
>
> + value = (char *)xh + xe->xe_name_offset +
> + OCFS2_XATTR_SIZE(xe->xe_name_len);
> +
> if (!ocfs2_xattr_is_local(xe)) {
> struct ocfs2_xattr_value_root *xr =
> - (struct ocfs2_xattr_value_root *)
> - ((char *)xh + xe->xe_name_offset +
> - OCFS2_XATTR_SIZE(xe->xe_name_len));
> + (struct ocfs2_xattr_value_root *)value;
> +
> + if (ocfs2_swap_barrier(&fake_fs, obj, xr,
> + OCFS2_XATTR_ROOT_SIZE))
> + break;
>
> ocfs2_swap_xattr_value_root(xr);
> - ocfs2_swap_extent_list_to_cpu(&xr->xr_list);
> - }
> + ocfs2_swap_extent_list_to_cpu(&fake_fs, xh,
> + &xr->xr_list);
> + } else if (ocfs2_swap_barrier(&fake_fs, obj, value,
> + OCFS2_XATTR_SIZE(xe->xe_value_size)))
> + break;
> }
> }
>
> -static void ocfs2_swap_xattr_entries_from_cpu(struct ocfs2_xattr_header *xh)
> +static void ocfs2_swap_xattr_entries_from_cpu(ocfs2_filesys *fs, void *obj,
> + size_t objsize,
> + struct ocfs2_xattr_header *xh)
> {
> uint16_t i;
> + char *value;
> + ocfs2_filesys fake_fs = {
> + .fs_blocksize = objsize,
> + };
>
> if (cpu_is_little_endian)
> return;
> @@ -140,56 +175,87 @@ static void ocfs2_swap_xattr_entries_from_cpu(struct ocfs2_xattr_header *xh)
> for (i = 0; i < xh->xh_count; i++) {
> struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
>
> + if (ocfs2_swap_barrier(&fake_fs, obj, xe,
> + sizeof(struct ocfs2_xattr_entry)))
> + break;
> +
> + value = (char *)xh + xe->xe_name_offset +
> + OCFS2_XATTR_SIZE(xe->xe_name_len);
> +
> if (!ocfs2_xattr_is_local(xe)) {
> struct ocfs2_xattr_value_root *xr =
> - (struct ocfs2_xattr_value_root *)
> - ((char *)xh + xe->xe_name_offset +
> - OCFS2_XATTR_SIZE(xe->xe_name_len));
> + (struct ocfs2_xattr_value_root *)value;
> +
> + if (ocfs2_swap_barrier(&fake_fs, obj, xr,
> + OCFS2_XATTR_ROOT_SIZE))
> + break;
>
> - ocfs2_swap_extent_list_from_cpu(&xr->xr_list);
> + ocfs2_swap_extent_list_from_cpu(&fake_fs, xh,
> + &xr->xr_list);
> ocfs2_swap_xattr_value_root(xr);
> - }
> + } else if (ocfs2_swap_barrier(&fake_fs, obj, value,
> + OCFS2_XATTR_SIZE(xe->xe_value_size)))
> + break;
> +
> ocfs2_swap_xattr_entry(xe);
> }
> }
>
> -void ocfs2_swap_xattrs_to_cpu(struct ocfs2_xattr_header *xh)
> +static void __ocfs2_swap_xattrs_to_cpu(ocfs2_filesys *fs, void *obj,
> + size_t objsize,
> + struct ocfs2_xattr_header *xh)
> {
> ocfs2_swap_xattr_header(xh);
> - ocfs2_swap_xattr_entries_to_cpu(xh);
> + ocfs2_swap_xattr_entries_to_cpu(fs, obj, objsize, xh);
> +}
> +
> +void ocfs2_swap_xattrs_to_cpu(ocfs2_filesys *fs, void *obj,
> + struct ocfs2_xattr_header *xh)
> +{
> + return __ocfs2_swap_xattrs_to_cpu(fs, obj, fs->fs_blocksize, xh);
> }
>
> -void ocfs2_swap_xattrs_from_cpu(struct ocfs2_xattr_header *xh)
> +static void __ocfs2_swap_xattrs_from_cpu(ocfs2_filesys *fs, void *obj,
> + size_t objsize,
> + struct ocfs2_xattr_header *xh)
> {
> - ocfs2_swap_xattr_entries_from_cpu(xh);
> + ocfs2_swap_xattr_entries_from_cpu(fs, obj, objsize, xh);
> ocfs2_swap_xattr_header(xh);
> }
>
> -void ocfs2_swap_xattr_block_to_cpu(struct ocfs2_xattr_block *xb)
> +void ocfs2_swap_xattrs_from_cpu(ocfs2_filesys *fs, void *obj,
> + struct ocfs2_xattr_header *xh)
> +{
> + return __ocfs2_swap_xattrs_from_cpu(fs, obj, fs->fs_blocksize, xh);
> +}
> +
> +void ocfs2_swap_xattr_block_to_cpu(ocfs2_filesys *fs,
> + struct ocfs2_xattr_block *xb)
> {
> if (cpu_is_little_endian)
> return;
>
> ocfs2_swap_xattr_block_header(xb);
> - if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
> - ocfs2_swap_xattr_header(&xb->xb_attrs.xb_header);
> - ocfs2_swap_xattr_entries_to_cpu(&xb->xb_attrs.xb_header);
> - } else {
> + if (!(xb->xb_flags & OCFS2_XATTR_INDEXED))
> + ocfs2_swap_xattrs_to_cpu(fs, xb, &xb->xb_attrs.xb_header);
> + else {
> ocfs2_swap_xattr_tree_root(&xb->xb_attrs.xb_root);
> - ocfs2_swap_extent_list_to_cpu(&xb->xb_attrs.xb_root.xt_list);
> + ocfs2_swap_extent_list_to_cpu(fs, xb,
> + &xb->xb_attrs.xb_root.xt_list);
> }
> }
>
> -void ocfs2_swap_xattr_block_from_cpu(struct ocfs2_xattr_block *xb)
> +void ocfs2_swap_xattr_block_from_cpu(ocfs2_filesys *fs,
> + struct ocfs2_xattr_block *xb)
> {
> if (cpu_is_little_endian)
> return;
>
> - if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
> - ocfs2_swap_xattr_entries_from_cpu(&xb->xb_attrs.xb_header);
> - ocfs2_swap_xattr_header(&xb->xb_attrs.xb_header);
> - } else {
> - ocfs2_swap_extent_list_from_cpu(&xb->xb_attrs.xb_root.xt_list);
> + if (!(xb->xb_flags & OCFS2_XATTR_INDEXED))
> + ocfs2_swap_xattrs_from_cpu(fs, xb, &xb->xb_attrs.xb_header);
> + else {
> + ocfs2_swap_extent_list_from_cpu(fs, xb,
> + &xb->xb_attrs.xb_root.xt_list);
> ocfs2_swap_xattr_tree_root(&xb->xb_attrs.xb_root);
> }
>
> @@ -230,7 +296,7 @@ errcode_t ocfs2_read_xattr_block(ocfs2_filesys *fs,
>
> memcpy(xb_buf, blk, fs->fs_blocksize);
> xb = (struct ocfs2_xattr_block *)xb_buf;
> - ocfs2_swap_xattr_block_to_cpu(xb);
> + ocfs2_swap_xattr_block_to_cpu(fs, xb);
> out:
> ocfs2_free(&blk);
> return ret;
> @@ -258,7 +324,7 @@ errcode_t ocfs2_write_xattr_block(ocfs2_filesys *fs,
> memcpy(blk, xb_buf, fs->fs_blocksize);
>
> xb = (struct ocfs2_xattr_block *)blk;
> - ocfs2_swap_xattr_block_from_cpu(xb);
> + ocfs2_swap_xattr_block_from_cpu(fs, xb);
>
> ocfs2_compute_meta_ecc(fs, blk, &xb->xb_check);
> ret = io_write_block(fs->fs_io, blkno, 1, blk);
> @@ -395,7 +461,7 @@ errcode_t ocfs2_read_xattr_bucket(ocfs2_filesys *fs,
>
> memcpy(bucket_buf, bucket, OCFS2_XATTR_BUCKET_SIZE);
> xh = (struct ocfs2_xattr_header *)bucket_buf;
> - ocfs2_swap_xattrs_to_cpu(xh);
> + __ocfs2_swap_xattrs_to_cpu(fs, xh, OCFS2_XATTR_BUCKET_SIZE, xh);
> out:
> ocfs2_free(&bucket);
> return ret;
> @@ -425,7 +491,7 @@ errcode_t ocfs2_write_xattr_bucket(ocfs2_filesys *fs,
> memcpy(bucket, bucket_buf, OCFS2_XATTR_BUCKET_SIZE);
>
> xh = (struct ocfs2_xattr_header *)bucket;
> - ocfs2_swap_xattrs_from_cpu(xh);
> + __ocfs2_swap_xattrs_from_cpu(fs, xh, OCFS2_XATTR_BUCKET_SIZE, xh);
>
> if (ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super)))
> ocfs2_block_check_compute(bucket, OCFS2_XATTR_BUCKET_SIZE,
> diff --git a/mkfs.ocfs2/mkfs.c b/mkfs.ocfs2/mkfs.c
> index 048f70f..d6151cf 100644
> --- a/mkfs.ocfs2/mkfs.c
> +++ b/mkfs.ocfs2/mkfs.c
> @@ -1945,6 +1945,15 @@ check_32bit_blocks(State *s)
> exit(1);
> }
>
> +static void mkfs_swap_inode_from_cpu(State *s, struct ocfs2_dinode *di)
> +{
> + ocfs2_filesys fake_fs;
> + char super_buf[OCFS2_MAX_BLOCKSIZE];
> +
> + fill_fake_fs(s, &fake_fs, super_buf);
> + ocfs2_swap_inode_from_cpu(&fake_fs, di);
> +}
> +
> static void
> format_superblock(State *s, SystemFileDiskRecord *rec,
> SystemFileDiskRecord *root_rec, SystemFileDiskRecord *sys_rec)
> @@ -2025,7 +2034,7 @@ format_superblock(State *s, SystemFileDiskRecord *rec,
> strcpy((char *)di->id2.i_super.s_label, s->vol_label);
> memcpy(di->id2.i_super.s_uuid, s->uuid, 16);
>
> - ocfs2_swap_inode_from_cpu(di, s->blocksize);
> + mkfs_swap_inode_from_cpu(s, di);
> mkfs_compute_meta_ecc(s, di, &di->i_check);
> do_pwrite(s, di, s->blocksize, super_off);
> free(di);
> @@ -2191,7 +2200,7 @@ format_file(State *s, SystemFileDiskRecord *rec)
> }
>
> write_out:
> - ocfs2_swap_inode_from_cpu(di, s->blocksize);
> + mkfs_swap_inode_from_cpu(s, di);
> mkfs_compute_meta_ecc(s, di, &di->i_check);
> do_pwrite(s, di, s->blocksize, rec->fe_off);
> free(di);
> diff --git a/tunefs.ocfs2/libocfs2ne.c b/tunefs.ocfs2/libocfs2ne.c
> index c5362db..6f89175 100644
> --- a/tunefs.ocfs2/libocfs2ne.c
> +++ b/tunefs.ocfs2/libocfs2ne.c
> @@ -498,7 +498,7 @@ static errcode_t tunefs_validate_inode(ocfs2_filesys *fs,
> strlen(OCFS2_INODE_SIGNATURE)))
> return OCFS2_ET_BAD_INODE_MAGIC;
>
> - ocfs2_swap_inode_to_cpu(di, fs->fs_blocksize);
> + ocfs2_swap_inode_to_cpu(fs, di);
>
> if (di->i_fs_generation != fs->fs_super->i_fs_generation)
> return OCFS2_ET_INODE_NOT_VALID;
More information about the Ocfs2-tools-devel
mailing list