diff options
Diffstat (limited to 'drivers/block')
-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 |
3 files changed, 74 insertions, 19 deletions
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); | |||
191 | struct aoedev *aoedev_by_sysminor_m(ulong sysminor); | 191 | struct aoedev *aoedev_by_sysminor_m(ulong sysminor); |
192 | void aoedev_downdev(struct aoedev *d); | 192 | void aoedev_downdev(struct aoedev *d); |
193 | int aoedev_isbusy(struct aoedev *d); | 193 | int aoedev_isbusy(struct aoedev *d); |
194 | int aoedev_flush(const char __user *str, size_t size); | ||
194 | 195 | ||
195 | int aoenet_init(void); | 196 | int aoenet_init(void); |
196 | void aoenet_exit(void); | 197 | 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 { | |||
15 | MINOR_DISCOVER, | 15 | MINOR_DISCOVER, |
16 | MINOR_INTERFACES, | 16 | MINOR_INTERFACES, |
17 | MINOR_REVALIDATE, | 17 | MINOR_REVALIDATE, |
18 | MINOR_FLUSH, | ||
18 | MSGSZ = 2048, | 19 | MSGSZ = 2048, |
19 | NMSG = 100, /* message backlog to retain */ | 20 | NMSG = 100, /* message backlog to retain */ |
20 | }; | 21 | }; |
@@ -43,6 +44,7 @@ static struct aoe_chardev chardevs[] = { | |||
43 | { MINOR_DISCOVER, "discover" }, | 44 | { MINOR_DISCOVER, "discover" }, |
44 | { MINOR_INTERFACES, "interfaces" }, | 45 | { MINOR_INTERFACES, "interfaces" }, |
45 | { MINOR_REVALIDATE, "revalidate" }, | 46 | { MINOR_REVALIDATE, "revalidate" }, |
47 | { MINOR_FLUSH, "flush" }, | ||
46 | }; | 48 | }; |
47 | 49 | ||
48 | static int | 50 | static int |
@@ -158,6 +160,9 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp | |||
158 | break; | 160 | break; |
159 | case MINOR_REVALIDATE: | 161 | case MINOR_REVALIDATE: |
160 | ret = revalidate(buf, cnt); | 162 | ret = revalidate(buf, cnt); |
163 | break; | ||
164 | case MINOR_FLUSH: | ||
165 | ret = aoedev_flush(buf, cnt); | ||
161 | } | 166 | } |
162 | if (ret == 0) | 167 | if (ret == 0) |
163 | ret = cnt; | 168 | 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 @@ | |||
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 | { |