diff options
Diffstat (limited to 'drivers/block/aoe/aoedev.c')
-rw-r--r-- | drivers/block/aoe/aoedev.c | 87 |
1 files changed, 68 insertions, 19 deletions
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 @@ | |||
9 | #include <linux/netdevice.h> | 9 | #include <linux/netdevice.h> |
10 | #include "aoe.h" | 10 | #include "aoe.h" |
11 | 11 | ||
12 | static void dummy_timer(ulong); | ||
13 | static void aoedev_freedev(struct aoedev *); | ||
14 | static void freetgt(struct aoetgt *t); | ||
15 | |||
12 | static struct aoedev *devlist; | 16 | static struct aoedev *devlist; |
13 | static spinlock_t devlist_lock; | 17 | static spinlock_t devlist_lock; |
14 | 18 | ||
@@ -108,6 +112,70 @@ aoedev_downdev(struct aoedev *d) | |||
108 | d->flags &= ~DEVFL_UP; | 112 | d->flags &= ~DEVFL_UP; |
109 | } | 113 | } |
110 | 114 | ||
115 | static void | ||
116 | aoedev_freedev(struct aoedev *d) | ||
117 | { | ||
118 | struct aoetgt **t, **e; | ||
119 | |||
120 | if (d->gd) { | ||
121 | aoedisk_rm_sysfs(d); | ||
122 | del_gendisk(d->gd); | ||
123 | put_disk(d->gd); | ||
124 | } | ||
125 | t = d->targets; | ||
126 | e = t + NTARGETS; | ||
127 | for (; t < e && *t; t++) | ||
128 | freetgt(*t); | ||
129 | if (d->bufpool) | ||
130 | mempool_destroy(d->bufpool); | ||
131 | kfree(d); | ||
132 | } | ||
133 | |||
134 | int | ||
135 | aoedev_flush(const char __user *str, size_t cnt) | ||
136 | { | ||
137 | ulong flags; | ||
138 | struct aoedev *d, **dd; | ||
139 | struct aoedev *rmd = NULL; | ||
140 | char buf[16]; | ||
141 | int all = 0; | ||
142 | |||
143 | if (cnt >= 3) { | ||
144 | if (cnt > sizeof buf) | ||
145 | cnt = sizeof buf; | ||
146 | if (copy_from_user(buf, str, cnt)) | ||
147 | return -EFAULT; | ||
148 | all = !strncmp(buf, "all", 3); | ||
149 | } | ||
150 | |||
151 | flush_scheduled_work(); | ||
152 | spin_lock_irqsave(&devlist_lock, flags); | ||
153 | dd = &devlist; | ||
154 | while ((d = *dd)) { | ||
155 | spin_lock(&d->lock); | ||
156 | if ((!all && (d->flags & DEVFL_UP)) | ||
157 | || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) | ||
158 | || d->nopen) { | ||
159 | spin_unlock(&d->lock); | ||
160 | dd = &d->next; | ||
161 | continue; | ||
162 | } | ||
163 | *dd = d->next; | ||
164 | aoedev_downdev(d); | ||
165 | d->flags |= DEVFL_TKILL; | ||
166 | spin_unlock(&d->lock); | ||
167 | d->next = rmd; | ||
168 | rmd = d; | ||
169 | } | ||
170 | spin_unlock_irqrestore(&devlist_lock, flags); | ||
171 | while ((d = rmd)) { | ||
172 | rmd = d->next; | ||
173 | del_timer_sync(&d->timer); | ||
174 | aoedev_freedev(d); /* must be able to sleep */ | ||
175 | } | ||
176 | return 0; | ||
177 | } | ||
178 | |||
111 | /* find it or malloc it */ | 179 | /* find it or malloc it */ |
112 | struct aoedev * | 180 | struct aoedev * |
113 | aoedev_by_sysminor_m(ulong sysminor) | 181 | aoedev_by_sysminor_m(ulong sysminor) |
@@ -161,25 +229,6 @@ freetgt(struct aoetgt *t) | |||
161 | kfree(t); | 229 | kfree(t); |
162 | } | 230 | } |
163 | 231 | ||
164 | static void | ||
165 | aoedev_freedev(struct aoedev *d) | ||
166 | { | ||
167 | struct aoetgt **t, **e; | ||
168 | |||
169 | if (d->gd) { | ||
170 | aoedisk_rm_sysfs(d); | ||
171 | del_gendisk(d->gd); | ||
172 | put_disk(d->gd); | ||
173 | } | ||
174 | t = d->targets; | ||
175 | e = t + NTARGETS; | ||
176 | for (; t < e && *t; t++) | ||
177 | freetgt(*t); | ||
178 | if (d->bufpool) | ||
179 | mempool_destroy(d->bufpool); | ||
180 | kfree(d); | ||
181 | } | ||
182 | |||
183 | void | 232 | void |
184 | aoedev_exit(void) | 233 | aoedev_exit(void) |
185 | { | 234 | { |