aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorEd Cashin <ecashin@coraid.com>2012-12-17 19:03:30 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-17 20:15:23 -0500
commit4ba9aa7f9819bafb304f09dee90bb1fa40627358 (patch)
treec36e336dacf1bb8be15f9fca48b69641a2ec22fe /drivers/block
parent1b8a1636ceea573b1d452a1cccf01c990d8d628a (diff)
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>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/aoe/aoedev.c44
1 files changed, 38 insertions, 6 deletions
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 90e5b537f94b..63b26609400f 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -241,6 +241,30 @@ aoedev_freedev(struct aoedev *d)
241 kfree(d); 241 kfree(d);
242} 242}
243 243
244/* return whether the user asked for this particular
245 * device to be flushed
246 */
247static int
248user_req(char *s, size_t slen, struct aoedev *d)
249{
250 char *p;
251 size_t lim;
252
253 if (!d->gd)
254 return 0;
255 p = strrchr(d->gd->disk_name, '/');
256 if (!p)
257 p = d->gd->disk_name;
258 else
259 p += 1;
260 lim = sizeof(d->gd->disk_name);
261 lim -= p - d->gd->disk_name;
262 if (slen < lim)
263 lim = slen;
264
265 return !strncmp(s, p, lim);
266}
267
244int 268int
245aoedev_flush(const char __user *str, size_t cnt) 269aoedev_flush(const char __user *str, size_t cnt)
246{ 270{
@@ -249,6 +273,7 @@ aoedev_flush(const char __user *str, size_t cnt)
249 struct aoedev *rmd = NULL; 273 struct aoedev *rmd = NULL;
250 char buf[16]; 274 char buf[16];
251 int all = 0; 275 int all = 0;
276 int specified = 0; /* flush a specific device */
252 277
253 if (cnt >= 3) { 278 if (cnt >= 3) {
254 if (cnt > sizeof buf) 279 if (cnt > sizeof buf)
@@ -256,26 +281,33 @@ aoedev_flush(const char __user *str, size_t cnt)
256 if (copy_from_user(buf, str, cnt)) 281 if (copy_from_user(buf, str, cnt))
257 return -EFAULT; 282 return -EFAULT;
258 all = !strncmp(buf, "all", 3); 283 all = !strncmp(buf, "all", 3);
284 if (!all)
285 specified = 1;
259 } 286 }
260 287
261 spin_lock_irqsave(&devlist_lock, flags); 288 spin_lock_irqsave(&devlist_lock, flags);
262 dd = &devlist; 289 dd = &devlist;
263 while ((d = *dd)) { 290 while ((d = *dd)) {
264 spin_lock(&d->lock); 291 spin_lock(&d->lock);
265 if ((!all && (d->flags & DEVFL_UP)) 292 if (specified) {
293 if (!user_req(buf, cnt, d))
294 goto skip;
295 } else if ((!all && (d->flags & DEVFL_UP))
266 || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) 296 || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
267 || d->nopen 297 || d->nopen
268 || d->ref) { 298 || d->ref)
269 spin_unlock(&d->lock); 299 goto skip;
270 dd = &d->next; 300
271 continue;
272 }
273 *dd = d->next; 301 *dd = d->next;
274 aoedev_downdev(d); 302 aoedev_downdev(d);
275 d->flags |= DEVFL_TKILL; 303 d->flags |= DEVFL_TKILL;
276 spin_unlock(&d->lock); 304 spin_unlock(&d->lock);
277 d->next = rmd; 305 d->next = rmd;
278 rmd = d; 306 rmd = d;
307 continue;
308skip:
309 spin_unlock(&d->lock);
310 dd = &d->next;
279 } 311 }
280 spin_unlock_irqrestore(&devlist_lock, flags); 312 spin_unlock_irqrestore(&devlist_lock, flags);
281 while ((d = rmd)) { 313 while ((d = rmd)) {