<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/">
  <channel rdf:about="http://blog.gmane.org/gmane.linux.kernel.device-mapper.devel">
    <title>gmane.linux.kernel.device-mapper.devel</title>
    <link>http://blog.gmane.org/gmane.linux.kernel.device-mapper.devel</link>
    <description/>
    <syn:updatePeriod>hourly</syn:updatePeriod>
    <syn:updateFrequency>1</syn:updateFrequency>
    <syn:updateBase>1901-01-01T00:00+00:00</syn:updateBase>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15964"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15963"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15962"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15961"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15959"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15958"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15957"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15956"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15947"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15946"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15928"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15922"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15921"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15918"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15907"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15906"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15904"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15903"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15902"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15901"/>
      </rdf:Seq>
    </items>
    <image rdf:resource="http://gmane.org/img/gmane-25t.png"/>
    <textinput rdf:resource=""/>
  </channel>
  <image rdf:about="http://gmane.org/img/gmane-25t.png">
    <title>Gmane</title>
    <url>http://gmane.org/img/gmane-25t.png</url>
    <link>http://gmane.org</link>
  </image>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15964">
    <title>[RFC PATCH v2 2/3] Adds support for security checks inthe linear target</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15964</link>
    <description>&lt;pre&gt;Just a security check implementation for linear target

---
 drivers/md/dm-linear.c |   19 ++++++++++++++++++-
 1 files changed, 18 insertions(+), 1 deletions(-)

diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 3639eea..b04aa00 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -153,9 +153,25 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int linear_iterate_devices(struct dm_target *ti,
 return fn(ti, lc-&amp;gt;dev, lc-&amp;gt;start, ti-&amp;gt;len, data);
 }
 
+static int linear_security(struct dm_target *ti, unsigned int argc, char **argv)
+{
+int r;
+
+if (argc &amp;lt; 1) {
+ti-&amp;gt;error = "dm-linear: Security check: invalid number of parameters";
+return -EINVAL;
+}
+
+r = dm_check_backing_dev_permission(ti, argv[0]);
+if (r)
+ti-&amp;gt;error = "dm-linear: Security check failed";
+
+return r;
+}
+
 static struct target_type linear_target = {
 .name   = "linear",
-.version = {1, 1, 0},
+.version = {1, 2, 0},
 .module = THIS_MODULE,
 .ctr    = linear_ctr,
 .dtr    = linear_dtr,
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -164,6 +180,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct target_type linear_target = {
 .ioctl  = linear_ioctl,
 .merge  = linear_merge,
 .iterate_devices = linear_iterate_devices,
+.security = linear_security
 };
 
 int __init dm_linear_init(void)
&lt;/pre&gt;</description>
    <dc:creator>Ondrej Kozina</dc:creator>
    <dc:date>2012-05-25T13:22:27</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15963">
    <title>[RFC PATCH v2 1/3] Adds support for user-submitted ioctlcommands</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15963</link>
    <description>&lt;pre&gt;The core of changes in DM ioctl operations

Changes in version No. 2:
^^^^^^^^^^^^^^^^^^^^^^^^

(*) With security enabled, open file descriptor for backing device has to be 
    passed in target parameters (e.g. "fd:9" instead of "8:2")

(*) Load time parameter for dm-mod "enable_security"

(*) Removed owner_gid from sysfs attributes

---
 drivers/md/Makefile           |    2 +-
 drivers/md/dm-ioctl.c         |  141 +++++++++++++++++++++++++++++++++++------
 drivers/md/dm-security.c      |   95 +++++++++++++++++++++++++++
 drivers/md/dm-sysfs.c         |   15 +++++
 drivers/md/dm-table.c         |   23 +++++++-
 drivers/md/dm.c               |   87 +++++++++++++++++++++++++
 drivers/md/dm.h               |   12 ++++
 include/linux/device-mapper.h |    5 ++
 8 files changed, 358 insertions(+), 22 deletions(-)
 create mode 100644 drivers/md/dm-security.c

diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 8b2e0df..28d0808 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3,7 +3,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #
 
 dm-mod-y+= dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
-   dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o
+   dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o dm-security.o
 dm-multipath-y+= dm-path-selector.o dm-mpath.o
 dm-snapshot-y+= dm-snap.o dm-exception-store.o dm-snap-transient.o \
     dm-snap-persistent.o
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index a1a3e6d..e94a883 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -351,6 +351,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static char *__change_cell_name(struct hash_cell *hc, char *new_name)
 static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
     const char *new)
 {
+int r;
 char *new_data, *old_name = NULL;
 struct hash_cell *hc;
 struct dm_table *table;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -397,6 +398,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
 return ERR_PTR(-ENXIO);
 }
 
+r = dm_check_dm_dev_permission(hc-&amp;gt;md, 1, NULL);
+if (r) {
+dm_put(hc-&amp;gt;md);
+up_write(&amp;amp;_hash_lock);
+kfree(new_data);
+return ERR_PTR(-EACCES);
+}
+
 /*
  * Does this device already have a uuid?
  */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -434,6 +443,44 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
 return md;
 }
 
+/*
+ * non-root submited ioctl helper function
+ */
+static int initial_permission_check(unsigned int cmd)
+{
+if (capable(CAP_SYS_ADMIN))
+return 0;
+
+if (!sec_enabled)
+return 1;
+
+/* FIXME: This is only an example */
+switch(_IOC_NR(cmd)) {
+case DM_REMOVE_ALL_CMD:
+case DM_DEV_SET_GEOMETRY_CMD:
+DMDEBUG("non-root user cant't call this ioctl: 0x%x", cmd);
+return 1;
+}
+return 0;
+}
+
+static int deny_create(void)
+{
+if (capable(CAP_SYS_ADMIN))
+return 0;
+
+/*
+ * FIXME: Add some function to limit user to create
+ * only reasonable number of DM_DEVS
+ *
+ * sugestions:
+ * a) only limited number of devices per second
+ * b) limited number in total per specific user
+ * c) limited number in total per non-root user
+ */
+return 0;
+}
+
 /*-----------------------------------------------------------------
  * Implementation of the ioctl commands
  *---------------------------------------------------------------*/
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -492,9 +539,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int list_devices(struct dm_ioctl *param, size_t param_size)
  */
 for (i = 0; i &amp;lt; NUM_BUCKETS; i++) {
 list_for_each_entry (hc, _name_buckets + i, name_list) {
-needed += sizeof(struct dm_name_list);
-needed += strlen(hc-&amp;gt;name) + 1;
-needed += ALIGN_MASK;
+BUG_ON(!hc-&amp;gt;md);
+if (!dm_check_dm_dev_permission(hc-&amp;gt;md, 0, NULL)) {
+needed += sizeof(struct dm_name_list);
+needed += strlen(hc-&amp;gt;name) + 1;
+needed += ALIGN_MASK;
+}
 }
 }
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -515,16 +565,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int list_devices(struct dm_ioctl *param, size_t param_size)
  */
 for (i = 0; i &amp;lt; NUM_BUCKETS; i++) {
 list_for_each_entry (hc, _name_buckets + i, name_list) {
-if (old_nl)
-old_nl-&amp;gt;next = (uint32_t) ((void *) nl -
-   (void *) old_nl);
-disk = dm_disk(hc-&amp;gt;md);
-nl-&amp;gt;dev = huge_encode_dev(disk_devt(disk));
-nl-&amp;gt;next = 0;
-strcpy(nl-&amp;gt;name, hc-&amp;gt;name);
-
-old_nl = nl;
-nl = align_ptr(((void *) ++nl) + strlen(hc-&amp;gt;name) + 1);
+BUG_ON(!hc-&amp;gt;md);
+if (!dm_check_dm_dev_permission(hc-&amp;gt;md, 0, NULL)) {
+if (old_nl)
+old_nl-&amp;gt;next = (uint32_t) ((void *) nl -
+(void *) old_nl);
+disk = dm_disk(hc-&amp;gt;md);
+nl-&amp;gt;dev = huge_encode_dev(disk_devt(disk));
+nl-&amp;gt;next = 0;
+strcpy(nl-&amp;gt;name, hc-&amp;gt;name);
+
+old_nl = nl;
+nl = align_ptr(((void *) ++nl) + strlen(hc-&amp;gt;name) + 1);
+}
 }
 }
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -704,6 +757,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int dev_create(struct dm_ioctl *param, size_t param_size)
 int r, m = DM_ANY_MINOR;
 struct mapped_device *md;
 
+if (deny_create())
+return -EACCES;
+
 r = check_name(param-&amp;gt;name);
 if (r)
 return r;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -808,6 +864,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int dev_remove(struct dm_ioctl *param, size_t param_size)
 
 md = hc-&amp;gt;md;
 
+if (dm_check_dm_dev_permission(md, 1, NULL)) {
+up_write(&amp;amp;_hash_lock);
+dm_put(md);
+return -EACCES;
+}
+
 /*
  * Ensure the device is not open and nothing further can open it.
  */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -930,6 +992,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int do_suspend(struct dm_ioctl *param)
 if (!md)
 return -ENXIO;
 
+if (dm_check_dm_dev_permission(md, 1, NULL)) {
+r = -EACCES;
+goto out;
+}
+
 if (param-&amp;gt;flags &amp;amp; DM_SKIP_LOCKFS_FLAG)
 suspend_flags &amp;amp;= ~DM_SUSPEND_LOCKFS_FLAG;
 if (param-&amp;gt;flags &amp;amp; DM_NOFLUSH_FLAG)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -968,6 +1035,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int do_resume(struct dm_ioctl *param)
 
 md = hc-&amp;gt;md;
 
+if (dm_check_dm_dev_permission(md, 1, NULL)) {
+r = -EACCES;
+goto out;
+}
+
 new_map = hc-&amp;gt;new_map;
 hc-&amp;gt;new_map = NULL;
 param-&amp;gt;flags &amp;amp;= ~DM_INACTIVE_PRESENT_FLAG;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1008,7 +1080,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int do_resume(struct dm_ioctl *param)
 
 if (!r)
 __dev_status(md, param);
-
+out:
 dm_put(md);
 return r;
 }
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1123,6 +1195,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int dev_wait(struct dm_ioctl *param, size_t param_size)
 if (!md)
 return -ENXIO;
 
+if (dm_check_dm_dev_permission(md, 1, NULL)) {
+r = -EACCES;
+goto out;
+}
+
 /*
  * Wait for a notification event
  */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1222,6 +1299,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int table_load(struct dm_ioctl *param, size_t param_size)
 if (!md)
 return -ENXIO;
 
+if (dm_check_dm_dev_permission(md, 1, NULL)) {
+r = -EACCES;
+goto out;
+}
+
 r = dm_table_create(&amp;amp;t, get_mode(param), param-&amp;gt;target_count, md);
 if (r)
 goto out;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1292,6 +1374,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; out:
 
 static int table_clear(struct dm_ioctl *param, size_t param_size)
 {
+int r = 0;
 struct hash_cell *hc;
 struct mapped_device *md;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1304,6 +1387,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int table_clear(struct dm_ioctl *param, size_t param_size)
 return -ENXIO;
 }
 
