[PATCH] fstatat64 support
The *at patches introduced fstatat and, due to inusfficient research, I used the newfstat functions generally as the guideline. The result is that on 32-bit platforms we don't have all the information needed to implement fstatat64. This patch modifies the code to pass up 64-bit information if __ARCH_WANT_STAT64 is defined. I renamed the syscall entry point to make this clear. Other archs will continue to use the existing code. On x86-64 the compat code is implemented using a new sys32_ function. this is what is done for the other stat syscalls as well. This patch might break some other archs (those which define __ARCH_WANT_STAT64 and which already wired up the syscall). Yet others might need changes to accomodate the compatibility mode. I really don't want to do that work because all this stat handling is a mess (more so in glibc, but the kernel is also affected). It should be done by the arch maintainers. I'll provide some stand-alone test shortly. Those who are eager could compile glibc and run 'make check' (no installation needed). The patch below has been tested on x86 and x86-64. Signed-off-by: Ulrich Drepper <drepper@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Andi Kleen <ak@muc.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
25bf368b3d
Коммит
cff2b76009
|
@ -299,7 +299,7 @@ ENTRY(sys_call_table)
|
|||
.long sys_mknodat
|
||||
.long sys_fchownat
|
||||
.long sys_futimesat
|
||||
.long sys_newfstatat /* 300 */
|
||||
.long sys_fstatat64 /* 300 */
|
||||
.long sys_unlinkat
|
||||
.long sys_renameat
|
||||
.long sys_linkat
|
||||
|
|
|
@ -677,7 +677,7 @@ ia32_sys_call_table:
|
|||
.quad sys_mknodat
|
||||
.quad sys_fchownat
|
||||
.quad compat_sys_futimesat
|
||||
.quad compat_sys_newfstatat /* 300 */
|
||||
.quad sys32_fstatat /* 300 */
|
||||
.quad sys_unlinkat
|
||||
.quad sys_renameat
|
||||
.quad sys_linkat
|
||||
|
|
|
@ -180,6 +180,28 @@ sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage long
|
||||
sys32_fstatat(unsigned int dfd, char __user *filename,
|
||||
struct stat64 __user* statbuf, int flag)
|
||||
{
|
||||
struct kstat stat;
|
||||
int error = -EINVAL;
|
||||
|
||||
if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
|
||||
goto out;
|
||||
|
||||
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||
error = vfs_lstat_fd(dfd, filename, &stat);
|
||||
else
|
||||
error = vfs_stat_fd(dfd, filename, &stat);
|
||||
|
||||
if (!error)
|
||||
error = cp_stat64(statbuf, &stat);
|
||||
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux/i386 didn't use to be able to handle more than
|
||||
* 4 system call parameters, so these system calls used a memory
|
||||
|
|
22
fs/stat.c
22
fs/stat.c
|
@ -261,6 +261,7 @@ asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
|
|||
return error;
|
||||
}
|
||||
|
||||
#ifndef __ARCH_WANT_STAT64
|
||||
asmlinkage long sys_newfstatat(int dfd, char __user *filename,
|
||||
struct stat __user *statbuf, int flag)
|
||||
{
|
||||
|
@ -281,6 +282,7 @@ asmlinkage long sys_newfstatat(int dfd, char __user *filename,
|
|||
out:
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
|
||||
{
|
||||
|
@ -395,6 +397,26 @@ asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user * statbuf)
|
|||
return error;
|
||||
}
|
||||
|
||||
asmlinkage long sys_fstatat64(int dfd, char __user *filename,
|
||||
struct stat64 __user *statbuf, int flag)
|
||||
{
|
||||
struct kstat stat;
|
||||
int error = -EINVAL;
|
||||
|
||||
if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
|
||||
goto out;
|
||||
|
||||
if (flag & AT_SYMLINK_NOFOLLOW)
|
||||
error = vfs_lstat_fd(dfd, filename, &stat);
|
||||
else
|
||||
error = vfs_stat_fd(dfd, filename, &stat);
|
||||
|
||||
if (!error)
|
||||
error = cp_new_stat64(&stat, statbuf);
|
||||
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
#endif /* __ARCH_WANT_STAT64 */
|
||||
|
||||
void inode_add_bytes(struct inode *inode, loff_t bytes)
|
||||
|
|
|
@ -305,7 +305,7 @@
|
|||
#define __NR_mknodat 297
|
||||
#define __NR_fchownat 298
|
||||
#define __NR_futimesat 299
|
||||
#define __NR_newfstatat 300
|
||||
#define __NR_fstatat64 300
|
||||
#define __NR_unlinkat 301
|
||||
#define __NR_renameat 302
|
||||
#define __NR_linkat 303
|
||||
|
|
|
@ -305,7 +305,7 @@
|
|||
#define __NR_ia32_mknodat 297
|
||||
#define __NR_ia32_fchownat 298
|
||||
#define __NR_ia32_futimesat 299
|
||||
#define __NR_ia32_newfstatat 300
|
||||
#define __NR_ia32_fstatat64 300
|
||||
#define __NR_ia32_unlinkat 301
|
||||
#define __NR_ia32_renameat 302
|
||||
#define __NR_ia32_linkat 303
|
||||
|
|
|
@ -557,6 +557,8 @@ asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
|
|||
int mode);
|
||||
asmlinkage long sys_newfstatat(int dfd, char __user *filename,
|
||||
struct stat __user *statbuf, int flag);
|
||||
asmlinkage long sys_fstatat64(int dfd, char __user *filename,
|
||||
struct stat64 __user *statbuf, int flag);
|
||||
asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf,
|
||||
int bufsiz);
|
||||
asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename,
|
||||
|
|
Загрузка…
Ссылка в новой задаче