From: Damien Diederen Date: Mon, 18 Sep 2017 10:18:39 +0000 (+0200) Subject: Linux: Use kernel_read/kernel_write when __vfs variants are unavailable X-Git-Tag: openafs-devel-1_9_0~667 X-Git-Url: http://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=refs%2Fchanges%2F29%2F12729%2F3 Linux: Use kernel_read/kernel_write when __vfs variants are unavailable We hide the uses of set_fs/get_fs behind a macro, as those functions are likely to soon become unavailable: > Christoph Hellwig suggested removing all calls outside of the core > filesystem and architecture code; Andy Lutomirski went one step > further and said they should all go. https://lwn.net/Articles/722267/ Change-Id: Ib668f8fdb62ca01fe14321c07bd14d218744d909 Reviewed-on: https://gerrit.openafs.org/12729 Tested-by: BuildBot Reviewed-by: Mark Vitale Reviewed-by: Benjamin Kaduk --- diff --git a/acinclude.m4 b/acinclude.m4 index 162a3e9..703d3ea 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1004,6 +1004,9 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*) AC_CHECK_LINUX_FUNC([__vfs_write], [#include ], [__vfs_write(NULL, NULL, 0, NULL);]) + AC_CHECK_LINUX_FUNC([kernel_write], + [#include ], + [kernel_write(NULL, NULL, 0, NULL);]) AC_CHECK_LINUX_FUNC([bdi_init], [#include ], [bdi_init(NULL);]) diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h index 13915b9..60cfdc1 100644 --- a/src/afs/LINUX/osi_compat.h +++ b/src/afs/LINUX/osi_compat.h @@ -645,11 +645,21 @@ afs_d_invalidate(struct dentry *dp) #endif } +#if defined(HAVE_LINUX___VFS_WRITE) +# define AFS_FILE_NEEDS_SET_FS 1 +#elif defined(HAVE_LINUX_KERNEL_WRITE) +/* #undef AFS_FILE_NEEDS_SET_FS */ +#else +# define AFS_FILE_NEEDS_SET_FS 1 +#endif + static inline int afs_file_read(struct file *filp, char __user *buf, size_t len, loff_t *pos) { #if defined(HAVE_LINUX___VFS_WRITE) return __vfs_read(filp, buf, len, pos); +#elif defined(HAVE_LINUX_KERNEL_WRITE) + return kernel_read(filp, buf, len, pos); #else return filp->f_op->read(filp, buf, len, pos); #endif @@ -660,6 +670,8 @@ afs_file_write(struct file *filp, char __user *buf, size_t len, loff_t *pos) { #if defined(HAVE_LINUX___VFS_WRITE) return __vfs_write(filp, buf, len, pos); +#elif defined(HAVE_LINUX_KERNEL_WRITE) + return kernel_write(filp, buf, len, pos); #else return filp->f_op->write(filp, buf, len, pos); #endif diff --git a/src/afs/LINUX/osi_file.c b/src/afs/LINUX/osi_file.c index 1718c96..0374c1c 100644 --- a/src/afs/LINUX/osi_file.c +++ b/src/afs/LINUX/osi_file.c @@ -356,7 +356,9 @@ int osi_rdwr(struct osi_file *osifile, struct uio *uiop, int rw) { struct file *filp = osifile->filp; +#ifdef AFS_FILE_NEEDS_SET_FS mm_segment_t old_fs = {0}; +#endif /* AFS_FILE_NEEDS_SET_FS */ int code = 0; struct iovec *iov; size_t count; @@ -366,11 +368,13 @@ osi_rdwr(struct osi_file *osifile, struct uio *uiop, int rw) savelim = current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur; current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; +#ifdef AFS_FILE_NEEDS_SET_FS if (uiop->uio_seg == AFS_UIOSYS) { /* Switch into user space */ old_fs = get_fs(); set_fs(get_ds()); } +#endif /* AFS_FILE_NEEDS_SET_FS */ while (code == 0 && uiop->uio_resid > 0 && uiop->uio_iovcnt > 0) { iov = uiop->uio_iov; @@ -407,10 +411,12 @@ osi_rdwr(struct osi_file *osifile, struct uio *uiop, int rw) code = 0; } +#ifdef AFS_FILE_NEEDS_SET_FS if (uiop->uio_seg == AFS_UIOSYS) { /* Switch back into kernel space */ set_fs(old_fs); } +#endif /* AFS_FILE_NEEDS_SET_FS */ current->TASK_STRUCT_RLIM[RLIMIT_FSIZE].rlim_cur = savelim; diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index d935cf5..b7e4734 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -825,7 +825,7 @@ struct file_operations afs_file_fops = { #ifdef STRUCT_FILE_OPERATIONS_HAS_READ_ITER .read_iter = afs_linux_read_iter, .write_iter = afs_linux_write_iter, -# if !defined(HAVE_LINUX___VFS_WRITE) +# if !defined(HAVE_LINUX___VFS_WRITE) && !defined(HAVE_LINUX_KERNEL_WRITE) .read = new_sync_read, .write = new_sync_write, # endif