Re: Enlarging w/ xfs_growfs: XFS_IOC_FSGROWFSDATA xfsctl failed: Inappropriate ioctl for device

Nick Bowler
2018-12-13T04:49:39Z

On 2018-12-12, Nick Bowler <nbowler@draconx.ca> wrote:
> On 2018-12-12, Dave Chinner <david@fromorbit.com> wrote:
>> On Tue, Dec 11, 2018 at 11:56:33PM -0500, Nick Bowler wrote:
>>> OK, xfstests has revealed some trouble with the three "bulkstat" ioctls,
>>> since while the xfs_bulkstat structure itself is fine, one of its
>>> members
>>> is used as a pointer to various structures which are not fine. This
>>> wasn't too hard to fix though.
>>
>> IIRC, there's bigger problems than you realise here - the bulkstat
>> structure has embedded timestamps in them and on x32 struct timeval
>> doesn't match either ia32 or x86-64. i.e. on ia32, struct timeval is
>> 8 bytes, on x86-64 it is 16 bytes, and in x32 it is 12 bytes.
>
> This is not the case: struct timeval is 16 bytes on x32:
>
> sizeof (struct timeval): 16
> tv_sec size: 8 offset: 0
> tv_usec size: 8 offset: 8
>
> This is the same as what I get on native 64-bit compilations; but
> anyway the xfs_bstat structure has xfs_bstime members, with the
> following characteristics on x32:
>
> sizeof (struct xfs_bstime): 16
> tv_sec size: 8 offset: 0
> tv_nsec size: 4 offset: 8
>
> which is also the same as native 64-bit (time_t is the same on x32 and
> native: 8 bytes with 8 byte alignment).
>
> I manually verified every member of the xfs_bstat structure with sizeof
> and offsetof on -mx32 and -m64 compilations to ensure that this structure
> matches precisely between the x32 and native 64-bit cases.

To expand on this, for each structure which my RFC patchset feeds up to
the native handler, I first checked them by manual inspection and then
double checked using the following program; we can compile with both
-mx32 and -m64 and check that the output is identical.

#include <stdio.h>
#include <stddef.h>
#include <xfs/xfs.h>
#include <time.h>

#define SHOWSIZE(type) do { \
printf("sizeof (%s): %zu\n", #type, sizeof (type)); \
} while(0)

#define SHOWMEMBER(type, member) do { \
printf(" %-15s size: %3zu offset: %3zu\n", #member, \
sizeof (type){0}.member, offsetof(type, member)); \
} while(0)

