fs: Add new pre-allocation ioctls to vfs for compatibility with legacy xfs ioctls
Subsystems (3)
PATCH 1/1 fs: Add new pre-allocation ioctls to vfs for compatibility with legacy xfs ioctls
Al, Could this be included in the vfs queue?
This patch adds ioctls to vfs for compatibility with legacy XFS pre-allocation ioctls (XFS_IOC_*RESVP*). The implementation effectively invokes sys_fallocate for the new ioctls. Also handles the compat_ioctl case.
Note: These legacy ioctls are also implemented by OCFS2.
--- fs/compat_ioctl.c | 29 +++++++++++++++++++++++++++ fs/ioctl.c | 35 ++++++++++++++++++++++++++++++++ fs/open.c | 51 +++++++++++++++++++++++------------------------ include/linux/falloc.h | 44 +++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 6 +++++ 5 files changed, 139 insertions(+), 26 deletions(-)
fs/compat_ioctl.c +29 -0
@@ -2765,6 +2765,26 @@ static void compat_ioctl_error(struct fifree_page ((unsigned long )path); } +#ifdef BROKEN_X86_ALIGNMENT +/* just account for different alignment */ +static unsigned long copy_to_space_resv (unsigned long arg) +{ +struct space_resv_32 __user *p32 = (void __user *)arg; +struct space_resv __user *p =compat_alloc_user_space (sizeof (*p)); + +if (copy_in_user (&p->l_type, &p32->l_type,sizeof (s16)) || +copy_in_user (&p->l_whence, &p32->l_whence,sizeof (s16)) || +copy_in_user (&p->l_start, &p32->l_start,sizeof (s64)) || +copy_in_user (&p->l_len, &p32->l_len,sizeof (s64)) || +copy_in_user (&p->l_sysid, &p32->l_sysid,sizeof (s32)) || +copy_in_user (&p->l_pid, &p32->l_pid,sizeof (u32)) || +copy_in_user (&p->l_pad, &p32->l_pad,4 *sizeof (u32))) +return -EFAULT ; + +return (unsigned long )p; +} +#endif +asmlinkage long compat_sys_ioctl (unsigned int fd,unsigned int cmd,unsigned long arg) {
@@ -2795,6 +2815,15 @@ asmlinkage long compat_sys_ioctl(unsignecase FIOQSIZE :break ; +case F_IOC_RESVSP_32 : +case F_IOC_RESVSP64_32 : +#ifdef BROKEN_X86_ALIGNMENT + arg =copy_to_space_resv (arg); + cmd = _NATIVE_IOC(cmd, struct space_resv); +#endif + error =ioctl_preallocate (filp, arg); + goto out_fput; +case FIBMAP :case FIGETBSZ :case FIONREAD :
fs/ioctl.c +35 -0
@@ -15,6 +15,7 @@#include <linux/uaccess.h> #include <linux/writeback.h> #include <linux/buffer_head.h> +#include <linux/falloc.h> #include <asm/ioctls.h>
@@ -370,6 +371,37 @@ EXPORT_SYMBOL(generic_block_fiemap);#endif /* CONFIG_BLOCK */ +/* +* This provides compatibility with legacy XFS pre-allocation ioctls +* which predate the fallocate syscall. +* +* Only the l_start, l_len and l_whence fields of the 'struct space_resv' +* are used here, rest are ignored. +*/ +int ioctl_preallocate (struct file *filp,unsigned long arg) +{ +struct inode *inode = filp->f_path.dentry->d_inode; +struct space_resv sr; + +if (copy_from_user (&sr, (struct space_resv __user *) arg,sizeof (sr))) +return -EFAULT ; + +switch (sr.l_whence) { +case SEEK_SET : +break ; +case SEEK_CUR : + sr.l_start += filp->f_pos; +break ; +case SEEK_END : + sr.l_start +=i_size_read (inode); +break ; +default : +return -EINVAL ; + } + +return do_fallocate (filp,FALLOC_FL_KEEP_SIZE , sr.l_start, sr.l_len); +} +static int file_ioctl (struct file *filp,unsigned int cmd,unsigned long arg) {
@@ -385,6 +417,9 @@ static int file_ioctl(struct file *filp,return put_user (inode->i_sb->s_blocksize, p);case FIONREAD :return put_user (i_size_read (inode) - filp->f_pos, p); +case F_IOC_RESVSP : +case F_IOC_RESVSP64 : +return ioctl_preallocate (filp, arg); }return vfs_ioctl (filp, cmd, arg);
fs/open.c +29 -29
92 lines not on this page · raw message
include/linux/falloc.h +44 -0
48 lines not on this page · raw message
include/linux/fs.h +6 -0
@@ -1694,6 +1694,8 @@ static inline int break_lease(struct inoextern int do_truncate (struct dentry *,loff_t start,unsigned int time_attrs,struct file *filp); +extern int do_fallocate (struct file *file,int mode,loff_t offset, +loff_t len);extern long do_sys_open (int dfd,const char __user *filename,int flags,int mode);extern struct file *filp_open (const char *,int ,int );
@@ -1702,6 +1704,10 @@ extern struct file * dentry_open(structextern int filp_close (struct file *,fl_owner_t id);extern char *getname (const char __user *); +/* fs/ioctl.c */ + +extern int ioctl_preallocate (struct file *filp,unsigned long arg); +/* fs/dcache.c */ extern void __init vfs_caches_init_early (void );extern void __init vfs_caches_init (unsigned long );
Quoted 14 lines · On Thu, 29 Jan 2009 02:29:11 +0530 Ankit Jain <[email protected]> wrote:
include/linux/falloc.h +8
-0@@ -3,4 +3,48 @@#define FALLOC_FL_KEEP_SIZE 0x01/* default is extend size */ +#ifdef __KERNEL__ + +/* + * Space reservation ioctls and argument structure + * are designed to be compatible with the legacy XFS ioctls. + */ +struct space_resv { + __s16 l_type;
include/linux/falloc.h line 23
Quoted 10 lines
include/linux/falloc.h +10
-0+__s16 l_whence; +__s64 l_start; +__s64 l_len;/* len == 0 means until end of file */ +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserve area */ +}; + +#define F_IOC_RESVSP _IOW('X', 40, struct space_resv) +#define F_IOC_RESVSP64 _IOW('X', 42, struct space_resv)
Should this stuff be inside #ifdef __KERNEL__? It is shared with userspace.
Are we sure that the aligment of l_start will be reliably the same across all compilers and versions thereof for all time?
Quoted 16 lines · Andrew Morton
include/linux/falloc.h line 23
Quoted 12 lines · On Thu, 29 Jan 2009 02:29:11 +0530 Ankit Jain <[email protected]> wrote:
include/linux/falloc.h +12
-0+struct space_resv { +__s16 l_type; +__s16 l_whence; +__s64 l_start; +__s64 l_len;/* len == 0 means until end of file */ +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserve area */ +}; + +#define F_IOC_RESVSP _IOW('X', 40, struct space_resv) +#define F_IOC_RESVSP64 _IOW('X', 42, struct space_resv)Are we sure that the aligment of
l_startwill be reliably the same across all compilers and versions thereof for all time?
On x86, the alignment differs between 32 and 64 bit, otherwise it's ok. XFS handles the conversion for compat_ioctl in fs/xfs/linux-2.6/xfs_ioctl32.c. If this becomes a generic file ioctl, the conversion code should be moved to fs/compat_ioctl.c.
Arnd <><
Quoted 18 lines · On Sat, 31 Jan 2009 01:38:32 +0100 Arnd Bergmann <[email protected]> wrote:
Quoted 16 lines · Andrew Morton
include/linux/falloc.h line 23
Quoted 12 lines · On Thu, 29 Jan 2009 02:29:11 +0530 Ankit Jain <[email protected]> wrote:
include/linux/falloc.h +12
-0+struct space_resv { +__s16 l_type; +__s16 l_whence; +__s64 l_start; +__s64 l_len;/* len == 0 means until end of file */ +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserve area */ +}; + +#define F_IOC_RESVSP _IOW('X', 40, struct space_resv) +#define F_IOC_RESVSP64 _IOW('X', 42, struct space_resv)Are we sure that the aligment of
l_startwill be reliably the same across all compilers and versions thereof for all time?
Quoted 1 line
On x86, the alignment differs between 32 and 64 bit, otherwise it's ok.
Is this written in a standard somewhere? Is it guaranteed?
If some (perhaps non-gcc) compiler were to lay this out differently (perhaps with suitable command-line options) then that's liveable with - as long as the kernel never changes the layout. Of course it would be better to avoid this if poss.
The other potential issue with a structure like this is that there's a risk that it will lead us to copy four bytes of uninitialised kernel memory out to userspace.
IOW, it seems a generally bad idea to rely upon compiler-added padding for this sort of thing.
Quoted 3 lines
XFS handles the conversion for
compat_ioctlinfs/xfs/linux-2.6/xfs_ioctl32.c. If this becomes a generic file ioctl, the conversion code should be moved tofs/compat_ioctl.c.
Quoted 1 line · Andrew Morton
Is this written in a standard somewhere? Is it guaranteed?
Alignment is defined in the architecture psABI documents. Unfortunately, many of them were written before the 'long long' type became part of the C standard, so it's not strictly guaranteed. AFAICT, the alignment of __u64 on x86 is the same as the alignment of 'double' by convention.
However, the problem is well-understood: x86 is the only one that has a problem in 32/64 bit compat mode. m68k has similar issues with 16/32 bit integers, but those don't apply here.
Quoted 4 lines
If some (perhaps non-gcc) compiler were to lay this out differently (perhaps with suitable command-line options) then that's liveable with - as long as the kernel never changes the layout. Of course it would be better to avoid this if poss.
If a compiler was using irregular structure alignment, all sorts of library interfaces would break. The kernel ABI is only a small part of the problem then.
Quoted 6 lines
The other potential issue with a structure like this is that there's a risk that it will lead us to copy four bytes of uninitialised kernel memory out to userspace.
IOW, it seems a generally bad idea to rely upon compiler-added padding for this sort of thing.
Agreed in general, but the whole point of this particular patch was to provide compatibility with an interface that has been part of XFS for many years.
Linux already has a better interface for new users (sys_fallocate), so changing the patch would not be helpful and not provide any advantage.
There is also no leak of uninitialized data here, because this structure is only read, never written.
Arnd <><
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 39 lines · Arnd Bergmann
Quoted 1 line · Andrew Morton
Is this written in a standard somewhere? Is it guaranteed?
Alignment is defined in the architecture psABI documents. Unfortunately, many of them were written before the 'long long' type became part of the C standard, so it's not strictly guaranteed. AFAICT, the alignment of
__u64on x86 is the same as the alignment of 'double' by convention.However, the problem is well-understood: x86 is the only one that has a problem in 32/64 bit compat mode. m68k has similar issues with 16/32 bit integers, but those don't apply here.
Quoted 4 lines
If some (perhaps non-gcc) compiler were to lay this out differently (perhaps with suitable command-line options) then that's liveable with - as long as the kernel never changes the layout. Of course it would be better to avoid this if poss.
If a compiler was using irregular structure alignment, all sorts of library interfaces would break. The kernel ABI is only a small part of the problem then.
Quoted 6 lines
The other potential issue with a structure like this is that there's a risk that it will lead us to copy four bytes of uninitialised kernel memory out to userspace.
IOW, it seems a generally bad idea to rely upon compiler-added padding for this sort of thing.
Agreed in general, but the whole point of this particular patch was to provide compatibility with an interface that has been part of XFS for many years.
Linux already has a better interface for new users (sys_fallocate), so changing the patch would not be helpful and not provide any advantage.There is also no leak of uninitialized data here, because this structure is only read, never written.
Arnd <><
include/linux/falloc.h line 20
Quoted 9 lines · Arnd Bergmann
include/linux/falloc.h +9
-0+struct space_resv { +__s16 l_type; +__s16 l_whence; +__s64 l_start; +__s64 l_len;/* len == 0 means until end of file */ +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserve area */ +};
What about telling the compiler exactly what you said above, just to be sure we all mean the same thing. (And as documentation for new comers):
+struct space_resv_64 {
+ __s16 l_type;
+ __s16 l_whence;
+ __u32 reserved;
+ __s64 l_start;
+ __s64 l_len; /* len == 0 means until end of file */
+ __s32 l_sysid;
+ __u32 l_pid;
+ __s32 l_pad[4]; /* reserve area */
+} __packed;
And define another one for x86_32
Boaz
Quoted 55 lines · Boaz Harrosh
Quoted 39 lines · Arnd Bergmann
Quoted 1 line · Andrew Morton
Is this written in a standard somewhere? Is it guaranteed?
Alignment is defined in the architecture psABI documents. Unfortunately, many of them were written before the 'long long' type became part of the C standard, so it's not strictly guaranteed. AFAICT, the alignment of
__u64on x86 is the same as the alignment of 'double' by convention.However, the problem is well-understood: x86 is the only one that has a problem in 32/64 bit compat mode. m68k has similar issues with 16/32 bit integers, but those don't apply here.
Quoted 4 lines
If some (perhaps non-gcc) compiler were to lay this out differently (perhaps with suitable command-line options) then that's liveable with - as long as the kernel never changes the layout. Of course it would be better to avoid this if poss.
If a compiler was using irregular structure alignment, all sorts of library interfaces would break. The kernel ABI is only a small part of the problem then.
Quoted 6 lines
The other potential issue with a structure like this is that there's a risk that it will lead us to copy four bytes of uninitialised kernel memory out to userspace.
IOW, it seems a generally bad idea to rely upon compiler-added padding for this sort of thing.
Agreed in general, but the whole point of this particular patch was to provide compatibility with an interface that has been part of XFS for many years.
Linux already has a better interface for new users (sys_fallocate), so changing the patch would not be helpful and not provide any advantage.There is also no leak of uninitialized data here, because this structure is only read, never written.
Arnd <><include/linux/falloc.h line 20
Quoted 9 lines · Arnd Bergmann
include/linux/falloc.h +9
-0+struct space_resv { +__s16 l_type; +__s16 l_whence; +__s64 l_start; +__s64 l_len;/* len == 0 means until end of file */ +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserve area */ +};What about telling the compiler exactly what you said above, just to be sure we all mean the same thing. (And as documentation for new comers):
include/linux/falloc.h
Quoted 10 lines
include/linux/falloc.h +10
-0+struct space_resv_64 { +__s16 l_type; +__s16 l_whence; +__u32 reserved; +__s64 l_start; +__s64 l_len;/* len == 0 means until end of file */ +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserve area */ +} __packed;
Because the compiler will assume all fields are always unaligned and will use very suboptimal code to access them?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Quoted 66 lines · Geert Uytterhoeven
Quoted 51 lines · Boaz Harrosh
Quoted 36 lines · Arnd Bergmann
Quoted 1 line · Andrew Morton
Is this written in a standard somewhere? Is it guaranteed?
Alignment is defined in the architecture psABI documents. Unfortunately, many of them were written before the 'long long' type became part of the C standard, so it's not strictly guaranteed. AFAICT, the alignment of
__u64on x86 is the same as the alignment of 'double' by convention.However, the problem is well-understood: x86 is the only one that has a problem in 32/64 bit compat mode. m68k has similar issues with 16/32 bit integers, but those don't apply here.
Quoted 4 lines
If some (perhaps non-gcc) compiler were to lay this out differently (perhaps with suitable command-line options) then that's liveable with - as long as the kernel never changes the layout. Of course it would be better to avoid this if poss.
If a compiler was using irregular structure alignment, all sorts of library interfaces would break. The kernel ABI is only a small part of the problem then.
Quoted 6 lines
The other potential issue with a structure like this is that there's a risk that it will lead us to copy four bytes of uninitialised kernel memory out to userspace.
IOW, it seems a generally bad idea to rely upon compiler-added padding for this sort of thing.
Agreed in general, but the whole point of this particular patch was to provide compatibility with an interface that has been part of XFS for many years.
Linux already has a better interface for new users (sys_fallocate), so changing the patch would not be helpful and not provide any advantage.There is also no leak of uninitialized data here, because this structure is only read, never written.
Arnd <><Review
Quoted 9 lines · Arnd Bergmann
(quoted diff) +9
-0+struct space_resv { + __s16 l_type; + __s16 l_whence; + __s64 l_start; + __s64 l_len; /* len == 0 means until end of file */ + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserve area */ +};What about telling the compiler exactly what you said above, just to be sure we all mean the same thing. (And as documentation for new comers):
Review
Quoted 10 lines
(quoted diff) +10
-0+struct space_resv_64 { + __s16 l_type; + __s16 l_whence; + __u32 reserved; + __s64 l_start; + __s64 l_len; /* len == 0 means until end of file */ + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserve area */ +} __packed;Because the compiler will assume all fields are always unaligned and will use very suboptimal code to access them?
Quoted 4 lines
Gr{oetje,eeting}s,
Geert
This discussion comes up every once in a while. I'm using an old FC7 compiler (gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)) And tests show that when the layout of a structure is exactly the same the "__packed" on structure declarations does nothing. It only starts to affect when there are real differences in alignment. Also tests with gcc 3.4.x showed the same effect.
On previous discussions no one could come forward and say what compiler version breaks when __packed is applied on structure definition. I'm afraid your statement above is a myth.
Boaz
Quoted 36 lines · Boaz Harrosh
Quoted 15 lines · Geert Uytterhoeven
Quoted 14 lines · Boaz Harrosh
Review
Quoted 9 lines · Arnd Bergmann
(quoted diff) +9
-0+struct space_resv { + __s16 l_type; + __s16 l_whence; + __s64 l_start; + __s64 l_len; /* len == 0 means until end of file */ + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserve area */ +};What about telling the compiler exactly what you said above, just to be sure we all mean the same thing. (And as documentation for new comers):
Quoted 13 lines
Review
Quoted 10 lines
(quoted diff) +10
-0+struct space_resv_64 { + __s16 l_type; + __s16 l_whence; + __u32 reserved; + __s64 l_start; + __s64 l_len; /* len == 0 means until end of file */ + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserve area */ +} __packed;Because the compiler will assume all fields are always unaligned and will use very suboptimal code to access them?
This discussion comes up every once in a while. I'm using an old FC7 compiler (gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)) And tests show that when the layout of a structure is exactly the same the "
__packed" on structure declarations does nothing. It only starts to affect when there are real differences in alignment. Also tests with gcc 3.4.x showed the same effect.
Quoted 3 lines
On previous discussions no one could come forward and say what compiler version breaks when
__packedis applied on structure definition. I'm afraid your statement above is a myth.
FC7, targeting ia32? Sure, ia32 has no alignment restrictions. Try e.g. MIPS.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Quoted 39 lines · Geert Uytterhoeven
Quoted 34 lines · Boaz Harrosh
Quoted 15 lines · Geert Uytterhoeven
Quoted 14 lines · Boaz Harrosh
Review
Quoted 9 lines · Arnd Bergmann
(quoted diff) +9
-0+struct space_resv { + __s16 l_type; + __s16 l_whence; + __s64 l_start; + __s64 l_len; /* len == 0 means until end of file */ + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserve area */ +};What about telling the compiler exactly what you said above, just to be sure we all mean the same thing. (And as documentation for new comers):
Quoted 12 lines
Review
Quoted 10 lines
(quoted diff) +10
-0+struct space_resv_64 { + __s16 l_type; + __s16 l_whence; + __u32 reserved; + __s64 l_start; + __s64 l_len; /* len == 0 means until end of file */ + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserve area */ +} __packed;Because the compiler will assume all fields are always unaligned and will use very suboptimal code to access them?
This discussion comes up every once in a while. I'm using an old FC7 compiler (gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)) And tests show that when the layout of a structure is exactly the same the "
__packed" on structure declarations does nothing. It only starts to affect when there are real differences in alignment. Also tests with gcc 3.4.x showed the same effect.Quoted 3 lines
On previous discussions no one could come forward and say what compiler version breaks when
__packedis applied on structure definition. I'm afraid your statement above is a myth.
Quoted 7 lines
FC7, targeting ia32? Sure, ia32 has no alignment restrictions. Try e.g. MIPS.
Gr{oetje,eeting}s,
Geert
I don't understand
if you have a structure like
struct foo {
u32 one;
u32 two;
};
vs
struct foo_packed {
u32 one;
u32 two;
} __packed;Just adding an __attribute__((packed)) to it clearly does not change the layout of the structure. Are you saying the __attribute__((packed)) is an hint to the compiler that foo_packed might be used unaligned. This is just brain-dead, because I can use an unaligned pointer to foo just as I can to foo_packed. Otherwise there is no difference what-so-ever between the two. I have to see it to believe. It is totally the wrong hint in the wrong place taking away valuable meaning of saying "please don't use padding holes in this structure"
Sorry for been so slow, I just don't get it.
Boaz
Boaz Harrosh wrote:
...
Quoted 22 lines
I don't understand
if you have a structure like
struct foo { u32 one; u32 two; }; vs struct foo_packed { u32 one; u32 two; } __packed;Just adding an __attribute__((packed)) to it clearly does not change the layout of the structure. Are you saying the __attribute__((packed)) is an hint to the compiler that
foo_packedmight be used unaligned. This is just brain-dead, because I can use an unaligned pointer to foo just as I can tofoo_packed. Otherwise there is no difference what-so-ever between the two. I have to see it to believe. It is totally the wrong hint in the wrong place taking away valuable meaning of saying "please don't use padding holes in this structure"
Quoted 2 lines
Sorry for been so slow, I just don't get it.
Boaz
While I'm no gcc guru, I can confirm that gratuitous use of the packed attribute is suboptimal; adding "packed" to every ondisk structure made obdump -d xfs.ko | wc -l explode by about 15,000 lines on ia64.
-Eric
Quoted 26 lines · Eric Sandeen
Boaz Harrosh wrote:
...
Quoted 22 lines
I don't understand
if you have a structure like
struct foo { u32 one; u32 two; }; vs struct foo_packed { u32 one; u32 two; } __packed;Just adding an __attribute__((packed)) to it clearly does not change the layout of the structure. Are you saying the __attribute__((packed)) is an hint to the compiler that
foo_packedmight be used unaligned. This is just brain-dead, because I can use an unaligned pointer to foo just as I can tofoo_packed. Otherwise there is no difference what-so-ever between the two. I have to see it to believe. It is totally the wrong hint in the wrong place taking away valuable meaning of saying "please don't use padding holes in this structure"
Quoted 6 lines
Quoted 2 lines
Sorry for been so slow, I just don't get it.
BoazWhile I'm no gcc guru, I can confirm that gratuitous use of the packed attribute is suboptimal; adding "packed" to every ondisk structure made obdump -d xfs.ko | wc -l explode by about 15,000 lines on ia64.
Yes! but are the structures the same? that is sizeof(foo_packed) == sizeof(foo) ? If not then clearly above is expected.
In anyway, if __attribute__((packed)) makes some brain-dead gcc do the wrong thing putting a _Padding member where you expect an alignment hole, and a BUILD_BUG_ON(sizeof() != ()) statement somewhere in code is a must, specifically for the brain-dead.
Quoted 2 lines
-Eric
There are to many places in Kernel where these things are left to chance that give me an headache, not talking about cross platform mounts.
Boaz
Quoted 27 lines · Boaz Harrosh
Quoted 26 lines · Eric Sandeen
Boaz Harrosh wrote:
...
Quoted 22 lines
I don't understand
if you have a structure like
struct foo { u32 one; u32 two; }; vs struct foo_packed { u32 one; u32 two; } __packed;Just adding an __attribute__((packed)) to it clearly does not change the layout of the structure. Are you saying the __attribute__((packed)) is an hint to the compiler that
foo_packedmight be used unaligned. This is just brain-dead, because I can use an unaligned pointer to foo just as I can tofoo_packed. Otherwise there is no difference what-so-ever between the two. I have to see it to believe. It is totally the wrong hint in the wrong place taking away valuable meaning of saying "please don't use padding holes in this structure"
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
Sorry for been so slow, I just don't get it.
BoazWhile I'm no gcc guru, I can confirm that gratuitous use of the packed attribute is suboptimal; adding "packed" to every ondisk structure made obdump -d xfs.ko | wc -l explode by about 15,000 lines on ia64.
Yes! but are the structures the same? that is
sizeof(foo_packed)== sizeof(foo) ? If not then clearly above is expected.
Yes, they are the same. They're disk structure definitions after all; ia64 doesn't *need* the packing, but adding the packed attribute changes the code that gcc generates.
See also, perhaps,
http://digitalvampire.org/blog/index.php/2006/07/31/why-you-shouldnt-use-__attribute__packed/
For an interface like this maybe it's fine, but sprnkling it around like pixie dust may not be a good plan. :)
-Eric
The structures have been defined exactly like that in XFS (and ocfs2) before, and there are similar cases in other ioctls handlers.
If anyone feels like changing this in some way feel free to wade through the endless discussions about the pros and cons for it, but I think doing it in context of this patch is not helpful.
Quoted 6 lines · Christoph Hellwig
The structures have been defined exactly like that in XFS (and ocfs2) before, and there are similar cases in other ioctls handlers.
If anyone feels like changing this in some way feel free to wade through the endless discussions about the pros and cons for it, but I think doing it in context of this patch is not helpful.
OK so ia64 gcc is broken in regard to __attribute__((packed(1))), and it should not be used.
But clearly the programmer, Like in this patch exactly, should spell out the hole created by padding and spell that hole out and call it __Padding. The porgrammer thought about it, identified there is an hole, please don't drop this information on the floor. Put it in the code so I don't have to break my head on it.
Quoted 15 lines
Quoted 9 lines · Arnd Bergmann
Review
Quoted 9 lines
(quoted diff) +9
-0+struct space_resv { + __s16 l_type; + __s16 l_whence; + __s64 l_start; + __s64 l_len; /* len == 0 means until end of file */ + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserve area */ +};What about telling the compiler exactly what you said above, just to be sure we all mean the same thing. (And as documentation for new comers):
Review
Quoted 4 lines
(quoted diff) +4
-0+struct space_resv_64 { + __s16 l_type; + __s16 l_whence; + __u32 reserved;
change that to
__u32 __padding_hole;
Review
Quoted 6 lines
(quoted diff) +6
-0+ __s64 l_start; + __s64 l_len; /* len == 0 means until end of file */ + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserve area */ +} __packed;
Drop the evil __packed but show me the padding
Thanks
Boaz
Quoted 10 lines · Boaz Harrosh
Quoted 6 lines · Christoph Hellwig
The structures have been defined exactly like that in XFS (and ocfs2) before, and there are similar cases in other ioctls handlers.
If anyone feels like changing this in some way feel free to wade through the endless discussions about the pros and cons for it, but I think doing it in context of this patch is not helpful.
OK so ia64 gcc is broken in regard to __attribute__((packed(1))), and it should not be used.
No, the compiler is correct, it has to generate more complex code if it cannot assume that data is naturally aligned and the architecture does not support unaligned loads. If you don't understand this, please at least read the list archives about the last five times this came up before claiming that the compiler is broken.
Quoted 5 lines
But clearly the programmer, Like in this patch exactly, should spell out the hole created by padding and spell that hole out and call it
__Padding. The porgrammer thought about it, identified there is an hole, please don't drop this information on the floor. Put it in the code so I don't have to break my head on it.
Again, you are missing the point. The patch has to leave out the padding and whatnot because the idea of the patch is to provide a backwards-compatible API for programs written against the legacy XFS API. The original definition of the interface was flawed, but unless you can travel back in time to complain about this in the initial submission of the XFS file system, you should not blame the entirely correct patch now.
Arnd <><
Quoted 8 lines · Arnd Bergmann
Quoted 7 lines · Boaz Harrosh
Quoted 6 lines · Christoph Hellwig
The structures have been defined exactly like that in XFS (and ocfs2) before, and there are similar cases in other ioctls handlers.
If anyone feels like changing this in some way feel free to wade through the endless discussions about the pros and cons for it, but I think doing it in context of this patch is not helpful.
Quoted 9 lines
Quoted 2 lines
OK so ia64 gcc is broken in regard to __attribute__((packed(1))), and it should not be used.
No, the compiler is correct, it has to generate more complex code if it cannot assume that data is naturally aligned and the architecture does not support unaligned loads. If you don't understand this, please at least read the list archives about the last five times this came up before claiming that the compiler is broken.
Wrong!! Sorry, you guys don't listen.
I'm talking of the case where the structures are EXACTLY the same anyway you look at them. sizeof(foo) == sizeof(foo_packed) and offsetof(foo_memmber) == offsetof(foo_packed_member) for every member of the structure. foo && foo_packed are declared exactly the same but with __attribute__((packed(1))) applied to the later.
THEN in ia64 case the compiler is brain dead, because it relates "unalignment" to packed(1) which are two different things.
Quoted 6 lines
Quoted 5 lines
But clearly the programmer, Like in this patch exactly, should spell out the hole created by padding and spell that hole out and call it
__Padding. The porgrammer thought about it, identified there is an hole, please don't drop this information on the floor. Put it in the code so I don't have to break my head on it.
Quoted 7 lines
Again, you are missing the point. The patch has to leave out the padding and whatnot because the idea of the patch is to provide a backwards-compatible API for programs written against the legacy XFS API. The original definition of the interface was flawed, but unless you can travel back in time to complain about this in the initial submission of the XFS file system, you should not blame the entirely correct patch now.
Lets make a small test is: sizeof(orig_struct) == sizeof(my_struct)? offsetof(orig_any_memmber) == offsetof(my_any_memmber)?
Yes because the padding is there if you shove it under the rug or expose it.
What I'm saying is don't repeat the passed mistakes, spell out the exact structure layout. So it will compile the same for any <= 64bit machine. If the way a structure was defined in the passed, produced two or more memory representations, spell these out with different structure definitions and choose the one you need at compile time.
Otherwise you have fixed nothing. You are just repeating the same passed mistake. And down the future some programmer will wish he add a time machine to go back and fix what we've done today. But bingo, he did and told me about it, and now it is time to fix that.
Quoted 1 line
Arnd <><
Don't let the compiler have the driver's sit. You do the driving, because he does not know where you want to go.
Boaz
Quoted 26 lines · Boaz Harrosh
Quoted 8 lines · Arnd Bergmann
Quoted 7 lines · Boaz Harrosh
Quoted 6 lines · Christoph Hellwig
The structures have been defined exactly like that in XFS (and ocfs2) before, and there are similar cases in other ioctls handlers.
If anyone feels like changing this in some way feel free to wade through the endless discussions about the pros and cons for it, but I think doing it in context of this patch is not helpful.
Quoted 9 lines
Quoted 2 lines
OK so ia64 gcc is broken in regard to __attribute__((packed(1))), and it should not be used.
No, the compiler is correct, it has to generate more complex code if it cannot assume that data is naturally aligned and the architecture does not support unaligned loads. If you don't understand this, please at least read the list archives about the last five times this came up before claiming that the compiler is broken.
Wrong!! Sorry, you guys don't listen.
I'm talking of the case where the structures are EXACTLY the same anyway you look at them. sizeof(foo) ==sizeof(foo_packed)andoffsetof(foo_memmber)==offsetof(foo_packed_member)for every member of the structure. foo &&foo_packedare declared exactly the same but with __attribute__((packed(1))) applied to the later.
Quoted 2 lines
THEN in ia64 case the compiler is brain dead, because it relates "unalignment" to packed(1) which are two different things.
The natural alignment of a structure is max(alignment(member)), for all members. With __attribute__((packed)), the natural alignment of the structure is 1, so the compiler cannot assume anything.
While the ints in the structure may still be at offsets 0, 4, 8, and so on, this doesn't say anything about their actual memory addresses, as the struct base address itself may be unaligned.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Quoted 15 lines · Geert Uytterhoeven
Quoted 14 lines · Boaz Harrosh
Quoted 6 lines · Arnd Bergmann
No, the compiler is correct, it has to generate more complex code if it cannot assume that data is naturally aligned and the architecture does not support unaligned loads. If you don't understand this, please at least read the list archives about the last five times this came up before claiming that the compiler is broken.
Wrong!! Sorry, you guys don't listen.
I'm talking of the case where the structures are EXACTLY the same anyway you look at them. sizeof(foo) ==sizeof(foo_packed)andoffsetof(foo_memmber)==offsetof(foo_packed_member)for every member of the structure. foo &&foo_packedare declared exactly the same but with __attribute__((packed(1))) applied to the later.
Quoted 7 lines
Quoted 2 lines
THEN in ia64 case the compiler is brain dead, because it relates "unalignment" to packed(1) which are two different things.
The natural alignment of a structure is max(alignment(member)), for all members. With __attribute__((packed)), the natural alignment of the structure is 1, so the compiler cannot assume anything.
No the natural alignment is what it is, after the application of __attribute__((packed(1))). In a well defined structure that is a no-opt. But yes in ai64 the gcc programmers got lazy and did not make that analysis after laying out the structure.
Quoted 4 lines
While the ints in the structure may still be at offsets 0, 4, 8, and so on, this doesn't say anything about their actual memory addresses, as the struct base address itself may be unaligned.
The base address can be unaligned even if the structure is aligned. In that case you need the __atrubute__((aligned)) thingy. It is true that if the sizeof(foo_packed) is though unaligned, the compiler will have to assume unalignment in array operations. but if the sizeof(foo_packed) is naturally aligned at the output then the compiler has all the needed information to know that even if I declared __packed, it calculated and knows that it is well aligned at the end.
Quoted 4 lines
Gr{oetje,eeting}s,
Geert
Please note that I gave up on the compiler and understand that the use of __packed is dangerous in some cases, sigh. My standing point is to make sure there are no guesses left, and a BUILD_BUG_ON to make sure of that.
Boaz
Quoted 4 lines · Boaz Harrosh
No the natural alignment is what it is, after the application of __attribute__((packed(1))). In a well defined structure that is a no-opt. But yes in ai64 the gcc programmers got lazy and did not make that analysis after laying out the structure.
No. That's what you *want* packed to mean, but it doesn't mean that.
__attribute__ packed on a struct definition means to pack the structure _and_ set its assumed alignment to 1.
This is what the packed attribute historically means, and it cannot be changed without breaking existing code.
If you want to remove padding from a structure, but still keep its natural alignment, you do it with two attributes together:__attribute__((packed, aligned(4))). You have to choose the alignment you want in that case.
GCC manual:
When used on a struct, or struct member, the aligned' attribute can only increase the alignment; in order to decrease it, the packed' attribute must be specified as well. When used as part of a typedef, the aligned' attribute can both increase and decrease alignment, and specifying the packed' attribute will generate a warning.
It's a counterintuitive, because you must use __attribute__((aligned(1))) when declaring a variable to reduce its alignment, but you must use __attribute__((packed)) when declaring a struct type. Doing it at the end of a struct typedef is a weird mix of semantics, so don't do that.
By the way, this discussion is why the "-Wpacked" and "-Wpadding" options are available.
Quoted 2 lines
The base address can be unaligned even if the structure is aligned. In that case you need the __atrubute__((aligned)) thingy.
No, because __attribute__((packed)) on a struct doesn't mean what you want it to mean. Use __attribute((packed,aligned(4))) if that's what you want.
Quoted 4 lines
Please note that I gave up on the compiler and understand that the use of
__packedis dangerous in some cases, sigh. My standing point is to make sure there are no guesses left, and aBUILD_BUG_ONto make sure of that.
In this code, it's not a bug because it must be backward compatible with existing binary code. "Fixing" the padding breaks compatibility, which is pointless for this patch.
-- Jamie
Quoted 36 lines · Jamie Lokier
Quoted 4 lines · Boaz Harrosh
No the natural alignment is what it is, after the application of __attribute__((packed(1))). In a well defined structure that is a no-opt. But yes in ai64 the gcc programmers got lazy and did not make that analysis after laying out the structure.
No. That's what you *want* packed to mean, but it doesn't mean that.
__attribute__packed on a struct definition means to pack the structure _and_ set its assumed alignment to 1.This is what the packed attribute historically means, and it cannot be changed without breaking existing code.
If you want to remove padding from a structure, but still keep its natural alignment, you do it with two attributes together:
__attribute__((packed, aligned(4))). You have to choose the alignment you want in that case.GCC manual:
When used on a struct, or struct member, thealigned' attribute can only increase the alignment; in order to decrease it, thepacked' attribute must be specified as well. When used as part of a typedef, thealigned' attribute can both increase and decrease alignment, and specifying thepacked' attribute will generate a warning.It's a counterintuitive, because you must use __attribute__((aligned(1))) when declaring a variable to reduce its alignment, but you must use __attribute__((packed)) when declaring a struct type. Doing it at the end of a struct typedef is a weird mix of semantics, so don't do that.
By the way, this discussion is why the "-Wpacked" and "-Wpadding" options are available.
Quoted 7 lines
Quoted 2 lines
The base address can be unaligned even if the structure is aligned. In that case you need the __atrubute__((aligned)) thingy.
No, because __attribute__((packed)) on a struct doesn't mean what you want it to mean. Use __attribute((packed,aligned(4))) if that's what you want.
OK Thanks I'll use that then.
(And BUILD_BUG_ON to make sure)
Quoted 9 lines
Quoted 4 lines
Please note that I gave up on the compiler and understand that the use of
__packedis dangerous in some cases, sigh. My standing point is to make sure there are no guesses left, and aBUILD_BUG_ONto make sure of that.In this code, it's not a bug because it must be backward compatible with existing binary code. "Fixing" the padding breaks compatibility, which is pointless for this patch.
That's what I don't like. In compatibility problems situation, we actually have two kind of structures. I rather that they are spelled out explicitly and chosen from at the appropriate places. But I'll give up it is probably just me. (Though proof that it was not me who raised the subject)
I would at least expect a big fat comment explaining what happened to the structure on what known ARCHs, and how it is expected to look in memory. And a BUILD_BUG_ON to make sure of that.
Quoted 1 line
-- Jamie
Thanks, the __attribute((packed,aligned(__WORD_SIZE))) is new for me
Boaz
Quoted 3 lines · Boaz Harrosh
I would at least expect a big fat comment explaining what happened to the structure on what known ARCHs, and how it is expected to look in memory. And a
BUILD_BUG_ONto make sure of that.
You may have a point.
Struct layout on some architectures changes between compiler default ABIs in these implicit-padding cases. Kernel binary compatibility will be affected. It is a good reason why we have explicit padding to natural alignment normally.
Quoted 1 line
"With the new ABI, default structure packing changes, as do some default data sizes and alignment (which also have a knock-on effect on structure packing). In particular the minimum size and alignment of a structure was 4 bytes. Under the EABI there is no minimum and the alignment is determined by the types of the components it contains. This will break programs that know too much about the way structures are packed and can break code that writes binary files by dumping and reading structures."
"One of the key differences between the traditional GNU/Linux ABI and the EABI is that 64-bit types (like long long) are aligned differently. In the traditional ABI, these types had 4-byte alignment; in the EABI they have 8-byte alignment. As a result, if you use the same structure definitions (in a header file) and include it in code used in both the kernel and in application code, you may find that the structure size and alignment differ."
-- Jamie
Quoted 7 lines · Ankit Jain
Al, Could this be included in the vfs queue?
This patch adds ioctls to vfs for compatibility with legacy XFS pre-allocation ioctls (XFS_IOC_*RESVP*). The implementation effectively invokes
sys_fallocatefor the new ioctls. Also handles thecompat_ioctlcase.
Note: These legacy ioctls are also implemented by OCFS2.
Still not in, but I remember Al pinged me because it broke on 64bit architectures due issues in the compat_ioctl support.
Below is a version with that fixed and the ioctl renamed to FS_IOC_* instead of F_IOC_* to match other generic filesystem ioctls.
--
Subject: fs: Add new pre-allocation ioctls to vfs for compatibility with legacy xfs ioctls
From: Ankit Jain <[email protected]>
This patch adds ioctls to vfs for compatibility with legacy XFS pre-allocation ioctls (XFS_IOC_*RESVP*). The implementation effectively invokes sys_fallocate for the new ioctls. Also handles the compat_ioctl case.
Note: These legacy ioctls are also implemented by OCFS2.
fs/compat_ioctl.c +48 -0
@@ -31,6 +31,7 @@#include <linux/skbuff.h> #include <linux/netlink.h> #include <linux/vt.h> +#include <linux/falloc.h> #include <linux/fs.h> #include <linux/file.h> #include <linux/ppp_defs.h>
@@ -1820,6 +1821,41 @@ lp_timeout_trans(unsigned int fd, unsignreturn sys_ioctl (fd, cmd, (unsigned long )tn); } +/* on ia32 l_start is on a 32-bit boundary */ +#if defined(CONFIG_IA64 ) || defined(CONFIG_X86_64 ) +struct space_resv_32 { +__s16 l_type; +__s16 l_whence; +__s64 l_start __attribute__((packed)); +/* len == 0 means until end of file */ +__s64 l_len __attribute__((packed)); +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserve area */ +}; + +#define FS_IOC_RESVSP_32 _IOW ('X', 40, struct space_resv_32) +#define FS_IOC_RESVSP64_32 _IOW ('X', 42, struct space_resv_32) + +/* just account for different alignment */ +static int compat_ioctl_preallocate (struct file *file,unsigned long arg) +{ +struct space_resv_32 __user *p32 = (void __user *)arg; +struct space_resv __user *p =compat_alloc_user_space (sizeof (*p)); + +if (copy_in_user (&p->l_type, &p32->l_type,sizeof (s16)) || +copy_in_user (&p->l_whence, &p32->l_whence,sizeof (s16)) || +copy_in_user (&p->l_start, &p32->l_start,sizeof (s64)) || +copy_in_user (&p->l_len, &p32->l_len,sizeof (s64)) || +copy_in_user (&p->l_sysid, &p32->l_sysid,sizeof (s32)) || +copy_in_user (&p->l_pid, &p32->l_pid,sizeof (u32)) || +copy_in_user (&p->l_pad, &p32->l_pad,4 *sizeof (u32))) +return -EFAULT ; + +return ioctl_preallocate (file, p); +} +#endif +typedef int (*ioctl_trans_handler_t )(unsigned int ,unsigned int ,unsigned long ,struct file *);
@@ -2808,6 +2844,18 @@ asmlinkage long compat_sys_ioctl(unsignecase FIOQSIZE :break ; +#if defined(CONFIG_IA64 ) || defined(CONFIG_X86_64 ) +case FS_IOC_RESVSP_32 : +case FS_IOC_RESVSP64_32 : + error =compat_ioctl_preallocate (filp, arg); + goto out_fput; +#else +case FS_IOC_RESVSP : +case FS_IOC_RESVSP64 : + error =ioctl_preallocate (filp, (void __user *)arg); + goto out_fput; +#endif +case FIBMAP :case FIGETBSZ :case FIONREAD :
fs/ioctl.c +35 -0
@@ -15,6 +15,7 @@#include <linux/uaccess.h> #include <linux/writeback.h> #include <linux/buffer_head.h> +#include <linux/falloc.h> #include <asm/ioctls.h>
@@ -403,6 +404,37 @@ EXPORT_SYMBOL(generic_block_fiemap);#endif /* CONFIG_BLOCK */ +/* +* This provides compatibility with legacy XFS pre-allocation ioctls +* which predate the fallocate syscall. +* +* Only the l_start, l_len and l_whence fields of the 'struct space_resv' +* are used here, rest are ignored. +*/ +int ioctl_preallocate (struct file *filp,void __user *argp) +{ +struct inode *inode = filp->f_path.dentry->d_inode; +struct space_resv sr; + +if (copy_from_user (&sr, argp,sizeof (sr))) +return -EFAULT ; + +switch (sr.l_whence) { +case SEEK_SET : +break ; +case SEEK_CUR : + sr.l_start += filp->f_pos; +break ; +case SEEK_END : + sr.l_start +=i_size_read (inode); +break ; +default : +return -EINVAL ; + } + +return do_fallocate (filp,FALLOC_FL_KEEP_SIZE , sr.l_start, sr.l_len); +} +static int file_ioctl (struct file *filp,unsigned int cmd,unsigned long arg) {
@@ -414,6 +446,9 @@ static int file_ioctl(struct file *filp,return ioctl_fibmap (filp, p);case FIONREAD :return put_user (i_size_read (inode) - filp->f_pos, p); +case FS_IOC_RESVSP : +case FS_IOC_RESVSP64 : +return ioctl_preallocate (filp, p); }return vfs_ioctl (filp, cmd, arg);
fs/open.c +29 -29
92 lines not on this page · raw message
include/linux/falloc.h +21 -0
@@ -3,4 +3,25 @@#define FALLOC_FL_KEEP_SIZE 0x01/* default is extend size */ +#ifdef __KERNEL__ + +/* +* Space reservation ioctls and argument structure +* are designed to be compatible with the legacy XFS ioctls. +*/ +struct space_resv { +__s16 l_type; +__s16 l_whence; +__s64 l_start; +__s64 l_len;/* len == 0 means until end of file */ +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserved area */ +}; + +#define FS_IOC_RESVSP _IOW('X', 40, struct space_resv) +#define FS_IOC_RESVSP64 _IOW('X', 42, struct space_resv) + +#endif /* __KERNEL__ */ +#endif /* _FALLOC_H_ */
include/linux/fs.h +6 -0
@@ -1905,6 +1905,8 @@ static inline int break_lease(struct inoextern int do_truncate (struct dentry *,loff_t start,unsigned int time_attrs,struct file *filp); +extern int do_fallocate (struct file *file,int mode,loff_t offset, +loff_t len);extern long do_sys_open (int dfd,const char __user *filename,int flags,int mode);extern struct file *filp_open (const char *,int ,int );
@@ -1913,6 +1915,10 @@ extern struct file * dentry_open(structextern int filp_close (struct file *,fl_owner_t id);extern char *getname (const char __user *); +/* fs/ioctl.c */ + +extern int ioctl_preallocate (struct file *filp,void __user *argp); +/* fs/dcache.c */ extern void __init vfs_caches_init_early (void );extern void __init vfs_caches_init (unsigned long );
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 5 lines · Christoph Hellwig
fs/compat_ioctl.c +5
-0+/* on ia32 l_start is on a 32-bit boundary */ +#if defined(CONFIG_IA64) || defined(CONFIG_X86_64) +struct space_resv_32 { + __s16 l_type; + __s16 l_whence;
fs/compat_ioctl.c lp_timeout_trans(unsigned int fd, unsign · line 1838
Quoted 10 lines
fs/compat_ioctl.c +10
-0+ __s64 l_start __attribute__((packed)); +/* len == 0 means until end of file */ + __s64 l_len __attribute__((packed)); +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserve area */ +}; + +#define FS_IOC_RESVSP_32 _IOW ('X', 40, struct space_resv_32) +#define FS_IOC_RESVSP64_32 _IOW ('X', 42, struct space_resv_32)
I'd just define this using compat_s64 instead of __s64 __packed so we can use the same code on all architectures, even at the small cost of extra text size on non-x86 architectures.
Quoted 9 lines
fs/compat_ioctl.c +9
-0+/* just account for different alignment */ +static int compat_ioctl_preallocate (struct file *file,unsigned long arg) +{ +struct space_resv_32 __user *p32 = (void __user *)arg; +struct space_resv __user *p =compat_alloc_user_space (sizeof (*p)); + + if (copy_in_user(&p->l_type, &p32->l_type, sizeof(s16)) || + copy_in_user(&p->l_whence, &p32->l_whence, sizeof(s16)) || + copy_in_user(&p->l_start, &p32->l_start, sizeof(s64)) ||
fs/compat_ioctl.c lp_timeout_trans(unsigned int fd, unsign · line 1858
Quoted 10 lines
fs/compat_ioctl.c +10
-0+copy_in_user (&p->l_len, &p32->l_len,sizeof (s64)) || +copy_in_user (&p->l_sysid, &p32->l_sysid,sizeof (s32)) || +copy_in_user (&p->l_pid, &p32->l_pid,sizeof (u32)) || + copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32))) + return -EFAULT; + + return ioctl_preallocate(file, p); +} +#endif +
Here, you can call do_fallocate directly in the same way that ioctl_preallocate does, replacing the copy_in_user calls with __get_user().
Arnd <><
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 3 lines · Arnd Bergmann
I'd just define this using
compat_s64instead of__s64__packedso we can use the same code on all architectures, even at the small cost of extra text size on non-x86 architectures.
I'm not a big fan of imposing the translation overhead to all architectures, but doing it allows using the good old HANDLE_IOCTL and futher simplifying things.
fs/compat_ioctl.c +35 -0
@@ -31,6 +31,7 @@#include <linux/skbuff.h> #include <linux/netlink.h> #include <linux/vt.h> +#include <linux/falloc.h> #include <linux/fs.h> #include <linux/file.h> #include <linux/ppp_defs.h>
@@ -1820,6 +1821,38 @@ lp_timeout_trans(unsigned int fd, unsignreturn sys_ioctl (fd, cmd, (unsigned long )tn); } +/* on ia32 l_start is on a 32-bit boundary */ +struct space_resv_32 { +__s16 l_type; +__s16 l_whence; +compat_s64 l_start; +compat_s64 l_len;/* len == 0 means until end of file */ +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserve area */ +}; + +#define FS_IOC_RESVSP_32 _IOW ('X', 40, struct space_resv_32) +#define FS_IOC_RESVSP64_32 _IOW ('X', 42, struct space_resv_32) + +/* just account for different alignment */ +static int compat_ioctl_resvsp (unsigned fd,unsigned cmd,unsigned long arg) +{ +struct space_resv_32 __user *p32 = (void __user *)arg; +struct space_resv __user *p =compat_alloc_user_space (sizeof (*p)); + +if (copy_in_user (&p->l_type, &p32->l_type,sizeof (s16)) || +copy_in_user (&p->l_whence, &p32->l_whence,sizeof (s16)) || +copy_in_user (&p->l_start, &p32->l_start,sizeof (s64)) || +copy_in_user (&p->l_len, &p32->l_len,sizeof (s64)) || +copy_in_user (&p->l_sysid, &p32->l_sysid,sizeof (s32)) || +copy_in_user (&p->l_pid, &p32->l_pid,sizeof (u32)) || +copy_in_user (&p->l_pad, &p32->l_pad,4 *sizeof (u32))) +return -EFAULT ; + +return sys_ioctl (fd,FS_IOC_RESVSP , p); +} +typedef int (*ioctl_trans_handler_t )(unsigned int ,unsigned int ,unsigned long ,struct file *);
@@ -1915,6 +1948,8 @@ COMPATIBLE_IOCTL(FIGETBSZ)/* 'X' - originally XFS but some now in the VFS */ COMPATIBLE_IOCTL(FIFREEZE) COMPATIBLE_IOCTL(FITHAW) +HANDLE_IOCTL(FS_IOC_RESVSP_32, compat_ioctl_resvsp) +HANDLE_IOCTL(FS_IOC_RESVSP64_32, compat_ioctl_resvsp) /* RAID */ COMPATIBLE_IOCTL(RAID_VERSION) COMPATIBLE_IOCTL(GET_ARRAY_INFO)
fs/ioctl.c +35 -0
@@ -15,6 +15,7 @@#include <linux/uaccess.h> #include <linux/writeback.h> #include <linux/buffer_head.h> +#include <linux/falloc.h> #include <asm/ioctls.h>
@@ -403,6 +404,37 @@ EXPORT_SYMBOL(generic_block_fiemap);#endif /* CONFIG_BLOCK */ +/* +* This provides compatibility with legacy XFS pre-allocation ioctls +* which predate the fallocate syscall. +* +* Only the l_start, l_len and l_whence fields of the 'struct space_resv' +* are used here, rest are ignored. +*/ +static int ioctl_resvsp (struct file *filp,void __user *argp) +{ +struct inode *inode = filp->f_path.dentry->d_inode; +struct space_resv sr; + +if (copy_from_user (&sr, argp,sizeof (sr))) +return -EFAULT ; + +switch (sr.l_whence) { +case SEEK_SET : +break ; +case SEEK_CUR : + sr.l_start += filp->f_pos; +break ; +case SEEK_END : + sr.l_start +=i_size_read (inode); +break ; +default : +return -EINVAL ; + } + +return do_fallocate (filp,FALLOC_FL_KEEP_SIZE , sr.l_start, sr.l_len); +} +static int file_ioctl (struct file *filp,unsigned int cmd,unsigned long arg) {
@@ -414,6 +446,9 @@ static int file_ioctl(struct file *filp,return ioctl_fibmap (filp, p);case FIONREAD :return put_user (i_size_read (inode) - filp->f_pos, p); +case FS_IOC_RESVSP : +case FS_IOC_RESVSP64 : +return ioctl_resvsp (filp, p); }return vfs_ioctl (filp, cmd, arg);
fs/open.c +29 -29
92 lines not on this page · raw message
include/linux/falloc.h +21 -0
@@ -3,4 +3,25 @@#define FALLOC_FL_KEEP_SIZE 0x01/* default is extend size */ +#ifdef __KERNEL__ + +/* +* Space reservation ioctls and argument structure +* are designed to be compatible with the legacy XFS ioctls. +*/ +struct space_resv { +__s16 l_type; +__s16 l_whence; +__s64 l_start; +__s64 l_len;/* len == 0 means until end of file */ +__s32 l_sysid; +__u32 l_pid; +__s32 l_pad[4 ];/* reserved area */ +}; + +#define FS_IOC_RESVSP _IOW('X', 40, struct space_resv) +#define FS_IOC_RESVSP64 _IOW('X', 42, struct space_resv) + +#endif /* __KERNEL__ */ +#endif /* _FALLOC_H_ */
include/linux/fs.h +2 -0
@@ -1905,6 +1905,8 @@ static inline int break_lease(struct inoextern int do_truncate (struct dentry *,loff_t start,unsigned int time_attrs,struct file *filp); +extern int do_fallocate (struct file *file,int mode,loff_t offset, +loff_t len);extern long do_sys_open (int dfd,const char __user *filename,int flags,int mode);extern struct file *filp_open (const char *,int ,int );