linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/16] Cleanup chardev instances with helper function
@ 2017-03-06  7:04 Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 01/16] chardev: add helper function to register char devs with a struct device Logan Gunthorpe
                   ` (15 more replies)
  0 siblings, 16 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Hi,

Here's v3 of this patchset. It's based off of v4.11-rc1 which mostly
rebased clearly except for Jason's IB/ucm patch (but it was pretty
trivial to fix).

I've made this set available on github here (cdev_v3 branch):

https://github.com/lsgunth/linux.git

Also, I've noticed these emails aren't getting through to the
mailing lists at vger.kernel.org. Though, I'm not sure why as my
email logs show they are accepted. Perhaps it has something to do
with the number of lists it's addressed to. I won't be surprised if
v3 doesn't make it either as I'm not sure how to deal with that problem.

Thanks,

Logan

Changes since v2:

* Expanded comments as per Jason's suggestions
* Collected tags
* Updated the switchtec patch seeing it's underlying patch set changed


--

v2 description:

Here's v2 of my chardev cleanup patch-set. I've incorporated some
feedback and decided to extend the concept a little further. The new
helper function now includes both cdev_add and device_add which
significantly simplifies every instance that called it.

Jason's also expressed an interest in creating a general solution to
the problem that occurs if a user tries to utilize a newly created
cdev right before device_add fails. This series doesn't address that
specifically but will make it much easier to do so in future work.

I've also added cdev_set_parent for the cases in IB that set
the kobject parent without using device_add. This is just to ensure
the parent setting code is private within char_dev.c and removes the
lines that appear suspect but are in fact correct. Dan's suggested
WARN_ON is included in this function.

Seeing the new helper function takes in a bit more than before,
the instance patches are a bit heavier. Thus, I've refrained from
collecting the acks and reviews I've already received. In a couple
of cases (mtd and scsi) the cleanup required was a bit more involved
than I would have liked and thus these patches probably need more
attention, review and testing. (Unfortunately, I don't have hardware
to actually test them.) Hopefully that process doesn't throw too big
a wrench in the overall series moving forward.

I've included Dan's cdev_leak patch in this series to avoid a merge
conflict between the two of us.

While the diff stats for the series are much heavier than in v1, we now
have a net loss of more than 100 lines! So this feels much more like a
successful cleanup.

--

v1 story:

Our story for this patch-set begins with a new driver I wrote and am in
the process of submitting upstream. That driver creates a fairly
standard char device and the code for it was copied from a similar
instance in device-dax. However, upon review, Greg Kroah-Hartman
noticed [1] a suspicious line that assigned to the parent field of
the underlying kobject for the char device.

I removed that from my code and endeavoured to remove it from the
code I copied as well. However, Dan Williams pointed out [2] that this
code is necessary for correct reference counting of the underlying
structures. This prompted me to do a fair bit more research and
investigation into whats going on and I found it to be a common pattern.
(Although misleading and though required to be correct, frequently
forgotten.) This pattern is used in at least 15 places in the kernel
and probably should have been used in at least 5 more.

This patch-set aims to correct this and hopefully prevent future
developers from wasting their time on it. The first patch introduces
a new helper API as originally proposed by Dan Williams [3]. Please
see the commit message for that patch for a longer description of the
problem and history.

The subsequent patches either update correct instances to use the
new API or fix incorrect usages to ensure the cdev correctly takes
a reference count using the new API (this is noted in those patches).

This moves all except four of the cdev.kobj.parent usages into the one
cdev function, the remaining four are in the infiniband subsystem and
I've left alone because that subsystem seems to make use of kobjects
directly (instead of struct devices). These are noted in patch 7 of
this series.

This series is based on v4.10 with the exception of the last patch
which is for my new driver which, as yet, has not been accepted
upstream.

[1] https://lkml.org/lkml/2017/2/10/370
[2] https://lkml.org/lkml/2017/2/10/607
[3] https://lkml.org/lkml/2017/2/13/700

Dan Williams (1):
  device-dax: fix cdev leak

Jason Gunthorpe (1):
  IB/ucm: utilize new cdev_device_add helper function

Logan Gunthorpe (14):
  chardev: add helper function to register char devs with a struct
    device
  device-dax: utilize new cdev_device_add helper function
  input: utilize new cdev_device_add helper function
  gpiolib: utilize new cdev_device_add helper function
  tpm-chip: utilize new cdev_device_add helper function
  platform/chrome: cros_ec_dev - utilize new cdev_device_add helper
    function
  infiniband: utilize the new cdev_set_parent function
  iio:core: utilize new cdev_device_add helper function
  media: utilize new cdev_device_add helper function
  mtd: utilize new cdev_device_add helper function
  rapidio: utilize new cdev_device_add helper function
  rtc: utilize new cdev_device_add helper function
  scsi: utilize new cdev_device_add helper function
  switchtec: utilize new device_add_cdev helper function

 drivers/char/tpm/tpm-chip.c              | 19 ++-----
 drivers/dax/dax.c                        | 33 ++++++------
 drivers/gpio/gpiolib.c                   | 23 +++-----
 drivers/iio/industrialio-core.c          | 15 ++----
 drivers/infiniband/core/ucm.c            | 35 ++++++------
 drivers/infiniband/core/user_mad.c       |  4 +-
 drivers/infiniband/core/uverbs_main.c    |  2 +-
 drivers/infiniband/hw/hfi1/device.c      |  2 +-
 drivers/input/evdev.c                    | 11 +---
 drivers/input/joydev.c                   | 11 +---
 drivers/input/mousedev.c                 | 11 +---
 drivers/media/cec/cec-core.c             | 16 ++----
 drivers/media/media-devnode.c            | 20 ++-----
 drivers/mtd/ubi/build.c                  | 91 ++++++--------------------------
 drivers/mtd/ubi/vmt.c                    | 49 ++++++-----------
 drivers/pci/switch/switchtec.c           | 11 +---
 drivers/platform/chrome/cros_ec_dev.c    | 31 +++--------
 drivers/rapidio/devices/rio_mport_cdev.c | 24 +++------
 drivers/rtc/class.c                      | 14 +++--
 drivers/rtc/rtc-dev.c                    | 17 ------
 drivers/scsi/osd/osd_uld.c               | 56 +++++++-------------
 fs/char_dev.c                            | 77 +++++++++++++++++++++++++++
 include/linux/cdev.h                     |  4 ++
 23 files changed, 229 insertions(+), 347 deletions(-)

--
2.1.4

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 01/16] chardev: add helper function to register char devs with a struct device
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-16 13:22   ` Greg Kroah-Hartman
  2017-03-06  7:04 ` [PATCH v3 02/16] device-dax: fix cdev leak Logan Gunthorpe
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Credit for this patch goes is shared with Dan Williams [1]. I've
taken things one step further to make the helper function more
useful and clean up calling code.

There's a common pattern in the kernel whereby a struct cdev is placed
in a structure along side a struct device which manages the life-cycle
of both. In the naive approach, the reference counting is broken and
the struct device can free everything before the chardev code
is entirely released.

Many developers have solved this problem by linking the internal kobjs
in this fashion:

cdev.kobj.parent = &parent_dev.kobj;

The cdev code explicitly gets and puts a reference to it's kobj parent.
So this seems like it was intended to be used this way. Dmitrty Torokhov
first put this in place in 2012 with this commit:

2f0157f char_dev: pin parent kobject

and the first instance of the fix was then done in the input subsystem
in the following commit:

4a215aa Input: fix use-after-free introduced with dynamic minor changes

Subsequently over the years, however, this issue seems to have tripped
up multiple developers independently. For example, see these commits:

0d5b7da iio: Prevent race between IIO chardev opening and IIO device
(by Lars-Peter Clausen in 2013)

ba0ef85 tpm: Fix initialization of the cdev
(by Jason Gunthorpe in 2015)

5b28dde [media] media: fix use-after-free in cdev_put() when app exits
after driver unbind
(by Shauh Khan in 2016)

This technique is similarly done in at least 15 places within the kernel
and probably should have been done so in another, at least, 5 places.
The kobj line also looks very suspect in that one would not expect
drivers to have to mess with kobject internals in this way.
Even highly experienced kernel developers can be surprised by this
code, as seen in [2].

To help alleviate this situation, and hopefully prevent future
wasted effort on this problem, this patch introduces a helper function
to register a char device along with its parent struct device.
This creates a more regular API for tying a char device to its parent
without the developer having to set members in the underlying kobject.

This patch introduce cdev_device_add and cdev_device_del which
replaces a common pattern including setting the kobj parent, calling
cdev_add and then calling device_add. It also introduces cdev_set_parent
for the few cases that set the kobject parent without using device_add.

[1] https://lkml.org/lkml/2017/2/13/700
[2] https://lkml.org/lkml/2017/2/10/370

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 fs/char_dev.c        | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/cdev.h |  4 +++
 2 files changed, 81 insertions(+)

diff --git a/fs/char_dev.c b/fs/char_dev.c
index 44a240c..09b93fb 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -471,6 +471,76 @@ int cdev_add(struct cdev *p, dev_t dev, unsigned count)
 	return 0;
 }
 
+/**
+ * cdev_set_parent() - set the parent kobject for a char device
+ * @p: the cdev structure
+ * @kobj: the kobject to take a reference to
+ *
+ * cdev_set_parent() sets a parent kobject which will be referenced
+ * appropriately so the parent is not freed before the cdev. This
+ * should be called before cdev_add.
+ */
+void cdev_set_parent(struct cdev *p, struct kobject *kobj)
+{
+	WARN_ON(!kobj->state_initialized);
+	p->kobj.parent = kobj;
+}
+
+/**
+ * cdev_device_add() - add a char device and it's corresponding
+ *	struct device, linkink
+ * @dev: the device structure
+ * @cdev: the cdev structure
+ *
+ * cdev_device_add() adds the char device represented by @cdev to the system,
+ * just as cdev_add does. It then adds @dev to the system using device_add
+ * The dev_t for the char device will be taken from the struct device which
+ * needs to be initialized first. This helper function correctly takes a
+ * reference to the parent device so the parent will not get released until
+ * all references to the cdev are released.
+ *
+ * This function should be used whenever the struct cdev and the
+ * struct device are members of the same structure whose lifetime is
+ * managed by the struct device.
+ *
+ * NOTE: Callers must assume that userspace was able to open the cdev and
+ * can call cdev fops callbacks at any time, even if this function fails.
+ */
+int cdev_device_add(struct cdev *cdev, struct device *dev)
+{
+	int rc = 0;
+
+	cdev_set_parent(cdev, &dev->kobj);
+
+	rc = cdev_add(cdev, dev->devt, 1);
+	if (rc)
+		return rc;
+
+	rc = device_add(dev);
+	if (rc)
+		cdev_del(cdev);
+
+	return rc;
+}
+
+/**
+ * cdev_device_del() - inverse of cdev_device_add
+ * @dev: the device structure
+ * @cdev: the cdev structure
+ *
+ * cdev_device_del() is a helper function to call cdev_del and device_del.
+ * It should be used whenever cdev_device_add is used.
+ *
+ * NOTE: This guarantees that associated sysfs callbacks are not running
+ * or runnable, however any cdevs already open will remain and their fops
+ * will still be callable even after this function returns.
+ */
+void cdev_device_del(struct cdev *cdev, struct device *dev)
+{
+	device_del(dev);
+	cdev_del(cdev);
+}
+
 static void cdev_unmap(dev_t dev, unsigned count)
 {
 	kobj_unmap(cdev_map, dev, count);
@@ -482,6 +552,10 @@ static void cdev_unmap(dev_t dev, unsigned count)
  *
  * cdev_del() removes @p from the system, possibly freeing the structure
  * itself.
+ *
+ * NOTE: This guarantees that cdev device will no longer be able to be
+ * opened, however any cdevs already open will remain and their fops will
+ * still be callable even after cdev_del returns.
  */
 void cdev_del(struct cdev *p)
 {
@@ -570,5 +644,8 @@ EXPORT_SYMBOL(cdev_init);
 EXPORT_SYMBOL(cdev_alloc);
 EXPORT_SYMBOL(cdev_del);
 EXPORT_SYMBOL(cdev_add);
+EXPORT_SYMBOL(cdev_set_parent);
+EXPORT_SYMBOL(cdev_device_add);
+EXPORT_SYMBOL(cdev_device_del);
 EXPORT_SYMBOL(__register_chrdev);
 EXPORT_SYMBOL(__unregister_chrdev);
diff --git a/include/linux/cdev.h b/include/linux/cdev.h
index f876361..4c99579 100644
--- a/include/linux/cdev.h
+++ b/include/linux/cdev.h
@@ -26,6 +26,10 @@ void cdev_put(struct cdev *p);
 
 int cdev_add(struct cdev *, dev_t, unsigned);
 
+void cdev_set_parent(struct cdev *p, struct kobject *kobj);
+int cdev_device_add(struct cdev *cdev, struct device *dev);
+void cdev_device_del(struct cdev *cdev, struct device *dev);
+
 void cdev_del(struct cdev *);
 
 void cd_forget(struct inode *);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 02/16] device-dax: fix cdev leak
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 01/16] chardev: add helper function to register char devs with a struct device Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  8:27   ` Johannes Thumshirn
  2017-03-06  7:04 ` [PATCH v3 03/16] device-dax: utilize new cdev_device_add helper function Logan Gunthorpe
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, stable, Logan Gunthorpe

From: Dan Williams <dan.j.williams@intel.com>

If device_add() fails, cleanup the cdev. Otherwise, we leak a kobj_map()
with a stale device number.

As Jason points out, there is a small possibility that userspace has
opened and mapped the device in the time between cdev_add() and the
device_add() failure. We need a new kill_dax_dev() helper to invalidate
any established mappings.

Fixes: ba09c01d2fa8 ("dax: convert to the cdev api")
Cc: <stable@vger.kernel.org>
Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dax/dax.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c
index 8d9829f..a5ed59a 100644
--- a/drivers/dax/dax.c
+++ b/drivers/dax/dax.c
@@ -675,13 +675,10 @@ static void dax_dev_release(struct device *dev)
 	kfree(dax_dev);
 }
 
-static void unregister_dax_dev(void *dev)
+static void kill_dax_dev(struct dax_dev *dax_dev)
 {
-	struct dax_dev *dax_dev = to_dax_dev(dev);
 	struct cdev *cdev = &dax_dev->cdev;
 
-	dev_dbg(dev, "%s\n", __func__);
-
 	/*
 	 * Note, rcu is not protecting the liveness of dax_dev, rcu is
 	 * ensuring that any fault handlers that might have seen
@@ -693,6 +690,15 @@ static void unregister_dax_dev(void *dev)
 	synchronize_rcu();
 	unmap_mapping_range(dax_dev->inode->i_mapping, 0, 0, 1);
 	cdev_del(cdev);
+}
+
+static void unregister_dax_dev(void *dev)
+{
+	struct dax_dev *dax_dev = to_dax_dev(dev);
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	kill_dax_dev(dax_dev);
 	device_unregister(dev);
 }
 
@@ -769,6 +775,7 @@ struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region,
 	dev_set_name(dev, "dax%d.%d", dax_region->id, dax_dev->id);
 	rc = device_add(dev);
 	if (rc) {
+		kill_dax_dev(dax_dev);
 		put_device(dev);
 		return ERR_PTR(rc);
 	}
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 03/16] device-dax: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 01/16] chardev: add helper function to register char devs with a struct device Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 02/16] device-dax: fix cdev leak Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  8:29   ` Johannes Thumshirn
  2017-03-06  7:04 ` [PATCH v3 04/16] input: " Logan Gunthorpe
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Replace the open coded registration of the cdev and dev with the
new device_add_cdev() helper. The helper replaces a common pattern by
taking the proper reference against the parent device and adding both
the cdev and the device.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/dax/dax.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c
index a5ed59a..e5f8555 100644
--- a/drivers/dax/dax.c
+++ b/drivers/dax/dax.c
@@ -677,8 +677,6 @@ static void dax_dev_release(struct device *dev)
 
 static void kill_dax_dev(struct dax_dev *dax_dev)
 {
-	struct cdev *cdev = &dax_dev->cdev;
-
 	/*
 	 * Note, rcu is not protecting the liveness of dax_dev, rcu is
 	 * ensuring that any fault handlers that might have seen
@@ -689,7 +687,6 @@ static void kill_dax_dev(struct dax_dev *dax_dev)
 	dax_dev->alive = false;
 	synchronize_rcu();
 	unmap_mapping_range(dax_dev->inode->i_mapping, 0, 0, 1);
-	cdev_del(cdev);
 }
 
 static void unregister_dax_dev(void *dev)
@@ -699,7 +696,8 @@ static void unregister_dax_dev(void *dev)
 	dev_dbg(dev, "%s\n", __func__);
 
 	kill_dax_dev(dax_dev);
-	device_unregister(dev);
+	cdev_device_del(&dax_dev->cdev, dev);
+	put_device(dev);
 }
 
 struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region,
@@ -750,18 +748,13 @@ struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region,
 		goto err_inode;
 	}
 
-	/* device_initialize() so cdev can reference kobj parent */
+	/* from here on we're committed to teardown via dax_dev_release() */
 	device_initialize(dev);
 
 	cdev = &dax_dev->cdev;
 	cdev_init(cdev, &dax_fops);
 	cdev->owner = parent->driver->owner;
-	cdev->kobj.parent = &dev->kobj;
-	rc = cdev_add(&dax_dev->cdev, dev_t, 1);
-	if (rc)
-		goto err_cdev;
 
-	/* from here on we're committed to teardown via dax_dev_release() */
 	dax_dev->num_resources = count;
 	dax_dev->alive = true;
 	dax_dev->region = dax_region;
@@ -773,7 +766,8 @@ struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region,
 	dev->groups = dax_attribute_groups;
 	dev->release = dax_dev_release;
 	dev_set_name(dev, "dax%d.%d", dax_region->id, dax_dev->id);
-	rc = device_add(dev);
+
+	rc = cdev_device_add(cdev, dev);
 	if (rc) {
 		kill_dax_dev(dax_dev);
 		put_device(dev);
@@ -786,8 +780,6 @@ struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region,
 
 	return dax_dev;
 
- err_cdev:
-	iput(dax_dev->inode);
  err_inode:
 	ida_simple_remove(&dax_minor_ida, minor);
  err_minor:
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 04/16] input: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (2 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 03/16] device-dax: utilize new cdev_device_add helper function Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 05/16] gpiolib: " Logan Gunthorpe
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Replace the open coded registration of the cdev and dev with the
new device_add_cdev() helper in evdev, joydev and mousedev. The helper
replaces a common pattern by taking the proper reference against the
parent device and adding both the cdev and the device.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/evdev.c    | 11 ++---------
 drivers/input/joydev.c   | 11 ++---------
 drivers/input/mousedev.c | 11 ++---------
 3 files changed, 6 insertions(+), 27 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index e9ae3d5..9255714 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -1354,8 +1354,6 @@ static void evdev_cleanup(struct evdev *evdev)
 	evdev_mark_dead(evdev);
 	evdev_hangup(evdev);
 
-	cdev_del(&evdev->cdev);
-
 	/* evdev is marked dead so no one else accesses evdev->open */
 	if (evdev->open) {
 		input_flush_device(handle, NULL);
@@ -1416,12 +1414,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
 		goto err_free_evdev;
 
 	cdev_init(&evdev->cdev, &evdev_fops);
-	evdev->cdev.kobj.parent = &evdev->dev.kobj;
-	error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
-	if (error)
-		goto err_unregister_handle;
 
-	error = device_add(&evdev->dev);
+	error = cdev_device_add(&evdev->cdev, &evdev->dev);
 	if (error)
 		goto err_cleanup_evdev;
 
@@ -1429,7 +1423,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
 
  err_cleanup_evdev:
 	evdev_cleanup(evdev);
- err_unregister_handle:
 	input_unregister_handle(&evdev->handle);
  err_free_evdev:
 	put_device(&evdev->dev);
@@ -1442,7 +1435,7 @@ static void evdev_disconnect(struct input_handle *handle)
 {
 	struct evdev *evdev = handle->private;
 
-	device_del(&evdev->dev);
+	cdev_device_del(&evdev->cdev, &evdev->dev);
 	evdev_cleanup(evdev);
 	input_free_minor(MINOR(evdev->dev.devt));
 	input_unregister_handle(handle);
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 065e67b..29d677c 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -742,8 +742,6 @@ static void joydev_cleanup(struct joydev *joydev)
 	joydev_mark_dead(joydev);
 	joydev_hangup(joydev);
 
-	cdev_del(&joydev->cdev);
-
 	/* joydev is marked dead so no one else accesses joydev->open */
 	if (joydev->open)
 		input_close_device(handle);
@@ -913,12 +911,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
 		goto err_free_joydev;
 
 	cdev_init(&joydev->cdev, &joydev_fops);
-	joydev->cdev.kobj.parent = &joydev->dev.kobj;
-	error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
-	if (error)
-		goto err_unregister_handle;
 
-	error = device_add(&joydev->dev);
+	error = cdev_device_add(&joydev->cdev, &joydev->dev);
 	if (error)
 		goto err_cleanup_joydev;
 
@@ -926,7 +920,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
 
  err_cleanup_joydev:
 	joydev_cleanup(joydev);
- err_unregister_handle:
 	input_unregister_handle(&joydev->handle);
  err_free_joydev:
 	put_device(&joydev->dev);
@@ -939,7 +932,7 @@ static void joydev_disconnect(struct input_handle *handle)
 {
 	struct joydev *joydev = handle->private;
 
-	device_del(&joydev->dev);
+	cdev_device_del(&joydev->cdev, &joydev->dev);
 	joydev_cleanup(joydev);
 	input_free_minor(MINOR(joydev->dev.devt));
 	input_unregister_handle(handle);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index b604564..0e0ff84 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -812,8 +812,6 @@ static void mousedev_cleanup(struct mousedev *mousedev)
 	mousedev_mark_dead(mousedev);
 	mousedev_hangup(mousedev);
 
-	cdev_del(&mousedev->cdev);
-
 	/* mousedev is marked dead so no one else accesses mousedev->open */
 	if (mousedev->open)
 		input_close_device(handle);
@@ -901,12 +899,8 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
 	}
 
 	cdev_init(&mousedev->cdev, &mousedev_fops);
-	mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
-	error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
-	if (error)
-		goto err_unregister_handle;
 
-	error = device_add(&mousedev->dev);
+	error = cdev_device_add(&mousedev->cdev, &mousedev->dev);
 	if (error)
 		goto err_cleanup_mousedev;
 
@@ -914,7 +908,6 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
 
  err_cleanup_mousedev:
 	mousedev_cleanup(mousedev);
- err_unregister_handle:
 	if (!mixdev)
 		input_unregister_handle(&mousedev->handle);
  err_free_mousedev:
@@ -927,7 +920,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
 
 static void mousedev_destroy(struct mousedev *mousedev)
 {
-	device_del(&mousedev->dev);
+	cdev_device_del(&mousedev->cdev, &mousedev->dev);
 	mousedev_cleanup(mousedev);
 	input_free_minor(MINOR(mousedev->dev.devt));
 	if (mousedev != mousedev_mix)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 05/16] gpiolib: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (3 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 04/16] input: " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-14 15:28   ` [rtc-linux] " Linus Walleij
  2017-03-06  7:04 ` [PATCH v3 06/16] tpm-chip: " Logan Gunthorpe
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Replace the open coded registration of the cdev and dev with the
new device_add_cdev() helper. The helper replaces a common pattern by
taking the proper reference against the parent device and adding both
the cdev and the device.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/gpio/gpiolib.c | 23 ++++++++---------------
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 8b4d721..3ce2a27 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1035,18 +1035,14 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
 
 	cdev_init(&gdev->chrdev, &gpio_fileops);
 	gdev->chrdev.owner = THIS_MODULE;
-	gdev->chrdev.kobj.parent = &gdev->dev.kobj;
 	gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id);
-	status = cdev_add(&gdev->chrdev, gdev->dev.devt, 1);
-	if (status < 0)
-		chip_warn(gdev->chip, "failed to add char device %d:%d\n",
-			  MAJOR(gpio_devt), gdev->id);
-	else
-		chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
-			 MAJOR(gpio_devt), gdev->id);
-	status = device_add(&gdev->dev);
+
+	status = cdev_device_add(&gdev->chrdev, &gdev->dev);
 	if (status)
-		goto err_remove_chardev;
+		return status;
+
+	chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
+		 MAJOR(gpio_devt), gdev->id);
 
 	status = gpiochip_sysfs_register(gdev);
 	if (status)
@@ -1061,9 +1057,7 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
 	return 0;
 
 err_remove_device:
-	device_del(&gdev->dev);
-err_remove_chardev:
-	cdev_del(&gdev->chrdev);
+	cdev_device_del(&gdev->chrdev, &gdev->dev);
 	return status;
 }
 
@@ -1347,8 +1341,7 @@ void gpiochip_remove(struct gpio_chip *chip)
 	 * be removed, else it will be dangling until the last user is
 	 * gone.
 	 */
-	cdev_del(&gdev->chrdev);
-	device_del(&gdev->dev);
+	cdev_device_del(&gdev->chrdev, &gdev->dev);
 	put_device(&gdev->dev);
 }
 EXPORT_SYMBOL_GPL(gpiochip_remove);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 06/16] tpm-chip: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (4 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 05/16] gpiolib: " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06 21:04   ` Jarkko Sakkinen
  2017-03-06  7:04 ` [PATCH v3 07/16] platform/chrome: cros_ec_dev - " Logan Gunthorpe
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Replace the open coded registration of the cdev and dev with the
new device_add_cdev() helper. The helper replaces a common pattern by
taking the proper reference against the parent device and adding both
the cdev and the device.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
 drivers/char/tpm/tpm-chip.c | 19 +++----------------
 1 file changed, 3 insertions(+), 16 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index c406343..935f0e9 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -187,7 +187,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 
 	cdev_init(&chip->cdev, &tpm_fops);
 	chip->cdev.owner = THIS_MODULE;
-	chip->cdev.kobj.parent = &chip->dev.kobj;
 
 	return chip;
 
@@ -230,27 +229,16 @@ static int tpm_add_char_device(struct tpm_chip *chip)
 {
 	int rc;
 
-	rc = cdev_add(&chip->cdev, chip->dev.devt, 1);
+	rc = cdev_device_add(&chip->cdev, &chip->dev);
 	if (rc) {
 		dev_err(&chip->dev,
-			"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
+			"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
 			dev_name(&chip->dev), MAJOR(chip->dev.devt),
 			MINOR(chip->dev.devt), rc);
 
 		return rc;
 	}
 
-	rc = device_add(&chip->dev);
-	if (rc) {
-		dev_err(&chip->dev,
-			"unable to device_register() %s, major %d, minor %d, err=%d\n",
-			dev_name(&chip->dev), MAJOR(chip->dev.devt),
-			MINOR(chip->dev.devt), rc);
-
-		cdev_del(&chip->cdev);
-		return rc;
-	}
-
 	/* Make the chip available. */
 	mutex_lock(&idr_lock);
 	idr_replace(&dev_nums_idr, chip, chip->dev_num);
@@ -261,8 +249,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
 
 static void tpm_del_char_device(struct tpm_chip *chip)
 {
-	cdev_del(&chip->cdev);
-	device_del(&chip->dev);
+	cdev_device_del(&chip->cdev, &chip->dev);
 
 	/* Make the chip unavailable. */
 	mutex_lock(&idr_lock);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 07/16] platform/chrome: cros_ec_dev - utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (5 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 06/16] tpm-chip: " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 08/16] IB/ucm: " Logan Gunthorpe
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Replace the open coded registration of the cdev and dev with the
new device_add_cdev() helper. The helper replaces a common pattern by
taking the proper reference against the parent device and adding both
the cdev and the device.

At the same time we cleanup the error path through device_probe
function: we use put_device instead of kfree directly as recommended
by the device_initialize documentation.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/platform/chrome/cros_ec_dev.c | 31 +++++++------------------------
 1 file changed, 7 insertions(+), 24 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
index 6f09da4..6aa120c 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -391,7 +391,6 @@ static int ec_device_probe(struct platform_device *pdev)
 	int retval = -ENOMEM;
 	struct device *dev = &pdev->dev;
 	struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
-	dev_t devno = MKDEV(ec_major, pdev->id);
 	struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
 
 	if (!ec)
@@ -407,23 +406,11 @@ static int ec_device_probe(struct platform_device *pdev)
 	cdev_init(&ec->cdev, &fops);
 
 	/*
-	 * Add the character device
-	 * Link cdev to the class device to be sure device is not used
-	 * before unbinding it.
-	 */
-	ec->cdev.kobj.parent = &ec->class_dev.kobj;
-	retval = cdev_add(&ec->cdev, devno, 1);
-	if (retval) {
-		dev_err(dev, ": failed to add character device\n");
-		goto cdev_add_failed;
-	}
-
-	/*
 	 * Add the class device
 	 * Link to the character device for creating the /dev entry
 	 * in devtmpfs.
 	 */
-	ec->class_dev.devt = ec->cdev.dev;
+	ec->class_dev.devt = MKDEV(ec_major, pdev->id);
 	ec->class_dev.class = &cros_class;
 	ec->class_dev.parent = dev;
 	ec->class_dev.release = __remove;
@@ -431,13 +418,13 @@ static int ec_device_probe(struct platform_device *pdev)
 	retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
 	if (retval) {
 		dev_err(dev, "dev_set_name failed => %d\n", retval);
-		goto set_named_failed;
+		goto failed;
 	}
 
-	retval = device_add(&ec->class_dev);
+	retval = cdev_device_add(&ec->cdev, &ec->class_dev);
 	if (retval) {
-		dev_err(dev, "device_register failed => %d\n", retval);
-		goto dev_reg_failed;
+		dev_err(dev, "cdev_device_add failed => %d\n", retval);
+		goto failed;
 	}
 
 	/* check whether this EC is a sensor hub. */
@@ -446,12 +433,8 @@ static int ec_device_probe(struct platform_device *pdev)
 
 	return 0;
 
-dev_reg_failed:
-set_named_failed:
-	dev_set_drvdata(dev, NULL);
-	cdev_del(&ec->cdev);
-cdev_add_failed:
-	kfree(ec);
+failed:
+	put_device(&ec->class_dev);
 	return retval;
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 08/16] IB/ucm: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (6 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 07/16] platform/chrome: cros_ec_dev - " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  7:24   ` Leon Romanovsky
  2017-03-06  7:04 ` [PATCH v3 09/16] infiniband: utilize the new cdev_set_parent function Logan Gunthorpe
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>

The use after free is not triggerable here because the cdev holds
the module lock and the only device_unregister is only triggered by
module unload, however make the change for consistency.

To make this work the cdev_del needs to move out of the struct device
release function.

This cleans up the error path significantly and thus also fixes a minor
bug where the devnum would not be released if cdev_add failed.

Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/infiniband/core/ucm.c | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index cc0d51f..d15efa4 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1205,12 +1205,15 @@ static void ib_ucm_release_dev(struct device *dev)
 	struct ib_ucm_device *ucm_dev;
 
 	ucm_dev = container_of(dev, struct ib_ucm_device, dev);
-	cdev_del(&ucm_dev->cdev);
+	kfree(ucm_dev);
+}
+
+static void ib_ucm_free_dev(struct ib_ucm_device *ucm_dev)
+{
 	if (ucm_dev->devnum < IB_UCM_MAX_DEVICES)
 		clear_bit(ucm_dev->devnum, dev_map);
 	else
 		clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, overflow_map);
-	kfree(ucm_dev);
 }
 
 static const struct file_operations ucm_fops = {
@@ -1266,7 +1269,9 @@ static void ib_ucm_add_one(struct ib_device *device)
 	if (!ucm_dev)
 		return;
 
+	device_initialize(&ucm_dev->dev);
 	ucm_dev->ib_dev = device;
+	ucm_dev->dev.release = ib_ucm_release_dev;
 
 	devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES);
 	if (devnum >= IB_UCM_MAX_DEVICES) {
@@ -1286,16 +1291,14 @@ static void ib_ucm_add_one(struct ib_device *device)
 	cdev_init(&ucm_dev->cdev, &ucm_fops);
 	ucm_dev->cdev.owner = THIS_MODULE;
 	kobject_set_name(&ucm_dev->cdev.kobj, "ucm%d", ucm_dev->devnum);
-	if (cdev_add(&ucm_dev->cdev, base, 1))
-		goto err;
 
 	ucm_dev->dev.class = &cm_class;
 	ucm_dev->dev.parent = device->dev.parent;
-	ucm_dev->dev.devt = ucm_dev->cdev.dev;
-	ucm_dev->dev.release = ib_ucm_release_dev;
+	ucm_dev->dev.devt = base;
+
 	dev_set_name(&ucm_dev->dev, "ucm%d", ucm_dev->devnum);
-	if (device_register(&ucm_dev->dev))
-		goto err_cdev;
+	if (cdev_device_add(&ucm_dev->cdev, &ucm_dev->dev))
+		goto err_devnum;
 
 	if (device_create_file(&ucm_dev->dev, &dev_attr_ibdev))
 		goto err_dev;
@@ -1304,15 +1307,11 @@ static void ib_ucm_add_one(struct ib_device *device)
 	return;
 
 err_dev:
-	device_unregister(&ucm_dev->dev);
-err_cdev:
-	cdev_del(&ucm_dev->cdev);
-	if (ucm_dev->devnum < IB_UCM_MAX_DEVICES)
-		clear_bit(devnum, dev_map);
-	else
-		clear_bit(devnum, overflow_map);
+	cdev_device_del(&ucm_dev->cdev, &ucm_dev->dev);
+err_devnum:
+	ib_ucm_free_dev(ucm_dev);
 err:
-	kfree(ucm_dev);
+	put_device(&ucm_dev->dev);
 	return;
 }
 
@@ -1323,7 +1322,9 @@ static void ib_ucm_remove_one(struct ib_device *device, void *client_data)
 	if (!ucm_dev)
 		return;
 
-	device_unregister(&ucm_dev->dev);
+	cdev_device_del(&ucm_dev->cdev, &ucm_dev->dev);
+	ib_ucm_free_dev(ucm_dev);
+	put_device(&ucm_dev->dev);
 }
 
 static CLASS_ATTR_STRING(abi_version, S_IRUGO,
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 09/16] infiniband: utilize the new cdev_set_parent function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (7 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 08/16] IB/ucm: " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 10/16] iio:core: utilize new cdev_device_add helper function Logan Gunthorpe
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

This replaces the suspect looking cdev.kobj.parent lines with the
equivalent cdev_set_parent function. This is a straightforward change
that's largely cosmetic but it does push the kobj.parent ownership
into char_dev.c where it belongs.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/infiniband/core/user_mad.c    | 4 ++--
 drivers/infiniband/core/uverbs_main.c | 2 +-
 drivers/infiniband/hw/hfi1/device.c   | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index aca7ff7..25071b8 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -1183,7 +1183,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
 
 	cdev_init(&port->cdev, &umad_fops);
 	port->cdev.owner = THIS_MODULE;
-	port->cdev.kobj.parent = &umad_dev->kobj;
+	cdev_set_parent(&port->cdev, &umad_dev->kobj);
 	kobject_set_name(&port->cdev.kobj, "umad%d", port->dev_num);
 	if (cdev_add(&port->cdev, base, 1))
 		goto err_cdev;
@@ -1202,7 +1202,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
 	base += IB_UMAD_MAX_PORTS;
 	cdev_init(&port->sm_cdev, &umad_sm_fops);
 	port->sm_cdev.owner = THIS_MODULE;
-	port->sm_cdev.kobj.parent = &umad_dev->kobj;
+	cdev_set_parent(&port->sm_cdev, &umad_dev->kobj);
 	kobject_set_name(&port->sm_cdev.kobj, "issm%d", port->dev_num);
 	if (cdev_add(&port->sm_cdev, base, 1))
 		goto err_sm_cdev;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 35c788a..f02d7b9 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -1189,7 +1189,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
 	cdev_init(&uverbs_dev->cdev, NULL);
 	uverbs_dev->cdev.owner = THIS_MODULE;
 	uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
-	uverbs_dev->cdev.kobj.parent = &uverbs_dev->kobj;
+	cdev_set_parent(&uverbs_dev->cdev, &uverbs_dev->kobj);
 	kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
 	if (cdev_add(&uverbs_dev->cdev, base, 1))
 		goto err_cdev;
diff --git a/drivers/infiniband/hw/hfi1/device.c b/drivers/infiniband/hw/hfi1/device.c
index bf64b5a..bbb6069 100644
--- a/drivers/infiniband/hw/hfi1/device.c
+++ b/drivers/infiniband/hw/hfi1/device.c
@@ -69,7 +69,7 @@ int hfi1_cdev_init(int minor, const char *name,
 
 	cdev_init(cdev, fops);
 	cdev->owner = THIS_MODULE;
-	cdev->kobj.parent = parent;
+	cdev_set_parent(cdev, parent);
 	kobject_set_name(&cdev->kobj, name);
 
 	ret = cdev_add(cdev, dev, 1);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 10/16] iio:core: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (8 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 09/16] infiniband: utilize the new cdev_set_parent function Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 11/16] media: " Logan Gunthorpe
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Replace the open coded registration of the cdev and dev with the
new device_add_cdev() helper. The helper replaces a common pattern by
taking the proper reference against the parent device and adding both
the cdev and the device.

In doing so we have to remove a guard statement from cdev_del,
but this doesn't appear to be required in any way.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/iio/industrialio-core.c | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index d18ded4..26a03c6 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -1720,18 +1720,13 @@ int iio_device_register(struct iio_dev *indio_dev)
 
 	cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
 	indio_dev->chrdev.owner = indio_dev->info->driver_module;
-	indio_dev->chrdev.kobj.parent = &indio_dev->dev.kobj;
-	ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1);
-	if (ret < 0)
-		goto error_unreg_eventset;
 
-	ret = device_add(&indio_dev->dev);
+	ret = cdev_device_add(&indio_dev->chrdev, &indio_dev->dev);
 	if (ret < 0)
-		goto error_cdev_del;
+		goto error_unreg_eventset;
 
 	return 0;
-error_cdev_del:
-	cdev_del(&indio_dev->chrdev);
+
 error_unreg_eventset:
 	iio_device_unregister_eventset(indio_dev);
 error_free_sysfs:
@@ -1752,10 +1747,8 @@ void iio_device_unregister(struct iio_dev *indio_dev)
 {
 	mutex_lock(&indio_dev->info_exist_lock);
 
-	device_del(&indio_dev->dev);
+	cdev_device_del(&indio_dev->chrdev, &indio_dev->dev);
 
-	if (indio_dev->chrdev.dev)
-		cdev_del(&indio_dev->chrdev);
 	iio_device_unregister_debugfs(indio_dev);
 
 	iio_disable_all_buffers(indio_dev);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 11/16] media: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (9 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 10/16] iio:core: utilize new cdev_device_add helper function Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 12/16] mtd: " Logan Gunthorpe
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Replace the open coded registration of the cdev and dev with the
new device_add_cdev() helper. The helper replaces a common pattern by
taking the proper reference against the parent device and adding both
the cdev and the device.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/cec/cec-core.c  | 16 ++++------------
 drivers/media/media-devnode.c | 20 +++++---------------
 2 files changed, 9 insertions(+), 27 deletions(-)

diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c
index 37217e2..3163e03 100644
--- a/drivers/media/cec/cec-core.c
+++ b/drivers/media/cec/cec-core.c
@@ -137,24 +137,17 @@ static int __must_check cec_devnode_register(struct cec_devnode *devnode,
 
 	/* Part 2: Initialize and register the character device */
 	cdev_init(&devnode->cdev, &cec_devnode_fops);
-	devnode->cdev.kobj.parent = &devnode->dev.kobj;
 	devnode->cdev.owner = owner;
 
-	ret = cdev_add(&devnode->cdev, devnode->dev.devt, 1);
-	if (ret < 0) {
-		pr_err("%s: cdev_add failed\n", __func__);
+	ret = cdev_device_add(&devnode->cdev, &devnode->dev);
+	if (ret) {
+		pr_err("%s: cdev_device_add failed\n", __func__);
 		goto clr_bit;
 	}
 
-	ret = device_add(&devnode->dev);
-	if (ret)
-		goto cdev_del;
-
 	devnode->registered = true;
 	return 0;
 
-cdev_del:
-	cdev_del(&devnode->cdev);
 clr_bit:
 	mutex_lock(&cec_devnode_lock);
 	clear_bit(devnode->minor, cec_devnode_nums);
@@ -190,8 +183,7 @@ static void cec_devnode_unregister(struct cec_devnode *devnode)
 	devnode->unregistered = true;
 	mutex_unlock(&devnode->lock);
 
-	device_del(&devnode->dev);
-	cdev_del(&devnode->cdev);
+	cdev_device_del(&devnode->cdev, &devnode->dev);
 	put_device(&devnode->dev);
 }
 
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index ae46753..423248f 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -248,31 +248,22 @@ int __must_check media_devnode_register(struct media_device *mdev,
 	dev_set_name(&devnode->dev, "media%d", devnode->minor);
 	device_initialize(&devnode->dev);
 
-	/* Part 2: Initialize and register the character device */
+	/* Part 2: Initialize the character device */
 	cdev_init(&devnode->cdev, &media_devnode_fops);
 	devnode->cdev.owner = owner;
-	devnode->cdev.kobj.parent = &devnode->dev.kobj;
 
-	ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
+	/* Part 3: Add the media and char device */
+	ret = cdev_device_add(&devnode->cdev, &devnode->dev);
 	if (ret < 0) {
-		pr_err("%s: cdev_add failed\n", __func__);
+		pr_err("%s: cdev_device_add failed\n", __func__);
 		goto cdev_add_error;
 	}
 
-	/* Part 3: Add the media device */
-	ret = device_add(&devnode->dev);
-	if (ret < 0) {
-		pr_err("%s: device_add failed\n", __func__);
-		goto device_add_error;
-	}
-
 	/* Part 4: Activate this minor. The char device can now be used. */
 	set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
 
 	return 0;
 
-device_add_error:
-	cdev_del(&devnode->cdev);
 cdev_add_error:
 	mutex_lock(&media_devnode_lock);
 	clear_bit(devnode->minor, media_devnode_nums);
@@ -298,9 +289,8 @@ void media_devnode_unregister(struct media_devnode *devnode)
 {
 	mutex_lock(&media_devnode_lock);
 	/* Delete the cdev on this minor as well */
-	cdev_del(&devnode->cdev);
+	cdev_device_del(&devnode->cdev, &devnode->dev);
 	mutex_unlock(&media_devnode_lock);
-	device_del(&devnode->dev);
 	devnode->media_dev = NULL;
 	put_device(&devnode->dev);
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 12/16] mtd: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (10 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 11/16] media: " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 13/16] rapidio: " Logan Gunthorpe
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

This is not as straightforward a conversion as the others
in this series. These drivers did not originally make use of
kobj.parent so they likely suffered from a use after free bug if
someone unregistered the devices while they are being used.

In order to make the conversions, switch from device_register
to device_initialize / cdev_device_add.

In build.c, this patch unwinds a complicated mess of extra
get_device/put_devices and reference tracking by moving device_initialize
early in the attach process. Then it always uses put_device and instead of
using device_unregister and extra get_devices everywhere we just use
cdev_device_del and one put_device once everything is completely done.
This simplifies things dramatically and makes it easier to reason about.

In vmt.c, the patch pushes device initialization up to the beginning of the
device creation and then that function only needs to use put_device
in the error path which simplifies things a good deal.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/mtd/ubi/build.c | 91 +++++++++----------------------------------------
 drivers/mtd/ubi/vmt.c   | 49 +++++++++-----------------
 2 files changed, 33 insertions(+), 107 deletions(-)

diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 7751319..8bae373 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -421,41 +421,6 @@ static void dev_release(struct device *dev)
 }
 
 /**
- * ubi_sysfs_init - initialize sysfs for an UBI device.
- * @ubi: UBI device description object
- * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
- *       taken
- *
- * This function returns zero in case of success and a negative error code in
- * case of failure.
- */
-static int ubi_sysfs_init(struct ubi_device *ubi, int *ref)
-{
-	int err;
-
-	ubi->dev.release = dev_release;
-	ubi->dev.devt = ubi->cdev.dev;
-	ubi->dev.class = &ubi_class;
-	ubi->dev.groups = ubi_dev_groups;
-	dev_set_name(&ubi->dev, UBI_NAME_STR"%d", ubi->ubi_num);
-	err = device_register(&ubi->dev);
-	if (err)
-		return err;
-
-	*ref = 1;
-	return 0;
-}
-
-/**
- * ubi_sysfs_close - close sysfs for an UBI device.
- * @ubi: UBI device description object
- */
-static void ubi_sysfs_close(struct ubi_device *ubi)
-{
-	device_unregister(&ubi->dev);
-}
-
-/**
  * kill_volumes - destroy all user volumes.
  * @ubi: UBI device description object
  */
@@ -471,27 +436,19 @@ static void kill_volumes(struct ubi_device *ubi)
 /**
  * uif_init - initialize user interfaces for an UBI device.
  * @ubi: UBI device description object
- * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
- *       taken, otherwise set to %0
  *
  * This function initializes various user interfaces for an UBI device. If the
  * initialization fails at an early stage, this function frees all the
- * resources it allocated, returns an error, and @ref is set to %0. However,
- * if the initialization fails after the UBI device was registered in the
- * driver core subsystem, this function takes a reference to @ubi->dev, because
- * otherwise the release function ('dev_release()') would free whole @ubi
- * object. The @ref argument is set to %1 in this case. The caller has to put
- * this reference.
+ * resources it allocated, returns an error.
  *
  * This function returns zero in case of success and a negative error code in
  * case of failure.
  */
-static int uif_init(struct ubi_device *ubi, int *ref)
+static int uif_init(struct ubi_device *ubi)
 {
 	int i, err;
 	dev_t dev;
 
-	*ref = 0;
 	sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
 
 	/*
@@ -508,20 +465,17 @@ static int uif_init(struct ubi_device *ubi, int *ref)
 		return err;
 	}
 
+	ubi->dev.devt = dev;
+
 	ubi_assert(MINOR(dev) == 0);
 	cdev_init(&ubi->cdev, &ubi_cdev_operations);
 	dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev));
 	ubi->cdev.owner = THIS_MODULE;
 
-	err = cdev_add(&ubi->cdev, dev, 1);
-	if (err) {
-		ubi_err(ubi, "cannot add character device");
-		goto out_unreg;
-	}
-
-	err = ubi_sysfs_init(ubi, ref);
+	dev_set_name(&ubi->dev, UBI_NAME_STR "%d", ubi->ubi_num);
+	err = cdev_device_add(&ubi->cdev, &ubi->dev);
 	if (err)
-		goto out_sysfs;
+		goto out_unreg;
 
 	for (i = 0; i < ubi->vtbl_slots; i++)
 		if (ubi->volumes[i]) {
@@ -536,11 +490,7 @@ static int uif_init(struct ubi_device *ubi, int *ref)
 
 out_volumes:
 	kill_volumes(ubi);
-out_sysfs:
-	if (*ref)
-		get_device(&ubi->dev);
-	ubi_sysfs_close(ubi);
-	cdev_del(&ubi->cdev);
+	cdev_device_del(&ubi->cdev, &ubi->dev);
 out_unreg:
 	unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
 	ubi_err(ubi, "cannot initialize UBI %s, error %d",
@@ -559,8 +509,7 @@ static int uif_init(struct ubi_device *ubi, int *ref)
 static void uif_close(struct ubi_device *ubi)
 {
 	kill_volumes(ubi);
-	ubi_sysfs_close(ubi);
-	cdev_del(&ubi->cdev);
+	cdev_device_del(&ubi->cdev, &ubi->dev);
 	unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
 }
 
@@ -857,7 +806,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
 		       int vid_hdr_offset, int max_beb_per1024)
 {
 	struct ubi_device *ubi;
-	int i, err, ref = 0;
+	int i, err;
 
 	if (max_beb_per1024 < 0 || max_beb_per1024 > MAX_MTD_UBI_BEB_LIMIT)
 		return -EINVAL;
@@ -919,6 +868,11 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
 	if (!ubi)
 		return -ENOMEM;
 
+	device_initialize(&ubi->dev);
+	ubi->dev.release = dev_release;
+	ubi->dev.class = &ubi_class;
+	ubi->dev.groups = ubi_dev_groups;
+
 	ubi->mtd = mtd;
 	ubi->ubi_num = ubi_num;
 	ubi->vid_hdr_offset = vid_hdr_offset;
@@ -995,7 +949,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
 	/* Make device "available" before it becomes accessible via sysfs */
 	ubi_devices[ubi_num] = ubi;
 
-	err = uif_init(ubi, &ref);
+	err = uif_init(ubi);
 	if (err)
 		goto out_detach;
 
@@ -1045,8 +999,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
 out_debugfs:
 	ubi_debugfs_exit_dev(ubi);
 out_uif:
-	get_device(&ubi->dev);
-	ubi_assert(ref);
 	uif_close(ubi);
 out_detach:
 	ubi_devices[ubi_num] = NULL;
@@ -1056,10 +1008,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
 out_free:
 	vfree(ubi->peb_buf);
 	vfree(ubi->fm_buf);
-	if (ref)
-		put_device(&ubi->dev);
-	else
-		kfree(ubi);
+	put_device(&ubi->dev);
 	return err;
 }
 
@@ -1120,12 +1069,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
 	if (ubi->bgt_thread)
 		kthread_stop(ubi->bgt_thread);
 
-	/*
-	 * Get a reference to the device in order to prevent 'dev_release()'
-	 * from freeing the @ubi object.
-	 */
-	get_device(&ubi->dev);
-
 	ubi_debugfs_exit_dev(ubi);
 	uif_close(ubi);
 
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 7ac78c1..85237cf 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -155,11 +155,10 @@ static void vol_release(struct device *dev)
  */
 int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 {
-	int i, err, vol_id = req->vol_id, do_free = 1;
+	int i, err, vol_id = req->vol_id;
 	struct ubi_volume *vol;
 	struct ubi_vtbl_record vtbl_rec;
 	struct ubi_eba_table *eba_tbl = NULL;
-	dev_t dev;
 
 	if (ubi->ro_mode)
 		return -EROFS;
@@ -168,6 +167,12 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 	if (!vol)
 		return -ENOMEM;
 
+	device_initialize(&vol->dev);
+	vol->dev.release = vol_release;
+	vol->dev.parent = &ubi->dev;
+	vol->dev.class = &ubi_class;
+	vol->dev.groups = volume_dev_groups;
+
 	spin_lock(&ubi->volumes_lock);
 	if (vol_id == UBI_VOL_NUM_AUTO) {
 		/* Find unused volume ID */
@@ -268,24 +273,13 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 	/* Register character device for the volume */
 	cdev_init(&vol->cdev, &ubi_vol_cdev_operations);
 	vol->cdev.owner = THIS_MODULE;
-	dev = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1);
-	err = cdev_add(&vol->cdev, dev, 1);
-	if (err) {
-		ubi_err(ubi, "cannot add character device");
-		goto out_mapping;
-	}
-
-	vol->dev.release = vol_release;
-	vol->dev.parent = &ubi->dev;
-	vol->dev.devt = dev;
-	vol->dev.class = &ubi_class;
-	vol->dev.groups = volume_dev_groups;
 
+	vol->dev.devt = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1);
 	dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);
-	err = device_register(&vol->dev);
+	err = cdev_device_add(&vol->cdev, &vol->dev);
 	if (err) {
-		ubi_err(ubi, "cannot register device");
-		goto out_cdev;
+		ubi_err(ubi, "cannot add device");
+		goto out_mapping;
 	}
 
 	/* Fill volume table record */
@@ -318,28 +312,17 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
 	 * We have registered our device, we should not free the volume
 	 * description object in this function in case of an error - it is
 	 * freed by the release function.
-	 *
-	 * Get device reference to prevent the release function from being
-	 * called just after sysfs has been closed.
 	 */
-	do_free = 0;
-	get_device(&vol->dev);
-	device_unregister(&vol->dev);
-out_cdev:
-	cdev_del(&vol->cdev);
+	cdev_device_del(&vol->cdev, &vol->dev);
 out_mapping:
-	if (do_free)
-		ubi_eba_destroy_table(eba_tbl);
+	ubi_eba_destroy_table(eba_tbl);
 out_acc:
 	spin_lock(&ubi->volumes_lock);
 	ubi->rsvd_pebs -= vol->reserved_pebs;
 	ubi->avail_pebs += vol->reserved_pebs;
 out_unlock:
 	spin_unlock(&ubi->volumes_lock);
-	if (do_free)
-		kfree(vol);
-	else
-		put_device(&vol->dev);
+	put_device(&vol->dev);
 	ubi_err(ubi, "cannot create volume %d, error %d", vol_id, err);
 	return err;
 }
@@ -391,8 +374,8 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
 			goto out_err;
 	}
 
-	cdev_del(&vol->cdev);
-	device_unregister(&vol->dev);
+	cdev_device_del(&vol->cdev, &vol->dev);
+	put_device(&vol->dev);
 
 	spin_lock(&ubi->volumes_lock);
 	ubi->rsvd_pebs -= reserved_pebs;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 13/16] rapidio: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (11 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 12/16] mtd: " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 14/16] rtc: " Logan Gunthorpe
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

This driver did not originally set kobj.parent so it likely had
potential a use after free bug which this patch fixes.

We convert from device_register to device_initialize/cdev_device_add.
While we are at it we use put_device instead of kfree (as recommended
by the device_initialize documentation). We also remove an unnecessary
extra get_device from the code.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/rapidio/devices/rio_mport_cdev.c | 24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c
index 50b617a..5beb0c3 100644
--- a/drivers/rapidio/devices/rio_mport_cdev.c
+++ b/drivers/rapidio/devices/rio_mport_cdev.c
@@ -2444,31 +2444,25 @@ static struct mport_dev *mport_cdev_add(struct rio_mport *mport)
 	mutex_init(&md->buf_mutex);
 	mutex_init(&md->file_mutex);
 	INIT_LIST_HEAD(&md->file_list);
-	cdev_init(&md->cdev, &mport_fops);
-	md->cdev.owner = THIS_MODULE;
-	ret = cdev_add(&md->cdev, MKDEV(MAJOR(dev_number), mport->id), 1);
-	if (ret < 0) {
-		kfree(md);
-		rmcd_error("Unable to register a device, err=%d", ret);
-		return NULL;
-	}
 
-	md->dev.devt = md->cdev.dev;
+	device_initialize(&md->dev);
+	md->dev.devt = MKDEV(MAJOR(dev_number), mport->id);
 	md->dev.class = dev_class;
 	md->dev.parent = &mport->dev;
 	md->dev.release = mport_device_release;
 	dev_set_name(&md->dev, DEV_NAME "%d", mport->id);
 	atomic_set(&md->active, 1);
 
-	ret = device_register(&md->dev);
+	cdev_init(&md->cdev, &mport_fops);
+	md->cdev.owner = THIS_MODULE;
+
+	ret = cdev_device_add(&md->cdev, &md->dev);
 	if (ret) {
 		rmcd_error("Failed to register mport %d (err=%d)",
 		       mport->id, ret);
 		goto err_cdev;
 	}
 
-	get_device(&md->dev);
-
 	INIT_LIST_HEAD(&md->doorbells);
 	spin_lock_init(&md->db_lock);
 	INIT_LIST_HEAD(&md->portwrites);
@@ -2513,8 +2507,7 @@ static struct mport_dev *mport_cdev_add(struct rio_mport *mport)
 	return md;
 
 err_cdev:
-	cdev_del(&md->cdev);
-	kfree(md);
+	put_device(&md->dev);
 	return NULL;
 }
 
@@ -2578,7 +2571,7 @@ static void mport_cdev_remove(struct mport_dev *md)
 	atomic_set(&md->active, 0);
 	mport_cdev_terminate_dma(md);
 	rio_del_mport_pw_handler(md->mport, md, rio_mport_pw_handler);
-	cdev_del(&(md->cdev));
+	cdev_device_del(&md->cdev, &md->dev);
 	mport_cdev_kill_fasync(md);
 
 	flush_workqueue(dma_wq);
@@ -2603,7 +2596,6 @@ static void mport_cdev_remove(struct mport_dev *md)
 
 	rio_release_inb_dbell(md->mport, 0, 0x0fff);
 
-	device_unregister(&md->dev);
 	put_device(&md->dev);
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 14/16] rtc: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (12 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 13/16] rapidio: " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-07 22:41   ` Alexandre Belloni
  2017-03-06  7:04 ` [PATCH v3 15/16] scsi: " Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 16/16] switchtec: utilize new device_add_cdev " Logan Gunthorpe
  15 siblings, 1 reply; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Mostly straightforward, but we had to remove the rtc_dev_add/del_device
functions as they split up the cdev_add and the device_add.

Doing this also revealed that there was likely another subtle bug:
seeing cdev_add was done after device_register, the cdev probably
was not ready before device_add when the uevent occurs. This would
race with userspace, if it tried to use the device directly after
the uevent. This is fixed just by using the new helper function.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/rtc/class.c   | 14 ++++++++++----
 drivers/rtc/rtc-dev.c | 17 -----------------
 2 files changed, 10 insertions(+), 21 deletions(-)

diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 74fd974..5fb4398 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -195,6 +195,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
 		goto exit_ida;
 	}
 
+	device_initialize(&rtc->dev);
+
 	rtc->id = id;
 	rtc->ops = ops;
 	rtc->owner = owner;
@@ -233,14 +235,19 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
 
 	rtc_dev_prepare(rtc);
 
-	err = device_register(&rtc->dev);
+	err = cdev_device_add(&rtc->char_dev, &rtc->dev);
 	if (err) {
+		dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n",
+			 rtc->name, MAJOR(rtc->dev.devt), rtc->id);
+
 		/* This will free both memory and the ID */
 		put_device(&rtc->dev);
 		goto exit;
+	} else {
+		dev_dbg(&rtc->dev, "%s: dev (%d:%d)\n", rtc->name,
+			MAJOR(rtc->dev.devt), rtc->id);
 	}
 
-	rtc_dev_add_device(rtc);
 	rtc_proc_add_device(rtc);
 
 	dev_info(dev, "rtc core: registered %s as %s\n",
@@ -271,9 +278,8 @@ void rtc_device_unregister(struct rtc_device *rtc)
 	 * Remove innards of this RTC, then disable it, before
 	 * letting any rtc_class_open() users access it again
 	 */
-	rtc_dev_del_device(rtc);
 	rtc_proc_del_device(rtc);
-	device_del(&rtc->dev);
+	cdev_device_del(&rtc->char_dev, &rtc->dev);
 	rtc->ops = NULL;
 	mutex_unlock(&rtc->ops_lock);
 	put_device(&rtc->dev);
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 6dc8f29..e81a871 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -477,23 +477,6 @@ void rtc_dev_prepare(struct rtc_device *rtc)
 
 	cdev_init(&rtc->char_dev, &rtc_dev_fops);
 	rtc->char_dev.owner = rtc->owner;
-	rtc->char_dev.kobj.parent = &rtc->dev.kobj;
-}
-
-void rtc_dev_add_device(struct rtc_device *rtc)
-{
-	if (cdev_add(&rtc->char_dev, rtc->dev.devt, 1))
-		dev_warn(&rtc->dev, "%s: failed to add char device %d:%d\n",
-			rtc->name, MAJOR(rtc_devt), rtc->id);
-	else
-		dev_dbg(&rtc->dev, "%s: dev (%d:%d)\n", rtc->name,
-			MAJOR(rtc_devt), rtc->id);
-}
-
-void rtc_dev_del_device(struct rtc_device *rtc)
-{
-	if (rtc->dev.devt)
-		cdev_del(&rtc->char_dev);
 }
 
 void __init rtc_dev_init(void)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 15/16] scsi: utilize new cdev_device_add helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (13 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 14/16] rtc: " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-06  7:04 ` [PATCH v3 16/16] switchtec: utilize new device_add_cdev " Logan Gunthorpe
  15 siblings, 0 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