int main(void)
{
SHOWSIZE(struct xfs_flock64);
SHOWMEMBER(struct xfs_flock64, l_type);
SHOWMEMBER(struct xfs_flock64, l_whence);
SHOWMEMBER(struct xfs_flock64, l_start);
SHOWMEMBER(struct xfs_flock64, l_len);
SHOWMEMBER(struct xfs_flock64, l_sysid);
SHOWMEMBER(struct xfs_flock64, l_pid);
SHOWMEMBER(struct xfs_flock64, l_pad);

SHOWSIZE(struct xfs_fsop_geom_v1);
SHOWMEMBER(struct xfs_fsop_geom_v1, blocksize);
SHOWMEMBER(struct xfs_fsop_geom_v1, rtextsize);
SHOWMEMBER(struct xfs_fsop_geom_v1, agblocks);
SHOWMEMBER(struct xfs_fsop_geom_v1, agcount);
SHOWMEMBER(struct xfs_fsop_geom_v1, logblocks);
SHOWMEMBER(struct xfs_fsop_geom_v1, sectsize);
SHOWMEMBER(struct xfs_fsop_geom_v1, inodesize);
SHOWMEMBER(struct xfs_fsop_geom_v1, imaxpct);
SHOWMEMBER(struct xfs_fsop_geom_v1, datablocks);
SHOWMEMBER(struct xfs_fsop_geom_v1, rtblocks);
SHOWMEMBER(struct xfs_fsop_geom_v1, rtextents);
SHOWMEMBER(struct xfs_fsop_geom_v1, logstart);
SHOWMEMBER(struct xfs_fsop_geom_v1, uuid);
SHOWMEMBER(struct xfs_fsop_geom_v1, sunit);
SHOWMEMBER(struct xfs_fsop_geom_v1, swidth);
SHOWMEMBER(struct xfs_fsop_geom_v1, version);
SHOWMEMBER(struct xfs_fsop_geom_v1, flags);
SHOWMEMBER(struct xfs_fsop_geom_v1, logsectsize);
SHOWMEMBER(struct xfs_fsop_geom_v1, rtsectsize);
SHOWMEMBER(struct xfs_fsop_geom_v1, dirblocksize);

SHOWSIZE(struct xfs_growfs_data);
SHOWMEMBER(struct xfs_growfs_data, newblocks);
SHOWMEMBER(struct xfs_growfs_data, imaxpct);

SHOWSIZE(struct xfs_growfs_rt);
SHOWMEMBER(struct xfs_growfs_rt, newblocks);
SHOWMEMBER(struct xfs_growfs_rt, extsize);

SHOWSIZE(struct xfs_bstime);
SHOWMEMBER(struct xfs_bstime, tv_sec);
SHOWMEMBER(struct xfs_bstime, tv_nsec);

SHOWSIZE(struct xfs_bstat);
SHOWMEMBER(struct xfs_bstat, bs_ino);
SHOWMEMBER(struct xfs_bstat, bs_mode);
SHOWMEMBER(struct xfs_bstat, bs_nlink);
SHOWMEMBER(struct xfs_bstat, bs_uid);
SHOWMEMBER(struct xfs_bstat, bs_gid);
SHOWMEMBER(struct xfs_bstat, bs_rdev);
SHOWMEMBER(struct xfs_bstat, bs_blksize);
SHOWMEMBER(struct xfs_bstat, bs_size);
SHOWMEMBER(struct xfs_bstat, bs_atime);
SHOWMEMBER(struct xfs_bstat, bs_mtime);
SHOWMEMBER(struct xfs_bstat, bs_ctime);
SHOWMEMBER(struct xfs_bstat, bs_blocks);
SHOWMEMBER(struct xfs_bstat, bs_xflags);
SHOWMEMBER(struct xfs_bstat, bs_extsize);
SHOWMEMBER(struct xfs_bstat, bs_extents);
SHOWMEMBER(struct xfs_bstat, bs_gen);
SHOWMEMBER(struct xfs_bstat, bs_projid_lo);
SHOWMEMBER(struct xfs_bstat, bs_forkoff);
SHOWMEMBER(struct xfs_bstat, bs_projid_hi);
SHOWMEMBER(struct xfs_bstat, bs_pad);
SHOWMEMBER(struct xfs_bstat, bs_cowextsize);
SHOWMEMBER(struct xfs_bstat, bs_dmevmask);
SHOWMEMBER(struct xfs_bstat, bs_dmstate);
SHOWMEMBER(struct xfs_bstat, bs_aextents);

SHOWSIZE(struct xfs_inogrp);
SHOWMEMBER(struct xfs_inogrp, xi_startino);
SHOWMEMBER(struct xfs_inogrp, xi_alloccount);
SHOWMEMBER(struct xfs_inogrp, xi_allocmask);

SHOWSIZE(struct xfs_swapext);
SHOWMEMBER(struct xfs_swapext, sx_version);
SHOWMEMBER(struct xfs_swapext, sx_fdtarget);
SHOWMEMBER(struct xfs_swapext, sx_fdtmp);
SHOWMEMBER(struct xfs_swapext, sx_offset);
SHOWMEMBER(struct xfs_swapext, sx_length);
SHOWMEMBER(struct xfs_swapext, sx_pad);
SHOWMEMBER(struct xfs_swapext, sx_stat);
}