cregit-Linux how code gets into the kernel

Release 4.11 drivers/block/aoe/aoechr.c

/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
/*
 * aoechr.c
 * AoE character device driver
 */

#include <linux/hdreg.h>
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/skbuff.h>
#include <linux/export.h>
#include "aoe.h"

enum {
	//MINOR_STAT = 1, (moved to sysfs)
	
MINOR_ERR = 2,
	
MINOR_DISCOVER,
	
MINOR_INTERFACES,
	
MINOR_REVALIDATE,
	
MINOR_FLUSH,
	
MSGSZ = 2048,
	
NMSG = 100,		/* message backlog to retain */
};


struct aoe_chardev {
	
ulong minor;
	
char name[32];
};


enum { EMFL_VALID = 1 };


struct ErrMsg {
	
short flags;
	
short len;
	
char *msg;
};

static DEFINE_MUTEX(aoechr_mutex);

/* A ring buffer of error messages, to be read through
 * "/dev/etherd/err".  When no messages are present,
 * readers will block waiting for messages to appear.
 */

static struct ErrMsg emsgs[NMSG];


static int emsgs_head_idx, emsgs_tail_idx;

static struct completion emsgs_comp;

static spinlock_t emsgs_lock;

static int nblocked_emsgs_readers;

static struct class *aoe_class;

static struct aoe_chardev chardevs[] = {
	{ MINOR_ERR, "err" },
	{ MINOR_DISCOVER, "discover" },
	{ MINOR_INTERFACES, "interfaces" },
	{ MINOR_REVALIDATE, "revalidate" },
	{ MINOR_FLUSH, "flush" },
};


