Files
@ bd21c8aa7237
Branch filter:
Location: vmkdrivers/vmkdrivers/src_9/drivers/scsi/fnic/fnic_procfs.c
bd21c8aa7237
4.3 KiB
text/x-csrc
ESXi-6.0.0b
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | /*
* Copyright 2011 Cisco Systems, Inc. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* [Insert appropriate license here when releasing outside of Cisco]
* $Id: fnic_procfs.c 111268 2012-08-27 17:11:40Z atungara $
*/
/*
* This file contains routines to create an interface to
* fnic in /proc/ on ESX 5.0 (MN). MN does not support
* sysfs, but it does support /proc/. So we'll use that
* to set fnic_log_level to the required debug level, and
* pass it on to fnic after fnic is loaded.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#define FNIC_LOG_FILE "fnic_log_level"
#define FNIC_MODULE_DIR "fnic"
#define FNIC_PROCFS_MAX_BUF_LEN 80
extern unsigned int fnic_log_level;
static char procfs_buf[FNIC_PROCFS_MAX_BUF_LEN];
static unsigned long procfs_buf_size;
static struct proc_dir_entry *fnic_log_level_file;
static struct proc_dir_entry *fnic_dir;
int f_l_l_proc_read(char *buf, char **buf_locn,
off_t offset, int buf_len, int *eof,
void *data);
int f_l_l_proc_write(struct file *filp, const char *buf,
unsigned long count, void *data);
int init_fnic_procfs(void);
void teardown_fnic_procfs(void);
int f_l_l_proc_read(char *buf, char **buf_locn,
off_t offset, int buf_len, int *eof,
void *data)
{
int ret;
if (offset > 0) {
/* We're finished reading */
ret = 0;
} else {
/* fill up buf, return buf size */
memcpy(buf, procfs_buf, procfs_buf_size);
ret = procfs_buf_size;
}
return ret;
}
int f_l_l_proc_write(struct file *filp, const char __user *buf,
unsigned long count, void *data)
{
unsigned long fnic_log_val;
procfs_buf_size = (count > FNIC_PROCFS_MAX_BUF_LEN) ?
FNIC_PROCFS_MAX_BUF_LEN : count;
/* write out the data to our kernel buffer */
if (copy_from_user(procfs_buf, buf, procfs_buf_size)) {
printk(KERN_ALERT "\nFailed to copy user buf to kernel buf\n");
return -EFAULT;
}
/* Ok, now we need to convert this char buffer to an int */
fnic_log_val = simple_strtoul(procfs_buf, NULL, 0);
/*
* If fnic_log_val is a valid value, set fnic_log_level to it. Else,
* keep it at its previous value.
*/
fnic_log_level = (fnic_log_val > 0 && fnic_log_val <= 7) ?
fnic_log_val : fnic_log_level;
/* Returning the correct size of the buffer read in will allow the
* user to break out of an echo "value" > /proc/fnic/fnic_log_level
*/
return procfs_buf_size;
}
int init_fnic_procfs(void)
{
int err = 0;
/* First, create a directory called "fnic" under /proc/ */
fnic_dir = proc_mkdir(FNIC_MODULE_DIR, NULL);
if (fnic_dir == NULL) {
printk(KERN_ALERT "Create /proc/fnic/ failed \n");
err = -ENOMEM;
goto remove_fnic_dir;
}
/* Then, create a file called "fnic_log_level" under /proc/fnic/ */
fnic_log_level_file = create_proc_entry(FNIC_LOG_FILE, 0644, fnic_dir);
if (!fnic_log_level_file) {
printk(KERN_ALERT "Create /proc/fnic/fnic_log_level failed\n");
err = -ENOMEM;
goto remove_fnic_log_level_file;
}
/*
* Initialize the proc read and write routines that will let users
* write to and read respectively, from these files.
*/
fnic_log_level_file->read_proc = f_l_l_proc_read;
fnic_log_level_file->write_proc = f_l_l_proc_write;
fnic_log_level_file->owner = THIS_MODULE;
fnic_log_level_file->mode = S_IFREG | S_IRUGO;
fnic_log_level_file->size = 2*FNIC_PROCFS_MAX_BUF_LEN;
return err;
remove_fnic_log_level_file:
remove_proc_entry(FNIC_LOG_FILE, fnic_log_level_file);
remove_fnic_dir:
remove_proc_entry(FNIC_MODULE_DIR, fnic_dir);
return err;
}
void teardown_fnic_procfs(void)
{
printk(KERN_INFO "Tearing down procfs for fnic\n");
remove_proc_entry(FNIC_LOG_FILE, fnic_dir);
remove_proc_entry(FNIC_MODULE_DIR, NULL);
return;
}
|