- driver-core-introduce-device_find_child.patch removed from -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch titled
     driver core: Introduce device_find_child()
has been removed from the -mm tree.  Its filename was
     driver-core-introduce-device_find_child.patch

This patch was dropped because an updated version will be merged

------------------------------------------------------
Subject: driver core: Introduce device_find_child()
From: Cornelia Huck <cornelia.huck@xxxxxxxxxx>

For quite a while, we've been trying to make block devices on s390 channel
attached devices (aka ccw devices) more resilent against outages of storage
servers.

The main problem is that the kernel doesn't take well to having a mounted
device removed (and that might happen if, for instance, there is an
intermittant outage at the switch connecting the storage server and we get
machine checks indicating the dasd devices are no longer there).

To work around this, we introduced a "disconnected" status for ccw devices
which are in use ("online") but currently not there (or without a path).  The
dasd driver will plug its queue when it is notified that the device is gone,
and unplug it when notified that the device is there again.  We have a rather
complex logic in the s390 common I/O layer (see drivers/s390/cio/) in order to
get disconnected devices operational again without introducing lockups with
other non-functional devices coming or going or allocating memory (our swap
device may just be disconnected...)

Currently, our logic works well with most real-world scenarios. Except
one: Re-attaching devices under z/VM.

ccw devices are addressed via io subchannels residing on the css bus:
css0 -> 0.0.0000 -> 0.0.0815
     -> 0.0.0001 -> 0.0.4711  
     ...
(There also may be non-io subchannels with no attached ccw device,
although we currently don't support them).

On LPAR, the subchannel<->device relationship is defined in the IOCDS (which
requires manual intervention to change), but z/VM will assign the first free
subchannel to a device when it is attached (and attach is done by specifying
the device number of the ccw device (like 0815 and 4711 in the example above),
the subchannel number is completely uninteresting to z/VM).  This may lead to
the following:

- z/VM recognizes it can no longer access devices 0815 and 4711 and
  detaches them from the guest.
- Linux gets machine checks indicating devices 0815 and 4711 are gone.
  Since they are currently in use, they are put into "disconnected"
  state.
- Access to devices 0815 and 4711 is reestablished. However, z/VM won't
  automatically reattach them.
- The operator manually reattaches 0815 and 4711. However, since he has
  no way of knowing in which order they were originally attached, he
  first attaches 4711 and then 0815. The layout z/VM presents to Linux
  is now the following:
	subchannel 0 -> device 4711
	subchannel 1 -> device 0815
  So we've now got different devices than before on the same
  subchannel. Currently, we have to deregister the old (disconnected)
  device and register the new one, which leads to all the problems we
  wanted to avoid with the "disconnected" state in the first place.

(There are more ways you can mix up your devices, like "DEFINE xxxx AS yyyy"
under z/VM (which changes the device number from xxxx to yyyy), but I consider
those "shoot yourself in the foot" unlike the above, which is a real world
recovery scenario.)

[Still reading? Here comes the fun part.]

What we really want to do is to switch the devices around, i. e. move
ccw device 0.0.4711 to subchannel 0.0.0000 and ccw device 0.0.0815 to
subchannel 0.0.0001. That is what the following patchset implements:
- Ability to move devices to a new parent in the device tree, keeping
  established relationships intact.
- Using this to move ccw devices appearing on a different subchannel to
  their new parent. There also is a "pseudo subchannel" per channel
  subsystem which servers as a temporary parent for ccw devices which
  have been displaced by a new ccw device on their old subchannel.

This patchset works well for me when detaching several used ccw devices
and reattaching them in random order. It should make us survive storage
server outages in nearly all cases (except when we need to move devices
and we have no chance of getting some memory).


This patch:

Introduce device_find_child() to match device_for_each_child().

Signed-off-by: Cornelia Huck <cornelia.huck@xxxxxxxxxx>
Cc: Martin Schwidefsky <schwidefsky@xxxxxxxxxx>
Cc: Greg KH <greg@xxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
---

 drivers/base/core.c    |   33 +++++++++++++++++++++++++++++++++
 include/linux/device.h |    2 ++
 2 files changed, 35 insertions(+)

diff -puN drivers/base/core.c~driver-core-introduce-device_find_child drivers/base/core.c
--- a/drivers/base/core.c~driver-core-introduce-device_find_child
+++ a/drivers/base/core.c
@@ -750,12 +750,45 @@ int device_for_each_child(struct device 
 	return error;
 }
 
+/**
+ * device_find_child - device iterator for locating a particular device.
+ * @parent: parent struct device
+ * @data: Data to pass to match function
+ * @match: Callback function to check device
+ *
+ * This is similar to the device_for_each_child() function above, but it
+ * returns a reference to a device that is 'found' for later use, as
+ * determined by the @match callback.
+ *
+ * The callback should return 0 if the device doesn't match and non-zero
+ * if it does.  If the callback returns non-zero and a reference to the
+ * current device can be obtained, this function will return to the caller
+ * and not iterate over any more devices.
+ */
+struct device * device_find_child(struct device *parent, void *data,
+				  int (*match)(struct device *, void *))
+{
+	struct klist_iter i;
+	struct device *child;
+
+	if (!parent)
+		return NULL;
+
+	klist_iter_init(&parent->klist_children, &i);
+	while ((child = next_device(&i)))
+		if (match(child, data) && get_device(child))
+			break;
+	klist_iter_exit(&i);
+	return child;
+}
+
 int __init devices_init(void)
 {
 	return subsystem_register(&devices_subsys);
 }
 
 EXPORT_SYMBOL_GPL(device_for_each_child);
+EXPORT_SYMBOL_GPL(device_find_child);
 
 EXPORT_SYMBOL_GPL(device_initialize);
 EXPORT_SYMBOL_GPL(device_add);
diff -puN include/linux/device.h~driver-core-introduce-device_find_child include/linux/device.h
--- a/include/linux/device.h~driver-core-introduce-device_find_child
+++ a/include/linux/device.h
@@ -420,6 +420,8 @@ extern int __must_check device_add(struc
 extern void device_del(struct device * dev);
 extern int device_for_each_child(struct device *, void *,
 		     int (*fn)(struct device *, void *));
+extern struct device *device_find_child(struct device *, void *data,
+					int (*match)(struct device *, void *));
 extern int device_rename(struct device *dev, char *new_name);
 
 /*
_

Patches currently in -mm which might be from cornelia.huck@xxxxxxxxxx are

driver-core-introduce-device_find_child.patch
driver-core-introduce-device_move-move-a-device.patch
git-s390.patch
s390-preparatory-cleanup-in-common-i-o-layer.patch
s390-make-the-per-subchannel-lock-dynamic.patch
s390-dynamic-subchannel-mapping-of-ccw-devices.patch
tty-switch-to-ktermios-sclp-fix.patch

-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Newbies FAQ]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux