Commit 262bf541 authored by Ed L. Cashin's avatar Ed L. Cashin Committed by Linus Torvalds

aoe: user can ask driver to forget previously detected devices

When an AoE device is detected, the kernel is informed, and a new block device
is created.  If the device is unused, the block device corresponding to remote
device that is no longer available may be removed from the system by telling
the aoe driver to "flush" its list of devices.

Without this patch, software like GPFS and LVM may attempt to read from AoE
devices that were discovered earlier but are no longer present, blocking until
the I/O attempt times out.
Signed-off-by: default avatarEd L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent cf446f0d
...@@ -29,6 +29,8 @@ rm -f $dir/interfaces ...@@ -29,6 +29,8 @@ rm -f $dir/interfaces
mknod -m 0200 $dir/interfaces c $MAJOR 4 mknod -m 0200 $dir/interfaces c $MAJOR 4
rm -f $dir/revalidate rm -f $dir/revalidate
mknod -m 0200 $dir/revalidate c $MAJOR 5 mknod -m 0200 $dir/revalidate c $MAJOR 5
rm -f $dir/flush
mknod -m 0200 $dir/flush c $MAJOR 6
export n_partitions export n_partitions
mkshelf=`echo $0 | sed 's!mkdevs!mkshelf!'` mkshelf=`echo $0 | sed 's!mkdevs!mkshelf!'`
......
...@@ -20,6 +20,7 @@ SUBSYSTEM=="aoe", KERNEL=="discover", NAME="etherd/%k", GROUP="disk", MODE="0220 ...@@ -20,6 +20,7 @@ SUBSYSTEM=="aoe", KERNEL=="discover", NAME="etherd/%k", GROUP="disk", MODE="0220
SUBSYSTEM=="aoe", KERNEL=="err", NAME="etherd/%k", GROUP="disk", MODE="0440" SUBSYSTEM=="aoe", KERNEL=="err", NAME="etherd/%k", GROUP="disk", MODE="0440"
SUBSYSTEM=="aoe", KERNEL=="interfaces", NAME="etherd/%k", GROUP="disk", MODE="0220" SUBSYSTEM=="aoe", KERNEL=="interfaces", NAME="etherd/%k", GROUP="disk", MODE="0220"
SUBSYSTEM=="aoe", KERNEL=="revalidate", NAME="etherd/%k", GROUP="disk", MODE="0220" SUBSYSTEM=="aoe", KERNEL=="revalidate", NAME="etherd/%k", GROUP="disk", MODE="0220"
SUBSYSTEM=="aoe", KERNEL=="flush", NAME="etherd/%k", GROUP="disk", MODE="0220"
# aoe block devices # aoe block devices
KERNEL=="etherd*", NAME="%k", GROUP="disk" KERNEL=="etherd*", NAME="%k", GROUP="disk"
...@@ -191,6 +191,7 @@ struct aoedev *aoedev_by_aoeaddr(int maj, int min); ...@@ -191,6 +191,7 @@ struct aoedev *aoedev_by_aoeaddr(int maj, int min);
struct aoedev *aoedev_by_sysminor_m(ulong sysminor); struct aoedev *aoedev_by_sysminor_m(ulong sysminor);
void aoedev_downdev(struct aoedev *d); void aoedev_downdev(struct aoedev *d);
int aoedev_isbusy(struct aoedev *d); int aoedev_isbusy(struct aoedev *d);
int aoedev_flush(const char __user *str, size_t size);
int aoenet_init(void); int aoenet_init(void);
void aoenet_exit(void); void aoenet_exit(void);
......
...@@ -15,6 +15,7 @@ enum { ...@@ -15,6 +15,7 @@ enum {
MINOR_DISCOVER, MINOR_DISCOVER,
MINOR_INTERFACES, MINOR_INTERFACES,
MINOR_REVALIDATE, MINOR_REVALIDATE,
MINOR_FLUSH,
MSGSZ = 2048, MSGSZ = 2048,
NMSG = 100, /* message backlog to retain */ NMSG = 100, /* message backlog to retain */
}; };
...@@ -43,6 +44,7 @@ static struct aoe_chardev chardevs[] = { ...@@ -43,6 +44,7 @@ static struct aoe_chardev chardevs[] = {
{ MINOR_DISCOVER, "discover" }, { MINOR_DISCOVER, "discover" },
{ MINOR_INTERFACES, "interfaces" }, { MINOR_INTERFACES, "interfaces" },
{ MINOR_REVALIDATE, "revalidate" }, { MINOR_REVALIDATE, "revalidate" },
{ MINOR_FLUSH, "flush" },
}; };
static int static int
...@@ -158,6 +160,9 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp ...@@ -158,6 +160,9 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp
break; break;
case MINOR_REVALIDATE: case MINOR_REVALIDATE:
ret = revalidate(buf, cnt); ret = revalidate(buf, cnt);
break;
case MINOR_FLUSH:
ret = aoedev_flush(buf, cnt);
} }
if (ret == 0) if (ret == 0)
ret = cnt; ret = cnt;
......
...@@ -9,6 +9,10 @@ ...@@ -9,6 +9,10 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include "aoe.h" #include "aoe.h"
static void dummy_timer(ulong);
static void aoedev_freedev(struct aoedev *);
static void freetgt(struct aoetgt *t);
static struct aoedev *devlist; static struct aoedev *devlist;
static spinlock_t devlist_lock; static spinlock_t devlist_lock;
...@@ -108,6 +112,70 @@ aoedev_downdev(struct aoedev *d) ...@@ -108,6 +112,70 @@ aoedev_downdev(struct aoedev *d)
d->flags &= ~DEVFL_UP; d->flags &= ~DEVFL_UP;
} }
static void
aoedev_freedev(struct aoedev *d)
{
struct aoetgt **t, **e;
if (d->gd) {
aoedisk_rm_sysfs(d);
del_gendisk(d->gd);
put_disk(d->gd);
}
t = d->targets;
e = t + NTARGETS;
for (; t < e && *t; t++)
freetgt(*t);
if (d->bufpool)
mempool_destroy(d->bufpool);
kfree(d);
}
int
aoedev_flush(const char __user *str, size_t cnt)
{
ulong flags;
struct aoedev *d, **dd;
struct aoedev *rmd = NULL;
char buf[16];
int all = 0;
if (cnt >= 3) {
if (cnt > sizeof buf)
cnt = sizeof buf;
if (copy_from_user(buf, str, cnt))
return -EFAULT;
all = !strncmp(buf, "all", 3);
}
flush_scheduled_work();
spin_lock_irqsave(&devlist_lock, flags);
dd = &devlist;
while ((d = *dd)) {
spin_lock(&d->lock);
if ((!all && (d->flags & DEVFL_UP))
|| (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
|| d->nopen) {
spin_unlock(&d->lock);
dd = &d->next;
continue;
}
*dd = d->next;
aoedev_downdev(d);
d->flags |= DEVFL_TKILL;
spin_unlock(&d->lock);
d->next = rmd;
rmd = d;
}
spin_unlock_irqrestore(&devlist_lock, flags);
while ((d = rmd)) {
rmd = d->next;
del_timer_sync(&d->timer);
aoedev_freedev(d); /* must be able to sleep */
}
return 0;
}
/* find it or malloc it */ /* find it or malloc it */
struct aoedev * struct aoedev *
aoedev_by_sysminor_m(ulong sysminor) aoedev_by_sysminor_m(ulong sysminor)
...@@ -161,25 +229,6 @@ freetgt(struct aoetgt *t) ...@@ -161,25 +229,6 @@ freetgt(struct aoetgt *t)
kfree(t); kfree(t);
} }
static void
aoedev_freedev(struct aoedev *d)
{
struct aoetgt **t, **e;
if (d->gd) {
aoedisk_rm_sysfs(d);
del_gendisk(d->gd);
put_disk(d->gd);
}
t = d->targets;
e = t + NTARGETS;
for (; t < e && *t; t++)
freetgt(*t);
if (d->bufpool)
mempool_destroy(d->bufpool);
kfree(d);
}
void void
aoedev_exit(void) aoedev_exit(void)
{ {
......
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