Skip to content

Commit

Permalink
aoe: user can ask driver to forget previously detected devices
Browse files Browse the repository at this point in the history
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: Ed L. Cashin <ecashin@coraid.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Ed L. Cashin authored and Linus Torvalds committed Feb 8, 2008
1 parent cf446f0 commit 262bf54
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 19 deletions.
2 changes: 2 additions & 0 deletions Documentation/aoe/mkdevs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ rm -f $dir/interfaces
mknod -m 0200 $dir/interfaces c $MAJOR 4
rm -f $dir/revalidate
mknod -m 0200 $dir/revalidate c $MAJOR 5
rm -f $dir/flush
mknod -m 0200 $dir/flush c $MAJOR 6

export n_partitions
mkshelf=`echo $0 | sed 's!mkdevs!mkshelf!'`
Expand Down
1 change: 1 addition & 0 deletions Documentation/aoe/udev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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=="interfaces", 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
KERNEL=="etherd*", NAME="%k", GROUP="disk"
1 change: 1 addition & 0 deletions drivers/block/aoe/aoe.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ struct aoedev *aoedev_by_aoeaddr(int maj, int min);
struct aoedev *aoedev_by_sysminor_m(ulong sysminor);
void aoedev_downdev(struct aoedev *d);
int aoedev_isbusy(struct aoedev *d);
int aoedev_flush(const char __user *str, size_t size);

int aoenet_init(void);
void aoenet_exit(void);
Expand Down
5 changes: 5 additions & 0 deletions drivers/block/aoe/aoechr.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum {
MINOR_DISCOVER,
MINOR_INTERFACES,
MINOR_REVALIDATE,
MINOR_FLUSH,
MSGSZ = 2048,
NMSG = 100, /* message backlog to retain */
};
Expand Down Expand Up @@ -43,6 +44,7 @@ static struct aoe_chardev chardevs[] = {
{ MINOR_DISCOVER, "discover" },
{ MINOR_INTERFACES, "interfaces" },
{ MINOR_REVALIDATE, "revalidate" },
{ MINOR_FLUSH, "flush" },
};

static int
Expand Down Expand Up @@ -158,6 +160,9 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp
break;
case MINOR_REVALIDATE:
ret = revalidate(buf, cnt);
break;
case MINOR_FLUSH:
ret = aoedev_flush(buf, cnt);
}
if (ret == 0)
ret = cnt;
Expand Down
87 changes: 68 additions & 19 deletions drivers/block/aoe/aoedev.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include <linux/netdevice.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 spinlock_t devlist_lock;

Expand Down Expand Up @@ -108,6 +112,70 @@ aoedev_downdev(struct aoedev *d)
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 */
struct aoedev *
aoedev_by_sysminor_m(ulong sysminor)
Expand Down Expand Up @@ -161,25 +229,6 @@ freetgt(struct aoetgt *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
aoedev_exit(void)
{
Expand Down

0 comments on commit 262bf54

Please sign in to comment.