+if (dm_check_dm_dev_permission(hc-&amp;gt;md, 1, NULL)) {
+r = -EACCES;
+goto out;
+}
+
 if (hc-&amp;gt;new_map) {
 dm_table_destroy(hc-&amp;gt;new_map);
 hc-&amp;gt;new_map = NULL;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1313,10 +1401,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int table_clear(struct dm_ioctl *param, size_t param_size)
 
 __dev_status(hc-&amp;gt;md, param);
 md = hc-&amp;gt;md;
+
+out:
 up_write(&amp;amp;_hash_lock);
 dm_put(md);
 
-return 0;
+return r;
 }
 
 /*
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1387,6 +1477,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int table_deps(struct dm_ioctl *param, size_t param_size)
  */
 static int table_status(struct dm_ioctl *param, size_t param_size)
 {
+int r = 0;
 struct mapped_device *md;
 struct dm_table *table;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1394,6 +1485,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int table_status(struct dm_ioctl *param, size_t param_size)
 if (!md)
 return -ENXIO;
 
+if (dm_check_dm_dev_permission(md, 1, NULL)) {
+r = -EACCES;
+goto out;
+}
+
 __dev_status(md, param);
 
 table = dm_get_live_or_inactive_table(md, param);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1402,9 +1498,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int table_status(struct dm_ioctl *param, size_t param_size)
 dm_table_put(table);
 }
 
+out:
 dm_put(md);
 
-return 0;
+return r;
 }
 
 /*
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1423,6 +1520,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int target_message(struct dm_ioctl *param, size_t param_size)
 if (!md)
 return -ENXIO;
 
+if (dm_check_dm_dev_permission(md, 1, NULL)) {
+r = -EACCES;
+goto out;
+}
+
 if (tmsg &amp;lt; (struct dm_target_msg *) param-&amp;gt;data ||
     invalid_str(tmsg-&amp;gt;message, (void *) param + param_size)) {
 DMWARN("Invalid target message parameters.");
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1616,13 +1718,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
 ioctl_fn fn = NULL;
 size_t input_param_size;
 
-/* only root can play with this */
-if (!capable(CAP_SYS_ADMIN))
-return -EACCES;
-
 if (_IOC_TYPE(command) != DM_IOCTL)
 return -ENOTTY;
 
+if (initial_permission_check(command))
+return -EACCES;
+
 cmd = _IOC_NR(command);
 
 /*
diff --git a/drivers/md/dm-security.c b/drivers/md/dm-security.c
new file mode 100644
index 0000000..5ce80cf
--- /dev/null
+++ b/drivers/md/dm-security.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,95 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+#include "dm.h"
+#include &amp;lt;linux/fs.h&amp;gt;
+#include &amp;lt;linux/file.h&amp;gt;
+#include &amp;lt;linux/mount.h&amp;gt;
+
+static struct file *get_device_file(unsigned int fd)
+{
+int r;
+struct file *file;
+
+file = fget(fd);
+if (!file)
+return file;
+
+r = -ENOTBLK;
+if (!S_ISBLK(file-&amp;gt;f_dentry-&amp;gt;d_inode-&amp;gt;i_mode))
+goto err;
+
+r = -EACCES;
+if (file-&amp;gt;f_vfsmnt-&amp;gt;mnt_flags &amp;amp; MNT_NODEV)
+goto err;
+
+return file;
+err:
+fput(file);
+return ERR_PTR(r);
+}
+
+
+static struct inode *get_bdev_inode(const char *fd_string)
+{
+char dummy;
+struct file *dev_file;
+struct inode *inode;
+unsigned int fd;
+
+if (sscanf(fd_string, "fd:%u%c", &amp;amp;fd, &amp;amp;dummy) != 1)
+return ERR_PTR(-EINVAL);
+
+dev_file = get_device_file(fd);
+if (!dev_file)
+return ERR_PTR(-EINVAL);
+if (IS_ERR(dev_file))
+return (void *)dev_file;
+
+/*
+ * fd is open by process under it's context
+ * we're in kernel space
+ */
+ihold(dev_file-&amp;gt;f_dentry-&amp;gt;d_inode);
+
+inode = dev_file-&amp;gt;f_dentry-&amp;gt;d_inode;
+fput(dev_file);
+return inode;
+}
+
+int dm_check_backing_dev_permission(struct dm_target *ti, const char *fd_string)
+{
+int perm = 0, r;
+struct inode *inode;
+
+inode = get_bdev_inode(fd_string);
+if (!inode)
+return -EINVAL;
+if (IS_ERR(inode))
+return PTR_ERR(inode);
+
+if (dm_table_get_mode(ti-&amp;gt;table) &amp;amp; FMODE_READ)
+perm |= MAY_READ;
+if (dm_table_get_mode(ti-&amp;gt;table) &amp;amp; FMODE_WRITE)
+perm |= MAY_WRITE;
+
+r = inode_permission(inode, perm);
+
+iput(inode);
+
+return r;
+}
+
+/* fget_light would be better */
+int dm_get_device_from_fd(unsigned int fd, dev_t *devid)
+{
+struct file *file;
+
+file = get_device_file(fd);
+if (!file)
+return -EINVAL;
+if (IS_ERR(file))
+return PTR_ERR(file);
+
+*devid = file-&amp;gt;f_dentry-&amp;gt;d_inode-&amp;gt;i_rdev;
+
+fput(file);
+return 0;
+}
diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c
index 84d2b91..0efdb21 100644
--- a/drivers/md/dm-sysfs.c
+++ b/drivers/md/dm-sysfs.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -64,14 +64,29 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static ssize_t dm_attr_suspended_show(struct mapped_device *md, char *buf)
 return strlen(buf);
 }
 
+static ssize_t dm_attr_owner_uid_show(struct mapped_device *md, char *buf)
+{
+struct block_device *bdev = bdget_disk(dm_disk(md), 0);
+
+if (bdev) {
+sprintf(buf, "%d\n", bdev-&amp;gt;bd_inode-&amp;gt;i_uid);
+bdput(bdev);
+return strlen(buf);
+}
+
+return -EIO;
+}
+
 static DM_ATTR_RO(name);
 static DM_ATTR_RO(uuid);
 static DM_ATTR_RO(suspended);
+static DM_ATTR_RO(owner_uid);
 
 static struct attribute *dm_attrs[] = {
 &amp;amp;dm_attr_name.attr,
 &amp;amp;dm_attr_uuid.attr,
 &amp;amp;dm_attr_suspended.attr,
+&amp;amp;dm_attr_owner_uid.attr,
 NULL,
 };
 
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 2e227fb..f29cb19 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -461,7 +461,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
 int r;
 dev_t uninitialized_var(dev);
 struct dm_dev_internal *dd;
-unsigned int major, minor;
+unsigned int fd, major, minor;
 struct dm_table *t = ti-&amp;gt;table;
 char dummy;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -472,6 +472,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
 dev = MKDEV(major, minor);
 if (MAJOR(dev) != major || MINOR(dev) != minor)
 return -EOVERFLOW;
+} else if (sscanf(path, "fd:%u%c", &amp;amp;fd, &amp;amp;dummy) == 1) {
+r = dm_get_device_from_fd(fd, &amp;amp;dev);
+if (r)
+return r;
 } else {
 /* convert the path to a device */
 struct block_device *bdev = lookup_bdev(path);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -816,6 +820,21 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int dm_table_add_target(struct dm_table *t, const char *type,
 goto bad;
 }
 
+DMDEBUG("taget-type: %s, security-check %s defined", tgt-&amp;gt;type-&amp;gt;name, tgt-&amp;gt;type-&amp;gt;security ? "" : "not");
+
+if (sec_enabled) {
+if (tgt-&amp;gt;type-&amp;gt;security) {
+r = tgt-&amp;gt;type-&amp;gt;security(tgt, argc, argv);
+if (r)
+goto sec_bad;
+} else {
+tgt-&amp;gt;error = "target does not support security checks!";
+/* NOTE: think about suitable error number */
+r = -ENOTTY;
+goto sec_bad;
+}
+}
+
 r = tgt-&amp;gt;type-&amp;gt;ctr(tgt, argc, argv);
 kfree(argv);
 if (r)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -829,6 +848,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int dm_table_add_target(struct dm_table *t, const char *type,
 
 return 0;
 
+ sec_bad:
+kfree(argv);
  bad:
 DMERR("%s: %s: %s", dm_device_name(t-&amp;gt;md), type, tgt-&amp;gt;error);
 dm_put_target_type(tgt-&amp;gt;type);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index e24143c..a333ea7 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -46,6 +46,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static const char *_name = DM_NAME;
 static unsigned int major = 0;
 static unsigned int _major = 0;
 
+unsigned short sec_enabled = 0;
+
 static DEFINE_IDR(_minor_idr);
 
 static DEFINE_SPINLOCK(_minor_lock);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -333,6 +335,76 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void __exit dm_exit(void)
 }
 
 /*
+ * okozina: permissions
+ */
+
+/* FIXME: just simple test */
+/*
+ * Supposed to call during device initialization.
+ * Otherwise inode counter should be incremented.
+ */
+static int set_bdev_owner(struct block_device *bdev)
+{
+int r = 0;
+struct inode *inode;
+
+/*
+ * ATTR_FORCE is compulsory. otherwise perm dennied for
+ * user w/o CAP_FOWNER.
+ *
+ * Note that user that has no right to create dm device
+ * needs to be stopped before ioct() syscall on control
+ * nod.
+ */
+struct iattr attr = {
+.ia_valid = ATTR_UID | ATTR_FORCE,
+.ia_uid = current_fsuid()
+};
+
+inode = bdev-&amp;gt;bd_inode;
+
+mutex_lock(&amp;amp;inode-&amp;gt;i_mutex);
+
+/* for info only */
+BUG_ON(!inode-&amp;gt;i_sb);
+BUG_ON(!inode-&amp;gt;i_sb-&amp;gt;s_root);
+
+r = inode_change_ok(inode, &amp;amp;attr);
+if (r)
+goto out;
+
+setattr_copy(inode, &amp;amp;attr);
+mark_inode_dirty(inode);
+
+out:
+mutex_unlock(&amp;amp;inode-&amp;gt;i_mutex);
+return r;
+}
+
+/*
+ * This is only suggestion how to define ownership
+ * of block device in kernel
+ */
+int dm_check_dm_dev_permission(struct mapped_device *md, int warn, void *attr __attribute__((unused)))
+{
+int r;
+
+if (!md)
+return -EINVAL;
+
+BUG_ON(!md-&amp;gt;bdev);
+BUG_ON(!md-&amp;gt;bdev-&amp;gt;bd_inode);
+
+r = !inode_owner_or_capable(md-&amp;gt;bdev-&amp;gt;bd_inode);
+
+if (r &amp;amp;&amp;amp; warn)
+DMWARN("uid: %d is not owner (or capable) of the "
+"device %s", current_uid(), dm_device_name(md));
+
+return r;
+}
+
+/*
  * Block device functions
  */
 int dm_deleting_md(struct mapped_device *md)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -421,6 +493,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
 if (!map || !dm_table_get_size(map))
 goto out;
 
+if (!capable(CAP_SYS_ADMIN)) {
+r = -EACCES;
+goto out;
+}
+
 /* We only support devices that have a single target */
 if (dm_table_get_num_targets(map) != 1)
 goto out;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1884,6 +1961,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct mapped_device *alloc_dev(int minor)
 if (!md-&amp;gt;bdev)
 goto bad_bdev;
 
+/* It's just a test. This should be
+ * in block layer */
+if (set_bdev_owner(md-&amp;gt;bdev)) {
+DMDEBUG("set device ownership failed");
+goto bad_bdev;
+}
+DMDEBUG("Device %s has got owner uid: %d",
+md-&amp;gt;name, md-&amp;gt;bdev-&amp;gt;bd_inode-&amp;gt;i_uid);
+
 bio_init(&amp;amp;md-&amp;gt;flush_bio);
 md-&amp;gt;flush_bio.bi_bdev = md-&amp;gt;bdev;
 md-&amp;gt;flush_bio.bi_rw = WRITE_FLUSH;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2774,6 +2860,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; module_init(dm_init);
 module_exit(dm_exit);
 
 module_param(major, uint, 0);
+module_param_named(enable_security, sec_enabled, ushort, 0444);
 MODULE_PARM_DESC(major, "The major number of the device mapper");
 MODULE_DESCRIPTION(DM_NAME " driver");
 MODULE_AUTHOR("Joe Thornber &amp;lt;dm-devel&amp;lt; at &amp;gt;redhat.com&amp;gt;");
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index b7dacd5..82e98bd 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -156,4 +156,16 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void dm_kcopyd_exit(void);
 struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity);
 void dm_free_md_mempools(struct dm_md_mempools *pools);
 