This driver did not set kobj.parent so it likely suffered from
a potential use after free race if the user unregistered the
device while it was in use.

This was not so straightforward a conversion but I think this patch
cleans up its probe's error path significantly.

This patch adds device_initialize, which is required for
cdev_device_add. Then it switches to put_device instead of kfree as
recommended by device_initialize's documentation. This removes a lot
from the error path which was already in __remove.
A couple things needed to be re-ordered to be entirely correct, though.
ida_remove is also moved out of __remove and into unregister to
simplify things and follow the pattern other devices are using.

This also drop an extra unnecessary get_device/put_device in the code.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/scsi/osd/osd_uld.c | 56 +++++++++++++++++-----------------------------
 1 file changed, 20 insertions(+), 36 deletions(-)

diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index e0ce5d2..4101c31 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -400,9 +400,6 @@ static void __remove(struct device *dev)
 
 	kfree(oud->odi.osdname);
 
-	if (oud->cdev.owner)
-		cdev_del(&oud->cdev);
-
 	osd_dev_fini(&oud->od);
 	scsi_device_put(scsi_device);
 
@@ -411,7 +408,6 @@ static void __remove(struct device *dev)
 
 	if (oud->disk)
 		put_disk(oud->disk);
-	ida_remove(&osd_minor_ida, oud->minor);
 
 	kfree(oud);
 }
