Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 May 2016 09:06:54 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r299526 - in head/sys/compat/linuxkpi/common: include/linux src
Message-ID:  <201605120906.u4C96sb6035508@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Thu May 12 09:06:54 2016
New Revision: 299526
URL: https://svnweb.freebsd.org/changeset/base/299526

Log:
  Create a dummy "task_struct" on the stack which is returned by
  "current" inside all LinuxKPI file operation callbacks. The "current"
  is frequently used for various debug prints, printing the thread name
  and thread ID for example.
  
  Obtained from:	kmacy @
  MFC after:	1 week
  Sponsored by:	Mellanox Technologies

Modified:
  head/sys/compat/linuxkpi/common/include/linux/kthread.h
  head/sys/compat/linuxkpi/common/include/linux/sched.h
  head/sys/compat/linuxkpi/common/src/linux_compat.c

Modified: head/sys/compat/linuxkpi/common/include/linux/kthread.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/kthread.h	Thu May 12 08:55:57 2016	(r299525)
+++ head/sys/compat/linuxkpi/common/include/linux/kthread.h	Thu May 12 09:06:54 2016	(r299526)
@@ -2,7 +2,7 @@
  * Copyright (c) 2010 Isilon Systems, Inc.
  * Copyright (c) 2010 iX Systems, Inc.
  * Copyright (c) 2010 Panasas, Inc.
- * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
+ * Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,15 +45,18 @@ static inline void
 linux_kthread_fn(void *arg)
 {
 	struct task_struct *task;
+	struct thread *td = curthread;
 
 	task = arg;
-	task_struct_set(curthread, task);
+	task_struct_fill(td, task);
+	task_struct_set(td, task);
 	if (task->should_stop == 0)
 		task->task_ret = task->task_fn(task->task_data);
-	PROC_LOCK(task->task_thread->td_proc);
+	PROC_LOCK(td->td_proc);
 	task->should_stop = TASK_STOPPED;
 	wakeup(task);
-	PROC_UNLOCK(task->task_thread->td_proc);
+	PROC_UNLOCK(td->td_proc);
+	task_struct_set(td, NULL);
 	kthread_exit();
 }
 

Modified: head/sys/compat/linuxkpi/common/include/linux/sched.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/sched.h	Thu May 12 08:55:57 2016	(r299525)
+++ head/sys/compat/linuxkpi/common/include/linux/sched.h	Thu May 12 09:06:54 2016	(r299526)
@@ -2,7 +2,7 @@
  * Copyright (c) 2010 Isilon Systems, Inc.
  * Copyright (c) 2010 iX Systems, Inc.
  * Copyright (c) 2010 Panasas, Inc.
- * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
+ * Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -50,10 +50,12 @@
 #define	TASK_STOPPED		2
 
 /*
- * A task_struct is only provided for those tasks created with kthread.
- * Using these routines with threads not started via kthread will cause
- * panics because no task_struct is allocated and td_retval[1] is
- * overwritten by syscalls which kernel threads will not make use of.
+ * A task_struct is only provided for threads created by kthread() and
+ * file operation callbacks.
+ *
+ * Using these routines outside the above mentioned contexts will
+ * cause panics because no task_struct is assigned and td_retval[1] is
+ * overwritten by syscalls.
  */
 struct task_struct {
 	struct	thread *task_thread;
@@ -62,10 +64,17 @@ struct task_struct {
 	int	task_ret;
 	int	state;
 	int	should_stop;
+	pid_t	pid;
+	const char    *comm;
 };
 
 #define	current			task_struct_get(curthread)
 #define	task_struct_get(x)	((struct task_struct *)(uintptr_t)(x)->td_retval[1])
+#define	task_struct_fill(x, y) do {		\
+  	(y)->task_thread = (x);			\
+	(y)->comm = (x)->td_name;		\
+	(y)->pid = (x)->td_tid;			\
+} while (0)
 #define	task_struct_set(x, y)	(x)->td_retval[1] = (uintptr_t)(y)
 
 /* ensure the task_struct pointer fits into the td_retval[1] field */

Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_compat.c	Thu May 12 08:55:57 2016	(r299525)
+++ head/sys/compat/linuxkpi/common/src/linux_compat.c	Thu May 12 09:06:54 2016	(r299526)
@@ -374,12 +374,31 @@ kobject_init_and_add(struct kobject *kob
 }
 
 static void
+linux_set_current(struct thread *td, struct task_struct *t)
+{
+	memset(t, 0, sizeof(*t));
+	task_struct_fill(td, t);
+	task_struct_set(td, t);
+}
+
+static void
+linux_clear_current(struct thread *td)
+{
+	task_struct_set(td, NULL);
+}
+
+static void
 linux_file_dtor(void *cdp)
 {
 	struct linux_file *filp;
+	struct task_struct t;
+	struct thread *td;
 
+	td = curthread;
 	filp = cdp;
+	linux_set_current(td, &t);
 	filp->f_op->release(filp->f_vnode, filp);
+	linux_clear_current(td);
 	vdrop(filp->f_vnode);
 	kfree(filp);
 }
