Not all the world is an i386. Many architectures need 64-bit arguments to be aligned in suitable pairs of registers, and the original sys_sync_file_range(int, loff_t, loff_t, int) was therefore wasting an argument register for padding after the first integer. Since we don't normally have more than 6 arguments for system calls, that left no room for the final argument on some architectures. Fix this by introducing sys_sync_file_range2(int, int, loff_t, loff_t) which all fits nicely. In fact, ARM already had that, but called it sys_arm_sync_file_range. Move it to fs/sync.c and rename it, then implement the needed compatibility routine. And stop the missing syscall check from bitching about the absence of sys_sync_file_range() if we've implemented sys_sync_file_range2() instead. Tested on PPC32 and with 32-bit and 64-bit userspace on PPC64.
Unified · Split
| @@ -350,7 +350,7 @@ · 349 unmodified lines | ||
| 350 | 350 | CALL(sys_set_robust_list) |
| 351 | 351 | CALL(sys_get_robust_list) |
| 352 | 352 | /* 340 */ CALL(sys_splice) |
| 353 | − CALL(sys_arm_sync_file_range) | |
| 353 | + CALL(sys_sync_file_range2) | |
| 354 | 354 | CALL(sys_tee) |
| 355 | 355 | CALL(sys_vmsplice) |
| 356 | 356 | CALL(sys_move_pages) |
| @@ -328,16 +328,3 @@ asmlinkage long sys_arm_fadvise64_64(int fd, int advice, · 327 unmodified lines | ||
| 328 | 328 | { |
| 329 | 329 | return sys_fadvise64_64(fd, offset, len, advice); |
| 330 | 330 | } |
| 331 | − | |
| 332 | −/* | |
| 333 | − * Yet more syscall fsckage - we can't fit sys_sync_file_range's | |
| 334 | − * arguments into the available registers with EABI. So, let's | |
| 335 | − * create an ARM specific syscall for this which has _sane_ | |
| 336 | − * arguments. (This incidentally also has an ABI-independent | |
| 337 | − * argument layout.) | |
| 338 | − */ | |
| 339 | −asmlinkage long sys_arm_sync_file_range(int fd, unsigned int flags, | |
| 340 | − loff_t offset, loff_t nbytes) | |
| 341 | −{ | |
| 342 | − return sys_sync_file_range(fd, offset, nbytes, flags); | |
| 343 | −} | |
| @@ -810,3 +810,12 @@ asmlinkage long compat_sys_request_key(const char __user *_type, · 809 unmodified lines | ||
| 810 | 810 | return sys_request_key(_type, _description, _callout_info, destringid); |
| 811 | 811 | } |
| 812 | 812 | |
| 813 | +asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags, | |
| 814 | + unsigned offset_hi, unsigned offset_lo, | |
| 815 | + unsigned nbytes_hi, unsigned nbytes_lo) | |
| 816 | +{ | |
| 817 | + loff_t offset = ((loff_t)offset_hi << 32) | offset_lo; | |
| 818 | + loff_t nbytes = ((loff_t)nbytes_hi << 32) | nbytes_lo; | |
| 819 | + | |
| 820 | + return sys_sync_file_range(fd, offset, nbytes, flags); | |
| 821 | +} | |
| @@ -236,6 +236,14 @@ out: · 235 unmodified lines | ||
| 236 | 236 | return ret; |
| 237 | 237 | } |
| 238 | 238 | |
| 239 | +/* It would be nice if people remember that not all the world's an i386 | |
| 240 | + when they introduce new system calls */ | |
| 241 | +asmlinkage long sys_sync_file_range2(int fd, unsigned int flags, | |
| 242 | + loff_t offset, loff_t nbytes) | |
| 243 | +{ | |
| 244 | + return sys_sync_file_range(fd, offset, nbytes, flags); | |
| 245 | +} | |
| 246 | + | |
| 239 | 247 | /* |
| 240 | 248 | * `endbyte' is inclusive |
| 241 | 249 | */ |
| @@ -367,6 +367,7 @@ · 366 unmodified lines | ||
| 367 | 367 | #define __NR_get_robust_list (__NR_SYSCALL_BASE+339) |
| 368 | 368 | #define __NR_splice (__NR_SYSCALL_BASE+340) |
| 369 | 369 | #define __NR_arm_sync_file_range (__NR_SYSCALL_BASE+341) |
| 370 | +#define __NR_sync_file_range2 __NR_arm_sync_file_range | |
| 370 | 371 | #define __NR_tee (__NR_SYSCALL_BASE+342) |
| 371 | 372 | #define __NR_vmsplice (__NR_SYSCALL_BASE+343) |
| 372 | 373 | #define __NR_move_pages (__NR_SYSCALL_BASE+344) |
| @@ -311,3 +311,4 @@ COMPAT_SYS_SPU(utimensat) · 310 unmodified lines | ||
| 311 | 311 | COMPAT_SYS_SPU(signalfd) |
| 312 | 312 | COMPAT_SYS_SPU(timerfd) |
| 313 | 313 | SYSCALL_SPU(eventfd) |
| 314 | +COMPAT_SYS_SPU(sync_file_range2) | |
| @@ -330,10 +330,11 @@ · 329 unmodified lines | ||
| 330 | 330 | #define __NR_signalfd 305 |
| 331 | 331 | #define __NR_timerfd 306 |
| 332 | 332 | #define __NR_eventfd 307 |
| 333 | +#define __NR_sync_file_range2 308 | |
| 333 | 334 | |
| 334 | 335 | #ifdef __KERNEL__ |
| 335 | 336 | |
| 336 | −#define __NR_syscalls 308 | |
| 337 | +#define __NR_syscalls 309 | |
| 337 | 338 | |
| 338 | 339 | #define __NR__exit __NR_exit |
| 339 | 340 | #define NR_syscalls __NR_syscalls |
| @@ -598,6 +598,8 @@ asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags); · 597 unmodified lines | ||
| 598 | 598 | |
| 599 | 599 | asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, |
| 600 | 600 | unsigned int flags); |
| 601 | +asmlinkage long sys_sync_file_range2(int fd, unsigned int flags, | |
| 602 | + loff_t offset, loff_t nbytes); | |
| 601 | 603 | asmlinkage long sys_get_robust_list(int pid, |
| 602 | 604 | struct robust_list_head __user * __user *head_ptr, |
| 603 | 605 | size_t __user *len_ptr); |
| @@ -99,6 +99,11 @@ cat << EOF · 98 unmodified lines | ||
| 99 | 99 | #define __IGNORE_setfsuid32 |
| 100 | 100 | #define __IGNORE_setfsgid32 |
| 101 | 101 | |
| 102 | +/* sync_file_range had a stupid ABI. Allow sync_file_range2 instead */ | |
| 103 | +#ifdef __NR_sync_file_range2 | |
| 104 | +#define __IGNORE_sync_file_range | |
| 105 | +#endif | |
| 106 | + | |
| 102 | 107 | /* Unmerged syscalls for AFS, STREAMS, etc. */ |
| 103 | 108 | #define __IGNORE_afs_syscall |
| 104 | 109 | #define __IGNORE_getpmsg |