@@ -446,8 +442,20 @@ static int osd_probe(struct device *dev)
 	if (NULL == oud)
 		goto err_retract_minor;
 
+	/* class device member */
+	device_initialize(&oud->class_dev);
 	dev_set_drvdata(dev, oud);
 	oud->minor = minor;
+	oud->class_dev.devt = MKDEV(SCSI_OSD_MAJOR, oud->minor);
+	oud->class_dev.class = &osd_uld_class;
+	oud->class_dev.parent = dev;
+	oud->class_dev.release = __remove;
+
+	/* hold one more reference to the scsi_device that will get released
+	 * in __release, in case a logout is happening while fs is mounted
+	 */
+	scsi_device_get(scsi_device);
+	osd_dev_init(&oud->od, scsi_device);
 
 	/* allocate a disk and set it up */
 	/* FIXME: do we need this since sg has already done that */
@@ -461,59 +469,34 @@ static int osd_probe(struct device *dev)
 	sprintf(disk->disk_name, "osd%d", oud->minor);
 	oud->disk = disk;
 
-	/* hold one more reference to the scsi_device that will get released
-	 * in __release, in case a logout is happening while fs is mounted
-	 */
-	scsi_device_get(scsi_device);
-	osd_dev_init(&oud->od, scsi_device);
-
 	/* Detect the OSD Version */
 	error = __detect_osd(oud);
 	if (error) {
 		OSD_ERR("osd detection failed, non-compatible OSD device\n");
-		goto err_put_disk;
+		goto err_free_osd;
 	}
 
 	/* init the char-device for communication with user-mode */
 	cdev_init(&oud->cdev, &osd_fops);
 	oud->cdev.owner = THIS_MODULE;
-	error = cdev_add(&oud->cdev,
-			 MKDEV(SCSI_OSD_MAJOR, oud->minor), 1);
-	if (error) {
-		OSD_ERR("cdev_add failed\n");
-		goto err_put_disk;
-	}
 
-	/* class device member */
-	oud->class_dev.devt = oud->cdev.dev;
-	oud->class_dev.class = &osd_uld_class;
-	oud->class_dev.parent = dev;
-	oud->class_dev.release = __remove;
 	error = dev_set_name(&oud->class_dev, "%s", disk->disk_name);
 	if (error) {
 		OSD_ERR("dev_set_name failed => %d\n", error);
-		goto err_put_cdev;
+		goto err_free_osd;
 	}
 
-	error = device_register(&oud->class_dev);
+	error = cdev_device_add(&oud->cdev, &oud->class_dev);
 	if (error) {
 		OSD_ERR("device_register failed => %d\n", error);
-		goto err_put_cdev;
+		goto err_free_osd;
 	}
 
-	get_device(&oud->class_dev);
-
 	OSD_INFO("osd_probe %s\n", disk->disk_name);
 	return 0;
 
-err_put_cdev:
-	cdev_del(&oud->cdev);
-err_put_disk:
-	scsi_device_put(scsi_device);
-	put_disk(disk);
 err_free_osd:
