|
|
| version 1.17, 2007/07/09 15:44:42 | version 1.18, 2007/07/09 15:45:29 |
|---|---|
| Line 23 | Line 23 |
| #include <linux/fs.h> | #include <linux/fs.h> |
| #include <asm/uaccess.h> | #include <asm/uaccess.h> |
| #include "xfs.h" | #include "xfs.h" |
| #include "xfs_types.h" | |
| #include "xfs_fs.h" | #include "xfs_fs.h" |
| #include "xfs_bit.h" | |
| #include "xfs_log.h" | |
| #include "xfs_inum.h" | |
| #include "xfs_trans.h" | |
| #include "xfs_sb.h" | |
| #include "xfs_ag.h" | |
| #include "xfs_dir2.h" | |
| #include "xfs_dmapi.h" | |
| #include "xfs_mount.h" | |
| #include "xfs_bmap_btree.h" | |
| #include "xfs_attr_sf.h" | |
| #include "xfs_dir2_sf.h" | |
| #include "xfs_vfs.h" | #include "xfs_vfs.h" |
| #include "xfs_vnode.h" | #include "xfs_vnode.h" |
| #include "xfs_dinode.h" | |
| #include "xfs_inode.h" | |
| #include "xfs_itable.h" | |
| #include "xfs_error.h" | |
| #include "xfs_dfrag.h" | #include "xfs_dfrag.h" |
| #define _NATIVE_IOC(cmd, type) \ | #define _NATIVE_IOC(cmd, type) \ |
| Line 34 | Line 49 |
| #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) | #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) |
| #define BROKEN_X86_ALIGNMENT | #define BROKEN_X86_ALIGNMENT |
| #define _PACKED __attribute__((packed)) | |
| /* on ia32 l_start is on a 32-bit boundary */ | /* on ia32 l_start is on a 32-bit boundary */ |
| typedef struct xfs_flock64_32 { | typedef struct xfs_flock64_32 { |
| __s16 l_type; | __s16 l_type; |
| Line 111 STATIC unsigned long xfs_ioctl32_geom_v1 | Line 127 STATIC unsigned long xfs_ioctl32_geom_v1 |
| return (unsigned long)p; | return (unsigned long)p; |
| } | } |
| typedef struct compat_xfs_inogrp { | |
| __u64 xi_startino; /* starting inode number */ | |
| __s32 xi_alloccount; /* # bits set in allocmask */ | |
| __u64 xi_allocmask; /* mask of allocated inodes */ | |
| } __attribute__((packed)) compat_xfs_inogrp_t; | |
| STATIC int xfs_inumbers_fmt_compat( | |
| void __user *ubuffer, | |
| const xfs_inogrp_t *buffer, | |
| long count, | |
| long *written) | |
| { | |
| compat_xfs_inogrp_t *p32 = ubuffer; | |
| long i; | |
| for (i = 0; i < count; i++) { | |
| if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) || | |
| put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) || | |
| put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask)) | |
| return -EFAULT; | |
| } | |
| *written = count * sizeof(*p32); | |
| return 0; | |
| } | |
| #else | #else |
| typedef struct xfs_fsop_bulkreq32 { | #define xfs_inumbers_fmt_compat xfs_inumbers_fmt |
| #define _PACKED | |
| #endif | |
| /* XFS_IOC_FSBULKSTAT and friends */ | |
| typedef struct compat_xfs_bstime { | |
| __s32 tv_sec; /* seconds */ | |
| __s32 tv_nsec; /* and nanoseconds */ | |
| } compat_xfs_bstime_t; | |
| STATIC int xfs_bstime_store_compat( | |
| compat_xfs_bstime_t __user *p32, | |
| const xfs_bstime_t *p) | |
| { | |
| __s32 sec32; | |
| sec32 = p->tv_sec; | |
| if (put_user(sec32, &p32->tv_sec) || | |
| put_user(p->tv_nsec, &p32->tv_nsec)) | |
| return -EFAULT; | |
| return 0; | |
| } | |
| typedef struct compat_xfs_bstat { | |
| __u64 bs_ino; /* inode number */ | |
| __u16 bs_mode; /* type and mode */ | |
| __u16 bs_nlink; /* number of links */ | |
| __u32 bs_uid; /* user id */ | |
| __u32 bs_gid; /* group id */ | |
| __u32 bs_rdev; /* device value */ | |
| __s32 bs_blksize; /* block size */ | |
| __s64 bs_size; /* file size */ | |
| compat_xfs_bstime_t bs_atime; /* access time */ | |
| compat_xfs_bstime_t bs_mtime; /* modify time */ | |
| compat_xfs_bstime_t bs_ctime; /* inode change time */ | |
| int64_t bs_blocks; /* number of blocks */ | |
| __u32 bs_xflags; /* extended flags */ | |
| __s32 bs_extsize; /* extent size */ | |
| __s32 bs_extents; /* number of extents */ | |
| __u32 bs_gen; /* generation count */ | |
| __u16 bs_projid; /* project id */ | |
| unsigned char bs_pad[14]; /* pad space, unused */ | |
| __u32 bs_dmevmask; /* DMIG event mask */ | |
| __u16 bs_dmstate; /* DMIG state info */ | |
| __u16 bs_aextents; /* attribute number of extents */ | |
| } _PACKED compat_xfs_bstat_t; | |
| STATIC int xfs_bulkstat_one_fmt_compat( | |
| void __user *ubuffer, | |
| const xfs_bstat_t *buffer) | |
| { | |
| compat_xfs_bstat_t __user *p32 = ubuffer; | |
| if (put_user(buffer->bs_ino, &p32->bs_ino) || | |
| put_user(buffer->bs_mode, &p32->bs_mode) || | |
| put_user(buffer->bs_nlink, &p32->bs_nlink) || | |
| put_user(buffer->bs_uid, &p32->bs_uid) || | |
| put_user(buffer->bs_gid, &p32->bs_gid) || | |
| put_user(buffer->bs_rdev, &p32->bs_rdev) || | |
| put_user(buffer->bs_blksize, &p32->bs_blksize) || | |
| put_user(buffer->bs_size, &p32->bs_size) || | |
| xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) || | |
| xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) || | |
| xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) || | |
| put_user(buffer->bs_blocks, &p32->bs_blocks) || | |
| put_user(buffer->bs_xflags, &p32->bs_xflags) || | |
| put_user(buffer->bs_extsize, &p32->bs_extsize) || | |
| put_user(buffer->bs_extents, &p32->bs_extents) || | |
| put_user(buffer->bs_gen, &p32->bs_gen) || | |
| put_user(buffer->bs_projid, &p32->bs_projid) || | |
| put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || | |
| put_user(buffer->bs_dmstate, &p32->bs_dmstate) || | |
| put_user(buffer->bs_aextents, &p32->bs_aextents)) | |
| return -EFAULT; | |
| return sizeof(*p32); | |
| } | |
| typedef struct compat_xfs_fsop_bulkreq { | |
| compat_uptr_t lastip; /* last inode # pointer */ | compat_uptr_t lastip; /* last inode # pointer */ |
| __s32 icount; /* count of entries in buffer */ | __s32 icount; /* count of entries in buffer */ |
| compat_uptr_t ubuffer; /* user buffer for inode desc. */ | compat_uptr_t ubuffer; /* user buffer for inode desc. */ |
| __s32 ocount; /* output count pointer */ | compat_uptr_t ocount; /* output count pointer */ |
| } xfs_fsop_bulkreq32_t; | } compat_xfs_fsop_bulkreq_t; |
| STATIC unsigned long | #define XFS_IOC_FSBULKSTAT_32 \ |
| xfs_ioctl32_bulkstat( | _IOWR('X', 101, struct compat_xfs_fsop_bulkreq) |
| unsigned long arg) | #define XFS_IOC_FSBULKSTAT_SINGLE_32 \ |
| _IOWR('X', 102, struct compat_xfs_fsop_bulkreq) | |
| #define XFS_IOC_FSINUMBERS_32 \ | |
| _IOWR('X', 103, struct compat_xfs_fsop_bulkreq) | |
| /* copied from xfs_ioctl.c */ | |
| STATIC int | |
| xfs_ioc_bulkstat_compat( | |
| xfs_mount_t *mp, | |
| unsigned int cmd, | |
| void __user *arg) | |
| { | { |
| xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg; | compat_xfs_fsop_bulkreq_t __user *p32 = (void __user *)arg; |
| xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p)); | |
| u32 addr; | u32 addr; |
| xfs_fsop_bulkreq_t bulkreq; | |
| int count; /* # of records returned */ | |
| xfs_ino_t inlast; /* last inode number */ | |
| int done; | |
| int error; | |
| /* done = 1 if there are more stats to get and if bulkstat */ | |
| /* should be called again (unused here, but used in dmapi) */ | |
| if (!capable(CAP_SYS_ADMIN)) | |
| return -EPERM; | |
| if (XFS_FORCED_SHUTDOWN(mp)) | |
| return -XFS_ERROR(EIO); | |
| if (get_user(addr, &p32->lastip) || | if (get_user(addr, &p32->lastip)) |
| put_user(compat_ptr(addr), &p->lastip) || | |
| copy_in_user(&p->icount, &p32->icount, sizeof(s32)) || | |
| get_user(addr, &p32->ubuffer) || | |
| put_user(compat_ptr(addr), &p->ubuffer) || | |
| get_user(addr, &p32->ocount) || | |
| put_user(compat_ptr(addr), &p->ocount)) | |
| return -EFAULT; | return -EFAULT; |
| bulkreq.lastip = compat_ptr(addr); | |
| if (get_user(bulkreq.icount, &p32->icount) || | |
| get_user(addr, &p32->ubuffer)) | |
| return -EFAULT; | |
| bulkreq.ubuffer = compat_ptr(addr); | |
| if (get_user(addr, &p32->ocount)) | |
| return -EFAULT; | |
| bulkreq.ocount = compat_ptr(addr); | |
| return (unsigned long)p; | if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64))) |
| return -XFS_ERROR(EFAULT); | |
| if ((count = bulkreq.icount) <= 0) | |
| return -XFS_ERROR(EINVAL); | |
| if (cmd == XFS_IOC_FSINUMBERS) | |
| error = xfs_inumbers(mp, &inlast, &count, | |
| bulkreq.ubuffer, xfs_inumbers_fmt_compat); | |
| else { | |
| /* declare a var to get a warning in case the type changes */ | |
| bulkstat_one_fmt_pf formatter = xfs_bulkstat_one_fmt_compat; | |
| error = xfs_bulkstat(mp, &inlast, &count, | |
| xfs_bulkstat_one, formatter, | |
| sizeof(compat_xfs_bstat_t), bulkreq.ubuffer, | |
| BULKSTAT_FG_QUICK, &done); | |
| } | |
| if (error) | |
| return -error; | |
| if (bulkreq.ocount != NULL) { | |
| if (copy_to_user(bulkreq.lastip, &inlast, | |
| sizeof(xfs_ino_t))) | |
| return -XFS_ERROR(EFAULT); | |
| if (copy_to_user(bulkreq.ocount, &count, sizeof(count))) | |
| return -XFS_ERROR(EFAULT); | |
| } | |
| return 0; | |
| } | } |
| #endif | |
| typedef struct compat_xfs_fsop_handlereq { | typedef struct compat_xfs_fsop_handlereq { |
| __u32 fd; /* fd for FD_TO_HANDLE */ | __u32 fd; /* fd for FD_TO_HANDLE */ |
| Line 261 xfs_compat_ioctl( | Line 438 xfs_compat_ioctl( |
| case XFS_IOC_SWAPEXT: | case XFS_IOC_SWAPEXT: |
| break; | break; |
| case XFS_IOC_FSBULKSTAT_SINGLE: | |
| case XFS_IOC_FSBULKSTAT: | |
| case XFS_IOC_FSINUMBERS: | |
| arg = xfs_ioctl32_bulkstat(arg); | |
| break; | |
| #endif | #endif |
| case XFS_IOC_FSBULKSTAT_32: | |
| case XFS_IOC_FSBULKSTAT_SINGLE_32: | |
| case XFS_IOC_FSINUMBERS_32: | |
| cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq); | |
| return xfs_ioc_bulkstat_compat(XFS_BHVTOI(VNHEAD(vp))->i_mount, | |
| cmd, (void*)arg); | |
| case XFS_IOC_FD_TO_HANDLE_32: | case XFS_IOC_FD_TO_HANDLE_32: |
| case XFS_IOC_PATH_TO_HANDLE_32: | case XFS_IOC_PATH_TO_HANDLE_32: |
| case XFS_IOC_PATH_TO_FSHANDLE_32: | case XFS_IOC_PATH_TO_FSHANDLE_32: |