+/*
+ * Check device permission
+ */
+int dm_check_dm_dev_permission(struct mapped_device *md, int warn, void *attr);
+
+/*
+ *  Security related functions
+ */
+
+int dm_get_device_from_fd(unsigned int fd, dev_t *devid);
+int dm_check_backing_dev_permission(struct dm_target *ti, const char *fd_string);
+
 #endif
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 98f34b8..7ddca63 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -12,6 +12,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #include &amp;lt;linux/blkdev.h&amp;gt;
 #include &amp;lt;linux/ratelimit.h&amp;gt;
 
+extern unsigned short sec_enabled;
+
 struct dm_dev;
 struct dm_target;
 struct dm_table;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -95,6 +97,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; typedef int (*dm_iterate_devices_fn) (struct dm_target *ti,
 typedef void (*dm_io_hints_fn) (struct dm_target *ti,
 struct queue_limits *limits);
 
+typedef int (*dm_security_fn) (struct dm_target *ti, unsigned int argc, char **argv);
+
 /*
  * Returns:
  *    0: The target can handle the next I/O immediately.
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -151,6 +155,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct target_type {
 dm_busy_fn busy;
 dm_iterate_devices_fn iterate_devices;
 dm_io_hints_fn io_hints;
+dm_security_fn security;
 
 /* For internal device-mapper use. */
 struct list_head list;
&lt;/pre&gt;</description>
    <dc:creator>Ondrej Kozina</dc:creator>
    <dc:date>2012-05-25T13:22:26</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15962">
    <title>[RFC PATCH v2 0/3] Allow user w/o CAP_SYS_ADMIN tosubmit ioctl commands into DM</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15962</link>
    <description>&lt;pre&gt;Hi,

I would like to post new version of my previous RFC with a set of changes for
device-mapper that would enable user w/o CAP_SYS_ADMIN capability to create 
and manage his own devices.

Changes in version No. 2:
^^^^^^^^^^^^^^^^^^^^^^^^

(*) No major:minor translation to dentry (inode) in kernel space. Supposing
    userspace should resolve that.

(*) Load time parameter to enable security enhancements

(*) Supposing security is enabled, userspace should handle open file descriptors
    and kernel checks whether the user is authorised to access the device
    linked to the device node.

The rest of message is the same as in original RFC

Simple use cases:
^^^^^^^^^^^^^^^^
(1) Non-root user would be able to create dm-crypt device from USB stick
    (assuming the user has permission to access backing device)
(2) You can create pool of storage space for virtual machines. VM managers
    would be able to administrate the pool w/o root permissions:

    .--------------. .----------------.
    |_owner: VM 01_| |__owner: VM 02__|
           |                |
           |                |
    .---------------------------------.
    |____owner: VM manager____________|

Short Overview:
^^^^^^^^^^^^^^
(1) The first checkpoint that decides whether the user has an access right to
    submit ioctl cmds into DM driver are actually the attributes on dentry of
    /dev/mapper/control (through general perm., ACL, LSM checks).

(2) After the DM_DEV_CREATE ioctl, new block device will receive FSUID and
    from the context on behalf of which we entered into kernel

(3) Whenever user asks to manipulate DM device he must pass the test whether
    he's the owner of DM device or he has CAP_FOWNER capability.

(4) During the table creation process we check whether the user has right to
    READ/WRITE the backing device, according to table mode. For that purpose
    I added a new function into target_type interface - dm_security_fn.

With regards
O.

Ondrej Kozina (3):
  Adds support for user-submitted ioctl commands
  Adds support for security checks in the linear target
  Adds support for security checks in the crypt target

 drivers/md/Makefile           |    2 +-
 drivers/md/dm-crypt.c         |   18 +++++-
 drivers/md/dm-ioctl.c         |  141 +++++++++++++++++++++++++++++++++++------
 drivers/md/dm-linear.c        |   19 +++++-
 drivers/md/dm-security.c      |   95 +++++++++++++++++++++++++++
 drivers/md/dm-sysfs.c         |   15 +++++
 drivers/md/dm-table.c         |   23 +++++++-
 drivers/md/dm.c               |   87 +++++++++++++++++++++++++
 drivers/md/dm.h               |   12 ++++
 include/linux/device-mapper.h |    5 ++
 10 files changed, 393 insertions(+), 24 deletions(-)
 create mode 100644 drivers/md/dm-security.c

&lt;/pre&gt;</description>
    <dc:creator>Ondrej Kozina</dc:creator>
    <dc:date>2012-05-25T13:22:25</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15961">
    <title>[RFC PATCH v2 3/3] Adds support for security checks inthe crypt target</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15961</link>
    <description>&lt;pre&gt;Just a security check implementation for the crypt target

---
 drivers/md/dm-crypt.c |   18 +++++++++++++++++-
 1 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 3f06df5..af6f319 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1867,9 +1867,24 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int crypt_iterate_devices(struct dm_target *ti,
 return fn(ti, cc-&amp;gt;dev, cc-&amp;gt;start, ti-&amp;gt;len, data);
 }
 
+static int crypt_security(struct dm_target *ti, unsigned int argc, char **argv)
+{
+int r;
+
+if (argc &amp;lt; 4) {
+ti-&amp;gt;error = "dm-crypt: Security check: invalid number of parameters";
+return -EINVAL;
+}
+r = dm_check_backing_dev_permission(ti, argv[3]);
+if (r)
+ti-&amp;gt;error = "dm-crypt: Security check failed";
+
+return r;
+}
+
 static struct target_type crypt_target = {
 .name   = "crypt",
-.version = {1, 11, 0},
+.version = {1, 12, 0},
 .module = THIS_MODULE,
 .ctr    = crypt_ctr,
 .dtr    = crypt_dtr,
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1881,6 +1896,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct target_type crypt_target = {
 .message = crypt_message,
 .merge  = crypt_merge,
 .iterate_devices = crypt_iterate_devices,
+.security = crypt_security
 };
 
 static int __init dm_crypt_init(void)
&lt;/pre&gt;</description>
    <dc:creator>Ondrej Kozina</dc:creator>
    <dc:date>2012-05-25T13:22:28</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15959">
    <title>Re: [PATCH 0/2] multipath: compile cleanup</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15959</link>
    <description>&lt;pre&gt;Merged.

Thanks.




&lt;/pre&gt;</description>
    <dc:creator>Christophe Varoqui</dc:creator>
    <dc:date>2012-05-25T05:20:53</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15958">
    <title>[PATCH 0/2] multipath: compile cleanup</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15958</link>
    <description>&lt;pre&gt;When the multipath code is compiled with the standard redhat rpm cflags,
there are a number of warnings that get issued, some about real problems.

These patches switch multipath to use those cflags, and then clean up
warnings. If people want upstream to continue using the existing cflags,
I don't particularly mind.  I really included the first patch to make sure
people can see the warnings that the second patch corrects.

Also, some of the warnings are for actual errors, and how to fix them is
obvious.  Others won't actually cause problems, and if people object to
the changes I made to make them go away, I'm happy to fix them differently. 

Benjamin Marzinski (2):
  multipath: Build with standard rpm cflags
  multipath: Fix warnings from stricter compile options.

 Makefile.inc                     |    6 +++++-
 libmpathpersist/mpath_persist.c  |   10 +++++++---
 libmpathpersist/mpath_pr_ioctl.c |    9 +++++++++
 libmultipath/alias.c             |    8 ++++++--
 mpathpersist/main.c              |    2 --
 multipathd/main.c                |   24 +++++++++++++++++++-----
 6 files changed, 46 insertions(+), 13 deletions(-)

&lt;/pre&gt;</description>
    <dc:creator>Benjamin Marzinski</dc:creator>
    <dc:date>2012-05-25T04:57:41</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15957">
    <title>[PATCH 2/2] multipath: Fix warnings from strictercompile options.</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15957</link>
    <description>&lt;pre&gt;With stricter compilation options, multipath printed number of
warnings during compilation. Some of them were actual bugs. Others
couldn't cause any problems.  This patch cleans up all the new
warnings.

Signed-off-by: Benjamin Marzinski &amp;lt;bmarzins&amp;lt; at &amp;gt;redhat.com&amp;gt;
---
 libmpathpersist/mpath_persist.c  |   10 +++++++---
 libmpathpersist/mpath_pr_ioctl.c |    9 +++++++++
 libmultipath/alias.c             |    8 ++++++--
 mpathpersist/main.c              |    2 --
 multipathd/main.c                |   24 +++++++++++++++++++-----
 5 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
index d99c0da..3041089 100644
--- a/libmpathpersist/mpath_persist.c
+++ b/libmpathpersist/mpath_persist.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -177,8 +177,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp *resp,
 goto out;
 }
 
-if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER))
+if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) {
+ret = MPATH_PR_DMMP_ERROR;
 goto out1;
+}
 
 /* get info of all paths from the dm device*/
 if (get_mpvec (curmp, pathvec, alias)){
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -265,8 +267,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
                 goto out;
         }
 
-if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER))
+if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) {
+ret = MPATH_PR_DMMP_ERROR;
 goto out1;
+}
 
 /* get info of all paths from the dm device     */
 if (get_mpvec(curmp, pathvec, alias)){
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -408,7 +412,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
 int rc;
 int count=0;
 int status = MPATH_PR_SUCCESS;
-uint64_t sa_key;
+uint64_t sa_key = 0;
 
 if (!mpp)
 return MPATH_PR_DMMP_ERROR; 
diff --git a/libmpathpersist/mpath_pr_ioctl.c b/libmpathpersist/mpath_pr_ioctl.c
index 2d4d968..de3292e 100644
--- a/libmpathpersist/mpath_pr_ioctl.c
+++ b/libmpathpersist/mpath_pr_ioctl.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -314,6 +314,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp * resp, int
 else
 mx_resp_len = get_prin_length(rq_servact);
 
+if (mx_resp_len == 0) {
+status = MPATH_PR_SYNTAX_ERROR;
+goto out;
+}
+
 cdb[1] = (unsigned char)(rq_servact &amp;amp; 0x1f);
 cdb[7] = (unsigned char)((mx_resp_len &amp;gt;&amp;gt; 8) &amp;amp; 0xff);
 cdb[8] = (unsigned char)(mx_resp_len &amp;amp; 0xff);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -569,6 +574,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int get_prin_length(int rq_servact)
                 case MPATH_PRIN_RFSTAT_SA:
                         mx_resp_len = sizeof(struct print_fulldescr_list) + sizeof(struct prin_fulldescr *)*32;
                         break;
+default:
+condlog(0, "invalid service action, %d", rq_servact);
+mx_resp_len = 0;
+break;
         }
         return mx_resp_len;
 }
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 4159ec6..ec3a225 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -165,7 +165,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; open_bindings_file(char *file, int *can_write)
 "Cannot write header to bindings file : %s",
 strerror(errno));
 /* cleanup partially written header */
-ftruncate(fd, 0);
+if (ftruncate(fd, 0))
+condlog(0, "Cannot truncate the header : %s",
+strerror(errno));
 goto fail;
 }
 fsync(fd);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -337,7 +339,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; allocate_binding(int fd, char *wwid, int id, char *prefix)
 condlog(0, "Cannot write binding to bindings file : %s",
 strerror(errno));
 /* clear partial write */