-	dev_set_drvdata(dev, NULL);
-	kfree(oud);
+	put_device(&oud->class_dev);
 err_retract_minor:
 	ida_remove(&osd_minor_ida, minor);
 	return error;
@@ -530,9 +513,10 @@ static int osd_remove(struct device *dev)
 			scsi_device);
 	}
 
-	device_unregister(&oud->class_dev);
-
+	cdev_device_del(&oud->cdev, &oud->class_dev);
+	ida_remove(&osd_minor_ida, oud->minor);
 	put_device(&oud->class_dev);
+
 	return 0;
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 16/16] switchtec: utilize new device_add_cdev helper function
  2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
                   ` (14 preceding siblings ...)
  2017-03-06  7:04 ` [PATCH v3 15/16] scsi: " Logan Gunthorpe
@ 2017-03-06  7:04 ` Logan Gunthorpe
  2017-03-16  8:42   ` Greg Kroah-Hartman
  15 siblings, 1 reply; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-06  7:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

Very straightforward conversion to device_add_cdev. Drop cdev_add and
device_add and use cdev_device_add.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/pci/switch/switchtec.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index 1f045c9..e27fd29 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -1291,7 +1291,6 @@ static struct switchtec_dev *stdev_create(struct pci_dev *pdev)
 	cdev = &stdev->cdev;
 	cdev_init(cdev, &switchtec_fops);
 	cdev->owner = THIS_MODULE;
-	cdev->kobj.parent = &dev->kobj;
 
 	return stdev;
 
@@ -1479,11 +1478,7 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
 		  SWITCHTEC_EVENT_EN_IRQ,
 		  &stdev->mmio_part_cfg->mrpc_comp_hdr);
 
-	rc = cdev_add(&stdev->cdev, stdev->dev.devt, 1);
-	if (rc)
-		goto err_put;
-
-	rc = device_add(&stdev->dev);
+	rc = cdev_device_add(&stdev->cdev, &stdev->dev);
 	if (rc)
 		goto err_devadd;
 
@@ -1492,7 +1487,6 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
 	return 0;
 
 err_devadd:
-	cdev_del(&stdev->cdev);
 	stdev_kill(stdev);
 err_put:
 	ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
@@ -1506,8 +1500,7 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
 
 	pci_set_drvdata(pdev, NULL);
 
-	device_del(&stdev->dev);
-	cdev_del(&stdev->cdev);
+	cdev_device_del(&stdev->cdev, &stdev->dev);
 	ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
 	dev_info(&stdev->dev, "unregistered.\n");
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 08/16] IB/ucm: utilize new cdev_device_add helper function
  2017-03-06  7:04 ` [PATCH v3 08/16] IB/ucm: " Logan Gunthorpe
@ 2017-03-06  7:24   ` Leon Romanovsky
  0 siblings, 0 replies; 31+ messages in thread
From: Leon Romanovsky @ 2017-03-06  7:24 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Hans Verkuil,
	Mauro Carvalho Chehab, Artem Bityutskiy, Richard Weinberger,
	David Woodhouse, Brian Norris, Boris Brezillon, Marek Vasut,
	Cyrille Pitchen, Matt Porter, Alexandre Bounine, Andrew Morton,
	Joe Perches, Lorenzo Stoakes, Vladimir Zapolskiy,
	Alessandro Zummo, Alexandre Belloni, Boaz Harrosh,
	James E.J. Bottomley, Martin K. Petersen, Stephen Bates,
	Bjorn Helgaas, linux-pci, linux-scsi, rtc-linux, linux-mtd,
	linux-media, linux-iio, linux-rdma, linux-gpio, linux-input,
	linux-nvdimm, linux-fsdevel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 799 bytes --]

On Mon, Mar 06, 2017 at 12:04:24AM -0700, Logan Gunthorpe wrote:
> From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
>
> The use after free is not triggerable here because the cdev holds
> the module lock and the only device_unregister is only triggered by
> module unload, however make the change for consistency.
>
> To make this work the cdev_del needs to move out of the struct device
> release function.
>
> This cleans up the error path significantly and thus also fixes a minor
> bug where the devnum would not be released if cdev_add failed.
>
> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Thanks,
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 02/16] device-dax: fix cdev leak
  2017-03-06  7:04 ` [PATCH v3 02/16] device-dax: fix cdev leak Logan Gunthorpe
@ 2017-03-06  8:27   ` Johannes Thumshirn
  0 siblings, 0 replies; 31+ messages in thread
