llseek: automatically add .llseek fop
[linux-2.6.git] / drivers / block / aoe / aoechr.c
index 1bc85aa..32b484b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoechr.c
  * AoE character device driver
@@ -6,7 +6,11 @@
 
 #include <linux/hdreg.h>
 #include <linux/blkdev.h>
+#include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/skbuff.h>
 #include "aoe.h"
 
 enum {
@@ -35,7 +39,7 @@ struct ErrMsg {
 
 static struct ErrMsg emsgs[NMSG];
 static int emsgs_head_idx, emsgs_tail_idx;
-static struct semaphore emsgs_sema;
+static struct completion emsgs_comp;
 static spinlock_t emsgs_lock;
 static int nblocked_emsgs_readers;
 static struct class *aoe_class;
@@ -101,7 +105,12 @@ loop:
                spin_lock_irqsave(&d->lock, flags);
                goto loop;
        }
-       aoenet_xmit(skb);
+       if (skb) {
+               struct sk_buff_head queue;
+               __skb_queue_head_init(&queue);
+               __skb_queue_tail(&queue, skb);
+               aoenet_xmit(&queue);
+       }
        aoecmd_cfg(major, minor);
        return 0;
 }
@@ -140,7 +149,7 @@ bail:               spin_unlock_irqrestore(&emsgs_lock, flags);
        spin_unlock_irqrestore(&emsgs_lock, flags);
 
        if (nblocked_emsgs_readers)
-               up(&emsgs_sema);
+               complete(&emsgs_comp);
 }
 
 static ssize_t
@@ -174,12 +183,16 @@ aoechr_open(struct inode *inode, struct file *filp)
 {
        int n, i;
 
+       lock_kernel();
        n = iminor(inode);
        filp->private_data = (void *) (unsigned long) n;
 
        for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
-               if (chardevs[i].minor == n)
+               if (chardevs[i].minor == n) {
+                       unlock_kernel();
                        return 0;
+               }
+       unlock_kernel();
        return -EINVAL;
 }
 
@@ -216,7 +229,7 @@ aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
 
                spin_unlock_irqrestore(&emsgs_lock, flags);
 
-               n = down_interruptible(&emsgs_sema);
+               n = wait_for_completion_interruptible(&emsgs_comp);
 
                spin_lock_irqsave(&emsgs_lock, flags);
 
@@ -252,8 +265,14 @@ static const struct file_operations aoe_fops = {
        .open = aoechr_open,
        .release = aoechr_rel,
        .owner = THIS_MODULE,
+       .llseek = noop_llseek,
 };
 
+static char *aoe_devnode(struct device *dev, mode_t *mode)
+{
+       return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev));
+}
+
 int __init
 aoechr_init(void)
 {
@@ -264,16 +283,19 @@ aoechr_init(void)
                printk(KERN_ERR "aoe: can't register char device\n");
                return n;
        }
-       sema_init(&emsgs_sema, 0);
+       init_completion(&emsgs_comp);
        spin_lock_init(&emsgs_lock);
        aoe_class = class_create(THIS_MODULE, "aoe");
        if (IS_ERR(aoe_class)) {
                unregister_chrdev(AOE_MAJOR, "aoechr");
                return PTR_ERR(aoe_class);
        }
+       aoe_class->devnode = aoe_devnode;
+
        for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
                device_create(aoe_class, NULL,
-                             MKDEV(AOE_MAJOR, chardevs[i].minor), chardevs[i].name);
+                             MKDEV(AOE_MAJOR, chardevs[i].minor), NULL,
+                             chardevs[i].name);
 
        return 0;
 }