Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-module.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *
5  *  Copyright (c) 2004 Cluster File Systems, Inc.
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
9  *   Lustre is free software; you can redistribute it and/or modify it under
10  *   the terms of version 2 of the GNU General Public License as published by
11  *   the Free Software Foundation. Lustre is distributed in the hope that it
12  *   will be useful, but WITHOUT ANY WARRANTY; without even the implied
13  *   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details. You should have received a
15  *   copy of the GNU General Public License along with Lustre; if not, write
16  *   to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
17  *   USA.
18  */
19
20
21 #define DEBUG_SUBSYSTEM S_LIBCFS
22
23 #include <libcfs/libcfs.h>
24 #include <libcfs/kp30.h>
25
26 #define LIBCFS_MINOR 240
27
28 int libcfs_ioctl_getdata(char *buf, char *end, void *arg)
29 {
30         struct libcfs_ioctl_hdr *hdr;
31         struct libcfs_ioctl_data *data;
32         int err;
33         ENTRY;
34
35         hdr = (struct libcfs_ioctl_hdr *)buf;
36         data = (struct libcfs_ioctl_data *)buf;
37
38         err = copy_from_user(buf, (void *)arg, sizeof(*hdr));
39         if (err)
40                 RETURN(err);
41
42         if (hdr->ioc_version != LIBCFS_IOCTL_VERSION) {
43                 CERROR(("LIBCFS: version mismatch kernel vs application\n"));
44                 RETURN(-EINVAL);
45         }
46
47         if (hdr->ioc_len + buf >= end) {
48                 CERROR(("LIBCFS: user buffer exceeds kernel buffer\n"));
49                 RETURN(-EINVAL);
50         }
51
52         if (hdr->ioc_len < sizeof(struct libcfs_ioctl_data)) {
53                 CERROR(("LIBCFS: user buffer too small for ioctl\n"));
54                 RETURN(-EINVAL);
55         }
56
57         err = copy_from_user(buf, (void *)arg, hdr->ioc_len);
58         if (err)
59                 RETURN(err);
60
61         if (libcfs_ioctl_is_invalid(data)) {
62                 CERROR(("LIBCFS: ioctl not correctly formatted\n"));
63                 RETURN(-EINVAL);
64         }
65
66         if (data->ioc_inllen1)
67                 data->ioc_inlbuf1 = &data->ioc_bulk[0];
68
69         if (data->ioc_inllen2)
70                 data->ioc_inlbuf2 = &data->ioc_bulk[0] +
71                         size_round(data->ioc_inllen1);
72
73         RETURN(0);
74 }
75                                                                                                                                                                         
76 extern struct cfs_psdev_ops          libcfs_psdev_ops;
77
78 static int 
79 libcfs_psdev_open(cfs_file_t * file)
80
81         struct libcfs_device_userstate **pdu = NULL;
82         int    rc = 0;
83
84         pdu = (struct libcfs_device_userstate **)&file->private_data;
85         if (libcfs_psdev_ops.p_open != NULL)
86                 rc = libcfs_psdev_ops.p_open(0, (void *)pdu);
87         else
88                 return (-EPERM);
89         return rc;
90 }
91
92 /* called when closing /dev/device */
93 static int 
94 libcfs_psdev_release(cfs_file_t * file)
95 {
96         struct libcfss_device_userstate *pdu;
97         int    rc = 0;
98
99         pdu = file->private_data;
100         if (libcfs_psdev_ops.p_close != NULL)
101                 rc = libcfs_psdev_ops.p_close(0, (void *)pdu);
102         else
103                 rc = -EPERM;
104         return rc;
105 }
106
107 static int 
108 libcfs_ioctl(cfs_file_t * file, unsigned int cmd, ulong_ptr arg)
109
110         struct cfs_psdev_file    pfile;
111         int    rc = 0;
112
113         if ( _IOC_TYPE(cmd) != IOC_LIBCFS_TYPE || 
114              _IOC_NR(cmd) < IOC_LIBCFS_MIN_NR  || 
115              _IOC_NR(cmd) > IOC_LIBCFS_MAX_NR ) { 
116                 CDEBUG(D_IOCTL, ("invalid ioctl ( type %d, nr %d, size %d )\n", 
117                        _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd))); 
118                 return (-EINVAL); 
119         } 
120         
121         /* Handle platform-dependent IOC requests */
122         switch (cmd) { 
123         case IOC_LIBCFS_PANIC: 
124                 if (!capable (CAP_SYS_BOOT)) 
125                         return (-EPERM); 
126                 CERROR(("debugctl-invoked panic"));
127         KeBugCheckEx('LUFS', (ULONG_PTR)libcfs_ioctl, (ULONG_PTR)NULL, (ULONG_PTR)NULL, (ULONG_PTR)NULL);
128
129                 return (0);
130         case IOC_LIBCFS_MEMHOG:
131
132                 if (!capable (CAP_SYS_ADMIN)) 
133                         return -EPERM;
134         break;
135         }
136
137         pfile.off = 0;
138         pfile.private_data = file->private_data;
139         if (libcfs_psdev_ops.p_ioctl != NULL) 
140                 rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg); 
141         else
142                 rc = -EPERM;
143         return (rc);
144 }
145
146 static struct file_operations libcfs_fops = {
147     /* lseek: */  NULL,
148     /* read: */   NULL,
149     /* write: */  NULL,
150     /* ioctl: */  libcfs_ioctl,
151     /* open: */   libcfs_psdev_open,
152     /* release:*/ libcfs_psdev_release
153 };
154
155 cfs_psdev_t libcfs_dev = { 
156         LIBCFS_MINOR, 
157         "lnet", 
158         &libcfs_fops
159 };
160