From: Johannes Thumshirn @ 2017-03-06  8:27 UTC (permalink / raw)
  To: Logan Gunthorpe, Greg Kroah-Hartman, Dan Williams,
	Alexander Viro, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel, stable

On 03/06/2017 08:04 AM, Logan Gunthorpe wrote:
> From: Dan Williams <dan.j.williams@intel.com>
> 
> If device_add() fails, cleanup the cdev. Otherwise, we leak a kobj_map()
> with a stale device number.
> 
> As Jason points out, there is a small possibility that userspace has
> opened and mapped the device in the time between cdev_add() and the
> device_add() failure. We need a new kill_dax_dev() helper to invalidate
> any established mappings.
> 
> Fixes: ba09c01d2fa8 ("dax: convert to the cdev api")
> Cc: <stable@vger.kernel.org>
> Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Looks good,
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>


-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 03/16] device-dax: utilize new cdev_device_add helper function
  2017-03-06  7:04 ` [PATCH v3 03/16] device-dax: utilize new cdev_device_add helper function Logan Gunthorpe
@ 2017-03-06  8:29   ` Johannes Thumshirn
  0 siblings, 0 replies; 31+ messages in thread
From: Johannes Thumshirn @ 2017-03-06  8:29 UTC (permalink / raw)
  To: Logan Gunthorpe, Greg Kroah-Hartman, Dan Williams,
	Alexander Viro, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Alexandre Belloni,
	Boaz Harrosh, James E.J. Bottomley, Martin K. Petersen,
	Stephen Bates, Bjorn Helgaas
  Cc: linux-pci, linux-scsi, rtc-linux, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, linux-input, linux-nvdimm,
	linux-fsdevel, linux-kernel

On 03/06/2017 08:04 AM, Logan Gunthorpe wrote:
> Replace the open coded registration of the cdev and dev with the
> new device_add_cdev() helper. The helper replaces a common pattern by
> taking the proper reference against the parent device and adding both
> the cdev and the device.
> 
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> ---

Looks good,
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>

-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 06/16] tpm-chip: utilize new cdev_device_add helper function
  2017-03-06  7:04 ` [PATCH v3 06/16] tpm-chip: " Logan Gunthorpe
@ 2017-03-06 21:04   ` Jarkko Sakkinen
  2017-03-07  5:31     ` Greg Kroah-Hartman
  0 siblings, 1 reply; 31+ messages in thread
From: Jarkko Sakkinen @ 2017-03-06 21:04 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jason Gunthorpe, Olof Johansson, Doug Ledford,
	Sean Hefty, Hal Rosenstock, Dmitry Vyukov, Haggai Eran,
	Parav Pandit, Leon Romanovsky, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Hans Verkuil,
	Mauro Carvalho Chehab, Artem Bityutskiy, Richard Weinberger,
	David Woodhouse, Brian Norris, Boris Brezillon, Marek Vasut,
	Cyrille Pitchen, Matt Porter, Alexandre Bounine, Andrew Morton,
	Joe Perches, Lorenzo Stoakes, Vladimir Zapolskiy,
	Alessandro Zummo, Alexandre Belloni, Boaz Harrosh,
	James E.J. Bottomley, Martin K. Petersen, Stephen Bates,
	Bjorn Helgaas, linux-pci, linux-scsi, rtc-linux, linux-mtd,
	linux-media, linux-iio, linux-rdma, linux-gpio, linux-input,
	linux-nvdimm, linux-fsdevel, linux-kernel

On Mon, Mar 06, 2017 at 12:04:22AM -0700, Logan Gunthorpe wrote:
> Replace the open coded registration of the cdev and dev with the
> new device_add_cdev() helper. The helper replaces a common pattern by
> taking the proper reference against the parent device and adding both
> the cdev and the device.
> 
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> ---
>  drivers/char/tpm/tpm-chip.c | 19 +++----------------
>  1 file changed, 3 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index c406343..935f0e9 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -187,7 +187,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
>  
>  	cdev_init(&chip->cdev, &tpm_fops);
>  	chip->cdev.owner = THIS_MODULE;
> -	chip->cdev.kobj.parent = &chip->dev.kobj;
>  
>  	return chip;
>  
> @@ -230,27 +229,16 @@ static int tpm_add_char_device(struct tpm_chip *chip)
>  {
>  	int rc;
>  
> -	rc = cdev_add(&chip->cdev, chip->dev.devt, 1);
> +	rc = cdev_device_add(&chip->cdev, &chip->dev);
>  	if (rc) {
>  		dev_err(&chip->dev,
> -			"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
> +			"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
>  			dev_name(&chip->dev), MAJOR(chip->dev.devt),
>  			MINOR(chip->dev.devt), rc);
>  
>  		return rc;
>  	}
>  
> -	rc = device_add(&chip->dev);
> -	if (rc) {
> -		dev_err(&chip->dev,
> -			"unable to device_register() %s, major %d, minor %d, err=%d\n",
> -			dev_name(&chip->dev), MAJOR(chip->dev.devt),
> -			MINOR(chip->dev.devt), rc);
> -
> -		cdev_del(&chip->cdev);
> -		return rc;
> -	}
> -
>  	/* Make the chip available. */
>  	mutex_lock(&idr_lock);
>  	idr_replace(&dev_nums_idr, chip, chip->dev_num);
> @@ -261,8 +249,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
>  
>  static void tpm_del_char_device(struct tpm_chip *chip)
>  {
> -	cdev_del(&chip->cdev);
> -	device_del(&chip->dev);
> +	cdev_device_del(&chip->cdev, &chip->dev);
>  
>  	/* Make the chip unavailable. */
>  	mutex_lock(&idr_lock);
> -- 
> 2.1.4
> 

Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>

I cannot test this at this point as security tree does not include
the commit that is dependent on this. I'm also wondering if this
commit is even going through my tree to upstream?

/Jarkko

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 06/16] tpm-chip: utilize new cdev_device_add helper function
  2017-03-06 21:04   ` Jarkko Sakkinen
@ 2017-03-07  5:31     ` Greg Kroah-Hartman
  2017-03-07  8:31       ` Jarkko Sakkinen
  0 siblings, 1 reply; 31+ messages in thread
From: Greg Kroah-Hartman @ 2017-03-07  5:31 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Logan Gunthorpe, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jason Gunthorpe, Olof Johansson, Doug Ledford,
	Sean Hefty, Hal Rosenstock, Dmitry Vyukov, Haggai Eran,
	Parav Pandit, Leon Romanovsky, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Hans Verkuil,
	Mauro Carvalho Chehab, Artem Bityutskiy, Richard Weinberger,
	David Woodhouse, Brian Norris, Boris Brezillon, Marek Vasut,
	Cyrille Pitchen, Matt Porter, Alexandre Bounine, Andrew Morton,
	Joe Perches, Lorenzo Stoakes, Vladimir Zapolskiy,
	Alessandro Zummo, Alexandre Belloni, Boaz Harrosh,
	James E.J. Bottomley, Martin K. Petersen, Stephen Bates,
	Bjorn Helgaas, linux-pci, linux-scsi, rtc-linux, linux-mtd,
	linux-media, linux-iio, linux-rdma, linux-gpio, linux-input,
	linux-nvdimm, linux-fsdevel, linux-kernel

