diff options
author | Ed Cashin <ecashin@coraid.com> | 2012-12-17 19:03:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-17 20:15:23 -0500 |
commit | 4ba9aa7f9819bafb304f09dee90bb1fa40627358 (patch) | |
tree | c36e336dacf1bb8be15f9fca48b69641a2ec22fe /drivers/block | |
parent | 1b8a1636ceea573b1d452a1cccf01c990d8d628a (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.c | 44 |
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 | */ | ||
247 | static int | ||
248 | user_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 | |||
244 | int | 268 | int |
245 | aoedev_flush(const char __user *str, size_t cnt) | 269 | aoedev_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; | ||
308 | skip: | ||
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)) { |