aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/aoe/aoechr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/aoe/aoechr.c')
-rw-r--r--drivers/block/aoe/aoechr.c93
1 files changed, 53 insertions, 40 deletions
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index d5480e34cb22..e8e60e7a2e70 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -1,4 +1,4 @@
1/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ 1/* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */
2/* 2/*
3 * aoechr.c 3 * aoechr.c
4 * AoE character device driver 4 * AoE character device driver
@@ -6,6 +6,7 @@
6 6
7#include <linux/hdreg.h> 7#include <linux/hdreg.h>
8#include <linux/blkdev.h> 8#include <linux/blkdev.h>
9#include <linux/delay.h>
9#include "aoe.h" 10#include "aoe.h"
10 11
11enum { 12enum {
@@ -14,6 +15,7 @@ enum {
14 MINOR_DISCOVER, 15 MINOR_DISCOVER,
15 MINOR_INTERFACES, 16 MINOR_INTERFACES,
16 MINOR_REVALIDATE, 17 MINOR_REVALIDATE,
18 MINOR_FLUSH,
17 MSGSZ = 2048, 19 MSGSZ = 2048,
18 NMSG = 100, /* message backlog to retain */ 20 NMSG = 100, /* message backlog to retain */
19}; 21};
@@ -42,6 +44,7 @@ static struct aoe_chardev chardevs[] = {
42 { MINOR_DISCOVER, "discover" }, 44 { MINOR_DISCOVER, "discover" },
43 { MINOR_INTERFACES, "interfaces" }, 45 { MINOR_INTERFACES, "interfaces" },
44 { MINOR_REVALIDATE, "revalidate" }, 46 { MINOR_REVALIDATE, "revalidate" },
47 { MINOR_FLUSH, "flush" },
45}; 48};
46 49
47static int 50static int
@@ -68,6 +71,7 @@ revalidate(const char __user *str, size_t size)
68 int major, minor, n; 71 int major, minor, n;
69 ulong flags; 72 ulong flags;
70 struct aoedev *d; 73 struct aoedev *d;
74 struct sk_buff *skb;
71 char buf[16]; 75 char buf[16];
72 76
73 if (size >= sizeof buf) 77 if (size >= sizeof buf)
@@ -85,13 +89,20 @@ revalidate(const char __user *str, size_t size)
85 d = aoedev_by_aoeaddr(major, minor); 89 d = aoedev_by_aoeaddr(major, minor);
86 if (!d) 90 if (!d)
87 return -EINVAL; 91 return -EINVAL;
88
89 spin_lock_irqsave(&d->lock, flags); 92 spin_lock_irqsave(&d->lock, flags);
90 d->flags &= ~DEVFL_MAXBCNT; 93 aoecmd_cleanslate(d);
91 d->flags |= DEVFL_PAUSE; 94loop:
95 skb = aoecmd_ata_id(d);
92 spin_unlock_irqrestore(&d->lock, flags); 96 spin_unlock_irqrestore(&d->lock, flags);
97 /* try again if we are able to sleep a bit,
98 * otherwise give up this revalidation
99 */
100 if (!skb && !msleep_interruptible(200)) {
101 spin_lock_irqsave(&d->lock, flags);
102 goto loop;
103 }
104 aoenet_xmit(skb);
93 aoecmd_cfg(major, minor); 105 aoecmd_cfg(major, minor);
94
95 return 0; 106 return 0;
96} 107}
97 108
@@ -149,6 +160,9 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp
149 break; 160 break;
150 case MINOR_REVALIDATE: 161 case MINOR_REVALIDATE:
151 ret = revalidate(buf, cnt); 162 ret = revalidate(buf, cnt);
163 break;
164 case MINOR_FLUSH:
165 ret = aoedev_flush(buf, cnt);
152 } 166 }
153 if (ret == 0) 167 if (ret == 0)
154 ret = cnt; 168 ret = cnt;
@@ -185,52 +199,51 @@ aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
185 ulong flags; 199 ulong flags;
186 200
187 n = (unsigned long) filp->private_data; 201 n = (unsigned long) filp->private_data;
188 switch (n) { 202 if (n != MINOR_ERR)
189 case MINOR_ERR: 203 return -EFAULT;
190 spin_lock_irqsave(&emsgs_lock, flags); 204
191loop: 205 spin_lock_irqsave(&emsgs_lock, flags);
192 em = emsgs + emsgs_head_idx;
193 if ((em->flags & EMFL_VALID) == 0) {
194 if (filp->f_flags & O_NDELAY) {
195 spin_unlock_irqrestore(&emsgs_lock, flags);
196 return -EAGAIN;
197 }
198 nblocked_emsgs_readers++;
199 206
207 for (;;) {
208 em = emsgs + emsgs_head_idx;
209 if ((em->flags & EMFL_VALID) != 0)
210 break;
211 if (filp->f_flags & O_NDELAY) {
200 spin_unlock_irqrestore(&emsgs_lock, flags); 212 spin_unlock_irqrestore(&emsgs_lock, flags);
213 return -EAGAIN;
214 }
215 nblocked_emsgs_readers++;
201 216
202 n = down_interruptible(&emsgs_sema); 217 spin_unlock_irqrestore(&emsgs_lock, flags);
218
219 n = down_interruptible(&emsgs_sema);
203 220
204 spin_lock_irqsave(&emsgs_lock, flags); 221 spin_lock_irqsave(&emsgs_lock, flags);
205 222
206 nblocked_emsgs_readers--; 223 nblocked_emsgs_readers--;
207 224
208 if (n) { 225 if (n) {
209 spin_unlock_irqrestore(&emsgs_lock, flags);
210 return -ERESTARTSYS;
211 }
212 goto loop;
213 }
214 if (em->len > cnt) {
215 spin_unlock_irqrestore(&emsgs_lock, flags); 226 spin_unlock_irqrestore(&emsgs_lock, flags);
216 return -EAGAIN; 227 return -ERESTARTSYS;
217 } 228 }
218 mp = em->msg; 229 }
219 len = em->len; 230 if (em->len > cnt) {
220 em->msg = NULL; 231 spin_unlock_irqrestore(&emsgs_lock, flags);
221 em->flags &= ~EMFL_VALID; 232 return -EAGAIN;
233 }
234 mp = em->msg;
235 len = em->len;
236 em->msg = NULL;
237 em->flags &= ~EMFL_VALID;
222 238
223 emsgs_head_idx++; 239 emsgs_head_idx++;
224 emsgs_head_idx %= ARRAY_SIZE(emsgs); 240 emsgs_head_idx %= ARRAY_SIZE(emsgs);
225 241
226 spin_unlock_irqrestore(&emsgs_lock, flags); 242 spin_unlock_irqrestore(&emsgs_lock, flags);
227 243
228 n = copy_to_user(buf, mp, len); 244 n = copy_to_user(buf, mp, len);
229 kfree(mp); 245 kfree(mp);
230 return n == 0 ? len : -EFAULT; 246 return n == 0 ? len : -EFAULT;
231 default:
232 return -EFAULT;
233 }
234} 247}
235 248
236static const struct file_operations aoe_fops = { 249static const struct file_operations aoe_fops = {