On Mon, Mar 06, 2017 at 11:04:26PM +0200, Jarkko Sakkinen wrote:
> On Mon, Mar 06, 2017 at 12:04:22AM -0700, Logan Gunthorpe wrote:
> > Replace the open coded registration of the cdev and dev with the
> > new device_add_cdev() helper. The helper replaces a common pattern by
> > taking the proper reference against the parent device and adding both
> > the cdev and the device.
> > 
> > Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> > Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> > ---
> >  drivers/char/tpm/tpm-chip.c | 19 +++----------------
> >  1 file changed, 3 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> > index c406343..935f0e9 100644
> > --- a/drivers/char/tpm/tpm-chip.c
> > +++ b/drivers/char/tpm/tpm-chip.c
> > @@ -187,7 +187,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
> >  
> >  	cdev_init(&chip->cdev, &tpm_fops);
> >  	chip->cdev.owner = THIS_MODULE;
> > -	chip->cdev.kobj.parent = &chip->dev.kobj;
> >  
> >  	return chip;
> >  
> > @@ -230,27 +229,16 @@ static int tpm_add_char_device(struct tpm_chip *chip)
> >  {
> >  	int rc;
> >  
> > -	rc = cdev_add(&chip->cdev, chip->dev.devt, 1);
> > +	rc = cdev_device_add(&chip->cdev, &chip->dev);
> >  	if (rc) {
> >  		dev_err(&chip->dev,
> > -			"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
> > +			"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
> >  			dev_name(&chip->dev), MAJOR(chip->dev.devt),
> >  			MINOR(chip->dev.devt), rc);
> >  
> >  		return rc;
> >  	}
> >  
> > -	rc = device_add(&chip->dev);
> > -	if (rc) {
> > -		dev_err(&chip->dev,
> > -			"unable to device_register() %s, major %d, minor %d, err=%d\n",
> > -			dev_name(&chip->dev), MAJOR(chip->dev.devt),
> > -			MINOR(chip->dev.devt), rc);
> > -
> > -		cdev_del(&chip->cdev);
> > -		return rc;
> > -	}
> > -
> >  	/* Make the chip available. */
> >  	mutex_lock(&idr_lock);
> >  	idr_replace(&dev_nums_idr, chip, chip->dev_num);
> > @@ -261,8 +249,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
> >  
> >  static void tpm_del_char_device(struct tpm_chip *chip)
> >  {
> > -	cdev_del(&chip->cdev);
> > -	device_del(&chip->dev);
> > +	cdev_device_del(&chip->cdev, &chip->dev);
> >  
> >  	/* Make the chip unavailable. */
> >  	mutex_lock(&idr_lock);
> > -- 
> > 2.1.4
> > 
> 
> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> 
> I cannot test this at this point as security tree does not include
> the commit that is dependent on this. I'm also wondering if this
> commit is even going through my tree to upstream?

I can take it all at once through my tree.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 06/16] tpm-chip: utilize new cdev_device_add helper function
  2017-03-07  5:31     ` Greg Kroah-Hartman
@ 2017-03-07  8:31       ` Jarkko Sakkinen
  0 siblings, 0 replies; 31+ messages in thread
From: Jarkko Sakkinen @ 2017-03-07  8:31 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Logan Gunthorpe, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jason Gunthorpe, Olof Johansson, Doug Ledford,
	Sean Hefty, Hal Rosenstock, Dmitry Vyukov, Haggai Eran,
	Parav Pandit, Leon Romanovsky, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Hans Verkuil,
	Mauro Carvalho Chehab, Artem Bityutskiy, Richard Weinberger,
	David Woodhouse, Brian Norris, Boris Brezillon, Marek Vasut,
	Cyrille Pitchen, Matt Porter, Alexandre Bounine, Andrew Morton,
	Joe Perches, Lorenzo Stoakes, Vladimir Zapolskiy,
	Alessandro Zummo, Alexandre Belloni, Boaz Harrosh,
	James E.J. Bottomley, Martin K. Petersen, Stephen Bates,
	Bjorn Helgaas, linux-pci, linux-scsi, rtc-linux, linux-mtd,
	linux-media, linux-iio, linux-rdma, linux-gpio, linux-input,
	linux-nvdimm, linux-fsdevel, linux-kernel

On Tue, Mar 07, 2017 at 06:31:38AM +0100, Greg Kroah-Hartman wrote:
> On Mon, Mar 06, 2017 at 11:04:26PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Mar 06, 2017 at 12:04:22AM -0700, Logan Gunthorpe wrote:
> > > Replace the open coded registration of the cdev and dev with the
> > > new device_add_cdev() helper. The helper replaces a common pattern by
> > > taking the proper reference against the parent device and adding both
> > > the cdev and the device.
> > > 
> > > Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> > > Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> > > ---
> > >  drivers/char/tpm/tpm-chip.c | 19 +++----------------
> > >  1 file changed, 3 insertions(+), 16 deletions(-)
> > > 
> > > diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> > > index c406343..935f0e9 100644
> > > --- a/drivers/char/tpm/tpm-chip.c
> > > +++ b/drivers/char/tpm/tpm-chip.c
> > > @@ -187,7 +187,6 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
> > >  
> > >  	cdev_init(&chip->cdev, &tpm_fops);
> > >  	chip->cdev.owner = THIS_MODULE;
> > > -	chip->cdev.kobj.parent = &chip->dev.kobj;
> > >  
> > >  	return chip;
> > >  
> > > @@ -230,27 +229,16 @@ static int tpm_add_char_device(struct tpm_chip *chip)
> > >  {
> > >  	int rc;
> > >  
> > > -	rc = cdev_add(&chip->cdev, chip->dev.devt, 1);
> > > +	rc = cdev_device_add(&chip->cdev, &chip->dev);
> > >  	if (rc) {
> > >  		dev_err(&chip->dev,
> > > -			"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
> > > +			"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
> > >  			dev_name(&chip->dev), MAJOR(chip->dev.devt),
> > >  			MINOR(chip->dev.devt), rc);
> > >  
> > >  		return rc;
> > >  	}
> > >  
> > > -	rc = device_add(&chip->dev);
> > > -	if (rc) {
> > > -		dev_err(&chip->dev,
> > > -			"unable to device_register() %s, major %d, minor %d, err=%d\n",
> > > -			dev_name(&chip->dev), MAJOR(chip->dev.devt),
> > > -			MINOR(chip->dev.devt), rc);
> > > -
> > > -		cdev_del(&chip->cdev);
> > > -		return rc;
> > > -	}
> > > -
> > >  	/* Make the chip available. */
> > >  	mutex_lock(&idr_lock);
> > >  	idr_replace(&dev_nums_idr, chip, chip->dev_num);
> > > @@ -261,8 +249,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
> > >  
> > >  static void tpm_del_char_device(struct tpm_chip *chip)
> > >  {
> > > -	cdev_del(&chip->cdev);
> > > -	device_del(&chip->dev);
> > > +	cdev_device_del(&chip->cdev, &chip->dev);
> > >  
> > >  	/* Make the chip unavailable. */
> > >  	mutex_lock(&idr_lock);
> > > -- 
> > > 2.1.4
> > > 
> > 
> > Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > 
> > I cannot test this at this point as security tree does not include
> > the commit that is dependent on this. I'm also wondering if this
> > commit is even going through my tree to upstream?
> 
> I can take it all at once through my tree.
> 
> thanks,
> 
> greg k-h

Alright, thank you!

/Jarkko

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 14/16] rtc: utilize new cdev_device_add helper function
  2017-03-06  7:04 ` [PATCH v3 14/16] rtc: " Logan Gunthorpe
@ 2017-03-07 22:41   ` Alexandre Belloni
  0 siblings, 0 replies; 31+ messages in thread
From: Alexandre Belloni @ 2017-03-07 22:41 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Linus Walleij, Alexandre Courbot, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe,
	Olof Johansson, Doug Ledford, Sean Hefty, Hal Rosenstock,
	Dmitry Vyukov, Haggai Eran, Parav Pandit, Leon Romanovsky,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Hans Verkuil, Mauro Carvalho Chehab, Artem Bityutskiy,
	Richard Weinberger, David Woodhouse, Brian Norris,
	Boris Brezillon, Marek Vasut, Cyrille Pitchen, Matt Porter,
	Alexandre Bounine, Andrew Morton, Joe Perches, Lorenzo Stoakes,
	Vladimir Zapolskiy, Alessandro Zummo, Boaz Harrosh,
	James E.J. Bottomley, Martin K. Petersen, Stephen Bates,
	Bjorn Helgaas, linux-pci, linux-scsi, rtc-linux, linux-mtd,
	linux-media, linux-iio, linux-rdma, linux-gpio, linux-input,
	linux-nvdimm, linux-fsdevel, linux-kernel

On 06/03/2017 at 00:04:30 -0700, Logan Gunthorpe wrote:
> Mostly straightforward, but we had to remove the rtc_dev_add/del_device
> functions as they split up the cdev_add and the device_add.
> 
> Doing this also revealed that there was likely another subtle bug:
> seeing cdev_add was done after device_register, the cdev probably
> was not ready before device_add when the uevent occurs. This would
> race with userspace, if it tried to use the device directly after
> the uevent. This is fixed just by using the new helper function.
> 
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>

I think I already acked v2 but
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [rtc-linux] [PATCH v3 05/16] gpiolib: utilize new cdev_device_add helper function
  2017-03-06  7:04 ` [PATCH v3 05/16] gpiolib: " Logan Gunthorpe
@ 2017-03-14 15:28   ` Linus Walleij
  2017-03-16  8:39     ` Greg Kroah-Hartman
  0 siblings, 1 reply; 31+ messages in thread
From: Linus Walleij @ 2017-03-14 15:28 UTC (permalink / raw)
  To: rtc-linux
  Cc: Greg Kroah-Hartman, Dan Williams, Alexander Viro,
	Johannes Thumshirn, Jan Kara, Arnd Bergmann, Sajjan Vikas C,
	Dmitry Torokhov, Alexandre Courbot, Peter Huewe, Marcel Selhorst,
	Jarkko Sakkinen, Jason Gunthorpe, Olof Johansson, Doug Ledford,
	Sean Hefty, Hal Rosenstock, Dmitry Vyukov, Haggai Eran,
	Parav Pandit, Leon Romanovsky, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Hans Verkuil,
	Mauro Carvalho Chehab, Artem Bityutskiy, Richard Weinberger,
	David Woodhouse, Brian Norris, Boris Brezillon, Marek Vasut,
	Cyrille Pitchen, Matt Porter, Alexandre Bounine, Andrew Morton,
	Joe Perches, Lorenzo Stoakes, Vladimir Zapolskiy,
	Alessandro Zummo, Alexandre Belloni, Boaz Harrosh,
	James E.J. Bottomley, Martin K. Petersen, Stephen Bates,
	Bjorn Helgaas, linux-pci, linux-scsi, linux-mtd, linux-media,
	linux-iio, linux-rdma, linux-gpio, Linux Input, linux-nvdimm,
	linux-fsdevel, linux-kernel, Logan Gunthorpe

On Mon, Mar 6, 2017 at 8:04 AM, Logan Gunthorpe <logang@deltatee.com> wrote:

> Replace the open coded registration of the cdev and dev with the
> new device_add_cdev() helper. The helper replaces a common pattern by
> taking the proper reference against the parent device and adding both
> the cdev and the device.
>
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Please inform me if you plan to merge this into the device core
tree or similar, or whether I should apply it for like v4.13 after merging
the core patch or so.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [rtc-linux] [PATCH v3 05/16] gpiolib: utilize new cdev_device_add helper function
  2017-03-14 15:28   ` [rtc-linux] " Linus Walleij
@ 2017-03-16  8:39     ` Greg Kroah-Hartman
  0 siblings, 0 replies; 31+ messages in thread
From: Greg Kroah-Hartman @ 2017-03-16  8:39 UTC (permalink / raw)
  To: Linus Walleij
  Cc: rtc-linux, Dan Williams, Alexander Viro, Johannes Thumshirn,
	Jan Kara, Arnd Bergmann, Sajjan Vikas C, Dmitry Torokhov,
	Alexandre Courbot, Peter Huewe, Marcel Selhorst, Jarkko Sakkinen,
	Jason Gunthorpe, Olof Johansson, Doug Ledford, Sean Hefty,
	Hal Rosenstock, Dmitry Vyukov, Haggai Eran, Parav Pandit,
	Leon Romanovsky, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Hans Verkuil, Mauro Carvalho Chehab,
	Artem Bityutskiy, Richard Weinberger, David Woodhouse,
	Brian Norris, Boris Brezillon, Marek Vasut, Cyrille Pitchen,
	Matt Porter, Alexandre Bounine, Andrew Morton, Joe Perches,
	Lorenzo Stoakes, Vladimir Zapolskiy, Alessandro Zummo,
	Alexandre Belloni, Boaz Harrosh, James E.J. Bottomley,
	Martin K. Petersen, Stephen Bates, Bjorn Helgaas, linux-pci,
	linux-scsi, linux-mtd, linux-media, linux-iio, linux-rdma,
	linux-gpio, Linux Input, linux-nvdimm, linux-fsdevel,
	linux-kernel, Logan Gunthorpe

On Tue, Mar 14, 2017 at 04:28:28PM +0100, Linus Walleij wrote:
> On Mon, Mar 6, 2017 at 8:04 AM, Logan Gunthorpe <logang@deltatee.com> wrote:
> 
> > Replace the open coded registration of the cdev and dev with the
> > new device_add_cdev() helper. The helper replaces a common pattern by
> > taking the proper reference against the parent device and adding both
> > the cdev and the device.
> >
> > Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> 
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> 
> Please inform me if you plan to merge this into the device core
> tree or similar, or whether I should apply it for like v4.13 after merging
> the core patch or so.

I'll take this through my tree, no need to bother you with it.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 16/16] switchtec: utilize new device_add_cdev helper function
  2017-03-06  7:04 ` [PATCH v3 16/16] switchtec: utilize new device_add_cdev " Logan Gunthorpe
@ 2017-03-16  8:42   ` Greg Kroah-Hartman
  2017-03-16 17:39     ` Logan Gunthorpe
  0 siblings, 1 reply; 31+ messages in thread
From: Greg Kroah-Hartman @ 2017-03-16  8:42 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: Dan Williams, Alexander Viro, Johannes Thumshirn, Jan Kara,
	Arnd Bergmann, Sajjan Vikas C, Dmitry Torokhov, Linus Walleij,
	Alexandre Courbot, Peter Huewe, Marcel Selhorst, Jarkko Sakkinen,
	Jason Gunthorpe, Olof Johansson, Doug Ledford, Sean Hefty,
	Hal Rosenstock, Dmitry Vyukov, Haggai Eran, Parav Pandit,
	Leon Romanovsky, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Hans Verkuil, Mauro Carvalho Chehab,
	Artem Bityutskiy, Richard Weinberger, David Woodhouse,
	Brian Norris, Boris Brezillon, Marek Vasut, Cyrille Pitchen,
	Matt Porter, Alexandre Bounine, Andrew Morton, Joe Perches,
	Lorenzo Stoakes, Vladimir Zapolskiy, Alessandro Zummo,
	Alexandre Belloni, Boaz Harrosh, James E.J. Bottomley,
	Martin K. Petersen, Stephen Bates, Bjorn Helgaas, linux-pci,
	linux-scsi, rtc-linux, linux-mtd, linux-media, linux-iio,
	linux-rdma, linux-gpio, linux-input, linux-nvdimm, linux-fsdevel,
	linux-kernel

On Mon, Mar 06, 2017 at 12:04:32AM -0700, Logan Gunthorpe wrote:
> Very straightforward conversion to device_add_cdev. Drop cdev_add and
> device_add and use cdev_device_add.
> 
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---
>  drivers/pci/switch/switchtec.c | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)

As this file isn't in 4.11-rc1, I can't take this patch, but I took all
of the others.  You should resend this to Bjorn after 4.12-rc1 is out.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 01/16] chardev: add helper function to register char devs with a struct device
  2017-03-06  7:04 ` [PATCH v3 01/16] chardev: add helper function to register char devs with a struct device Logan Gunthorpe
@ 2017-03-16 13:22   ` Greg Kroah-Hartman
  2017-03-16 17:38     ` Logan Gunthorpe
  0 siblings, 1 reply; 31+ messages in thread
From: Greg Kroah-Hartman @ 2017-03-16 13:22 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: Dan Williams, Alexander Viro, Johannes Thumshirn, Jan Kara,
	Arnd Bergmann, Sajjan Vikas C, Dmitry Torokhov, Linus Walleij,
	Alexandre Courbot, Peter Huewe, Marcel Selhorst, Jarkko Sakkinen,
	Jason Gunthorpe, Olof Johansson, Doug Ledford, Sean Hefty,
	Hal Rosenstock, Dmitry Vyukov, Haggai Eran, Parav Pandit,
	Leon Romanovsky, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Hans Verkuil, Mauro Carvalho Chehab,
	Artem Bityutskiy, Richard Weinberger, David Woodhouse,
	Brian Norris, Boris Brezillon, Marek Vasut, Cyrille Pitchen,
	Matt Porter, Alexandre Bounine, Andrew Morton, Joe Perches,
	Lorenzo Stoakes, Vladimir Zapolskiy, Alessandro Zummo,
	Alexandre Belloni, Boaz Harrosh, James E.J. Bottomley,
	Martin K. Petersen, Stephen Bates, Bjorn Helgaas, linux-pci,
	linux-scsi, rtc-linux, linux-mtd, linux-media, linux-iio,
	linux-rdma, linux-gpio, linux-input, linux-nvdimm, linux-fsdevel,
	linux-kernel

On Mon, Mar 06, 2017 at 12:04:17AM -0700, Logan Gunthorpe wrote:
> Credit for this patch goes is shared with Dan Williams [1]. I've
> taken things one step further to make the helper function more
> useful and clean up calling code.
> 
> There's a common pattern in the kernel whereby a struct cdev is placed
> in a structure along side a struct device which manages the life-cycle
> of both. In the naive approach, the reference counting is broken and
> the struct device can free everything before the chardev code
> is entirely released.
> 
> Many developers have solved this problem by linking the internal kobjs
> in this fashion:
> 
> cdev.kobj.parent = &parent_dev.kobj;
> 
> The cdev code explicitly gets and puts a reference to it's kobj parent.
> So this seems like it was intended to be used this way. Dmitrty Torokhov
> first put this in place in 2012 with this commit:
> 
> 2f0157f char_dev: pin parent kobject
> 
> and the first instance of the fix was then done in the input subsystem
> in the following commit:
> 
> 4a215aa Input: fix use-after-free introduced with dynamic minor changes
> 
> Subsequently over the years, however, this issue seems to have tripped
> up multiple developers independently. For example, see these commits:
> 
> 0d5b7da iio: Prevent race between IIO chardev opening and IIO device
> (by Lars-Peter Clausen in 2013)
> 
> ba0ef85 tpm: Fix initialization of the cdev
> (by Jason Gunthorpe in 2015)
> 
> 5b28dde [media] media: fix use-after-free in cdev_put() when app exits
> after driver unbind
> (by Shauh Khan in 2016)
> 
> This technique is similarly done in at least 15 places within the kernel
> and probably should have been done so in another, at least, 5 places.
> The kobj line also looks very suspect in that one would not expect
> drivers to have to mess with kobject internals in this way.
> Even highly experienced kernel developers can be surprised by this
> code, as seen in [2].
> 
> To help alleviate this situation, and hopefully prevent future
> wasted effort on this problem, this patch introduces a helper function
> to register a char device along with its parent struct device.
> This creates a more regular API for tying a char device to its parent
> without the developer having to set members in the underlying kobject.
> 
> This patch introduce cdev_device_add and cdev_device_del which
> replaces a common pattern including setting the kobj parent, calling
> cdev_add and then calling device_add. It also introduces cdev_set_parent
> for the few cases that set the kobject parent without using device_add.
> 
> [1] https://lkml.org/lkml/2017/2/13/700
> [2] https://lkml.org/lkml/2017/2/10/370
> 
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
> Reviewed-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> ---
>  fs/char_dev.c        | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/cdev.h |  4 +++
>  2 files changed, 81 insertions(+)
> 
> diff --git a/fs/char_dev.c b/fs/char_dev.c
> index 44a240c..09b93fb 100644
> --- a/fs/char_dev.c
> +++ b/fs/char_dev.c
> @@ -471,6 +471,76 @@ int cdev_add(struct cdev *p, dev_t dev, unsigned count)
>  	return 0;
>  }
>  
> +/**
> + * cdev_set_parent() - set the parent kobject for a char device
> + * @p: the cdev structure
> + * @kobj: the kobject to take a reference to
> + *
> + * cdev_set_parent() sets a parent kobject which will be referenced
> + * appropriately so the parent is not freed before the cdev. This
> + * should be called before cdev_add.
> + */
> +void cdev_set_parent(struct cdev *p, struct kobject *kobj)
> +{
> +	WARN_ON(!kobj->state_initialized);
> +	p->kobj.parent = kobj;
> +}
> +
> +/**
> + * cdev_device_add() - add a char device and it's corresponding
> + *	struct device, linkink
> + * @dev: the device structure
> + * @cdev: the cdev structure
> + *
> + * cdev_device_add() adds the char device represented by @cdev to the system,
> + * just as cdev_add does. It then adds @dev to the system using device_add
> + * The dev_t for the char device will be taken from the struct device which
> + * needs to be initialized first. This helper function correctly takes a
> + * reference to the parent device so the parent will not get released until
> + * all references to the cdev are released.
> + *
> + * This function should be used whenever the struct cdev and the
> + * struct device are members of the same structure whose lifetime is
> + * managed by the struct device.
> + *
> + * NOTE: Callers must assume that userspace was able to open the cdev and
> + * can call cdev fops callbacks at any time, even if this function fails.
> + */
> +int cdev_device_add(struct cdev *cdev, struct device *dev)
> +{
> +	int rc = 0;
> +
> +	cdev_set_parent(cdev, &dev->kobj);
> +
> +	rc = cdev_add(cdev, dev->devt, 1);
> +	if (rc)
> +		return rc;
> +
> +	rc = device_add(dev);
> +	if (rc)
> +		cdev_del(cdev);
> +
> +	return rc;
> +}
> +
> +/**
> + * cdev_device_del() - inverse of cdev_device_add
> + * @dev: the device structure
> + * @cdev: the cdev structure
> + *
> + * cdev_device_del() is a helper function to call cdev_del and device_del.
> + * It should be used whenever cdev_device_add is used.
> + *
> + * NOTE: This guarantees that associated sysfs callbacks are not running
> + * or runnable, however any cdevs already open will remain and their fops
> + * will still be callable even after this function returns.
> + */
> +void cdev_device_del(struct cdev *cdev, struct device *dev)
> +{
> +	device_del(dev);
> +	cdev_del(cdev);
> +}
> +
>  static void cdev_unmap(dev_t dev, unsigned count)
>  {
>  	kobj_unmap(cdev_map, dev, count);
> @@ -482,6 +552,10 @@ static void cdev_unmap(dev_t dev, unsigned count)
>   *
>   * cdev_del() removes @p from the system, possibly freeing the structure
>   * itself.
> + *
> + * NOTE: This guarantees that cdev device will no longer be able to be
> + * opened, however any cdevs already open will remain and their fops will
> + * still be callable even after cdev_del returns.
>   */
>  void cdev_del(struct cdev *p)
>  {
> @@ -570,5 +644,8 @@ EXPORT_SYMBOL(cdev_init);
>  EXPORT_SYMBOL(cdev_alloc);
>  EXPORT_SYMBOL(cdev_del);
>  EXPORT_SYMBOL(cdev_add);
> +EXPORT_SYMBOL(cdev_set_parent);
> +EXPORT_SYMBOL(cdev_device_add);
> +EXPORT_SYMBOL(cdev_device_del);
>  EXPORT_SYMBOL(__register_chrdev);
>  EXPORT_SYMBOL(__unregister_chrdev);
> diff --git a/include/linux/cdev.h b/include/linux/cdev.h
> index f876361..4c99579 100644
> --- a/include/linux/cdev.h
> +++ b/include/linux/cdev.h
> @@ -26,6 +26,10 @@ void cdev_put(struct cdev *p);
>  
>  int cdev_add(struct cdev *, dev_t, unsigned);
>  
> +void cdev_set_parent(struct cdev *p, struct kobject *kobj);
> +int cdev_device_add(struct cdev *cdev, struct device *dev);
> +void cdev_device_del(struct cdev *cdev, struct device *dev);
> +
>  void cdev_del(struct cdev *);
>  
>  void cd_forget(struct inode *);

I don't know why kbuild didn't catch these before, but it looks like we
really need to include device.h in cdev.h now to fix up these build
warnings, right?

I'll try that out and rebase the char-misc-testing tree in the morning
to see if that fixes the build problems...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 01/16] chardev: add helper function to register char devs with a struct device
  2017-03-16 13:22   ` Greg Kroah-Hartman