-ftruncate(fd, offset);
+if (ftruncate(fd, offset))
+condlog(0, "Cannot truncate the header : %s",
+strerror(errno));
 return NULL;
 }
 c = strchr(buf, ' ');
diff --git a/mpathpersist/main.c b/mpathpersist/main.c
index 33dad90..465fcb1 100644
--- a/mpathpersist/main.c
+++ b/mpathpersist/main.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -736,7 +736,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; mpath_print_transport_id(struct prin_fulldescr *fdesc)
 int
 construct_transportid(const char * lcp, struct transportid transid[], int num_transportids)
 {
-unsigned char * tidp;
 int k = 0;
 int j, n, b, c, len, alen;
 const char * ecp;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -792,7 +791,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; construct_transportid(const char * lcp, struct transportid transid[], int num_tr
 if (ecp &amp;amp;&amp;amp; (isip &amp;gt; ecp))
 isip = NULL;
 len = ecp ? (ecp - lcp) : (int)strlen(lcp);
-memset(&amp;amp;tidp, 0, 24);
 transid[num_transportids].format_code = (isip ? MPATH_WWUI_PORT_IDENTIFIER:MPATH_WWUI_DEVICE_NAME);
 transid[num_transportids].protocol_id = MPATH_PROTOCOL_ID_ISCSI;
 alen = len + 1; /* at least one trailing null */
diff --git a/multipathd/main.c b/multipathd/main.c
index 69cef3c..5dea995 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -664,7 +664,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; fail:
 static int
 uev_update_path (struct uevent *uev, struct vectors * vecs)
 {
-int retval, ro;
+int ro, retval = 0;
 
 ro = uevent_get_disk_ro(uev);
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1755,11 +1755,23 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; daemonize(void)
 }
 
 close(STDIN_FILENO);
-dup(dev_null_fd);
+if (dup(dev_null_fd) &amp;lt; 0) {
+fprintf(stderr, "cannot dup /dev/null to stdin : %s\n",
+strerror(errno));
+_exit(0);
+}
 close(STDOUT_FILENO);
-dup(dev_null_fd);
+if (dup(dev_null_fd) &amp;lt; 0) {
+fprintf(stderr, "cannot dup /dev/null to stdout : %s\n",
+strerror(errno));
+_exit(0);
+}
 close(STDERR_FILENO);
-dup(dev_null_fd);
+if (dup(dev_null_fd) &amp;lt; 0) {
+fprintf(stderr, "cannot dup /dev/null to stderr : %s\n",
+strerror(errno));
+_exit(0);
+}
 close(dev_null_fd);
 daemon_pid = getpid();
 return 0;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1783,7 +1795,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; main (int argc, char *argv[])
 }
 
 /* make sure we don't lock any path */
-chdir("/");
+if (chdir("/") &amp;lt; 0)
+fprintf(stderr, "can't chdir to root directory : %s\n",
+strerror(errno));
 umask(umask(077) | 022);
 
 conf = alloc_config();
&lt;/pre&gt;</description>
    <dc:creator>Benjamin Marzinski</dc:creator>
    <dc:date>2012-05-25T04:57:43</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15956">
    <title>[PATCH 1/2] multipath: Build with standard rpm cflags</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15956</link>
    <description>&lt;pre&gt;This patch makes multipath build with the standard redhat rpm cflags, which
can help catch some code errors.

Signed-off-by: Benjamin Marzinski &amp;lt;bmarzins&amp;lt; at &amp;gt;redhat.com&amp;gt;
---
 Makefile.inc |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/Makefile.inc b/Makefile.inc
index 02aef4f..b0c68f4 100644
--- a/Makefile.inc
+++ b/Makefile.inc
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -38,7 +38,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; mpathpersistdir = $(TOPDIR)/libmpathpersist
 GZIP        = /bin/gzip -9 -c
 INSTALL_PROGRAM = install
 
-OPTFLAGS     = -pipe -g -Wall -Wunused -Wstrict-prototypes
+ifndef RPM_OPT_FLAGS
+RPM_OPT_FLAGS = -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4
+endif
+
+OPTFLAGS     = $(RPM_OPT_FLAGS) -Wunused -Wstrict-prototypes
 CFLAGS     = $(OPTFLAGS) -fPIC -DLIB_STRING=\"${LIB}\"
 SHARED_FLAGS = -shared
 
&lt;/pre&gt;</description>
    <dc:creator>Benjamin Marzinski</dc:creator>
    <dc:date>2012-05-25T04:57:42</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15947">
    <title>Re: [PATCH v2 08/14] block: Kill bi_destructor</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15947</link>
    <description>&lt;pre&gt;
Just noticed bio_kmalloc_destructor() will take care of freeing bio_kmalloc()
bios and it has been dropped in this patch. So memory leak point is moot.
bio_reset() question still remains though.

Thanks
Vivek

&lt;/pre&gt;</description>
    <dc:creator>Vivek Goyal</dc:creator>
    <dc:date>2012-05-24T19:58:10</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15946">
    <title>Re: [PATCH v2 07/14] pktcdvd: Switch to bio_kmalloc()</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15946</link>
    <description>&lt;pre&gt;
bio_kmalloc() sets up bi_destructor, so there's no need to kfree() the
bio - bio_put() frees it just like normal.

&lt;/pre&gt;</description>
    <dc:creator>Kent Overstreet</dc:creator>
    <dc:date>2012-05-24T19:55:49</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15928">
    <title>bcache performance test problem</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15928</link>
    <description>&lt;pre&gt;Hi Kent,

I have tested bcache on my platform, but the result is not good. I think maybe the wrong config caused it. Would you pls help me to check the config, or give me some advice for bcache performance testing?

My SSD card is  a PCIe SSD card (about 120,000 IOPS), and I used 10GB.

I have download the code from git://evilpiepirate.org/~kent/linux-bcache.git.
The commands creating bcache is below:
make-bcache -B /dev/sdb8
make-bcache -C -w4k -b1M -writeback /dev/hioa5

I use FIO to test the seq./random IO performance, and the result is below:
write             read                    randwrite    randread
bcache               10809 KB/s    164502.5 KB/s     2713 KB/s    29640 KB/s
cache_hit_rate  80                  79                         94                92


And the basic test result is:
Write                   read                  randwrite             randread
HDD      81211.6 KB/s       172242 KB/s     2606 KB/s             1855 KB/s
SSD       250948.2 KB/s     813855 KB/s     238892.7 KB/s      657319.5 KB/s

&lt;/pre&gt;</description>
    <dc:creator>Qinling</dc:creator>
    <dc:date>2012-05-24T01:14:01</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15922">
    <title>[PATCH v2 04/14] block: Add bio_clone_kmalloc()</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15922</link>
    <description>&lt;pre&gt;Signed-off-by: Kent Overstreet &amp;lt;koverstreet&amp;lt; at &amp;gt;google.com&amp;gt;
---
 drivers/block/osdblk.c |    3 +--
 drivers/block/rbd.c    |    8 ++------
 fs/bio.c               |   13 +++++++++++++
 fs/exofs/ore.c         |    5 ++---
 include/linux/bio.h    |    1 +
 5 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
index 87311eb..1bbc681 100644
--- a/drivers/block/osdblk.c
+++ b/drivers/block/osdblk.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -266,11 +266,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask)
 struct bio *tmp, *new_chain = NULL, *tail = NULL;
 
 while (old_chain) {
-tmp = bio_kmalloc(gfpmask, old_chain-&amp;gt;bi_max_vecs);
+tmp = bio_clone_kmalloc(old_chain, gfpmask);
 if (!tmp)
 goto err_out;
 
-__bio_clone(tmp, old_chain);
 tmp-&amp;gt;bi_bdev = NULL;
 gfpmask &amp;amp;= ~__GFP_WAIT;
 tmp-&amp;gt;bi_next = NULL;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 013c7a5..5a953c6 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -729,7 +729,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct bio *bio_chain_clone(struct bio **old, struct bio **next,
 }
 
 while (old_chain &amp;amp;&amp;amp; (total &amp;lt; len)) {
-tmp = bio_kmalloc(gfpmask, old_chain-&amp;gt;bi_max_vecs);
+tmp = bio_clone_kmalloc(old_chain, gfpmask);
 if (!tmp)
 goto err_out;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -751,13 +751,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct bio *bio_chain_clone(struct bio **old, struct bio **next,
 if (!bp)
 goto err_out;
 
-__bio_clone(tmp, &amp;amp;bp-&amp;gt;bio1);
-
 *next = &amp;amp;bp-&amp;gt;bio2;
-} else {
-__bio_clone(tmp, old_chain);
+} else
 *next = old_chain-&amp;gt;bi_next;
-}
 
 tmp-&amp;gt;bi_bdev = NULL;
 gfpmask &amp;amp;= ~__GFP_WAIT;
diff --git a/fs/bio.c b/fs/bio.c
index 4cb621f..e2c0970 100644
--- a/fs/bio.c
+++ b/fs/bio.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -491,6 +491,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(bio_clone);
 
+struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask)
+{
+struct bio *b = bio_kmalloc(gfp_mask, bio-&amp;gt;bi_max_vecs);
+
+if (!b)
+return NULL;
+
+__bio_clone(b, bio);
+
+return b;
+}
+EXPORT_SYMBOL(bio_clone_kmalloc);
+
 /**
  *bio_get_nr_vecs- return approx number of vecs
  *&amp;lt; at &amp;gt;bdev:  I/O target
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c
index 49cf230..95c7264 100644
--- a/fs/exofs/ore.c
+++ b/fs/exofs/ore.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -820,8 +820,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int _write_mirror(struct ore_io_state *ios, int cur_comp)
 struct bio *bio;
 
 if (per_dev != master_dev) {
-bio = bio_kmalloc(GFP_KERNEL,
-  master_dev-&amp;gt;bio-&amp;gt;bi_max_vecs);
+bio = bio_clone_kmalloc(master_dev-&amp;gt;bio,
+GFP_KERNEL);
 if (unlikely(!bio)) {
 ORE_DBGMSG(
       "Failed to allocate BIO size=%u\n",
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -830,7 +830,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int _write_mirror(struct ore_io_state *ios, int cur_comp)
 goto out;
 }
 
-__bio_clone(bio, master_dev-&amp;gt;bio);
 bio-&amp;gt;bi_bdev = NULL;
 bio-&amp;gt;bi_next = NULL;
 per_dev-&amp;gt;offset = master_dev-&amp;gt;offset;
diff --git a/include/linux/bio.h b/include/linux/bio.h
index e068a68..b27f16b 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -225,6 +225,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; extern int bio_phys_segments(struct request_queue *, struct bio *);
 extern void __bio_clone(struct bio *, struct bio *);
 extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs);
 extern struct bio *bio_clone(struct bio *, gfp_t);
+struct bio *bio_clone_kmalloc(struct bio *, gfp_t);
 
 extern void bio_init(struct bio *);
 
&lt;/pre&gt;</description>
    <dc:creator>Kent Overstreet</dc:creator>
    <dc:date>2012-05-24T00:02:41</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15921">
    <title>[PATCH v2 03/14] block: Add bio_clone_bioset()</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15921</link>
    <description>&lt;pre&gt;This consolidates some code, and will help in a later patch changing how
bio cloning works.

Signed-off-by: Kent Overstreet &amp;lt;koverstreet&amp;lt; at &amp;gt;google.com&amp;gt;
Change-Id: If6cfd840db9cf90a798c6a5862e3314465c83000
---
 block/blk-core.c    |    8 +-------
 drivers/md/dm.c     |   27 ++++++++++-----------------
 drivers/md/md.c     |   20 +-------------------
 fs/bio.c            |   16 ++++++++++++----
 include/linux/bio.h |    1 +
 5 files changed, 25 insertions(+), 47 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 1f61b74..91617eb 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2660,16 +2660,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
 blk_rq_init(NULL, rq);
 
 __rq_for_each_bio(bio_src, rq_src) {
-bio = bio_alloc_bioset(gfp_mask, bio_src-&amp;gt;bi_max_vecs, bs);
+bio = bio_clone_bioset(bio_src, gfp_mask, bs);
 if (!bio)
 goto free_and_out;
 
-__bio_clone(bio, bio_src);
-
-if (bio_integrity(bio_src) &amp;amp;&amp;amp;
-    bio_integrity_clone(bio, bio_src, gfp_mask, bs))
-goto free_and_out;
-
 if (bio_ctr &amp;amp;&amp;amp; bio_ctr(bio, bio_src, data))
 goto free_and_out;
 
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index e6e7b19..e5076f2 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1062,26 +1062,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct bio *split_bvec(struct bio *bio, sector_t sector,
  * Creates a bio that consists of range of complete bvecs.
  */
 static struct bio *clone_bio(struct bio *bio, sector_t sector,
-     unsigned short idx, unsigned short bv_count,
+     unsigned short bv_count,
      unsigned int len, struct bio_set *bs)
 {
 struct bio *clone;
 
-clone = bio_alloc_bioset(GFP_NOIO, bio-&amp;gt;bi_max_vecs, bs);
-__bio_clone(clone, bio);
+clone = bio_clone_bioset(bio, GFP_NOIO, bs);
 clone-&amp;gt;bi_sector = sector;
-clone-&amp;gt;bi_idx = idx;
-clone-&amp;gt;bi_vcnt = idx + bv_count;
+clone-&amp;gt;bi_vcnt = bv_count;
 clone-&amp;gt;bi_size = to_bytes(len);
-clone-&amp;gt;bi_flags &amp;amp;= ~(1 &amp;lt;&amp;lt; BIO_SEG_VALID);
 
-if (bio_integrity(bio)) {
-bio_integrity_clone(clone, bio, GFP_NOIO, bs);
-
-if (idx != bio-&amp;gt;bi_idx || clone-&amp;gt;bi_size &amp;lt; bio-&amp;gt;bi_size)
-bio_integrity_trim(clone,
-   bio_sector_offset(bio, idx, 0), len);
-}
+if (bio_integrity(bio) &amp;amp;&amp;amp;
+    clone-&amp;gt;bi_size &amp;lt; bio-&amp;gt;bi_size)
+bio_integrity_trim(clone, 0, len);
 
 return clone;
 }
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1111,8 +1104,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void __issue_target_request(struct clone_info *ci, struct dm_target *ti,
  * ci-&amp;gt;bio-&amp;gt;bi_max_vecs is BIO_INLINE_VECS anyway, for both flush
  * and discard, so no need for concern about wasted bvec allocations.
  */
-clone = bio_alloc_bioset(GFP_NOIO, ci-&amp;gt;bio-&amp;gt;bi_max_vecs, ci-&amp;gt;md-&amp;gt;bs);
-__bio_clone(clone, ci-&amp;gt;bio);
+clone = bio_clone_bioset(ci-&amp;gt;bio, GFP_NOIO, ci-&amp;gt;md-&amp;gt;bs);
+
 if (len) {
 clone-&amp;gt;bi_sector = ci-&amp;gt;sector;
 clone-&amp;gt;bi_size = to_bytes(len);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1151,7 +1144,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti)
 struct dm_target_io *tio;
 
 tio = alloc_tio(ci, ti);
-clone = clone_bio(bio, ci-&amp;gt;sector, ci-&amp;gt;idx,
+clone = clone_bio(bio, ci-&amp;gt;sector,
   bio-&amp;gt;bi_vcnt - ci-&amp;gt;idx, ci-&amp;gt;sector_count,
   ci-&amp;gt;md-&amp;gt;bs);
 __map_bio(ti, clone, tio);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1230,7 +1223,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int __clone_and_map(struct clone_info *ci)
 }
 
 tio = alloc_tio(ci, ti);
-clone = clone_bio(bio, ci-&amp;gt;sector, ci-&amp;gt;idx, i - ci-&amp;gt;idx, len,
+clone = clone_bio(bio, ci-&amp;gt;sector, i - ci-&amp;gt;idx, len,
   ci-&amp;gt;md-&amp;gt;bs);
 __map_bio(ti, clone, tio);
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index a5a524e..508ae81 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -173,28 +173,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; EXPORT_SYMBOL_GPL(bio_alloc_mddev);
 struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
     struct mddev *mddev)
 {
-struct bio *b;
-
 if (!mddev || !mddev-&amp;gt;bio_set)
 return bio_clone(bio, gfp_mask);
 
-b = bio_alloc_bioset(gfp_mask, bio-&amp;gt;bi_max_vecs, mddev-&amp;gt;bio_set);
-if (!b)
-return NULL;
-
-__bio_clone(b, bio);
-if (bio_integrity(bio)) {
-int ret;
-
-ret = bio_integrity_clone(b, bio, gfp_mask, mddev-&amp;gt;bio_set);
-
-if (ret &amp;lt; 0) {
-bio_put(b);
-return NULL;
-}
-}
-
-return b;
+return bio_clone_bioset(bio, gfp_mask, mddev-&amp;gt;bio_set);
 }
 EXPORT_SYMBOL_GPL(bio_clone_mddev);
 
diff --git a/fs/bio.c b/fs/bio.c
index 3667cef..4cb621f 100644
--- a/fs/bio.c
+++ b/fs/bio.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -453,15 +453,17 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void __bio_clone(struct bio *bio, struct bio *bio_src)
 EXPORT_SYMBOL(__bio_clone);
 
 /**
- *bio_clone-clone a bio
+ *bio_clone_bioset -clone a bio
  *&amp;lt; at &amp;gt;bio: bio to clone
  *&amp;lt; at &amp;gt;gfp_mask: allocation priority
+ *&amp;lt; at &amp;gt;bs: bio_set to allocate from
  *
  * Like __bio_clone, only also allocates the returned bio
  */
-struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
+struct bio *bio_clone_bioset(struct bio *bio, gfp_t gfp_mask,
+     struct bio_set *bs)
 {
-struct bio *b = bio_alloc(gfp_mask, bio-&amp;gt;bi_max_vecs);
+struct bio *b = bio_alloc_bioset(gfp_mask, bio-&amp;gt;bi_max_vecs, bs);
 
 if (!b)
 return NULL;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -471,7 +473,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
 if (bio_integrity(bio)) {
 int ret;
 
-ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set);
+ret = bio_integrity_clone(b, bio, gfp_mask, bs);
 
 if (ret &amp;lt; 0) {
 bio_put(b);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -481,6 +483,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
 
 return b;
 }
+EXPORT_SYMBOL(bio_clone_bioset);
+
+struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
+{
+return bio_clone_bioset(bio, gfp_mask, fs_bio_set);
+}
 EXPORT_SYMBOL(bio_clone);
 
 /**
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 4d94eb8..e068a68 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -223,6 +223,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct request_queue;
 extern int bio_phys_segments(struct request_queue *, struct bio *);
 
 extern void __bio_clone(struct bio *, struct bio *);
+extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs);
 extern struct bio *bio_clone(struct bio *, gfp_t);
 
 extern void bio_init(struct bio *);
&lt;/pre&gt;</description>
    <dc:creator>Kent Overstreet</dc:creator>
    <dc:date>2012-05-24T00:02:40</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15918">
    <title>[PATCH v2 07/14] pktcdvd: Switch to bio_kmalloc()</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15918</link>
    <description>&lt;pre&gt;This is prep work for killing bi_destructor - previously, pktcdvd had
its own pkt_bio_alloc which was basically duplication bio_kmalloc(),
necessitating its own bi_destructor implementation.

Signed-off-by: Kent Overstreet &amp;lt;koverstreet&amp;lt; at &amp;gt;google.com&amp;gt;
Change-Id: I5604293e07f695c8f0106ae819e306f1def89a67
---
 drivers/block/pktcdvd.c |  115 ++++++++++++++++-------------------------------
 1 file changed, 39 insertions(+), 76 deletions(-)

diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index ba66e44..6fe693a 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -522,36 +522,38 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void pkt_bio_finished(struct pktcdvd_device *pd)
 }
 }
 
-static void pkt_bio_destructor(struct bio *bio)
+static void pkt_end_io_read(struct bio *bio, int err)
 {
-kfree(bio-&amp;gt;bi_io_vec);
-kfree(bio);
-}
+struct packet_data *pkt = bio-&amp;gt;bi_private;
+struct pktcdvd_device *pd = pkt-&amp;gt;pd;
+BUG_ON(!pd);
 
-static struct bio *pkt_bio_alloc(int nr_iovecs)
-{
-struct bio_vec *bvl = NULL;
-struct bio *bio;
+VPRINTK("pkt_end_io_read: bio=%p sec0=%llx sec=%llx err=%d\n", bio,
+(unsigned long long)pkt-&amp;gt;sector, (unsigned long long)bio-&amp;gt;bi_sector, err);
 
-bio = kmalloc(sizeof(struct bio), GFP_KERNEL);
-if (!bio)
-goto no_bio;
-bio_init(bio);
+if (err)
+atomic_inc(&amp;amp;pkt-&amp;gt;io_errors);
+if (atomic_dec_and_test(&amp;amp;pkt-&amp;gt;io_wait)) {
+atomic_inc(&amp;amp;pkt-&amp;gt;run_sm);
+wake_up(&amp;amp;pd-&amp;gt;wqueue);
+}
+pkt_bio_finished(pd);
+}
 
-bvl = kcalloc(nr_iovecs, sizeof(struct bio_vec), GFP_KERNEL);
-if (!bvl)
-goto no_bvl;
+static void pkt_end_io_packet_write(struct bio *bio, int err)
+{
+struct packet_data *pkt = bio-&amp;gt;bi_private;
+struct pktcdvd_device *pd = pkt-&amp;gt;pd;
+BUG_ON(!pd);
 
-bio-&amp;gt;bi_max_vecs = nr_iovecs;
-bio-&amp;gt;bi_io_vec = bvl;
-bio-&amp;gt;bi_destructor = pkt_bio_destructor;
+VPRINTK("pkt_end_io_packet_write: id=%d, err=%d\n", pkt-&amp;gt;id, err);
 
-return bio;
+pd-&amp;gt;stats.pkt_ended++;
 
- no_bvl:
-kfree(bio);
- no_bio:
-return NULL;
+pkt_bio_finished(pd);
+atomic_dec(&amp;amp;pkt-&amp;gt;io_wait);
+atomic_inc(&amp;amp;pkt-&amp;gt;run_sm);
+wake_up(&amp;amp;pd-&amp;gt;wqueue);
 }
 
 /*
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -567,10 +569,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct packet_data *pkt_alloc_packet_data(int frames)
 goto no_pkt;
 
 pkt-&amp;gt;frames = frames;
-pkt-&amp;gt;w_bio = pkt_bio_alloc(frames);
+pkt-&amp;gt;w_bio = bio_kmalloc(GFP_KERNEL, frames);
 if (!pkt-&amp;gt;w_bio)
 goto no_bio;
 
+pkt-&amp;gt;w_bio-&amp;gt;bi_end_io = pkt_end_io_packet_write;
+pkt-&amp;gt;w_bio-&amp;gt;bi_private = pkt;
+
 for (i = 0; i &amp;lt; frames / FRAMES_PER_PAGE; i++) {
 pkt-&amp;gt;pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO);
 if (!pkt-&amp;gt;pages[i])
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -581,9 +586,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct packet_data *pkt_alloc_packet_data(int frames)
 bio_list_init(&amp;amp;pkt-&amp;gt;orig_bios);
 
 for (i = 0; i &amp;lt; frames; i++) {
-struct bio *bio = pkt_bio_alloc(1);
+struct bio *bio = bio_kmalloc(GFP_KERNEL, 1);
 if (!bio)
 goto no_rd_bio;
+
+bio-&amp;gt;bi_end_io = pkt_end_io_read;
+bio-&amp;gt;bi_private = pkt;
 pkt-&amp;gt;r_bios[i] = bio;
 }
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1036,40 +1044,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec)
 }
 }
 
-static void pkt_end_io_read(struct bio *bio, int err)
-{
-struct packet_data *pkt = bio-&amp;gt;bi_private;
-struct pktcdvd_device *pd = pkt-&amp;gt;pd;
-BUG_ON(!pd);
-
-VPRINTK("pkt_end_io_read: bio=%p sec0=%llx sec=%llx err=%d\n", bio,
-(unsigned long long)pkt-&amp;gt;sector, (unsigned long long)bio-&amp;gt;bi_sector, err);
-
-if (err)
-atomic_inc(&amp;amp;pkt-&amp;gt;io_errors);
-if (atomic_dec_and_test(&amp;amp;pkt-&amp;gt;io_wait)) {
-atomic_inc(&amp;amp;pkt-&amp;gt;run_sm);
-wake_up(&amp;amp;pd-&amp;gt;wqueue);
-}
-pkt_bio_finished(pd);
-}
-
-static void pkt_end_io_packet_write(struct bio *bio, int err)
-{
-struct packet_data *pkt = bio-&amp;gt;bi_private;
-struct pktcdvd_device *pd = pkt-&amp;gt;pd;
-BUG_ON(!pd);
-
-VPRINTK("pkt_end_io_packet_write: id=%d, err=%d\n", pkt-&amp;gt;id, err);
-
-pd-&amp;gt;stats.pkt_ended++;
-
-pkt_bio_finished(pd);
-atomic_dec(&amp;amp;pkt-&amp;gt;io_wait);
-atomic_inc(&amp;amp;pkt-&amp;gt;run_sm);
-wake_up(&amp;amp;pd-&amp;gt;wqueue);
-}
-
 /*
  * Schedule reads for the holes in a packet
  */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1111,21 +1085,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
  * Schedule reads for missing parts of the packet.
  */
 for (f = 0; f &amp;lt; pkt-&amp;gt;frames; f++) {
-struct bio_vec *vec;
-
 int p, offset;
+
 if (written[f])
 continue;
+
 bio = pkt-&amp;gt;r_bios[f];
-vec = bio-&amp;gt;bi_io_vec;
-bio_init(bio);
-bio-&amp;gt;bi_max_vecs = 1;
-bio-&amp;gt;bi_sector = pkt-&amp;gt;sector + f * (CD_FRAMESIZE &amp;gt;&amp;gt; 9);
-bio-&amp;gt;bi_bdev = pd-&amp;gt;bdev;
-bio-&amp;gt;bi_end_io = pkt_end_io_read;
-bio-&amp;gt;bi_private = pkt;
-bio-&amp;gt;bi_io_vec = vec;
-bio-&amp;gt;bi_destructor = pkt_bio_destructor;
+bio_reset(bio);
+bio-&amp;gt;bi_sector= pkt-&amp;gt;sector + f * (CD_FRAMESIZE &amp;gt;&amp;gt; 9);
+bio-&amp;gt;bi_bdev= pd-&amp;gt;bdev;
 
 p = (f * CD_FRAMESIZE) / PAGE_SIZE;
 offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1418,14 +1386,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
 }
 
 /* Start the write request */
-bio_init(pkt-&amp;gt;w_bio);
-pkt-&amp;gt;w_bio-&amp;gt;bi_max_vecs = PACKET_MAX_SIZE;
+bio_reset(pkt-&amp;gt;w_bio);
 pkt-&amp;gt;w_bio-&amp;gt;bi_sector = pkt-&amp;gt;sector;
 pkt-&amp;gt;w_bio-&amp;gt;bi_bdev = pd-&amp;gt;bdev;
-pkt-&amp;gt;w_bio-&amp;gt;bi_end_io = pkt_end_io_packet_write;
-pkt-&amp;gt;w_bio-&amp;gt;bi_private = pkt;
-pkt-&amp;gt;w_bio-&amp;gt;bi_io_vec = bvec;
-pkt-&amp;gt;w_bio-&amp;gt;bi_destructor = pkt_bio_destructor;
 for (f = 0; f &amp;lt; pkt-&amp;gt;frames; f++)
 if (!bio_add_page(pkt-&amp;gt;w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
 BUG();
&lt;/pre&gt;</description>
    <dc:creator>Kent Overstreet</dc:creator>
    <dc:date>2012-05-24T00:02:44</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15907">
    <title>[PATCH] multipath: Some device configuration changes forNetAppLUNs</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15907</link>
    <description>&lt;pre&gt;NetApp has asked for these configuration changes.

Signed-off-by: Benjamin Marzinski &amp;lt;bmarzins&amp;lt; at &amp;gt;redhat.com&amp;gt;
---
 libmultipath/hwtable.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Index: multipath-tools-120518/libmultipath/hwtable.c
===================================================================
--- multipath-tools-120518.orig/libmultipath/hwtable.c
+++ multipath-tools-120518/libmultipath/hwtable.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -912,11 +912,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct hwentry default_hw[] = {
 {
 .vendor        = "NETAPP",
 .product       = "LUN.*",
-.features      = "1 queue_if_no_path",
+.features      = "3 queue_if_no_path pg_init_retries 50",
 .hwhandler     = DEFAULT_HWHANDLER,
 .selector      = DEFAULT_SELECTOR,
 .pgpolicy      = GROUP_BY_PRIO,
 .pgfailback    = -FAILBACK_IMMEDIATE,
+.flush_on_last_del = FLUSH_ENABLED,
 .rr_weight     = RR_WEIGHT_NONE,
 .no_path_retry = NO_PATH_RETRY_UNDEF,
 .minio         = 128,

&lt;/pre&gt;</description>
    <dc:creator>Benjamin Marzinski</dc:creator>
    <dc:date>2012-05-23T21:42:20</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15906">
    <title>[PATCH][RESEND] multipath: fix scsi async tur checkercorruption</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15906</link>
    <description>&lt;pre&gt;Since the tur checker runs asynchronously in its own thread, there is nothing
that keeps a path from being orphaned or deleted before the tur thread has
finished. When this happenes the checker struct gets deleted.  However, the tur
thread might still we writing to that memory.  This can lead to memory
corruption.  This patch adds all of the necessary data to the checker context,
and makes the tur thread only use that. This way, if the checker is deleted
while the thread is still using the context, the thread will clean up the
context itself.

Since the context can only be freed when both the thread and the paths checker
structure have stopped needing it, and these can get get finished with the
context asychronously with respect to each other, the context has a holders
counter, protected by a spinlock, to keep track of the users.  When the
counter drops to zero, the context gets freed.

Signed-off-by: Benjamin Marzinski &amp;lt;bmarzins&amp;lt; at &amp;gt;redhat.com&amp;gt;
---
 libmultipath/checkers/tur.c |   85 +++++++++++++++++++++++++++++++++-----------
 libmultipath/discovery.c    |    1 
 2 files changed, 65 insertions(+), 21 deletions(-)

Index: multipath-tools-120518/libmultipath/checkers/tur.c
===================================================================
--- multipath-tools-120518.orig/libmultipath/checkers/tur.c
+++ multipath-tools-120518/libmultipath/checkers/tur.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -35,10 +35,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct tur_checker_context {
 dev_t devt;
 int state;
 int running;
-time_t timeout;
+int fd;
+unsigned int timeout;
+time_t time;
 pthread_t thread;
 pthread_mutex_t lock;
 pthread_cond_t active;
+pthread_spinlock_t hldr_lock;
+int holders;
+char message[CHECKER_MSG_LEN];
 };
 
 #define TUR_DEVT(c) major((c)-&amp;gt;devt), minor((c)-&amp;gt;devt)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -53,28 +58,49 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int libcheck_init (struct checker * c)
 memset(ct, 0, sizeof(struct tur_checker_context));
 
 ct-&amp;gt;state = PATH_UNCHECKED;
+ct-&amp;gt;fd = -1;
+ct-&amp;gt;holders = 1;
 pthread_cond_init(&amp;amp;ct-&amp;gt;active, NULL);
 pthread_mutex_init(&amp;amp;ct-&amp;gt;lock, NULL);
+pthread_spin_init(&amp;amp;ct-&amp;gt;hldr_lock, PTHREAD_PROCESS_PRIVATE);
 c-&amp;gt;context = ct;
 
 return 0;
 }
 
+void cleanup_context(struct tur_checker_context *ct)
+{
+pthread_mutex_destroy(&amp;amp;ct-&amp;gt;lock);
+pthread_cond_destroy(&amp;amp;ct-&amp;gt;active);
+pthread_spin_destroy(&amp;amp;ct-&amp;gt;hldr_lock);
+free(ct);
+}
+
 void libcheck_free (struct checker * c)
 {
 if (c-&amp;gt;context) {
 struct tur_checker_context *ct = c-&amp;gt;context;
+int holders;
+pthread_t thread;
 
-pthread_mutex_destroy(&amp;amp;ct-&amp;gt;lock);
-pthread_cond_destroy(&amp;amp;ct-&amp;gt;active);
-free(c-&amp;gt;context);
+pthread_spin_lock(&amp;amp;ct-&amp;gt;hldr_lock);
+ct-&amp;gt;holders--;
+holders = ct-&amp;gt;holders;
+thread = ct-&amp;gt;thread;
+pthread_spin_unlock(&amp;amp;ct-&amp;gt;hldr_lock);
+if (holders)
+pthread_cancel(thread);
+else
+cleanup_context(ct);
 c-&amp;gt;context = NULL;
 }
 return;
 }
 
+#define TUR_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args);
+
 int
-tur_check (struct checker * c)
+tur_check(int fd, unsigned int timeout, char *msg)
 {
 struct sg_io_hdr io_hdr;
 unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -90,10 +116,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; tur_check (struct checker * c)
 io_hdr.dxfer_direction = SG_DXFER_NONE;
 io_hdr.cmdp = turCmdBlk;
 io_hdr.sbp = sense_buffer;
-io_hdr.timeout = c-&amp;gt;timeout;
+io_hdr.timeout = timeout;
 io_hdr.pack_id = 0;
-if (ioctl(c-&amp;gt;fd, SG_IO, &amp;amp;io_hdr) &amp;lt; 0) {
-MSG(c, MSG_TUR_DOWN);
+if (ioctl(fd, SG_IO, &amp;amp;io_hdr) &amp;lt; 0) {
+TUR_MSG(msg, MSG_TUR_DOWN);
 return PATH_DOWN;
 }
 if ((io_hdr.status &amp;amp; 0x7e) == 0x18) {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -101,7 +127,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; tur_check (struct checker * c)
  * SCSI-3 arrays might return
  * reservation conflict on TUR
  */
-MSG(c, MSG_TUR_UP);
+TUR_MSG(msg, MSG_TUR_UP);
 return PATH_UP;
 }
 if (io_hdr.info &amp;amp; SG_INFO_OK_MASK) {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -146,14 +172,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; tur_check (struct checker * c)
  * LOGICAL UNIT NOT ACCESSIBLE,
  * TARGET PORT IN STANDBY STATE
  */
-MSG(c, MSG_TUR_GHOST);
+TUR_MSG(msg, MSG_TUR_GHOST);
 return PATH_GHOST;
 }
 }
-MSG(c, MSG_TUR_DOWN);
+TUR_MSG(msg, MSG_TUR_DOWN);
 return PATH_DOWN;
 }
-MSG(c, MSG_TUR_UP);
+TUR_MSG(msg, MSG_TUR_UP);
 return PATH_UP;
 }
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -162,18 +188,25 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; tur_check (struct checker * c)
 
 void cleanup_func(void *data)
 {
+int holders;
 struct tur_checker_context *ct = data;
+pthread_spin_lock(&amp;amp;ct-&amp;gt;hldr_lock);
+ct-&amp;gt;holders--;
+holders = ct-&amp;gt;holders;
 ct-&amp;gt;thread = 0;
+pthread_spin_unlock(&amp;amp;ct-&amp;gt;hldr_lock);
+if (!holders)
+cleanup_context(ct);
 }
 
 void *tur_thread(void *ctx)
 {
-struct checker *c = ctx;
-struct tur_checker_context *ct = c-&amp;gt;context;
+struct tur_checker_context *ct = ctx;
 int state;
 
 condlog(3, "%d:%d: tur checker starting up", TUR_DEVT(ct));
 
+ct-&amp;gt;message[0] = '\0';
 /* This thread can be canceled, so setup clean up */
 tur_thread_cleanup_push(ct)
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -182,7 +215,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void *tur_thread(void *ctx)
 ct-&amp;gt;state = PATH_PENDING;
 pthread_mutex_unlock(&amp;amp;ct-&amp;gt;lock);
 
-state = tur_check(c);
+state = tur_check(ct-&amp;gt;fd, ct-&amp;gt;timeout, ct-&amp;gt;message);
 
 /* TUR checker done */
 pthread_mutex_lock(&amp;amp;ct-&amp;gt;lock);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -213,7 +246,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void tur_set_async_timeout(struct checke
 struct timeval now;
 
 gettimeofday(&amp;amp;now, NULL);
-ct-&amp;gt;timeout = now.tv_sec + c-&amp;gt;timeout;
+ct-&amp;gt;time = now.tv_sec + c-&amp;gt;timeout;
 }
 
 int tur_check_async_timeout(struct checker *c)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -222,7 +255,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int tur_check_async_timeout(struct check
 struct timeval now;
 
 gettimeofday(&amp;amp;now, NULL);
-return (now.tv_sec &amp;gt; ct-&amp;gt;timeout);
+return (now.tv_sec &amp;gt; ct-&amp;gt;time);
 }
 
 extern int
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -242,7 +275,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; libcheck_check (struct checker * c)
 ct-&amp;gt;devt = sb.st_rdev;
 
 if (c-&amp;gt;sync)
-return tur_check(c);
+return tur_check(c-&amp;gt;fd, c-&amp;gt;timeout, c-&amp;gt;message);
 
 /*
  * Async mode
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -276,6 +309,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; libcheck_check (struct checker * c)
 /* TUR checker done */
 ct-&amp;gt;running = 0;
 tur_status = ct-&amp;gt;state;
+strncpy(c-&amp;gt;message, ct-&amp;gt;message, CHECKER_MSG_LEN);
+c-&amp;gt;message[CHECKER_MSG_LEN - 1] = '\0';
 }
 pthread_mutex_unlock(&amp;amp;ct-&amp;gt;lock);
 } else {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -284,24 +319,32 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; libcheck_check (struct checker * c)
 pthread_mutex_unlock(&amp;amp;ct-&amp;gt;lock);
 condlog(3, "%d:%d: tur thread not responding, "
 "using sync mode", TUR_DEVT(ct));
-return tur_check(c);
+return tur_check(c-&amp;gt;fd, c-&amp;gt;timeout, c-&amp;gt;message);
 }
 /* Start new TUR checker */
 ct-&amp;gt;state = PATH_UNCHECKED;
+ct-&amp;gt;fd = c-&amp;gt;fd;
+ct-&amp;gt;timeout = c-&amp;gt;timeout;
+pthread_spin_lock(&amp;amp;ct-&amp;gt;hldr_lock);
+ct-&amp;gt;holders++;
+pthread_spin_unlock(&amp;amp;ct-&amp;gt;hldr_lock);
 tur_set_async_timeout(c);
 setup_thread_attr(&amp;amp;attr, 32 * 1024, 1);
-r = pthread_create(&amp;amp;ct-&amp;gt;thread, &amp;amp;attr, tur_thread, c);
+r = pthread_create(&amp;amp;ct-&amp;gt;thread, &amp;amp;attr, tur_thread, ct);
 if (r) {
 pthread_mutex_unlock(&amp;amp;ct-&amp;gt;lock);
 ct-&amp;gt;thread = 0;
+ct-&amp;gt;holders--;
 condlog(3, "%d:%d: failed to start tur thread, using"
 " sync mode", TUR_DEVT(ct));
-return tur_check(c);
+return tur_check(c-&amp;gt;fd, c-&amp;gt;timeout, c-&amp;gt;message);
 }
 pthread_attr_destroy(&amp;amp;attr);
 tur_timeout(&amp;amp;tsp);
 r = pthread_cond_timedwait(&amp;amp;ct-&amp;gt;active, &amp;amp;ct-&amp;gt;lock, &amp;amp;tsp);
 tur_status = ct-&amp;gt;state;
+strncpy(c-&amp;gt;message, ct-&amp;gt;message,CHECKER_MSG_LEN);
+c-&amp;gt;message[CHECKER_MSG_LEN -1] = '\0';
 pthread_mutex_unlock(&amp;amp;ct-&amp;gt;lock);
 if (ct-&amp;gt;thread &amp;amp;&amp;amp;
     (tur_status == PATH_PENDING || tur_status == PATH_UNCHECKED)) {
Index: multipath-tools-120518/libmultipath/discovery.c
===================================================================
--- multipath-tools-120518.orig/libmultipath/discovery.c
+++ multipath-tools-120518/libmultipath/discovery.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -747,6 +747,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; get_state (struct path * pp, int daemon)
 }
 checker_set_fd(c, pp-&amp;gt;fd);
 if (checker_init(c, pp-&amp;gt;mpp?&amp;amp;pp-&amp;gt;mpp-&amp;gt;mpcontext:NULL)) {
+memset(c, 0x0, sizeof(struct checker));
 condlog(3, "%s: checker init failed", pp-&amp;gt;dev);
 return PATH_UNCHECKED;
 }

&lt;/pre&gt;</description>
    <dc:creator>Benjamin Marzinski</dc:creator>
    <dc:date>2012-05-23T21:05:20</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15904">
    <title>Re: [PATCH] multipath: Make sure we store all the hwentry attributes.</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15904</link>
    <description>&lt;pre&gt;Applied.




&lt;/pre&gt;</description>
    <dc:creator>Christophe Varoqui</dc:creator>
    <dc:date>2012-05-23T20:37:23</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15903">
    <title>[PATCH] multipath: Allow user_friendly_names in moreconfigsections</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15903</link>
    <description>&lt;pre&gt;This patch adds support for setting user_friendly_names in the devices and
multipaths config sections.

Signed-off-by: Benjamin Marzinski &amp;lt;bmarzins&amp;lt; at &amp;gt;redhat.com&amp;gt;
---
 libmultipath/config.c  |    2 +
 libmultipath/config.h  |    2 +
 libmultipath/dict.c    |   94 +++++++++++++++++++++++++++++++++++++++++++++----
 libmultipath/propsel.c |   14 ++++++-
 libmultipath/structs.h |    6 +++
 5 files changed, 110 insertions(+), 8 deletions(-)

Index: multipath-tools-120518/libmultipath/config.c
===================================================================
--- multipath-tools-120518.orig/libmultipath/config.c
+++ multipath-tools-120518/libmultipath/config.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -325,6 +325,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; merge_hwe (struct hwentry * dst, struct
 merge_num(flush_on_last_del);
 merge_num(fast_io_fail);
 merge_num(dev_loss);
+merge_num(user_friendly_names);
 
 return 0;
 }
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -383,6 +384,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; store_hwe (vector hwtable, struct hwentr
 hwe-&amp;gt;flush_on_last_del = dhwe-&amp;gt;flush_on_last_del;
 hwe-&amp;gt;fast_io_fail = dhwe-&amp;gt;fast_io_fail;
 hwe-&amp;gt;dev_loss = dhwe-&amp;gt;dev_loss;
+hwe-&amp;gt;user_friendly_names = dhwe-&amp;gt;user_friendly_names;
 
 if (dhwe-&amp;gt;bl_product &amp;amp;&amp;amp; !(hwe-&amp;gt;bl_product = set_param_str(dhwe-&amp;gt;bl_product)))
 goto out;
Index: multipath-tools-120518/libmultipath/config.h
===================================================================
--- multipath-tools-120518.orig/libmultipath/config.h
+++ multipath-tools-120518/libmultipath/config.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -44,6 +44,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct hwentry {
 int flush_on_last_del;
 int fast_io_fail;
 unsigned int dev_loss;
+int user_friendly_names;
 char * bl_product;
 };
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -66,6 +67,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct mpentry {
 int pg_timeout;
 int flush_on_last_del;
 int attribute_flags;
+int user_friendly_names;
 uid_t uid;
 gid_t gid;
 mode_t mode;
Index: multipath-tools-120518/libmultipath/dict.c
===================================================================
--- multipath-tools-120518.orig/libmultipath/dict.c
+++ multipath-tools-120518/libmultipath/dict.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -583,7 +583,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; def_reservation_key_handler(vector strve
 }
 
 static int
-names_handler(vector strvec)
+def_names_handler(vector strvec)
 {
 char * buff;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -594,10 +594,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; names_handler(vector strvec)
 
 if ((strlen(buff) == 2 &amp;amp;&amp;amp; !strcmp(buff, "no")) ||
     (strlen(buff) == 1 &amp;amp;&amp;amp; !strcmp(buff, "0")))
-conf-&amp;gt;user_friendly_names = 0;
+conf-&amp;gt;user_friendly_names = USER_FRIENDLY_NAMES_OFF;
 else if ((strlen(buff) == 3 &amp;amp;&amp;amp; !strcmp(buff, "yes")) ||
  (strlen(buff) == 1 &amp;amp;&amp;amp; !strcmp(buff, "1")))
-conf-&amp;gt;user_friendly_names = 1;
+conf-&amp;gt;user_friendly_names = USER_FRIENDLY_NAMES_ON;
+else
+conf-&amp;gt;user_friendly_names = USER_FRIENDLY_NAMES_UNDEF;
 
 FREE(buff);
 return 0;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1207,6 +1209,32 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; hw_flush_on_last_del_handler(vector strv
 return 0;
 }
 
+static int
+hw_names_handler(vector strvec)
+{
+struct hwentry *hwe = VECTOR_LAST_SLOT(conf-&amp;gt;hwtable);
+char * buff;
+
+if (!hwe)
+return 1;
+
+buff = set_value(strvec);
+if (!buff)
+return 1;
+
+if ((strlen(buff) == 2 &amp;amp;&amp;amp; strcmp(buff, "no") == 0) ||
+    (strlen(buff) == 1 &amp;amp;&amp;amp; strcmp(buff, "0") == 0))
+hwe-&amp;gt;user_friendly_names = USER_FRIENDLY_NAMES_OFF;
+else if ((strlen(buff) == 3 &amp;amp;&amp;amp; strcmp(buff, "yes") == 0) ||
+ (strlen(buff) == 1 &amp;amp;&amp;amp; strcmp(buff, "1") == 0))
+hwe-&amp;gt;user_friendly_names = USER_FRIENDLY_NAMES_ON;
+else
+hwe-&amp;gt;user_friendly_names = USER_FRIENDLY_NAMES_UNDEF;
+
+FREE(buff);
+return 0;
+}
+
 /*
  * multipaths block handlers
  */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1654,6 +1682,31 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; mp_reservation_key_handler (vector strve
 return 0;
 }
 
+static int
+mp_names_handler(vector strvec)
+{
+struct mpentry *mpe = VECTOR_LAST_SLOT(conf-&amp;gt;mptable);
+char * buff;
+
+if (!mpe)
+return 1;
+
+buff = set_value(strvec);
+if (!buff)
+return 1;
+
+if ((strlen(buff) == 2 &amp;amp;&amp;amp; strcmp(buff, "no") == 0) ||
+    (strlen(buff) == 1 &amp;amp;&amp;amp; strcmp(buff, "0") == 0))
+mpe-&amp;gt;user_friendly_names = USER_FRIENDLY_NAMES_OFF;
+else if ((strlen(buff) == 3 &amp;amp;&amp;amp; strcmp(buff, "yes") == 0) ||
+ (strlen(buff) == 1 &amp;amp;&amp;amp; strcmp(buff, "1") == 0))
+mpe-&amp;gt;user_friendly_names = USER_FRIENDLY_NAMES_ON;
+else
+mpe-&amp;gt;user_friendly_names = USER_FRIENDLY_NAMES_UNDEF;
+
+FREE(buff);
+return 0;
+}
 
 /*
  * config file keywords printing
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1884,6 +1937,18 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; snprint_mp_reservation_key (char * buff,
 return snprintf(buff, len, "%s" , mpe-&amp;gt;reservation_key);
 }
 
+static int
+snprint_mp_user_friendly_names (char * buff, int len, void * data)
+{
+struct mpentry * mpe = (struct mpentry *)data;
+
+if (mpe-&amp;gt;user_friendly_names == USER_FRIENDLY_NAMES_UNDEF)
+return 0;
+else if (mpe-&amp;gt;user_friendly_names == USER_FRIENDLY_NAMES_OFF)
+return snprintf(buff, len, "no");
+else
+return snprintf(buff, len, "yes");
+}
 
 static int
 snprint_hw_fast_io_fail(char * buff, int len, void * data)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2174,6 +2239,19 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; snprint_hw_path_checker (char * buff, in
 return snprintf(buff, len, "%s", hwe-&amp;gt;checker_name);
 }
 
+static int
+snprint_hw_user_friendly_names (char * buff, int len, void * data)
+{
+struct hwentry * hwe = (struct hwentry *)data;
+
+if (hwe-&amp;gt;user_friendly_names == USER_FRIENDLY_NAMES_UNDEF)
+return 0;
+else if (hwe-&amp;gt;user_friendly_names == USER_FRIENDLY_NAMES_OFF)
+return snprintf(buff, len, "no");
+else
+return snprintf(buff, len, "yes");
+}
+
 static int
 snprint_def_polling_interval (char * buff, int len, void * data)
 {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2461,10 +2539,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; snprint_def_log_checker_err (char * buff
 static int
 snprint_def_user_friendly_names (char * buff, int len, void * data)
 {
-if (!conf-&amp;gt;user_friendly_names)
+if (conf-&amp;gt;user_friendly_names  == USER_FRIENDLY_NAMES_ON)
+return snprintf(buff, len, "yes");
+else
 return snprintf(buff, len, "no");
-
-return snprintf(buff, len, "yes");
 }
 
 static int
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2547,7 +2625,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; init_keywords(void)
 install_keyword("checker_timeout", &amp;amp;def_checker_timeout_handler, &amp;amp;snprint_def_checker_timeout);
 install_keyword("pg_timeout", &amp;amp;def_pg_timeout_handler, &amp;amp;snprint_def_pg_timeout);
 install_keyword("flush_on_last_del", &amp;amp;def_flush_on_last_del_handler, &amp;amp;snprint_def_flush_on_last_del);
-install_keyword("user_friendly_names", &amp;amp;names_handler, &amp;amp;snprint_def_user_friendly_names);
+install_keyword("user_friendly_names", &amp;amp;def_names_handler, &amp;amp;snprint_def_user_friendly_names);
 install_keyword("mode", &amp;amp;def_mode_handler, &amp;amp;snprint_def_mode);
 install_keyword("uid", &amp;amp;def_uid_handler, &amp;amp;snprint_def_uid);
 install_keyword("gid", &amp;amp;def_gid_handler, &amp;amp;snprint_def_gid);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2616,6 +2694,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; init_keywords(void)
 install_keyword("flush_on_last_del", &amp;amp;hw_flush_on_last_del_handler, &amp;amp;snprint_hw_flush_on_last_del);
 install_keyword("fast_io_fail_tmo", &amp;amp;hw_fast_io_fail_handler, &amp;amp;snprint_hw_fast_io_fail);
 install_keyword("dev_loss_tmo", &amp;amp;hw_dev_loss_handler, &amp;amp;snprint_hw_dev_loss);
+install_keyword("user_friendly_names", &amp;amp;hw_names_handler, &amp;amp;snprint_hw_user_friendly_names);
 install_sublevel_end();
 
 install_keyword_root("multipaths", &amp;amp;multipaths_handler);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2639,5 +2718,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; init_keywords(void)
 install_keyword("uid", &amp;amp;mp_uid_handler, &amp;amp;snprint_mp_uid);
 install_keyword("gid", &amp;amp;mp_gid_handler, &amp;amp;snprint_mp_gid);
 install_keyword("reservation_key", &amp;amp;mp_reservation_key_handler, &amp;amp;snprint_mp_reservation_key);
+install_keyword("user_friendly_names", &amp;amp;mp_names_handler, &amp;amp;snprint_mp_user_friendly_names);
 install_sublevel_end();
 }
Index: multipath-tools-120518/libmultipath/propsel.c
===================================================================
--- multipath-tools-120518.orig/libmultipath/propsel.c
+++ multipath-tools-120518/libmultipath/propsel.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -237,6 +237,18 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; select_alias_prefix (struct multipath *
 mp-&amp;gt;wwid, mp-&amp;gt;alias_prefix);
 }
 
+static int
+want_user_friendly_names(struct multipath * mp)
+{
+if (mp-&amp;gt;mpe &amp;amp;&amp;amp;
+    mp-&amp;gt;mpe-&amp;gt;user_friendly_names != USER_FRIENDLY_NAMES_UNDEF)
+return (mp-&amp;gt;mpe-&amp;gt;user_friendly_names == USER_FRIENDLY_NAMES_ON);
+if (mp-&amp;gt;hwe &amp;amp;&amp;amp;
+    mp-&amp;gt;hwe-&amp;gt;user_friendly_names != USER_FRIENDLY_NAMES_UNDEF)
+return (mp-&amp;gt;hwe-&amp;gt;user_friendly_names == USER_FRIENDLY_NAMES_ON);
+return (conf-&amp;gt;user_friendly_names  == USER_FRIENDLY_NAMES_ON);
+}
+
 extern int
 select_alias (struct multipath * mp)
 {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -244,7 +256,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; select_alias (struct multipath * mp)
 mp-&amp;gt;alias = STRDUP(mp-&amp;gt;mpe-&amp;gt;alias);
 else {
 mp-&amp;gt;alias = NULL;
-if (conf-&amp;gt;user_friendly_names) {
+if (want_user_friendly_names(mp)) {
 select_alias_prefix(mp);
 mp-&amp;gt;alias = get_user_friendly_alias(mp-&amp;gt;wwid,
 conf-&amp;gt;bindings_file, mp-&amp;gt;alias_prefix, conf-&amp;gt;bindings_read_only);
Index: multipath-tools-120518/libmultipath/structs.h
===================================================================
--- multipath-tools-120518.orig/libmultipath/structs.h
+++ multipath-tools-120518/libmultipath/structs.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -92,6 +92,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; enum log_checker_err_states {
 LOG_CHKR_ERR_ONCE,
 };
 
+enum user_friendly_names_states {
+USER_FRIENDLY_NAMES_UNDEF,
+USER_FRIENDLY_NAMES_OFF,
+USER_FRIENDLY_NAMES_ON,
+};
+
 struct scsi_idlun {
 int dev_id;
 int host_unique_id;

&lt;/pre&gt;</description>
    <dc:creator>Benjamin Marzinski</dc:creator>
    <dc:date>2012-05-23T20:36:30</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15902">
    <title>[PATCH] multipath: Make sure we store all the hwentryattributes.</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15902</link>
    <description>&lt;pre&gt;Not all of the attributes from the hardware table entries were getting stored
when the built-in devices configurations were being setup.

Signed-off-by: Benjamin Marzinski &amp;lt;bmarzins&amp;lt; at &amp;gt;redhat.com&amp;gt;
---
 libmultipath/config.c |    4 ++++
 1 file changed, 4 insertions(+)

Index: multipath-tools-120518/libmultipath/config.c
===================================================================
--- multipath-tools-120518.orig/libmultipath/config.c
+++ multipath-tools-120518/libmultipath/config.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -379,6 +379,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; store_hwe (vector hwtable, struct hwentr
 hwe-&amp;gt;no_path_retry = dhwe-&amp;gt;no_path_retry;
 hwe-&amp;gt;minio = dhwe-&amp;gt;minio;
 hwe-&amp;gt;minio_rq = dhwe-&amp;gt;minio_rq;
+hwe-&amp;gt;pg_timeout = dhwe-&amp;gt;pg_timeout;
+hwe-&amp;gt;flush_on_last_del = dhwe-&amp;gt;flush_on_last_del;
+hwe-&amp;gt;fast_io_fail = dhwe-&amp;gt;fast_io_fail;
+hwe-&amp;gt;dev_loss = dhwe-&amp;gt;dev_loss;
 
 if (dhwe-&amp;gt;bl_product &amp;amp;&amp;amp; !(hwe-&amp;gt;bl_product = set_param_str(dhwe-&amp;gt;bl_product)))
 goto out;

&lt;/pre&gt;</description>
    <dc:creator>Benjamin Marzinski</dc:creator>
    <dc:date>2012-05-23T20:29:05</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15901">
    <title>Re: [PATCH]] multipath-tools : Minor typo in multipath.conf.annotated</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15901</link>
    <description>&lt;pre&gt;
Applied,

Thanks.

&lt;/pre&gt;</description>
    <dc:creator>Christophe Varoqui</dc:creator>
    <dc:date>2012-05-23T20:26:43</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15900">
    <title>does file system page cache work after device mapping?</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.device-mapper.devel/15900</link>
    <description>&lt;pre&gt;Hi everyone, I have some questions regarding to the mechanism of device
mapper: After the device mapper layer gets the mapping information, it will
issue IO request to the real device. How does it perform IO operation at
this stage? For example, if the device is a block device, will it go to the
page cache and check whether the desired block is in cache? If the block is
not in cache and it read from the physical device, will the block be cached
in memory?

Thanks very much!


Zhiming
&lt;/pre&gt;</description>
    <dc:creator>zhiming shen</dc:creator>
    <dc:date>2012-05-22T19:18:42</dc:date>
  </item>
  <textinput rdf:about="http://search.gmane.org/?group=$group=gmane.linux.kernel.device-mapper.devel">
    <title>Search Engine</title>
    <description>Search the mailing list at Gmane</description>
    <name>query</name>
    <link>http://search.gmane.org/?group=$group=gmane.linux.kernel.device-mapper.devel</link>
  </textinput>
</rdf:RDF>

