From 110cc1cc6195d1f81ae9d063e061403c6854917e Mon Sep 17 00:00:00 2001 From: jdolecek Date: Mon, 20 Sep 2004 18:41:07 +0000 Subject: [PATCH] implement support for Linux statfs64() syscall - 64bit variant of statfs() --- sys/compat/linux/arch/arm/syscalls.master | 8 +- sys/compat/linux/arch/i386/syscalls.master | 8 +- sys/compat/linux/arch/mips/syscalls.master | 8 +- sys/compat/linux/arch/powerpc/syscalls.master | 8 +- sys/compat/linux/common/linux_misc.c | 22 ++- sys/compat/linux/common/linux_misc.h | 9 +- sys/compat/linux/common/linux_misc_notalpha.c | 139 +++++++++++++++++- sys/compat/linux/common/linux_types.h | 16 +- 8 files changed, 190 insertions(+), 28 deletions(-) diff --git a/sys/compat/linux/arch/arm/syscalls.master b/sys/compat/linux/arch/arm/syscalls.master index 668c77c75a8f..a71568c9de45 100644 --- a/sys/compat/linux/arch/arm/syscalls.master +++ b/sys/compat/linux/arch/arm/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.18 2004/09/08 19:45:22 jdolecek Exp $ + $NetBSD: syscalls.master,v 1.19 2004/09/20 18:41:07 jdolecek Exp $ ; Derived from sys/compat/linux/arch/*/syscalls.master ; and from Linux 2.4.12 arch/arm/kernel/calls.S @@ -420,8 +420,10 @@ 263 UNIMPL clock_gettime 264 UNIMPL clock_getres 265 UNIMPL clock_nanosleep -266 UNIMPL statfs64 -267 UNIMPL fstatfs64 +266 STD { int linux_sys_statfs64(const char *path, \ + size_t sz, struct linux_statfs64 *sp); } +267 STD { int linux_sys_fstatfs64(int fd, \ + size_t sz, struct linux_statfs64 *sp); } 268 UNIMPL tgkill 269 UNIMPL utimes 270 UNIMPL fadvise64_64 diff --git a/sys/compat/linux/arch/i386/syscalls.master b/sys/compat/linux/arch/i386/syscalls.master index 39cb2f60583b..41d3cb35e66d 100644 --- a/sys/compat/linux/arch/i386/syscalls.master +++ b/sys/compat/linux/arch/i386/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.70 2004/09/08 19:45:22 jdolecek Exp $ + $NetBSD: syscalls.master,v 1.71 2004/09/20 18:41:07 jdolecek Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -416,8 +416,10 @@ 265 UNIMPL clock_gettime 266 UNIMPL clock_getres 267 UNIMPL clock_nanosleep -268 UNIMPL statfs64 -269 UNIMPL fstatfs64 +268 STD { int linux_sys_statfs64(const char *path, \ + size_t sz, struct linux_statfs64 *sp); } +269 STD { int linux_sys_fstatfs64(int fd, \ + size_t sz, struct linux_statfs64 *sp); } 270 UNIMPL tgkill 271 UNIMPL utimes 272 UNIMPL fadvise64_64 diff --git a/sys/compat/linux/arch/mips/syscalls.master b/sys/compat/linux/arch/mips/syscalls.master index a9a343a89ac7..ebe3b2250c86 100644 --- a/sys/compat/linux/arch/mips/syscalls.master +++ b/sys/compat/linux/arch/mips/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.15 2004/09/08 19:45:22 jdolecek Exp $ + $NetBSD: syscalls.master,v 1.16 2004/09/20 18:41:07 jdolecek Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -420,8 +420,10 @@ 252 UNIMPL set_tid_address 253 UNIMPL restart_syscall 254 UNIMPL fadvise64 -255 UNIMPL statfs64 -256 UNIMPL fstatfs64 +255 STD { int linux_sys_statfs64(const char *path, \ + size_t sz, struct linux_statfs64 *sp); } +256 STD { int linux_sys_fstatfs64(int fd, \ + size_t sz, struct linux_statfs64 *sp); } 257 UNIMPL timer_create 258 UNIMPL timer_settime 259 UNIMPL timer_gettime diff --git a/sys/compat/linux/arch/powerpc/syscalls.master b/sys/compat/linux/arch/powerpc/syscalls.master index ee7044cd71b0..b50ed8dbf7db 100644 --- a/sys/compat/linux/arch/powerpc/syscalls.master +++ b/sys/compat/linux/arch/powerpc/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.19 2004/09/08 19:45:22 jdolecek Exp $ + $NetBSD: syscalls.master,v 1.20 2004/09/20 18:41:07 jdolecek Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -421,8 +421,10 @@ 249 UNIMPL swapcontext 250 UNIMPL tgkill 251 UNIMPL utimes -252 UNIMPL statfs64 -253 UNIMPL fstatfs64 +252 STD { int linux_sys_statfs64(const char *path, \ + size_t sz, struct linux_statfs64 *sp); } +253 STD { int linux_sys_fstatfs64(int fd, \ + size_t sz, struct linux_statfs64 *sp); } 254 UNIMPL fadvise64_64 255 UNIMPL rtas 256 UNIMPL /* reserved for sys_debug_setcontext */ diff --git a/sys/compat/linux/common/linux_misc.c b/sys/compat/linux/common/linux_misc.c index ab703cb9650d..d5a34260f554 100644 --- a/sys/compat/linux/common/linux_misc.c +++ b/sys/compat/linux/common/linux_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_misc.c,v 1.131 2004/09/19 16:50:11 jdolecek Exp $ */ +/* $NetBSD: linux_misc.c,v 1.132 2004/09/20 18:41:07 jdolecek Exp $ */ /*- * Copyright (c) 1995, 1998, 1999 The NetBSD Foundation, Inc. @@ -64,7 +64,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.131 2004/09/19 16:50:11 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.132 2004/09/20 18:41:07 jdolecek Exp $"); #include #include @@ -132,10 +132,7 @@ const int linux_ptrace_request_map[] = { -1 }; -static const struct mnttypes { - char *bsd; - int linux; -} fstypes[] = { +const struct linux_mnttypes linux_fstypes[] = { { MOUNT_FFS, LINUX_DEFAULT_SUPER_MAGIC }, { MOUNT_NFS, LINUX_NFS_SUPER_MAGIC }, { MOUNT_MFS, LINUX_DEFAULT_SUPER_MAGIC }, @@ -159,7 +156,7 @@ static const struct mnttypes { { MOUNT_NTFS, LINUX_DEFAULT_SUPER_MAGIC }, { MOUNT_SMBFS, LINUX_SMB_SUPER_MAGIC } }; -#define FSTYPESSIZE (sizeof(fstypes) / sizeof(fstypes[0])) +const int linux_fstypes_cnt = sizeof(linux_fstypes) / sizeof(linux_fstypes[0]); #ifdef DEBUG_LINUX #define DPRINTF(a) uprintf a @@ -307,16 +304,17 @@ bsd_to_linux_statfs(bsp, lsp) { int i; - for (i = 0; i < FSTYPESSIZE; i++) - if (strcmp(bsp->f_fstypename, fstypes[i].bsd) == 0) + for (i = 0; i < linux_fstypes_cnt; i++) { + if (strcmp(bsp->f_fstypename, linux_fstypes[i].bsd) == 0) { + lsp->l_ftype = linux_fstypes[i].linux; break; + } + } - if (i == FSTYPESSIZE) { + if (i == linux_fstypes_cnt) { DPRINTF(("unhandled fstype in linux emulation: %s\n", bsp->f_fstypename)); lsp->l_ftype = LINUX_DEFAULT_SUPER_MAGIC; - } else { - lsp->l_ftype = fstypes[i].linux; } /* diff --git a/sys/compat/linux/common/linux_misc.h b/sys/compat/linux/common/linux_misc.h index 1bbe0cbe926e..00fb6f72bad1 100644 --- a/sys/compat/linux/common/linux_misc.h +++ b/sys/compat/linux/common/linux_misc.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_misc.h,v 1.8 2003/01/18 08:02:53 thorpej Exp $ */ +/* $NetBSD: linux_misc.h,v 1.9 2004/09/20 18:41:07 jdolecek Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -109,6 +109,13 @@ struct linux_sysinfo { #define LINUX_USBDEVICE_SUPER_MAGIC 0x00009fa2 #define LINUX_XENIX_SUPER_MAGIC (LINUX_SYSV_MAGIC_BASE + 1) +struct linux_mnttypes { + const char *bsd; + int linux; +}; +extern const struct linux_mnttypes linux_fstypes[]; +extern const int linux_fstypes_cnt; + #ifdef _KERNEL __BEGIN_DECLS void bsd_to_linux_wstat __P((int *)); diff --git a/sys/compat/linux/common/linux_misc_notalpha.c b/sys/compat/linux/common/linux_misc_notalpha.c index 471cc820890c..ce18594615fa 100644 --- a/sys/compat/linux/common/linux_misc_notalpha.c +++ b/sys/compat/linux/common/linux_misc_notalpha.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_misc_notalpha.c,v 1.69 2003/06/29 22:29:31 fvdl Exp $ */ +/* $NetBSD: linux_misc_notalpha.c,v 1.70 2004/09/20 18:41:07 jdolecek Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.69 2003/06/29 22:29:31 fvdl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.70 2004/09/20 18:41:07 jdolecek Exp $"); #include #include @@ -75,6 +75,15 @@ __KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.69 2003/06/29 22:29:31 fvd /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */ /* Not used on: alpha */ +#ifdef DEBUG_LINUX +#define DPRINTF(a) uprintf a +#else +#define DPRINTF(a) +#endif + +static void bsd_to_linux_statfs64(const struct statvfs *, + struct linux_statfs64 *); + /* * Alarm. This is a libc call which uses setitimer(2) in NetBSD. * Fiddle with the timers to make it work. @@ -417,3 +426,129 @@ linux_sys_stime(l, v, retval) return 0; } + +#ifndef __m68k__ +/* + * Convert NetBSD statvfs structure to Linux statfs64 structure. + * See comments in bsd_to_linux_statfs() for further background. + * We can safely pass correct bsize and frsize here, since Linux glibc + * statvfs() doesn't use statfs64(). + */ +static void +bsd_to_linux_statfs64(bsp, lsp) + const struct statvfs *bsp; + struct linux_statfs64 *lsp; +{ + int i, div; + + for (i = 0; i < linux_fstypes_cnt; i++) { + if (strcmp(bsp->f_fstypename, linux_fstypes[i].bsd) == 0) { + lsp->l_ftype = linux_fstypes[i].linux; + break; + } + } + + if (i == linux_fstypes_cnt) { + DPRINTF(("unhandled fstype in linux emulation: %s\n", + bsp->f_fstypename)); + lsp->l_ftype = LINUX_DEFAULT_SUPER_MAGIC; + } + + div = bsp->f_bsize / bsp->f_frsize; + lsp->l_fbsize = bsp->f_bsize; + lsp->l_ffrsize = bsp->f_frsize; + lsp->l_fblocks = bsp->f_blocks / div; + lsp->l_fbfree = bsp->f_bfree / div; + lsp->l_fbavail = bsp->f_bavail / div; + lsp->l_ffiles = bsp->f_files; + lsp->l_fffree = bsp->f_ffree / div; + /* Linux sets the fsid to 0..., we don't */ + lsp->l_ffsid.val[0] = bsp->f_fsidx.__fsid_val[0]; + lsp->l_ffsid.val[1] = bsp->f_fsidx.__fsid_val[1]; + lsp->l_fnamelen = bsp->f_namemax; + (void)memset(lsp->l_fspare, 0, sizeof(lsp->l_fspare)); +} + +/* + * Implement the fs stat functions. Straightforward. + */ +int +linux_sys_statfs64(l, v, retval) + struct lwp *l; + void *v; + register_t *retval; +{ + struct linux_sys_statfs64_args /* { + syscallarg(const char *) path; + syscallarg(size_t) sz; + syscallarg(struct linux_statfs64 *) sp; + } */ *uap = v; + struct proc *p = l->l_proc; + struct statvfs btmp, *bsp; + struct linux_statfs64 ltmp; + struct sys_statvfs1_args bsa; + caddr_t sg; + int error; + + if (SCARG(uap, sz) != sizeof ltmp) + return (EINVAL); + + sg = stackgap_init(p, 0); + bsp = (struct statvfs *) stackgap_alloc(p, &sg, sizeof (struct statvfs)); + + CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + + SCARG(&bsa, path) = SCARG(uap, path); + SCARG(&bsa, buf) = bsp; + SCARG(&bsa, flags) = ST_WAIT; + + if ((error = sys_statvfs1(l, &bsa, retval))) + return error; + + if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) + return error; + + bsd_to_linux_statfs64(&btmp, <mp); + + return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); +} + +int +linux_sys_fstatfs64(l, v, retval) + struct lwp *l; + void *v; + register_t *retval; +{ + struct linux_sys_fstatfs64_args /* { + syscallarg(int) fd; + syscallarg(size_t) sz; + syscallarg(struct linux_statfs64 *) sp; + } */ *uap = v; + struct proc *p = l->l_proc; + struct statvfs btmp, *bsp; + struct linux_statfs64 ltmp; + struct sys_fstatvfs1_args bsa; + caddr_t sg; + int error; + + if (SCARG(uap, sz) != sizeof ltmp) + return (EINVAL); + + sg = stackgap_init(p, 0); + bsp = (struct statvfs *) stackgap_alloc(p, &sg, sizeof (struct statvfs)); + + SCARG(&bsa, fd) = SCARG(uap, fd); + SCARG(&bsa, buf) = bsp; + SCARG(&bsa, flags) = ST_WAIT; + + if ((error = sys_fstatvfs1(l, &bsa, retval))) + return error; + + if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp))) + return error; + + bsd_to_linux_statfs64(&btmp, <mp); + + return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp); +} +#endif /* !__m68k__ */ diff --git a/sys/compat/linux/common/linux_types.h b/sys/compat/linux/common/linux_types.h index 797637e27571..035fb001aef6 100644 --- a/sys/compat/linux/common/linux_types.h +++ b/sys/compat/linux/common/linux_types.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_types.h,v 1.18 2004/09/20 03:21:40 christos Exp $ */ +/* $NetBSD: linux_types.h,v 1.19 2004/09/20 18:41:08 jdolecek Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -118,6 +118,20 @@ struct linux_statfs { u_int32_t l_ffrsize; u_int32_t l_fspare[5]; }; + +struct linux_statfs64 { + u_int32_t l_ftype; + u_int32_t l_fbsize; + u_int64_t l_fblocks; + u_int64_t l_fbfree; + u_int64_t l_fbavail; + u_int64_t l_ffiles; + u_int64_t l_fffree; + linux_fsid_t l_ffsid; + u_int32_t l_fnamelen; + u_int32_t l_ffrsize; + u_int32_t l_fspare[5]; +}; #endif /* !__sparc64__ */ #endif /* !_LINUX_TYPES_H */