Commit 4ba9aa7f authored by Ed Cashin's avatar Ed Cashin Committed by Linus Torvalds

aoe: support the forgetting (flushing) of a user-specified AoE target

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: default avatarEd Cashin <ecashin@coraid.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1b8a1636
...@@ -241,6 +241,30 @@ aoedev_freedev(struct aoedev *d) ...@@ -241,6 +241,30 @@ aoedev_freedev(struct aoedev *d)
kfree(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 int
aoedev_flush(const char __user *str, size_t cnt) aoedev_flush(const char __user *str, size_t cnt)
{ {
...@@ -249,6 +273,7 @@ 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; struct aoedev *rmd = NULL;
char buf[16]; char buf[16];
int all = 0; int all = 0;
int specified = 0; /* flush a specific device */
if (cnt >= 3) { if (cnt >= 3) {
if (cnt > sizeof buf) if (cnt > sizeof buf)
...@@ -256,26 +281,33 @@ aoedev_flush(const char __user *str, size_t cnt) ...@@ -256,26 +281,33 @@ aoedev_flush(const char __user *str, size_t cnt)
if (copy_from_user(buf, str, cnt)) if (copy_from_user(buf, str, cnt))
return -EFAULT; return -EFAULT;
all = !strncmp(buf, "all", 3); all = !strncmp(buf, "all", 3);
if (!all)
specified = 1;
} }
spin_lock_irqsave(&devlist_lock, flags); spin_lock_irqsave(&devlist_lock, flags);
dd = &devlist; dd = &devlist;
while ((d = *dd)) { while ((d = *dd)) {
spin_lock(&d->lock); 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->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
|| d->nopen || d->nopen
|| d->ref) { || d->ref)
spin_unlock(&d->lock); goto skip;
dd = &d->next;
continue;
}
*dd = d->next; *dd = d->next;
aoedev_downdev(d); aoedev_downdev(d);
d->flags |= DEVFL_TKILL; d->flags |= DEVFL_TKILL;
spin_unlock(&d->lock); spin_unlock(&d->lock);
d->next = rmd; d->next = rmd;
rmd = d; rmd = d;
continue;
skip:
spin_unlock(&d->lock);
dd = &d->next;
} }
spin_unlock_irqrestore(&devlist_lock, flags); spin_unlock_irqrestore(&devlist_lock, flags);
while ((d = rmd)) { while ((d = rmd)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment