diff options
| -rw-r--r-- | Documentation/aoe/mkdevs.sh | 2 | ||||
| -rw-r--r-- | Documentation/aoe/udev.txt | 1 | ||||
| -rw-r--r-- | drivers/block/aoe/aoe.h | 1 | ||||
| -rw-r--r-- | drivers/block/aoe/aoechr.c | 5 | ||||
| -rw-r--r-- | drivers/block/aoe/aoedev.c | 87 | 
5 files changed, 77 insertions, 19 deletions
diff --git a/Documentation/aoe/mkdevs.sh b/Documentation/aoe/mkdevs.sh index 97374aacacb2..44c0ab702432 100644 --- a/Documentation/aoe/mkdevs.sh +++ b/Documentation/aoe/mkdevs.sh @@ -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!'` diff --git a/Documentation/aoe/udev.txt b/Documentation/aoe/udev.txt index 17e76c4f918e..8686e789542e 100644 --- a/Documentation/aoe/udev.txt +++ b/Documentation/aoe/udev.txt @@ -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" diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index aecaac3f2e58..2248ab226576 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -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); diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index f1124664c5c9..1bc85aa2271f 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -15,6 +15,7 @@ enum {  	MINOR_DISCOVER,  	MINOR_INTERFACES,  	MINOR_REVALIDATE, +	MINOR_FLUSH,  	MSGSZ = 2048,  	NMSG = 100,		/* message backlog to retain */  }; @@ -43,6 +44,7 @@ static struct aoe_chardev chardevs[] = {  	{ MINOR_DISCOVER, "discover" },  	{ MINOR_INTERFACES, "interfaces" },  	{ MINOR_REVALIDATE, "revalidate" }, +	{ MINOR_FLUSH, "flush" },  };  static int @@ -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; diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index a4d625aefeaa..e26f6f4a28a2 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -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; @@ -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) @@ -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)  {  |