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

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
Loading
Loading
Loading
Loading
+38 −6
Original line number Diff line number Diff line
@@ -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)) {