⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aoechr.c

📁 LINUX 2.6.17.4的源码
💻 C
字号:
/* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. *//* * aoechr.c * AoE character device driver */#include <linux/hdreg.h>#include <linux/blkdev.h>#include "aoe.h"enum {	//MINOR_STAT = 1, (moved to sysfs)	MINOR_ERR = 2,	MINOR_DISCOVER,	MINOR_INTERFACES,	MINOR_REVALIDATE,	MSGSZ = 2048,	NARGS = 10,	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 struct ErrMsg emsgs[NMSG];static int emsgs_head_idx, emsgs_tail_idx;static struct semaphore emsgs_sema;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" },};static intdiscover(void){	aoecmd_cfg(0xffff, 0xff);	return 0;}static intinterfaces(const char __user *str, size_t size){	if (set_aoe_iflist(str, size)) {		printk(KERN_CRIT		       "%s: could not set interface list: %s\n",		       __FUNCTION__, "too many interfaces");		return -EINVAL;	}	return 0;}static intrevalidate(const char __user *str, size_t size){	int major, minor, n;	ulong flags;	struct aoedev *d;	char buf[16];	if (size >= sizeof buf)		return -EINVAL;	buf[sizeof buf - 1] = '\0';	if (copy_from_user(buf, str, size))		return -EFAULT;	/* should be e%d.%d format */	n = sscanf(buf, "e%d.%d", &major, &minor);	if (n != 2) {		printk(KERN_ERR "aoe: %s: invalid device specification\n",			__FUNCTION__);		return -EINVAL;	}	d = aoedev_by_aoeaddr(major, minor);	if (!d)		return -EINVAL;	spin_lock_irqsave(&d->lock, flags);	d->flags |= DEVFL_PAUSE;	spin_unlock_irqrestore(&d->lock, flags);	aoecmd_cfg(major, minor);	return 0;}voidaoechr_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 = kmalloc(n, GFP_ATOMIC);	if (mp == NULL) {		printk(KERN_CRIT "aoe: aoechr_error: allocation failure, len=%ld\n", n);		goto bail;	}	memcpy(mp, msg, n);	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)		up(&emsgs_sema);}static ssize_taoechr_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: aoechr_write: 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);	}	if (ret == 0)		ret = cnt;	return ret;}static intaoechr_open(struct inode *inode, struct file *filp){	int n, i;	n = MINOR(inode->i_rdev);	filp->private_data = (void *) (unsigned long) n;	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)		if (chardevs[i].minor == n)			return 0;	return -EINVAL;}static intaoechr_rel(struct inode *inode, struct file *filp){	return 0;}static ssize_taoechr_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;	switch (n) {	case MINOR_ERR:		spin_lock_irqsave(&emsgs_lock, flags);loop:		em = emsgs + emsgs_head_idx;		if ((em->flags & EMFL_VALID) == 0) {			if (filp->f_flags & O_NDELAY) {				spin_unlock_irqrestore(&emsgs_lock, flags);				return -EAGAIN;			}			nblocked_emsgs_readers++;			spin_unlock_irqrestore(&emsgs_lock, flags);			n = down_interruptible(&emsgs_sema);			spin_lock_irqsave(&emsgs_lock, flags);			nblocked_emsgs_readers--;			if (n) {				spin_unlock_irqrestore(&emsgs_lock, flags);				return -ERESTARTSYS;			}			goto loop;		}		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;	default:		return -EFAULT;	}}static struct file_operations aoe_fops = {	.write = aoechr_write,	.read = aoechr_read,	.open = aoechr_open,	.release = aoechr_rel,	.owner = THIS_MODULE,};int __initaoechr_init(void){	int n, i;	n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops);	if (n < 0) { 		printk(KERN_ERR "aoe: aoechr_init: can't register char device\n");		return n;	}	sema_init(&emsgs_sema, 0);	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);	}	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)		class_device_create(aoe_class, NULL,					MKDEV(AOE_MAJOR, chardevs[i].minor),					NULL, chardevs[i].name);	return 0;}voidaoechr_exit(void){	int i;	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)		class_device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));	class_destroy(aoe_class);	unregister_chrdev(AOE_MAJOR, "aoechr");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -