"Fossies" - the Fresh Open Source Software Archive

Member "aoe-87/linux/drivers/block/aoe/aoechr.c" (23 Feb 2017, 6130 Bytes) of package /linux/misc/aoe-87.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "aoechr.c" see the Fossies "Dox" file reference documentation.

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