]) # LIBCFS_WAIT_QUEUE_ENTRY
#
+# LIBCFS_NEW_KERNEL_WRITE
+#
+# Kernel version 4.14 e13ec939e96b13e664bb6cee361cc976a0ee621a
+# changed kernel_write prototype to make is plug compatible
+# with the unexported vfs_write()
+#
+AC_DEFUN([LIBCFS_NEW_KERNEL_WRITE], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if 'kernel_write' matches other read/write helpers],
+kernel_write_match, [
+ #include <linux/fs.h>
+],[
+ const void *buf = NULL;
+ loff_t pos = 0;
+ return kernel_write(NULL, buf, 0, &pos);
+],[
+ AC_DEFINE(HAVE_NEW_KERNEL_WRITE, 1,
+ ['kernel_write' aligns with read/write helpers])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LIBCFS_NEW_KERNEL_WRITE
+
+#
# LIBCFS_PROG_LINUX
#
# LibCFS linux kernel checks
LIBCFS_SCHED_HEADERS
# 4.13
LIBCFS_WAIT_QUEUE_ENTRY
+# 4.14
+LIBCFS_NEW_KERNEL_WRITE
]) # LIBCFS_PROG_LINUX
#
#ifndef __LIBCFS_LINUX_MISC_H__
#define __LIBCFS_LINUX_MISC_H__
+#include <linux/fs.h>
#include <linux/mutex.h>
#include <linux/user_namespace.h>
#define wait_queue_entry_t wait_queue_t
#endif
+int cfs_kernel_write(struct file *filp, char *buf, size_t count, loff_t *pos);
+
/*
* For RHEL6 struct kernel_parm_ops doesn't exist. Also
* the arguments for .set and .get take different
#define DEBUG_SUBSYSTEM S_LNET
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/sched.h>
#ifdef HAVE_SCHED_HEADERS
#include <linux/sched/signal.h>
#include <linux/sched/mm.h>
#endif
+#include <linux/uaccess.h>
#include <libcfs/libcfs.h>
#if defined(CONFIG_KGDB)
EXPORT_SYMBOL(ktime_get_seconds);
#endif /* HAVE_KTIME_GET_SECONDS */
+int cfs_kernel_write(struct file *filp, const void *buf, size_t count,
+ loff_t *pos)
+{
+#ifdef HAVE_NEW_KERNEL_WRITE
+ return kernel_write(filp, buf, count, pos);
+#else
+ mm_segment_t __old_fs = get_fs();
+ int rc;
+
+ set_fs(get_ds());
+ rc = vfs_write(filp, (__force const char __user *)buf, count, pos);
+ set_fs(__old_fs);
+
+ return rc;
+#endif
+}
+EXPORT_SYMBOL(cfs_kernel_write);
+
#ifndef HAVE_KSET_FIND_OBJ
struct kobject *kset_find_obj(struct kset *kset, const char *name)
{
struct file *filp;
struct cfs_trace_page *tage;
struct cfs_trace_page *tmp;
- mm_segment_t __oldfs;
char *buf;
int rc;
rc = 0;
goto close;
}
- __oldfs = get_fs();
- set_fs(get_ds());
/* ok, for now, just write the pages. in the future we'll be building
* iobufs with the pages and calling generic_direct_IO */
__LASSERT_TAGE_INVARIANT(tage);
buf = kmap(tage->page);
- rc = vfs_write(filp, (__force const char __user *)buf,
- tage->used, &filp->f_pos);
+ rc = cfs_kernel_write(filp, buf, tage->used, &filp->f_pos);
kunmap(tage->page);
if (rc != (int)tage->used) {
printk(KERN_WARNING "wanted to write %u but wrote "
list_del(&tage->linkage);
cfs_tage_free(tage);
}
- set_fs(__oldfs);
+
rc = ll_vfs_fsync_range(filp, 0, LLONG_MAX, 1);
if (rc)
printk(KERN_ERR "sync returns %d\n", rc);
struct tracefiled_ctl *tctl = arg;
struct cfs_trace_page *tage;
struct cfs_trace_page *tmp;
- mm_segment_t __oldfs;
struct file *filp;
char *buf;
int last_loop = 0;
__LASSERT(list_empty(&pc.pc_pages));
goto end_loop;
}
- __oldfs = get_fs();
- set_fs(get_ds());
list_for_each_entry_safe(tage, tmp, &pc.pc_pages, linkage) {
struct dentry *de = file_dentry(filp);
f_pos = i_size_read(de->d_inode);
buf = kmap(tage->page);
- rc = vfs_write(filp, (__force const char __user *)buf,
- tage->used, &f_pos);
+ rc = cfs_kernel_write(filp, buf, tage->used, &f_pos);
kunmap(tage->page);
if (rc != (int)tage->used) {
printk(KERN_WARNING "wanted to write %u "
break;
}
}
- set_fs(__oldfs);
filp_close(filp, NULL);
put_pages_on_daemon_list(&pc);
#include <obd_support.h>
#include <lustre_kernelcomm.h>
-/* write a userspace buffer to disk.
- * NOTE: this returns 0 on success, not the number of bytes written. */
-static ssize_t
-filp_user_write(struct file *filp, const void *buf, size_t count,
- loff_t *offset)
-{
- mm_segment_t fs;
- ssize_t size = 0;
-
- fs = get_fs();
- set_fs(KERNEL_DS);
- while ((ssize_t)count > 0) {
- size = vfs_write(filp, (const void __user *)buf, count, offset);
- if (size < 0)
- break;
- count -= size;
- buf += size;
- size = 0;
- }
- set_fs(fs);
-
- return size;
-}
-
/**
* libcfs_kkuc_msg_put - send an message from kernel to userspace
* @param fp to send the message to
int libcfs_kkuc_msg_put(struct file *filp, void *payload)
{
struct kuc_hdr *kuch = (struct kuc_hdr *)payload;
- int rc = -ENOSYS;
+ ssize_t count = kuch->kuc_msglen;
loff_t offset = 0;
+ int rc = 0;
- if (filp == NULL || IS_ERR(filp))
+ if (IS_ERR_OR_NULL(filp))
return -EBADF;
if (kuch->kuc_magic != KUC_MAGIC) {
return -ENOSYS;
}
- rc = filp_user_write(filp, payload, kuch->kuc_msglen, &offset);
+ while (count > 0) {
+ rc = cfs_kernel_write(filp, payload, count, &offset);
+ if (rc < 0)
+ break;
+ count -= rc;
+ payload += rc;
+ rc = 0;
+ }
+
if (rc < 0)
CWARN("message send failed (%d)\n", rc);
else
int rc, i;
unsigned int len;
char *buf;
- mm_segment_t oldfs;
/* will only keep dump of pages on first error for the same range in
* file/fid, not during the resends/retries. */
return;
}
- oldfs = get_fs();
- set_fs(KERNEL_DS);
for (i = 0; i < page_count; i++) {
len = pga[i]->count;
buf = kmap(pga[i]->pg);
while (len != 0) {
- rc = vfs_write(filp, (__force const char __user *)buf,
- len, &filp->f_pos);
+ rc = cfs_kernel_write(filp, buf, len, &filp->f_pos);
if (rc < 0) {
CERROR("%s: wanted to write %u but got %d "
"error\n", dbgcksum_file_name, len, rc);
}
kunmap(pga[i]->pg);
}
- set_fs(oldfs);
rc = ll_vfs_fsync_range(filp, 0, LLONG_MAX, 1);
if (rc)
int rc, i;
unsigned int len;
char *buf;
- mm_segment_t oldfs;
/* will only keep dump of pages on first error for the same range in
* file/fid, not during the resends/retries. */
return;
}
- oldfs = get_fs();
- set_fs(KERNEL_DS);
for (i = 0; i < count; i++) {
len = local_nb[i].lnb_len;
buf = kmap(local_nb[i].lnb_page);
while (len != 0) {
- rc = vfs_write(filp, (__force const char __user *)buf,
- len, &filp->f_pos);
+ rc = cfs_kernel_write(filp, buf, len, &filp->f_pos);
if (rc < 0) {
CERROR("%s: wanted to write %u but got %d "
"error\n", dbgcksum_file_name, len, rc);
}
kunmap(local_nb[i].lnb_page);
}
- set_fs(oldfs);
rc = ll_vfs_fsync_range(filp, 0, LLONG_MAX, 1);
if (rc)