@@ -389,10 +408,11 @@ linux_dev_open(struct cdev *dev, int ofl
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
+	struct task_struct t;
 	struct file *file;
 	int error;
 
-	file = curthread->td_fpop;
+	file = td->td_fpop;
 	ldev = dev->si_drv1;
 	if (ldev == NULL)
 		return (ENODEV);
@@ -402,21 +422,22 @@ linux_dev_open(struct cdev *dev, int ofl
 	filp->f_flags = file->f_flag;
 	vhold(file->f_vnode);
 	filp->f_vnode = file->f_vnode;
+	linux_set_current(td, &t);
 	if (filp->f_op->open) {
 		error = -filp->f_op->open(file->f_vnode, filp);
 		if (error) {
 			kfree(filp);
-			return (error);
+			goto done;
 		}
 	}
 	error = devfs_set_cdevpriv(filp, linux_file_dtor);
 	if (error) {
 		filp->f_op->release(file->f_vnode, filp);
 		kfree(filp);
-		return (error);
 	}
-
-	return 0;
+done:
+	linux_clear_current(td);
+	return (error);
 }
 
 static int
@@ -427,7 +448,7 @@ linux_dev_close(struct cdev *dev, int ff
 	struct file *file;
 	int error;
 
-	file = curthread->td_fpop;
+	file = td->td_fpop;
 	ldev = dev->si_drv1;
 	if (ldev == NULL)
 		return (0);
@@ -446,16 +467,18 @@ linux_dev_ioctl(struct cdev *dev, u_long
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
+	struct task_struct t;
 	struct file *file;
 	int error;
 
-	file = curthread->td_fpop;
+	file = td->td_fpop;
 	ldev = dev->si_drv1;
 	if (ldev == NULL)
 		return (0);
 	if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
 		return (error);
 	filp->f_flags = file->f_flag;
+	linux_set_current(td, &t);
 	/*
 	 * Linux does not have a generic ioctl copyin/copyout layer.  All
 	 * linux ioctls must be converted to void ioctls which pass a
@@ -467,6 +490,7 @@ linux_dev_ioctl(struct cdev *dev, u_long
 		error = -filp->f_op->unlocked_ioctl(filp, cmd, (u_long)data);
 	else
 		error = ENOTTY;
+	linux_clear_current(td);
 
 	return (error);
 }
@@ -476,11 +500,14 @@ linux_dev_read(struct cdev *dev, struct 
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
+	struct task_struct t;
+	struct thread *td;
 	struct file *file;
 	ssize_t bytes;
 	int error;
 
-	file = curthread->td_fpop;
+	td = curthread;
+	file = td->td_fpop;
 	ldev = dev->si_drv1;
 	if (ldev == NULL)
 		return (0);
@@ -490,6 +517,7 @@ linux_dev_read(struct cdev *dev, struct 
 	/* XXX no support for I/O vectors currently */
 	if (uio->uio_iovcnt != 1)
 		return (EOPNOTSUPP);
+	linux_set_current(td, &t);
 	if (filp->f_op->read) {
 		bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
 		    uio->uio_iov->iov_len, &uio->uio_offset);
@@ -502,6 +530,7 @@ linux_dev_read(struct cdev *dev, struct 
 			error = -bytes;
 	} else
 		error = ENXIO;
+	linux_clear_current(td);
 
 	return (error);
 }
@@ -511,11 +540,14 @@ linux_dev_write(struct cdev *dev, struct
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
+	struct task_struct t;
+	struct thread *td;
 	struct file *file;
 	ssize_t bytes;
 	int error;
 
-	file = curthread->td_fpop;
+	td = curthread;
+	file = td->td_fpop;
 	ldev = dev->si_drv1;
 	if (ldev == NULL)
 		return (0);
@@ -525,6 +557,7 @@ linux_dev_write(struct cdev *dev, struct
 	/* XXX no support for I/O vectors currently */
 	if (uio->uio_iovcnt != 1)
 		return (EOPNOTSUPP);
+	linux_set_current(td, &t);
 	if (filp->f_op->write) {
 		bytes = filp->f_op->write(filp, uio->uio_iov->iov_base,
 		    uio->uio_iov->iov_len, &uio->uio_offset);
@@ -537,6 +570,7 @@ linux_dev_write(struct cdev *dev, struct
 			error = -bytes;
 	} else
 		error = ENXIO;
+	linux_clear_current(td);
 
 	return (error);
 }
@@ -546,21 +580,24 @@ linux_dev_poll(struct cdev *dev, int eve
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
+	struct task_struct t;
 	struct file *file;
 	int revents;
 	int error;
 
-	file = curthread->td_fpop;
+	file = td->td_fpop;
 	ldev = dev->si_drv1;
 	if (ldev == NULL)
 		return (0);
 	if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
 		return (error);
 	filp->f_flags = file->f_flag;
+	linux_set_current(td, &t);
 	if (filp->f_op->poll)
 		revents = filp->f_op->poll(filp, NULL) & events;
 	else
 		revents = 0;
+	linux_clear_current(td);
 
 	return (revents);
 }
@@ -571,17 +608,21 @@ linux_dev_mmap_single(struct cdev *dev, 
 {
 	struct linux_cdev *ldev;
 	struct linux_file *filp;
+	struct thread *td;
+	struct task_struct t;
 	struct file *file;
 	struct vm_area_struct vma;
 	int error;
 
-	file = curthread->td_fpop;
+	td = curthread;
+	file = td->td_fpop;
 	ldev = dev->si_drv1;
 	if (ldev == NULL)
 		return (ENODEV);
 	if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
 		return (error);
 	filp->f_flags = file->f_flag;
+	linux_set_current(td, &t);
 	vma.vm_start = 0;
 	vma.vm_end = size;
 	vma.vm_pgoff = *offset / PAGE_SIZE;
@@ -596,10 +637,11 @@ linux_dev_mmap_single(struct cdev *dev, 
 			sglist_append_phys(sg,
 			    (vm_paddr_t)vma.vm_pfn << PAGE_SHIFT, vma.vm_len);
 			*object = vm_pager_allocate(OBJT_SG, sg, vma.vm_len,
-			    nprot, 0, curthread->td_ucred);
+			    nprot, 0, td->td_ucred);
 		        if (*object == NULL) {
 				sglist_free(sg);
-				return (EINVAL);
+				error = EINVAL;
+				goto done;
 			}
 			*offset = 0;
 			if (vma.vm_page_prot != VM_MEMATTR_DEFAULT) {
@@ -611,7 +653,8 @@ linux_dev_mmap_single(struct cdev *dev, 
 		}
 	} else
 		error = ENODEV;
-
+done:
+	linux_clear_current(td);
 	return (error);
 }
 
@@ -632,6 +675,7 @@ linux_file_read(struct file *file, struc
     int flags, struct thread *td)
 {
 	struct linux_file *filp;
+	struct task_struct t;
 	ssize_t bytes;
 	int error;
 
@@ -641,6 +685,7 @@ linux_file_read(struct file *file, struc
 	/* XXX no support for I/O vectors currently */
 	if (uio->uio_iovcnt != 1)
 		return (EOPNOTSUPP);
+	linux_set_current(td, &t);
 	if (filp->f_op->read) {
 		bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
 		    uio->uio_iov->iov_len, &uio->uio_offset);
@@ -653,6 +698,7 @@ linux_file_read(struct file *file, struc
 			error = -bytes;
 	} else
 		error = ENXIO;
+	linux_clear_current(td);
 
 	return (error);
 }
@@ -662,14 +708,17 @@ linux_file_poll(struct file *file, int e
     struct thread *td)
 {
 	struct linux_file *filp;
+	struct task_struct t;
 	int revents;
 
 	filp = (struct linux_file *)file->f_data;
 	filp->f_flags = file->f_flag;
+	linux_set_current(td, &t);
 	if (filp->f_op->poll)
 		revents = filp->f_op->poll(filp, NULL) & events;
 	else
 		revents = 0;
+	linux_clear_current(td);
 
 	return (revents);
 }
@@ -678,11 +727,14 @@ static int
 linux_file_close(struct file *file, struct thread *td)
 {
 	struct linux_file *filp;
+	struct task_struct t;
 	int error;
 
 	filp = (struct linux_file *)file->f_data;
 	filp->f_flags = file->f_flag;
+	linux_set_current(td, &t);
 	error = -filp->f_op->release(NULL, filp);
+	linux_clear_current(td);
 	funsetown(&filp->f_sigio);
 	kfree(filp);
 
@@ -694,12 +746,14 @@ linux_file_ioctl(struct file *fp, u_long
     struct thread *td)
 {
 	struct linux_file *filp;
+	struct task_struct t;
 	int error;
 
 	filp = (struct linux_file *)fp->f_data;
 	filp->f_flags = fp->f_flag;
 	error = 0;
 
+	linux_set_current(td, &t);
 	switch (cmd) {
 	case FIONBIO:
 		break;
@@ -721,6 +775,7 @@ linux_file_ioctl(struct file *fp, u_long
 		error = ENOTTY;
 		break;
 	}
+	linux_clear_current(td);
 	return (error);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605120906.u4C96sb6035508>