Users sometimes want to cause the aoe driver to forget a
particular previously discovered device when it is no longer
online.  The aoetools provide an "aoe-flush" command that users
run to perform this administrative task.  The changes below
provide the support needed in the driver.

Signed-off-by: Ed Cashin <ecas...@coraid.com>
---
 drivers/block/aoe/aoedev.c |   44 ++++++++++++++++++++++++++++++++++++++------
 1 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 90e5b53..63b2660 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -241,6 +241,30 @@ aoedev_freedev(struct aoedev *d)
        kfree(d);
 }
 
+/* return whether the user asked for this particular
+ * device to be flushed
+ */
+static int
+user_req(char *s, size_t slen, struct aoedev *d)
+{
+       char *p;
+       size_t lim;
+
+       if (!d->gd)
+               return 0;
+       p = strrchr(d->gd->disk_name, '/');
+       if (!p)
+               p = d->gd->disk_name;
+       else
+               p += 1;
+       lim = sizeof(d->gd->disk_name);
+       lim -= p - d->gd->disk_name;
+       if (slen < lim)
+               lim = slen;
+
+       return !strncmp(s, p, lim);
+}
+
 int
 aoedev_flush(const char __user *str, size_t cnt)
 {
@@ -249,6 +273,7 @@ aoedev_flush(const char __user *str, size_t cnt)
        struct aoedev *rmd = NULL;
        char buf[16];
        int all = 0;
+       int specified = 0;      /* flush a specific device */
 
        if (cnt >= 3) {
                if (cnt > sizeof buf)
@@ -256,26 +281,33 @@ aoedev_flush(const char __user *str, size_t cnt)
                if (copy_from_user(buf, str, cnt))
                        return -EFAULT;
                all = !strncmp(buf, "all", 3);
+               if (!all)
+                       specified = 1;
        }
 
        spin_lock_irqsave(&devlist_lock, flags);
        dd = &devlist;
        while ((d = *dd)) {
                spin_lock(&d->lock);
-               if ((!all && (d->flags & DEVFL_UP))
+               if (specified) {
+                       if (!user_req(buf, cnt, d))
+                               goto skip;
+               } else if ((!all && (d->flags & DEVFL_UP))
                || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
                || d->nopen
-               || d->ref) {
-                       spin_unlock(&d->lock);
-                       dd = &d->next;
-                       continue;
-               }
+               || d->ref)
+                       goto skip;
+
                *dd = d->next;
                aoedev_downdev(d);
                d->flags |= DEVFL_TKILL;
                spin_unlock(&d->lock);
                d->next = rmd;
                rmd = d;
+               continue;
+skip:
+               spin_unlock(&d->lock);
+               dd = &d->next;
        }
        spin_unlock_irqrestore(&devlist_lock, flags);
        while ((d = rmd)) {
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to