static int discover(void) { aoecmd_cfg(0xffff, 0xff); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin18100.00%1100.00%
Total18100.00%1100.00%


static int interfaces(const char __user *str, size_t size) { if (set_aoe_iflist(str, size)) { printk(KERN_ERR "aoe: could not set interface list: too many interfaces\n"); return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin3282.05%266.67%
Greg Kroah-Hartman717.95%133.33%
Total39100.00%3100.00%


static int revalidate(const char __user *str, size_t size) { int major, minor, n; ulong flags; struct aoedev *d; struct sk_buff *skb; char buf[16]; if (size >= sizeof buf) return -EINVAL; buf[sizeof buf - 1] = '\0'; if (copy_from_user(buf, str, size)) return -EFAULT; n = sscanf(buf, "e%d.%d", &major, &minor); if (n != 2) { pr_err("aoe: invalid device specification %s\n", buf); return -EINVAL; } d = aoedev_by_aoeaddr(major, minor, 0); if (!d) return -EINVAL; spin_lock_irqsave(&d->lock, flags); aoecmd_cleanslate(d); aoecmd_cfg(major, minor); loop: skb = aoecmd_ata_id(d); spin_unlock_irqrestore(&d->lock, flags); /* try again if we are able to sleep a bit, * otherwise give up this revalidation */ if (!skb && !msleep_interruptible(250)) { spin_lock_irqsave(&d->lock, flags); goto loop; } aoedev_put(d); if (skb) { struct sk_buff_head queue; __skb_queue_head_init(&queue); __skb_queue_tail(&queue, skb); aoenet_xmit(&queue); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin21189.03%787.50%
David S. Miller2610.97%112.50%
Total237100.00%8100.00%


void aoechr_error(char *msg) { struct ErrMsg *em; char *mp; ulong flags, n; n = strlen(msg); spin_lock_irqsave(&emsgs_lock, flags); em = emsgs + emsgs_tail_idx; if ((em->flags & EMFL_VALID)) { bail: spin_unlock_irqrestore(&emsgs_lock, flags); return; } mp = kmemdup(msg, n, GFP_ATOMIC); if (mp == NULL) { printk(KERN_ERR "aoe: allocation failure, len=%ld\n", n); goto bail; } em->msg = mp; em->flags |= EMFL_VALID; em->len = n; emsgs_tail_idx++; emsgs_tail_idx %= ARRAY_SIZE(emsgs); spin_unlock_irqrestore(&emsgs_lock, flags); if (nblocked_emsgs_readers) complete(&emsgs_comp); }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin13896.50%250.00%
Mihnea Dobrescu-Balaur32.10%125.00%
Matthias Kaehlcke21.40%125.00%
Total143100.00%4100.00%


static ssize_t aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp) { int ret = -EINVAL; switch ((unsigned long) filp->private_data) { default: printk(KERN_INFO "aoe: can't write to that file.\n"); break; case MINOR_DISCOVER: ret = discover(); break; case MINOR_INTERFACES: ret = interfaces(buf, cnt); break; case MINOR_REVALIDATE: ret = revalidate(buf, cnt); break; case MINOR_FLUSH: ret = aoedev_flush(buf, cnt); break; } if (ret == 0) ret = cnt; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin10594.59%583.33%
Greg Kroah-Hartman65.41%116.67%
Total111100.00%6100.00%


static int aoechr_open(struct inode *inode, struct file *filp) { int n, i; mutex_lock(&aoechr_mutex); n = iminor(inode); filp->private_data = (void *) (unsigned long) n; for (i = 0; i < ARRAY_SIZE(chardevs); ++i) if (chardevs[i].minor == n) { mutex_unlock(&aoechr_mutex); return 0; } mutex_unlock(&aoechr_mutex); return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin7578.12%125.00%
Arnd Bergmann1515.62%125.00%
Jonathan Corbet55.21%125.00%
Eric Sesterhenn / Snakebyte11.04%125.00%
Total96100.00%4100.00%


static int aoechr_rel(struct inode *inode, struct file *filp) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin19100.00%1100.00%
Total19100.00%1100.00%


static ssize_t aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off) { unsigned long n; char *mp; struct ErrMsg *em; ssize_t len; ulong flags; n = (unsigned long) filp->private_data; if (n != MINOR_ERR) return -EFAULT; spin_lock_irqsave(&emsgs_lock, flags); for (;;) { em = emsgs + emsgs_head_idx; if ((em->flags & EMFL_VALID) != 0) break; if (filp->f_flags & O_NDELAY) { spin_unlock_irqrestore(&emsgs_lock, flags); return -EAGAIN; } nblocked_emsgs_readers++; spin_unlock_irqrestore(&emsgs_lock, flags); n = wait_for_completion_interruptible(&emsgs_comp); spin_lock_irqsave(&emsgs_lock, flags); nblocked_emsgs_readers--; if (n) { spin_unlock_irqrestore(&emsgs_lock, flags); return -ERESTARTSYS; } } if (em->len > cnt) { spin_unlock_irqrestore(&emsgs_lock, flags); return -EAGAIN; } mp = em->msg; len = em->len; em->msg = NULL; em->flags &= ~EMFL_VALID; emsgs_head_idx++; emsgs_head_idx %= ARRAY_SIZE(emsgs); spin_unlock_irqrestore(&emsgs_lock, flags); n = copy_to_user(buf, mp, len); kfree(mp); return n == 0 ? len : -EFAULT; }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin25097.28%240.00%
Alexander Nyberg41.56%120.00%
Matthias Kaehlcke20.78%120.00%
Greg Kroah-Hartman10.39%120.00%
Total257100.00%5100.00%

static const struct file_operations aoe_fops = { .write = aoechr_write, .read = aoechr_read, .open = aoechr_open, .release = aoechr_rel, .owner = THIS_MODULE, .llseek = noop_llseek, };
static char *aoe_devnode(struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "etherd/%s", dev_name(dev)); }

Contributors

PersonTokensPropCommitsCommitProp
Kay Sievers2896.55%266.67%
Al Viro13.45%133.33%
Total29100.00%3100.00%


int __init aoechr_init(void) { int n, i; n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); if (n < 0) { printk(KERN_ERR "aoe: can't register char device\n"); return n; } 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), NULL, chardevs[i].name); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin12489.86%222.22%
Kay Sievers64.35%222.22%
Greg Kroah-Hartman64.35%444.44%
Matthias Kaehlcke21.45%111.11%
Total138100.00%9100.00%


void aoechr_exit(void) { int i; for (i = 0; i < ARRAY_SIZE(chardevs); ++i) device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor)); class_destroy(aoe_class); unregister_chrdev(AOE_MAJOR, "aoechr"); }

Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin5192.73%133.33%
Greg Kroah-Hartman35.45%133.33%
Tony Jones11.82%133.33%
Total55100.00%3100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Ed L. Cashin120088.95%1542.86%
Kay Sievers342.52%25.71%
David S. Miller292.15%12.86%
Arnd Bergmann272.00%25.71%
Greg Kroah-Hartman241.78%514.29%
Matthias Kaehlcke110.82%12.86%
Jonathan Corbet70.52%12.86%
Alexander Nyberg40.30%12.86%
Paul Gortmaker30.22%12.86%
Tejun Heo30.22%12.86%
Mihnea Dobrescu-Balaur30.22%12.86%
Al Viro10.07%12.86%
Tony Jones10.07%12.86%
Arjan van de Ven10.07%12.86%
Eric Sesterhenn / Snakebyte10.07%12.86%
Total1349100.00%35100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.