From 12df63ce9a626dded034e90f92ec9f15326ab96c Mon Sep 17 00:00:00 2001 From: Chaskiel M Grundman Date: Thu, 14 Apr 2005 03:18:33 +0000 Subject: [PATCH] linux26-unlocked-ioctl-20050413 FIXES 18224 add unlocked_ioctl support and compat_ioctl support --- src/afs/LINUX/osi_machdep.h | 3 +++ src/afs/LINUX/osi_module.c | 29 +++++++++++++++++++++++------ src/afs/LINUX/osi_vnodeops.c | 21 +++++++++++++++++++++ src/afs/afs_pioctl.c | 5 ++--- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/afs/LINUX/osi_machdep.h b/src/afs/LINUX/osi_machdep.h index e3c8c1a167..ca7fb5b7d2 100644 --- a/src/afs/LINUX/osi_machdep.h +++ b/src/afs/LINUX/osi_machdep.h @@ -179,6 +179,9 @@ typedef struct uio { /* Get/set the inode in the osifile struct. */ #define FILE_INODE(F) (F)->f_dentry->d_inode +#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV) +#define NEED_IOCTL32 +#endif /* page offset is obtained and stored here during module initialization * We need a variable to do this because, the PAGE_OFFSET macro defined in diff --git a/src/afs/LINUX/osi_module.c b/src/afs/LINUX/osi_module.c index 7a5e56a089..4a9cc9917e 100644 --- a/src/afs/LINUX/osi_module.c +++ b/src/afs/LINUX/osi_module.c @@ -50,12 +50,21 @@ int afs_global_owner = 0; unsigned long afs_linux_page_offset = 0; /* contains the PAGE_OFFSET value */ #endif - -static int afs_ioctl(struct inode *, struct file *, unsigned int, +static inline int afs_ioctl(struct inode *, struct file *, unsigned int, unsigned long); +#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL) +static long afs_unlocked_ioctl(struct file *, unsigned int, unsigned long); +#endif static struct file_operations afs_syscall_fops = { +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = afs_unlocked_ioctl, +#else .ioctl = afs_ioctl, +#endif +#ifdef HAVE_COMPAT_IOCTL + .compat_ioctl = afs_unlocked_ioctl, +#endif }; int @@ -423,7 +432,7 @@ callproc_read(char *buffer, char **start, off_t offset, int count, } static struct proc_dir_entry *openafs_procfs; -#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV) +#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL) static int ioctl32_done; #endif @@ -454,7 +463,7 @@ afsproc_init(void) entry = create_proc_read_entry(PROC_SERVICES_NAME, (S_IFREG|S_IRUGO), openafs_procfs, servicesproc_read, NULL); entry = create_proc_read_entry(PROC_RXSTATS_NAME, (S_IFREG|S_IRUGO), openafs_procfs, rxstatsproc_read, NULL); -#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV) +#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL) if (register_ioctl32_conversion(VIOC_SYSCALL32, NULL) == 0) ioctl32_done = 1; #endif @@ -474,7 +483,7 @@ afsproc_exit(void) remove_proc_entry(PROC_CELLSERVDB_NAME, openafs_procfs); remove_proc_entry(PROC_SYSCALL_NAME, openafs_procfs); remove_proc_entry(PROC_FSDIRNAME, proc_root_fs); -#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV) +#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL) if (ioctl32_done) unregister_ioctl32_conversion(VIOC_SYSCALL32); #endif @@ -490,11 +499,13 @@ afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, { struct afsprocdata sysargs; +#ifdef NEED_IOCTL32 struct afsprocdata32 sysargs32; +#endif if (cmd != VIOC_SYSCALL && cmd != VIOC_SYSCALL32) return -EINVAL; -#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV) +#ifdef NEED_IOCTL32 #ifdef AFS_SPARC64_LINUX24_ENV if (current->thread.flags & SPARC_FLAG_32BIT) #elif defined(AFS_SPARC64_LINUX20_ENV) @@ -539,6 +550,12 @@ afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } } +#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL) +static long afs_unlocked_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { + return afs_ioctl(FILE_INODE(file), file, cmd, arg); +} +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) int __init diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index df5124a6e3..2da933c8fd 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -426,6 +426,13 @@ out1: extern int afs_xioctl(struct inode *ip, struct file *fp, unsigned int com, unsigned long arg); +#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL) +static long afs_unlocked_xioctl(struct file *fp, unsigned int com, + unsigned long arg) { + return afs_xioctl(FILE_INODE(fp), fp, com, arg); + +} +#endif /* We need to detect unmap's after close. To do that, we need our own * vm_operations_struct's. And we need to set them up for both the @@ -733,7 +740,14 @@ struct file_operations afs_dir_fops = { .read = generic_read_dir, #endif .readdir = afs_linux_readdir, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = afs_unlocked_xioctl, +#else .ioctl = afs_xioctl, +#endif +#ifdef HAVE_COMPAT_IOCTL + .compat_ioctl = afs_unlocked_xioctl, +#endif .open = afs_linux_open, .release = afs_linux_release, }; @@ -741,7 +755,14 @@ struct file_operations afs_dir_fops = { struct file_operations afs_file_fops = { .read = afs_linux_read, .write = afs_linux_write, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = afs_unlocked_xioctl, +#else .ioctl = afs_xioctl, +#endif +#ifdef HAVE_COMPAT_IOCTL + .compat_ioctl = afs_unlocked_xioctl, +#endif .mmap = afs_linux_mmap, .open = afs_linux_open, .flush = afs_linux_flush, diff --git a/src/afs/afs_pioctl.c b/src/afs/afs_pioctl.c index a85298b0b0..1d6a65ea05 100644 --- a/src/afs/afs_pioctl.c +++ b/src/afs/afs_pioctl.c @@ -195,7 +195,7 @@ static int (*(CpioctlSw[])) () = { #define PSetClientContext 99 /* Special pioctl to setup caller's creds */ int afs_nobody = NFS_NOBODY; -#if (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)) || defined(AFS_HPUX_64BIT_ENV) || defined(AFS_SUN57_64BIT_ENV) || (defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)) || (defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)) +#if (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)) || defined(AFS_HPUX_64BIT_ENV) || defined(AFS_SUN57_64BIT_ENV) || (defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)) || defined(NEED_IOCTL32) static void afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst) { @@ -603,8 +603,7 @@ afs_xioctl(void) AFS_GLOCK(); datap = (struct afs_ioctl *)osi_AllocSmallSpace(AFS_SMALLOCSIZ); - AFS_COPYIN((char *)uap->arg, (caddr_t) datap, - sizeof(struct afs_ioctl), code); + code=copyin_afs_ioctl((char *)uap->arg, datap); if (code) { osi_FreeSmallSpace(datap); AFS_GUNLOCK();