@ 2017-03-16 17:38     ` Logan Gunthorpe
  2017-03-17  0:24       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-16 17:38 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Dan Williams, Alexander Viro, Johannes Thumshirn, Jan Kara,
	Arnd Bergmann, Sajjan Vikas C, Dmitry Torokhov, Linus Walleij,
	Alexandre Courbot, Peter Huewe, Marcel Selhorst, Jarkko Sakkinen,
	Jason Gunthorpe, Olof Johansson, Doug Ledford, Sean Hefty,
	Hal Rosenstock, Dmitry Vyukov, Haggai Eran, Parav Pandit,
	Leon Romanovsky, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Hans Verkuil, Mauro Carvalho Chehab,
	Artem Bityutskiy, Richard Weinberger, David Woodhouse,
	Brian Norris, Boris Brezillon, Marek Vasut, Cyrille Pitchen,
	Matt Porter, Alexandre Bounine, Andrew Morton, Joe Perches,
	Lorenzo Stoakes, Vladimir Zapolskiy, Alessandro Zummo,
	Alexandre Belloni, Boaz Harrosh, James E.J. Bottomley,
	Martin K. Petersen, Stephen Bates, Bjorn Helgaas, linux-pci,
	linux-scsi, rtc-linux, linux-mtd, linux-media, linux-iio,
	linux-rdma, linux-gpio, linux-input, linux-nvdimm, linux-fsdevel,
	linux-kernel

> I don't know why kbuild didn't catch these before, but it looks like we
> really need to include device.h in cdev.h now to fix up these build
> warnings, right?

> I'll try that out and rebase the char-misc-testing tree in the morning
> to see if that fixes the build problems...


Yeah, I think the kbuild robot missed the series because the vger
mailing lists were dropping this series :(

I also don't know why my kernel config didn't catch this warning but
I reproduced and fixed it with the kbuild's config. I'll send an updated
patch which adds a include device.h line to cdev.h momentarily.

Logan

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 16/16] switchtec: utilize new device_add_cdev helper function
  2017-03-16  8:42   ` Greg Kroah-Hartman
@ 2017-03-16 17:39     ` Logan Gunthorpe
  0 siblings, 0 replies; 31+ messages in thread
From: Logan Gunthorpe @ 2017-03-16 17:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Dan Williams, Alexander Viro, Johannes Thumshirn, Jan Kara,
	Arnd Bergmann, Sajjan Vikas C, Dmitry Torokhov, Linus Walleij,
	Alexandre Courbot, Peter Huewe, Marcel Selhorst, Jarkko Sakkinen,
	Jason Gunthorpe, Olof Johansson, Doug Ledford, Sean Hefty,
	Hal Rosenstock, Dmitry Vyukov, Haggai Eran, Parav Pandit,
	Leon Romanovsky, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Hans Verkuil, Mauro Carvalho Chehab,
	Artem Bityutskiy, Richard Weinberger, David Woodhouse,
	Brian Norris, Boris Brezillon, Marek Vasut, Cyrille Pitchen,
	Matt Porter, Alexandre Bounine, Andrew Morton, Joe Perches,
	Lorenzo Stoakes, Vladimir Zapolskiy, Alessandro Zummo,
	Alexandre Belloni, Boaz Harrosh, James E.J. Bottomley,
	Martin K. Petersen, Stephen Bates, Bjorn Helgaas, linux-pci,
	linux-scsi, rtc-linux, linux-mtd, linux-media, linux-iio,
	linux-rdma, linux-gpio, linux-input, linux-nvdimm, linux-fsdevel,
	linux-kernel



On 16/03/17 02:42 AM, Greg Kroah-Hartman wrote:
> As this file isn't in 4.11-rc1, I can't take this patch, but I took all
> of the others.  You should resend this to Bjorn after 4.12-rc1 is out.

Yup, I expected this. I'll keep an eye out and make sure it gets in when
the time comes.

Thanks,

Logan

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 01/16] chardev: add helper function to register char devs with a struct device
  2017-03-16 17:38     ` Logan Gunthorpe
@ 2017-03-17  0:24       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 31+ messages in thread
From: Greg Kroah-Hartman @ 2017-03-17  0:24 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: Dan Williams, Alexander Viro, Johannes Thumshirn, Jan Kara,
	Arnd Bergmann, Sajjan Vikas C, Dmitry Torokhov, Linus Walleij,
	Alexandre Courbot, Peter Huewe, Marcel Selhorst, Jarkko Sakkinen,
	Jason Gunthorpe, Olof Johansson, Doug Ledford, Sean Hefty,
	Hal Rosenstock, Dmitry Vyukov, Haggai Eran, Parav Pandit,
	Leon Romanovsky, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Hans Verkuil, Mauro Carvalho Chehab,
	Artem Bityutskiy, Richard Weinberger, David Woodhouse,
	Brian Norris, Boris Brezillon, Marek Vasut, Cyrille Pitchen,
	Matt Porter, Alexandre Bounine, Andrew Morton, Joe Perches,
	Lorenzo Stoakes, Vladimir Zapolskiy, Alessandro Zummo,
	Alexandre Belloni, Boaz Harrosh, James E.J. Bottomley,
	Martin K. Petersen, Stephen Bates, Bjorn Helgaas, linux-pci,
	linux-scsi, rtc-linux, linux-mtd, linux-media, linux-iio,
	linux-rdma, linux-gpio, linux-input, linux-nvdimm, linux-fsdevel,
	linux-kernel

On Thu, Mar 16, 2017 at 11:38:40AM -0600, Logan Gunthorpe wrote:
> > I don't know why kbuild didn't catch these before, but it looks like we
> > really need to include device.h in cdev.h now to fix up these build
> > warnings, right?
> 
> > I'll try that out and rebase the char-misc-testing tree in the morning
> > to see if that fixes the build problems...
> 
> 
> Yeah, I think the kbuild robot missed the series because the vger
> mailing lists were dropping this series :(
> 
> I also don't know why my kernel config didn't catch this warning but
> I reproduced and fixed it with the kbuild's config. I'll send an updated
> patch which adds a include device.h line to cdev.h momentarily.

Thanks, I've updated my tree with your new patch, let's see what breaks
this time :)

greg k-h

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2017-03-17  0:25 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-06  7:04 [PATCH v3 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
2017-03-06  7:04 ` [PATCH v3 01/16] chardev: add helper function to register char devs with a struct device Logan Gunthorpe
2017-03-16 13:22   ` Greg Kroah-Hartman
2017-03-16 17:38     ` Logan Gunthorpe
2017-03-17  0:24       ` Greg Kroah-Hartman
2017-03-06  7:04 ` [PATCH v3 02/16] device-dax: fix cdev leak Logan Gunthorpe
2017-03-06  8:27   ` Johannes Thumshirn
2017-03-06  7:04 ` [PATCH v3 03/16] device-dax: utilize new cdev_device_add helper function Logan Gunthorpe
2017-03-06  8:29   ` Johannes Thumshirn
2017-03-06  7:04 ` [PATCH v3 04/16] input: " Logan Gunthorpe
2017-03-06  7:04 ` [PATCH v3 05/16] gpiolib: " Logan Gunthorpe
2017-03-14 15:28   ` [rtc-linux] " Linus Walleij
2017-03-16  8:39     ` Greg Kroah-Hartman
2017-03-06  7:04 ` [PATCH v3 06/16] tpm-chip: " Logan Gunthorpe
2017-03-06 21:04   ` Jarkko Sakkinen
2017-03-07  5:31     ` Greg Kroah-Hartman
2017-03-07  8:31       ` Jarkko Sakkinen
2017-03-06  7:04 ` [PATCH v3 07/16] platform/chrome: cros_ec_dev - " Logan Gunthorpe
2017-03-06  7:04 ` [PATCH v3 08/16] IB/ucm: " Logan Gunthorpe
2017-03-06  7:24   ` Leon Romanovsky
2017-03-06  7:04 ` [PATCH v3 09/16] infiniband: utilize the new cdev_set_parent function Logan Gunthorpe
2017-03-06  7:04 ` [PATCH v3 10/16] iio:core: utilize new cdev_device_add helper function Logan Gunthorpe
2017-03-06  7:04 ` [PATCH v3 11/16] media: " Logan Gunthorpe
2017-03-06  7:04 ` [PATCH v3 12/16] mtd: " Logan Gunthorpe
2017-03-06  7:04 ` [PATCH v3 13/16] rapidio: " Logan Gunthorpe
2017-03-06  7:04 ` [PATCH v3 14/16] rtc: " Logan Gunthorpe
2017-03-07 22:41   ` Alexandre Belloni
2017-03-06  7:04 ` [PATCH v3 15/16] scsi: " Logan Gunthorpe
2017-03-06  7:04 ` [PATCH v3 16/16] switchtec: utilize new device_add_cdev " Logan Gunthorpe
2017-03-16  8:42   ` Greg Kroah-Hartman
2017-03-16 17:39     ` Logan Gunthorpe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).