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

📄 linux-module.c

📁 非常经典的一个分布式系统
💻 C
字号:
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Object Devices Class Driver * *  Copyright (C) 2001-2003 Cluster File Systems, Inc. * *   This file is part of Lustre, http://www.lustre.org. * *   Lustre is free software; you can redistribute it and/or *   modify it under the terms of version 2 of the GNU General Public *   License as published by the Free Software Foundation. * *   Lustre is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with Lustre; if not, write to the Free Software *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * These are the only exported functions, they provide some generic * infrastructure for managing object devices */#define DEBUG_SUBSYSTEM S_CLASS#ifndef EXPORT_SYMTAB# define EXPORT_SYMTAB#endif#ifdef __KERNEL__#ifndef AUTOCONF_INCLUDED#include <linux/config.h> /* for CONFIG_PROC_FS */#endif#include <linux/module.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/sched.h>#include <linux/lp.h>#include <linux/slab.h>#include <linux/ioport.h>#include <linux/fcntl.h>#include <linux/delay.h>#include <linux/skbuff.h>#include <linux/proc_fs.h>#include <linux/fs.h>#include <linux/poll.h>#include <linux/init.h>#include <linux/list.h>#include <linux/highmem.h>#include <asm/io.h>#include <asm/ioctls.h>#include <asm/system.h>#include <asm/poll.h>#include <asm/uaccess.h>#include <linux/miscdevice.h>#include <linux/smp_lock.h>#include <linux/seq_file.h>#else# include <liblustre.h>#endif#include <libcfs/libcfs.h>#include <obd_support.h>#include <obd_class.h>#include <lprocfs_status.h>#include <lustre_ver.h>#include <lustre/lustre_build_version.h>#ifdef __KERNEL__#include <linux/lustre_version.h>int proc_version;/* buffer MUST be at least the size of obd_ioctl_hdr */int obd_ioctl_getdata(char **buf, int *len, void *arg){        struct obd_ioctl_hdr hdr;        struct obd_ioctl_data *data;        int err;        int offset = 0;        ENTRY;        err = copy_from_user(&hdr, (void *)arg, sizeof(hdr));        if ( err )                 RETURN(err);        if (hdr.ioc_version != OBD_IOCTL_VERSION) {                CERROR("Version mismatch kernel (%x) vs application (%x)\n",                       OBD_IOCTL_VERSION, hdr.ioc_version);                RETURN(-EINVAL);        }        if (hdr.ioc_len > OBD_MAX_IOCTL_BUFFER) {                CERROR("User buffer len %d exceeds %d max buffer\n",                       hdr.ioc_len, OBD_MAX_IOCTL_BUFFER);                RETURN(-EINVAL);        }        if (hdr.ioc_len < sizeof(struct obd_ioctl_data)) {                CERROR("User buffer too small for ioctl (%d)\n", hdr.ioc_len);                RETURN(-EINVAL);        }        /* XXX allocate this more intelligently, using kmalloc when         * appropriate */        OBD_VMALLOC(*buf, hdr.ioc_len);        if (*buf == NULL) {                CERROR("Cannot allocate control buffer of len %d\n",                       hdr.ioc_len);                RETURN(-EINVAL);        }        *len = hdr.ioc_len;        data = (struct obd_ioctl_data *)*buf;        err = copy_from_user(*buf, (void *)arg, hdr.ioc_len);        if ( err ) {                OBD_VFREE(*buf, hdr.ioc_len);                RETURN(err);        }        if (obd_ioctl_is_invalid(data)) {                CERROR("ioctl not correctly formatted\n");                OBD_VFREE(*buf, hdr.ioc_len);                RETURN(-EINVAL);        }        if (data->ioc_inllen1) {                data->ioc_inlbuf1 = &data->ioc_bulk[0];                offset += size_round(data->ioc_inllen1);        }        if (data->ioc_inllen2) {                data->ioc_inlbuf2 = &data->ioc_bulk[0] + offset;                offset += size_round(data->ioc_inllen2);        }        if (data->ioc_inllen3) {                data->ioc_inlbuf3 = &data->ioc_bulk[0] + offset;                offset += size_round(data->ioc_inllen3);        }        if (data->ioc_inllen4) {                data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset;        }        EXIT;        return 0;}int obd_ioctl_popdata(void *arg, void *data, int len){        int err;                 err = copy_to_user(arg, data, len);        if (err)                err = -EFAULT;        return err;}EXPORT_SYMBOL(obd_ioctl_getdata);EXPORT_SYMBOL(obd_ioctl_popdata);#define OBD_MINOR 241extern struct cfs_psdev_ops          obd_psdev_ops;/*  opening /dev/obd */static int obd_class_open(struct inode * inode, struct file * file){        if (obd_psdev_ops.p_open != NULL)                return obd_psdev_ops.p_open(0, NULL);        return -EPERM;}/*  closing /dev/obd */static int obd_class_release(struct inode * inode, struct file * file){        if (obd_psdev_ops.p_close != NULL)                return obd_psdev_ops.p_close(0, NULL);        return -EPERM;}/* to control /dev/obd */static int obd_class_ioctl(struct inode *inode, struct file *filp,                           unsigned int cmd, unsigned long arg){        int err = 0;        ENTRY;        if (current->fsuid != 0)                RETURN(err = -EACCES);        if ((cmd & 0xffffff00) == ((int)'T') << 8) /* ignore all tty ioctls */                RETURN(err = -ENOTTY);        if (obd_psdev_ops.p_ioctl != NULL)                err = obd_psdev_ops.p_ioctl(NULL, cmd, (void *)arg);        else                err = -EPERM;        RETURN(err);}/* declare character device */static struct file_operations obd_psdev_fops = {        .owner   = THIS_MODULE,        .ioctl   = obd_class_ioctl,     /* ioctl */        .open    = obd_class_open,      /* open */        .release = obd_class_release,   /* release */};/* modules setup */cfs_psdev_t obd_psdev = {        .minor = OBD_MINOR,        .name  = "obd_psdev",        .fops  = &obd_psdev_fops,};#endif#ifdef LPROCFSint obd_proc_read_version(char *page, char **start, off_t off, int count,                          int *eof, void *data){        *eof = 1;#ifdef HAVE_VFS_INTENT_PATCHES        return snprintf(page, count, "lustre: %s\nkernel: %u\nbuild:  %s\n",                        LUSTRE_VERSION_STRING, LUSTRE_KERNEL_VERSION,                        BUILD_VERSION);#else        return snprintf(page, count, "lustre: %s\nkernel: %s\nbuild:  %s\n",                        LUSTRE_VERSION_STRING, "patchless", BUILD_VERSION);#endif}int obd_proc_read_pinger(char *page, char **start, off_t off, int count,                         int *eof, void *data){        *eof = 1;        return snprintf(page, count, "%s\n",#ifdef ENABLE_PINGER                        "on"#else                        "off"#endif                       );}static int obd_proc_read_health(char *page, char **start, off_t off,                                int count, int *eof, void *data){        int rc = 0, i;        *eof = 1;        if (libcfs_catastrophe)                rc += snprintf(page + rc, count - rc, "LBUG\n");        spin_lock(&obd_dev_lock);        for (i = 0; i < class_devno_max(); i++) {                struct obd_device *obd;                obd = class_num2obd(i);                if (obd == NULL)                        continue;                LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);                if (obd->obd_stopping)                        continue;                class_incref(obd);                spin_unlock(&obd_dev_lock);                if (obd_health_check(obd)) {                        rc += snprintf(page + rc, count - rc,                                       "device %s reported unhealthy\n",                                       obd->obd_name);                }                class_decref(obd);                spin_lock(&obd_dev_lock);        }        spin_unlock(&obd_dev_lock);        if (rc == 0)                return snprintf(page, count, "healthy\n");        rc += snprintf(page + rc, count - rc, "NOT HEALTHY\n");        return rc;}static int obd_proc_rd_health_timeout(char *page, char **start, off_t off,                                      int count, int *eof, void *data){        *eof = 1;        return snprintf(page, count, "%d\n", obd_health_check_timeout);}static int obd_proc_wr_health_timeout(struct file *file, const char *buffer,                                      unsigned long count, void *data){        int val, rc;        rc = lprocfs_write_helper(buffer, count, &val);        if (rc)                return rc;        obd_health_check_timeout = val;        return count;}/* Root for /proc/fs/lustre */struct proc_dir_entry *proc_lustre_root = NULL;struct lprocfs_vars lprocfs_base[] = {        { "version", obd_proc_read_version, NULL, NULL },        { "pinger", obd_proc_read_pinger, NULL, NULL },        { "health_check", obd_proc_read_health, NULL, NULL },        { "health_check_timeout", obd_proc_rd_health_timeout,           obd_proc_wr_health_timeout, NULL },        { 0 }};#else#define lprocfs_base NULL#endif /* LPROCFS */#ifdef __KERNEL__static void *obd_device_list_seq_start(struct seq_file *p, loff_t *pos){        if (*pos >= class_devno_max())                return NULL;        return pos;}static void obd_device_list_seq_stop(struct seq_file *p, void *v){}static void *obd_device_list_seq_next(struct seq_file *p, void *v, loff_t *pos){              ++*pos;        if (*pos >= class_devno_max())                return NULL;        return pos;}static int obd_device_list_seq_show(struct seq_file *p, void *v){        loff_t index = *(loff_t *)v;        struct obd_device *obd = class_num2obd((int)index);        char *status;        if (obd == NULL)                return 0;        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);        if (obd->obd_stopping)                status = "ST";        else if (obd->obd_set_up)                status = "UP";        else if (obd->obd_attached)                status = "AT";        else                status = "--";        return seq_printf(p, "%3d %s %s %s %s %d\n",                          (int)index, status, obd->obd_type->typ_name,                          obd->obd_name, obd->obd_uuid.uuid,                          atomic_read(&obd->obd_refcount));}struct seq_operations obd_device_list_sops = {        .start = obd_device_list_seq_start,        .stop = obd_device_list_seq_stop,        .next = obd_device_list_seq_next,        .show = obd_device_list_seq_show,};static int obd_device_list_open(struct inode *inode, struct file *file){        struct proc_dir_entry *dp = PDE(inode);        struct seq_file *seq;        int rc = seq_open(file, &obd_device_list_sops);        if (rc)                return rc;        seq = file->private_data;        seq->private = dp->data;        return 0;}struct file_operations obd_device_list_fops = {        .owner   = THIS_MODULE,        .open    = obd_device_list_open,        .read    = seq_read,        .llseek  = seq_lseek,        .release = seq_release,};#endifint class_procfs_init(void){#ifdef __KERNEL__        struct proc_dir_entry *entry;        ENTRY;        obd_sysctl_init();        proc_lustre_root = proc_mkdir("lustre", proc_root_fs);        if (!proc_lustre_root) {                printk(KERN_ERR                       "LustreError: error registering /proc/fs/lustre\n");                RETURN(-ENOMEM);        }        proc_version = lprocfs_add_vars(proc_lustre_root, lprocfs_base, NULL);        entry = create_proc_entry("devices", 0444, proc_lustre_root);        if (entry == NULL) {                CERROR("error registering /proc/fs/lustre/devices\n");                lprocfs_remove(&proc_lustre_root);                RETURN(-ENOMEM);        }        entry->proc_fops = &obd_device_list_fops;#else        ENTRY;#endif        RETURN(0);}#ifdef __KERNEL__int class_procfs_clean(void){        ENTRY;        if (proc_lustre_root)                 lprocfs_remove(&proc_lustre_root);        RETURN(0);}/* Check that we're building against the appropriate version of the Lustre * kernel patch */#include <linux/lustre_version.h>#ifdef LUSTRE_KERNEL_VERSION#define LUSTRE_MIN_VERSION 45#define LUSTRE_MAX_VERSION 47#if (LUSTRE_KERNEL_VERSION < LUSTRE_MIN_VERSION)# error Cannot continue: Your Lustre kernel patch is older than the sources#elif (LUSTRE_KERNEL_VERSION > LUSTRE_MAX_VERSION)# error Cannot continue: Your Lustre sources are older than the kernel patch#endif#endif#endif

⌨️ 快捷键说明

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