You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
committed by
Linus Torvalds
parent
1b8a1636ce
commit
4ba9aa7f98
@@ -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)
|
|||||||
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)
|
|||||||
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)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user