1 /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ 2 /* 3 * aoechr.c 4 * AoE character device driver 5 */ 6 7 #include <linux/hdreg.h> 8 #include <linux/blkdev.h> 9 #include <linux/completion.h> 10 #include <linux/delay.h> 11 #include <linux/slab.h> 12 #include <linux/mutex.h> 13 #include <linux/skbuff.h> 14 #include <linux/export.h> 15 #include "aoe.h" 16 17 enum { 18 //MINOR_STAT = 1, (moved to sysfs) 19 MINOR_ERR = 2, 20 MINOR_DISCOVER, 21 MINOR_INTERFACES, 22 MINOR_REVALIDATE, 23 MINOR_FLUSH, 24 MSGSZ = 2048, 25 NMSG = 100, /* message backlog to retain */ 26 }; 27 28 struct aoe_chardev { 29 ulong minor; 30 char name[32]; 31 }; 32 33 enum { EMFL_VALID = 1 }; 34 35 struct ErrMsg { 36 short flags; 37 short len; 38 char *msg; 39 }; 40 41 static DEFINE_MUTEX(aoechr_mutex); 42 43 /* A ring buffer of error messages, to be read through 44 * "/dev/etherd/err". When no messages are present, 45 * readers will block waiting for messages to appear. 46 */ 47 static struct ErrMsg emsgs[NMSG]; 48 static int emsgs_head_idx, emsgs_tail_idx; 49 static struct completion emsgs_comp; 50 static spinlock_t emsgs_lock; 51 static int nblocked_emsgs_readers; 52 53 static struct aoe_chardev chardevs[] = { 54 { MINOR_ERR, "err" }, 55 { MINOR_DISCOVER, "discover" }, 56 { MINOR_INTERFACES, "interfaces" }, 57 { MINOR_REVALIDATE, "revalidate" }, 58 { MINOR_FLUSH, "flush" }, 59 }; 60 61 static char *aoe_devnode(const struct device *dev, umode_t *mode) 62 { 63 return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev)); 64 } 65 66 static const struct class aoe_class = { 67 .name = "aoe", 68 .devnode = aoe_devnode, 69 }; 70 71 static int 72 discover(void) 73 { 74 aoecmd_cfg(0xffff, 0xff); 75 return 0; 76 } 77 78 static int 79 interfaces(const char __user *str, size_t size) 80 { 81 if (set_aoe_iflist(str, size)) { 82 printk(KERN_ERR 83 "aoe: could not set interface list: too many interfaces\n"); 84 return -EINVAL; 85 } 86 return 0; 87 } 88 89 static int 90 revalidate(const char __user *str, size_t size) 91 { 92 int major, minor, n; 93 ulong flags; 94 struct aoedev *d; 95 struct sk_buff *skb; 96 char buf[16]; 97 98 if (size >= sizeof buf) 99 return -EINVAL; 100 buf[sizeof buf - 1] = '\0'; 101 if (copy_from_user(buf, str, size)) 102 return -EFAULT; 103 104 n = sscanf(buf, "e%d.%d", &major, &minor); 105 if (n != 2) { 106 pr_err("aoe: invalid device specification %s\n", buf); 107 return -EINVAL; 108 } 109 d = aoedev_by_aoeaddr(major, minor, 0); 110 if (!d) 111 return -EINVAL; 112 spin_lock_irqsave(&d->lock, flags); 113 aoecmd_cleanslate(d); 114 aoecmd_cfg(major, minor); 115 loop: 116 skb = aoecmd_ata_id(d); 117 spin_unlock_irqrestore(&d->lock, flags); 118 /* try again if we are able to sleep a bit, 119 * otherwise give up this revalidation 120 */ 121 if (!skb && !msleep_interruptible(250)) { 122 spin_lock_irqsave(&d->lock, flags); 123 goto loop; 124 } 125 aoedev_put(d); 126 if (skb) { 127 struct sk_buff_head queue; 128 __skb_queue_head_init(&queue); 129 __skb_queue_tail(&queue, skb); 130 aoenet_xmit(&queue); 131 } 132 return 0; 133 } 134 135 void 136 aoechr_error(char *msg) 137 { 138 struct ErrMsg *em; 139 char *mp; 140 ulong flags, n; 141 142 n = strlen(msg); 143 144 spin_lock_irqsave(&emsgs_lock, flags); 145 146 em = emsgs + emsgs_tail_idx; 147 if ((em->flags & EMFL_VALID)) { 148 bail: spin_unlock_irqrestore(&emsgs_lock, flags); 149 return; 150 } 151 152 mp = kmemdup(msg, n, GFP_ATOMIC); 153 if (!mp) 154 goto bail; 155 156 em->msg = mp; 157 em->flags |= EMFL_VALID; 158 em->len = n; 159 160 emsgs_tail_idx++; 161 emsgs_tail_idx %= ARRAY_SIZE(emsgs); 162 163 spin_unlock_irqrestore(&emsgs_lock, flags); 164 165 if (nblocked_emsgs_readers) 166 complete(&emsgs_comp); 167 } 168 169 static ssize_t 170 aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp) 171 { 172 int ret = -EINVAL; 173 174 switch ((unsigned long) filp->private_data) { 175 default: 176 printk(KERN_INFO "aoe: can't write to that file.\n"); 177 break; 178 case MINOR_DISCOVER: 179 ret = discover(); 180 break; 181 case MINOR_INTERFACES: 182 ret = interfaces(buf, cnt); 183 break; 184 case MINOR_REVALIDATE: 185 ret = revalidate(buf, cnt); 186 break; 187 case MINOR_FLUSH: 188 ret = aoedev_flush(buf, cnt); 189 break; 190 } 191 if (ret == 0) 192 ret = cnt; 193 return ret; 194 } 195 196 static int 197 aoechr_open(struct inode *inode, struct file *filp) 198 { 199 int n, i; 200 201 mutex_lock(&aoechr_mutex); 202 n = iminor(inode); 203 filp->private_data = (void *) (unsigned long) n; 204 205 for (i = 0; i < ARRAY_SIZE(chardevs); ++i) 206 if (chardevs[i].minor == n) { 207 mutex_unlock(&aoechr_mutex); 208 return 0; 209 } 210 mutex_unlock(&aoechr_mutex); 211 return -EINVAL; 212 } 213 214 static int 215 aoechr_rel(struct inode *inode, struct file *filp) 216 { 217 return 0; 218 } 219 220 static ssize_t 221 aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off) 222 { 223 unsigned long n; 224 char *mp; 225 struct ErrMsg *em; 226 ssize_t len; 227 ulong flags; 228 229 n = (unsigned long) filp->private_data; 230 if (n != MINOR_ERR) 231 return -EFAULT; 232 233 spin_lock_irqsave(&emsgs_lock, flags); 234 235 for (;;) { 236 em = emsgs + emsgs_head_idx; 237 if ((em->flags & EMFL_VALID) != 0) 238 break; 239 if (filp->f_flags & O_NDELAY) { 240 spin_unlock_irqrestore(&emsgs_lock, flags); 241 return -EAGAIN; 242 } 243 nblocked_emsgs_readers++; 244 245 spin_unlock_irqrestore(&emsgs_lock, flags); 246 247 n = wait_for_completion_interruptible(&emsgs_comp); 248 249 spin_lock_irqsave(&emsgs_lock, flags); 250 251 nblocked_emsgs_readers--; 252 253 if (n) { 254 spin_unlock_irqrestore(&emsgs_lock, flags); 255 return -ERESTARTSYS; 256 } 257 } 258 if (em->len > cnt) { 259 spin_unlock_irqrestore(&emsgs_lock, flags); 260 return -EAGAIN; 261 } 262 mp = em->msg; 263 len = em->len; 264 em->msg = NULL; 265 em->flags &= ~EMFL_VALID; 266 267 emsgs_head_idx++; 268 emsgs_head_idx %= ARRAY_SIZE(emsgs); 269 270 spin_unlock_irqrestore(&emsgs_lock, flags); 271 272 n = copy_to_user(buf, mp, len); 273 kfree(mp); 274 return n == 0 ? len : -EFAULT; 275 } 276 277 static const struct file_operations aoe_fops = { 278 .write = aoechr_write, 279 .read = aoechr_read, 280 .open = aoechr_open, 281 .release = aoechr_rel, 282 .owner = THIS_MODULE, 283 .llseek = noop_llseek, 284 }; 285 286 int __init 287 aoechr_init(void) 288 { 289 int n, i; 290 291 n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); 292 if (n < 0) { 293 printk(KERN_ERR "aoe: can't register char device\n"); 294 return n; 295 } 296 init_completion(&emsgs_comp); 297 spin_lock_init(&emsgs_lock); 298 n = class_register(&aoe_class); 299 if (n) { 300 unregister_chrdev(AOE_MAJOR, "aoechr"); 301 return n; 302 } 303 304 for (i = 0; i < ARRAY_SIZE(chardevs); ++i) 305 device_create(&aoe_class, NULL, 306 MKDEV(AOE_MAJOR, chardevs[i].minor), NULL, 307 chardevs[i].name); 308 309 return 0; 310 } 311 312 void 313 aoechr_exit(void) 314 { 315 int i; 316 317 for (i = 0; i < ARRAY_SIZE(chardevs); ++i) 318 device_destroy(&aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor)); 319 class_unregister(&aoe_class); 320 unregister_chrdev(AOE_MAJOR, "aoechr"); 321 } 322 323