Back to home page

OSCL-LXR

 
 

    


0001 /* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
0002 /*
0003  * aoechr.c
0004  * AoE character device driver
0005  */
0006 
0007 #include <linux/hdreg.h>
0008 #include <linux/blkdev.h>
0009 #include <linux/completion.h>
0010 #include <linux/delay.h>
0011 #include <linux/slab.h>
0012 #include <linux/mutex.h>
0013 #include <linux/skbuff.h>
0014 #include <linux/export.h>
0015 #include "aoe.h"
0016 
0017 enum {
0018     //MINOR_STAT = 1, (moved to sysfs)
0019     MINOR_ERR = 2,
0020     MINOR_DISCOVER,
0021     MINOR_INTERFACES,
0022     MINOR_REVALIDATE,
0023     MINOR_FLUSH,
0024     MSGSZ = 2048,
0025     NMSG = 100,     /* message backlog to retain */
0026 };
0027 
0028 struct aoe_chardev {
0029     ulong minor;
0030     char name[32];
0031 };
0032 
0033 enum { EMFL_VALID = 1 };
0034 
0035 struct ErrMsg {
0036     short flags;
0037     short len;
0038     char *msg;
0039 };
0040 
0041 static DEFINE_MUTEX(aoechr_mutex);
0042 
0043 /* A ring buffer of error messages, to be read through
0044  * "/dev/etherd/err".  When no messages are present,
0045  * readers will block waiting for messages to appear.
0046  */
0047 static struct ErrMsg emsgs[NMSG];
0048 static int emsgs_head_idx, emsgs_tail_idx;
0049 static struct completion emsgs_comp;
0050 static spinlock_t emsgs_lock;
0051 static int nblocked_emsgs_readers;
0052 static struct class *aoe_class;
0053 static struct aoe_chardev chardevs[] = {
0054     { MINOR_ERR, "err" },
0055     { MINOR_DISCOVER, "discover" },
0056     { MINOR_INTERFACES, "interfaces" },
0057     { MINOR_REVALIDATE, "revalidate" },
0058     { MINOR_FLUSH, "flush" },
0059 };
0060 
0061 static int
0062 discover(void)
0063 {
0064     aoecmd_cfg(0xffff, 0xff);
0065     return 0;
0066 }
0067 
0068 static int
0069 interfaces(const char __user *str, size_t size)
0070 {
0071     if (set_aoe_iflist(str, size)) {
0072         printk(KERN_ERR
0073             "aoe: could not set interface list: too many interfaces\n");
0074         return -EINVAL;
0075     }
0076     return 0;
0077 }
0078 
0079 static int
0080 revalidate(const char __user *str, size_t size)
0081 {
0082     int major, minor, n;
0083     ulong flags;
0084     struct aoedev *d;
0085     struct sk_buff *skb;
0086     char buf[16];
0087 
0088     if (size >= sizeof buf)
0089         return -EINVAL;
0090     buf[sizeof buf - 1] = '\0';
0091     if (copy_from_user(buf, str, size))
0092         return -EFAULT;
0093 
0094     n = sscanf(buf, "e%d.%d", &major, &minor);
0095     if (n != 2) {
0096         pr_err("aoe: invalid device specification %s\n", buf);
0097         return -EINVAL;
0098     }
0099     d = aoedev_by_aoeaddr(major, minor, 0);
0100     if (!d)
0101         return -EINVAL;
0102     spin_lock_irqsave(&d->lock, flags);
0103     aoecmd_cleanslate(d);
0104     aoecmd_cfg(major, minor);
0105 loop:
0106     skb = aoecmd_ata_id(d);
0107     spin_unlock_irqrestore(&d->lock, flags);
0108     /* try again if we are able to sleep a bit,
0109      * otherwise give up this revalidation
0110      */
0111     if (!skb && !msleep_interruptible(250)) {
0112         spin_lock_irqsave(&d->lock, flags);
0113         goto loop;
0114     }
0115     aoedev_put(d);
0116     if (skb) {
0117         struct sk_buff_head queue;
0118         __skb_queue_head_init(&queue);
0119         __skb_queue_tail(&queue, skb);
0120         aoenet_xmit(&queue);
0121     }
0122     return 0;
0123 }
0124 
0125 void
0126 aoechr_error(char *msg)
0127 {
0128     struct ErrMsg *em;
0129     char *mp;
0130     ulong flags, n;
0131 
0132     n = strlen(msg);
0133 
0134     spin_lock_irqsave(&emsgs_lock, flags);
0135 
0136     em = emsgs + emsgs_tail_idx;
0137     if ((em->flags & EMFL_VALID)) {
0138 bail:       spin_unlock_irqrestore(&emsgs_lock, flags);
0139         return;
0140     }
0141 
0142     mp = kmemdup(msg, n, GFP_ATOMIC);
0143     if (!mp)
0144         goto bail;
0145 
0146     em->msg = mp;
0147     em->flags |= EMFL_VALID;
0148     em->len = n;
0149 
0150     emsgs_tail_idx++;
0151     emsgs_tail_idx %= ARRAY_SIZE(emsgs);
0152 
0153     spin_unlock_irqrestore(&emsgs_lock, flags);
0154 
0155     if (nblocked_emsgs_readers)
0156         complete(&emsgs_comp);
0157 }
0158 
0159 static ssize_t
0160 aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp)
0161 {
0162     int ret = -EINVAL;
0163 
0164     switch ((unsigned long) filp->private_data) {
0165     default:
0166         printk(KERN_INFO "aoe: can't write to that file.\n");
0167         break;
0168     case MINOR_DISCOVER:
0169         ret = discover();
0170         break;
0171     case MINOR_INTERFACES:
0172         ret = interfaces(buf, cnt);
0173         break;
0174     case MINOR_REVALIDATE:
0175         ret = revalidate(buf, cnt);
0176         break;
0177     case MINOR_FLUSH:
0178         ret = aoedev_flush(buf, cnt);
0179         break;
0180     }
0181     if (ret == 0)
0182         ret = cnt;
0183     return ret;
0184 }
0185 
0186 static int
0187 aoechr_open(struct inode *inode, struct file *filp)
0188 {
0189     int n, i;
0190 
0191     mutex_lock(&aoechr_mutex);
0192     n = iminor(inode);
0193     filp->private_data = (void *) (unsigned long) n;
0194 
0195     for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
0196         if (chardevs[i].minor == n) {
0197             mutex_unlock(&aoechr_mutex);
0198             return 0;
0199         }
0200     mutex_unlock(&aoechr_mutex);
0201     return -EINVAL;
0202 }
0203 
0204 static int
0205 aoechr_rel(struct inode *inode, struct file *filp)
0206 {
0207     return 0;
0208 }
0209 
0210 static ssize_t
0211 aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
0212 {
0213     unsigned long n;
0214     char *mp;
0215     struct ErrMsg *em;
0216     ssize_t len;
0217     ulong flags;
0218 
0219     n = (unsigned long) filp->private_data;
0220     if (n != MINOR_ERR)
0221         return -EFAULT;
0222 
0223     spin_lock_irqsave(&emsgs_lock, flags);
0224 
0225     for (;;) {
0226         em = emsgs + emsgs_head_idx;
0227         if ((em->flags & EMFL_VALID) != 0)
0228             break;
0229         if (filp->f_flags & O_NDELAY) {
0230             spin_unlock_irqrestore(&emsgs_lock, flags);
0231             return -EAGAIN;
0232         }
0233         nblocked_emsgs_readers++;
0234 
0235         spin_unlock_irqrestore(&emsgs_lock, flags);
0236 
0237         n = wait_for_completion_interruptible(&emsgs_comp);
0238 
0239         spin_lock_irqsave(&emsgs_lock, flags);
0240 
0241         nblocked_emsgs_readers--;
0242 
0243         if (n) {
0244             spin_unlock_irqrestore(&emsgs_lock, flags);
0245             return -ERESTARTSYS;
0246         }
0247     }
0248     if (em->len > cnt) {
0249         spin_unlock_irqrestore(&emsgs_lock, flags);
0250         return -EAGAIN;
0251     }
0252     mp = em->msg;
0253     len = em->len;
0254     em->msg = NULL;
0255     em->flags &= ~EMFL_VALID;
0256 
0257     emsgs_head_idx++;
0258     emsgs_head_idx %= ARRAY_SIZE(emsgs);
0259 
0260     spin_unlock_irqrestore(&emsgs_lock, flags);
0261 
0262     n = copy_to_user(buf, mp, len);
0263     kfree(mp);
0264     return n == 0 ? len : -EFAULT;
0265 }
0266 
0267 static const struct file_operations aoe_fops = {
0268     .write = aoechr_write,
0269     .read = aoechr_read,
0270     .open = aoechr_open,
0271     .release = aoechr_rel,
0272     .owner = THIS_MODULE,
0273     .llseek = noop_llseek,
0274 };
0275 
0276 static char *aoe_devnode(struct device *dev, umode_t *mode)
0277 {
0278     return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev));
0279 }
0280 
0281 int __init
0282 aoechr_init(void)
0283 {
0284     int n, i;
0285 
0286     n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops);
0287     if (n < 0) {
0288         printk(KERN_ERR "aoe: can't register char device\n");
0289         return n;
0290     }
0291     init_completion(&emsgs_comp);
0292     spin_lock_init(&emsgs_lock);
0293     aoe_class = class_create(THIS_MODULE, "aoe");
0294     if (IS_ERR(aoe_class)) {
0295         unregister_chrdev(AOE_MAJOR, "aoechr");
0296         return PTR_ERR(aoe_class);
0297     }
0298     aoe_class->devnode = aoe_devnode;
0299 
0300     for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
0301         device_create(aoe_class, NULL,
0302                   MKDEV(AOE_MAJOR, chardevs[i].minor), NULL,
0303                   chardevs[i].name);
0304 
0305     return 0;
0306 }
0307 
0308 void
0309 aoechr_exit(void)
0310 {
0311     int i;
0312 
0313     for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
0314         device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
0315     class_destroy(aoe_class);
0316     unregister_chrdev(AOE_MAJOR, "aoechr");
0317 }
0318