[PATCH 2/2] staging: unisys: added virtpci info entry
Dan Carpenter
dan.carpenter at oracle.com
Tue Jul 8 17:52:00 UTC 2014
On Tue, Jul 08, 2014 at 01:21:31PM -0400, Erik Arfvidson wrote:
> This patch adds the virtpci debugfs directory and the info entry
> inside of it.
>
> Signed-off-by: Erik Arfvidson <erik.arfvidson at unisys.com>
> Signed-off-by: Benjamin Romer <benjamin.romer at unisys.com>
> ---
> drivers/staging/unisys/virtpci/virtpci.c | 122 ++++++++++++++++++++++++++++++-
> 1 file changed, 118 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c
> index 7d840b0..6c0aa96 100644
> --- a/drivers/staging/unisys/virtpci/virtpci.c
> +++ b/drivers/staging/unisys/virtpci/virtpci.c
> @@ -37,6 +37,7 @@
> #include <linux/if_ether.h>
> #include <linux/version.h>
> #include "version.h"
> + #include <linux/debugfs.h>
> #include "guestlinuxdebug.h"
> #include "timskmodutils.h"
>
> @@ -100,6 +101,12 @@ static int virtpci_device_resume(struct device *dev);
> static int virtpci_device_probe(struct device *dev);
> static int virtpci_device_remove(struct device *dev);
>
> +static ssize_t info_debugfs_read(struct file *file, char __user *buf,
> + size_t len, loff_t *offset);
> +
> +static const struct file_operations debugfs_info_fops = {
> + .read = info_debugfs_read,
> +};
>
> /*****************************************************/
> /* Globals */
> @@ -139,7 +146,19 @@ static DEFINE_RWLOCK(VpcidevListLock);
>
> /* filled in with info about this driver, wrt it servicing client busses */
> static ULTRA_VBUS_DEVICEINFO Bus_DriverInfo;
> -
> + /*****************************************************/
> + /* DebugFS entries */
> + /*****************************************************/
> +/* dentry is used to create the debugfs entry directory
> + * for virtpci
> + */
> +static struct dentry *virtpci_debugfs_dir;
> +static struct dentry *info_debugfs_entry;
> +/* info_debugfs_entry is used to tell virtpci to display current info
> + * kept in the driver
> + */
> +#define DIR_DEBUGFS_ENTRY "virtpci"
> +#define INFO_DEBUGFS_ENTRY_FN "info"
>
> struct virtpci_busdev {
> struct device virtpci_bus_device;
> @@ -588,7 +607,8 @@ static void delete_all(void)
> /* deletes all vnics or vhbas
> * returns 0 failure, 1 success,
> */
> -static int delete_all_virt(VIRTPCI_DEV_TYPE devtype, struct del_vbus_guestpart *delparams)
> +static int delete_all_virt(VIRTPCI_DEV_TYPE devtype,
> + struct del_vbus_guestpart *delparams)
> {
> int i;
> unsigned char busid[BUS_ID_SIZE];
> @@ -1375,6 +1395,95 @@ void virtpci_unregister_driver(struct virtpci_driver *drv)
> DBGINF("Leaving\n");
> }
> EXPORT_SYMBOL_GPL(virtpci_unregister_driver);
> +/*****************************************************/
> +/* debugfs filesystem functions */
> +/*****************************************************/
> +struct print_vbus_info {
> + int *length;
> + char *buf;
> +};
> +
> +static int print_vbus(struct device *vbus, void *data)
> +{
> + struct print_vbus_info *p = (struct print_vbus_info *) data;
Remove the space after the cast to remind that casting is high
precedence.
struct print_vbus_info *p = (struct print_vbus_info *)data;
> + int l = *(p->length);
Remove the extra parens.
int l = *p->length;
> +
> + *(p->length) = l + sprintf(p->buf + l, "bus_id:%s\n", dev_name(vbus));
You don't really need the "l" at all.
*p->length += sprintf(p->buf + *p->length, "bus_id:%s\n",
dev_name(vbus));
> + return 0; /* no error */
> +}
> +
> +static ssize_t info_debugfs_read(struct file *file, char __user *buf,
> + size_t len, loff_t *offset)
> +{
> + int length = 0;
"length" is going to be confusing because we already have "len".
> + struct virtpci_dev *tmpvpcidev;
> + unsigned long flags;
> + struct print_vbus_info printparam;
> + char *vbuf;
> + loff_t pos = *offset;
> +
> + if (pos < 0)
> + return -EINVAL;
> +
> + if (pos > 0 || !len)
> + return 0;
I don't understand the point of updating *offset and then not allowing
pos > 0. (This could be because I haven't paid attention as well
though).
> +
> + vbuf = kzalloc(len, GFP_KERNEL);
> + if (!vbuf)
> + return -ENOMEM;
> +
> + length += sprintf(vbuf + length, "CHANSOCK is not defined.\n");
This is memory corruption here because we don't verify that len is large
enough for the string. None of the sprintf() calls have checking.
> +
> + length += sprintf(vbuf + length, "\n Virtual PCI Bus devices\n");
> + printparam.length = &length;
> + printparam.buf = vbuf;
> + if (bus_for_each_dev(&virtpci_bus_type, NULL,
> + (void *) &printparam, print_vbus))
> + LOGERR("delete of all vbus failed\n");
"delete"? Probably cut and paste bug.
> +
> + length += sprintf(vbuf + length, "\n Virtual PCI devices\n");
> + read_lock_irqsave(&VpcidevListLock, flags);
> + tmpvpcidev = VpcidevListHead;
> + while (tmpvpcidev) {
> + if (tmpvpcidev->devtype == VIRTHBA_TYPE) {
> + length += sprintf(vbuf + length,
> + "[%d:%d] VHba:%08x:%08x max-config:%d-%d-%d-%d",
> + tmpvpcidev->busNo, tmpvpcidev->deviceNo,
> + tmpvpcidev->scsi.wwnn.wwnn1,
> + tmpvpcidev->scsi.wwnn.wwnn2,
> + tmpvpcidev->scsi.max.max_channel,
> + tmpvpcidev->scsi.max.max_id,
> + tmpvpcidev->scsi.max.max_lun,
> + tmpvpcidev->scsi.max.cmd_per_lun);
> + } else {
> + length += sprintf(vbuf + length, "[%d:%d] VNic:%02x:%02x:%02x:%02x:%02x:%02x num_rcv_bufs:%d mtu:%d",
> + tmpvpcidev->busNo, tmpvpcidev->deviceNo,
> + tmpvpcidev->net.mac_addr[0],
> + tmpvpcidev->net.mac_addr[1],
> + tmpvpcidev->net.mac_addr[2],
> + tmpvpcidev->net.mac_addr[3],
> + tmpvpcidev->net.mac_addr[4],
> + tmpvpcidev->net.mac_addr[5],
> + tmpvpcidev->net.num_rcv_bufs,
> + tmpvpcidev->net.mtu);
> + }
> + length +=
> + sprintf(vbuf + length, " chanptr:%p\n",
> + tmpvpcidev->queueinfo.chan);
> + tmpvpcidev = tmpvpcidev->next;
> + }
> + read_unlock_irqrestore(&VpcidevListLock, flags);
> +
> + length += sprintf(vbuf + length, "\n");
> + if (copy_to_user(buf, vbuf, length)) {
There should be some length checking here as well.
> + kfree(vbuf);
> + return -EFAULT;
> + }
> +
> + kfree(vbuf);
> + *offset += length;
> + return length;
> +}
>
> /*****************************************************/
> /* Module Init & Exit functions */
> @@ -1426,7 +1535,10 @@ static int __init virtpci_mod_init(void)
>
> LOGINF("successfully registered virtpci_ctrlchan_func (0x%p) as callback.\n",
> (void *) &virtpci_ctrlchan_func);
> -
> + /*create debugfs directory*/
> + virtpci_debugfs_dir = debugfs_create_dir(DIR_DEBUGFS_ENTRY, NULL);
> + info_debugfs_entry = debugfs_create_file(INFO_DEBUGFS_ENTRY_FN, 0660,
The owner has write permision but there is no ->write op. Don't use the
numbers use S_IRUSR or whatever.
> + virtpci_debugfs_dir, NULL, &debugfs_info_fops);
> LOGINF("Leaving\n");
> POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
> return 0;
> @@ -1442,7 +1554,9 @@ static void __exit virtpci_mod_exit(void)
>
> device_unregister(&virtpci_rootbus_device);
> bus_unregister(&virtpci_bus_type);
> -
> + /*debug_fs file and direcroty removal*/
> + debugfs_remove(info_debugfs_entry);
> + debugfs_remove(virtpci_debugfs_dir);
These are not indented correctly.
regards,
dan carpenter
More information about the devel
mailing list