Whamcloud - gitweb
* Landed portals:b_port_step as follows...
[fs/lustre-release.git] / lnet / libcfs / linux / linux-module.c
1 #define DEBUG_SUBSYSTEM S_PORTALS
2
3 #include <libcfs/libcfs.h>
4 #include <libcfs/kp30.h>
5
6 #define PORTAL_MINOR 240
7
8
9 void
10 kportal_daemonize (char *str)
11 {
12 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,63)) 
13         daemonize(str);
14 #else 
15         daemonize(); 
16         snprintf (current->comm, sizeof (current->comm), "%s", str);
17 #endif
18 }
19
20 void
21 kportal_blockallsigs ()
22
23         unsigned long  flags; 
24         
25         SIGNAL_MASK_LOCK(current, flags); 
26         sigfillset(&current->blocked); 
27         RECALC_SIGPENDING; 
28         SIGNAL_MASK_UNLOCK(current, flags);
29 }
30
31 int portal_ioctl_getdata(char *buf, char *end, void *arg)
32 {
33         struct portal_ioctl_hdr *hdr;
34         struct portal_ioctl_data *data;
35         int err;
36         ENTRY;
37
38         hdr = (struct portal_ioctl_hdr *)buf;
39         data = (struct portal_ioctl_data *)buf;
40
41         err = copy_from_user(buf, (void *)arg, sizeof(*hdr));
42         if (err)
43                 RETURN(err);
44
45         if (hdr->ioc_version != PORTAL_IOCTL_VERSION) {
46                 CERROR("PORTALS: version mismatch kernel vs application\n");
47                 RETURN(-EINVAL);
48         }
49
50         if (hdr->ioc_len + buf >= end) {
51                 CERROR("PORTALS: user buffer exceeds kernel buffer\n");
52                 RETURN(-EINVAL);
53         }
54
55
56         if (hdr->ioc_len < sizeof(struct portal_ioctl_data)) {
57                 CERROR("PORTALS: user buffer too small for ioctl\n");
58                 RETURN(-EINVAL);
59         }
60
61         err = copy_from_user(buf, (void *)arg, hdr->ioc_len);
62         if (err)
63                 RETURN(err);
64
65         if (portal_ioctl_is_invalid(data)) {
66                 CERROR("PORTALS: ioctl not correctly formatted\n");
67                 RETURN(-EINVAL);
68         }
69
70         if (data->ioc_inllen1)
71                 data->ioc_inlbuf1 = &data->ioc_bulk[0];
72
73         if (data->ioc_inllen2)
74                 data->ioc_inlbuf2 = &data->ioc_bulk[0] +
75                         size_round(data->ioc_inllen1);
76
77         RETURN(0);
78 }
79                                                                                                                                                                         
80 extern struct cfs_psdev_ops          libcfs_psdev_ops;
81
82 static int 
83 libcfs_psdev_open(struct inode * inode, struct file * file)
84
85         struct portals_device_userstate **pdu = NULL;
86         int    rc = 0;
87
88         if (!inode) 
89                 return (-EINVAL);
90         pdu = (struct portals_device_userstate **)&file->private_data;
91         if (libcfs_psdev_ops.p_open != NULL)
92                 rc = libcfs_psdev_ops.p_open(0, (void *)pdu);
93         else
94                 return (-EPERM);
95         return rc;
96 }
97
98 /* called when closing /dev/device */
99 static int 
100 libcfs_psdev_release(struct inode * inode, struct file * file)
101 {
102         struct portals_device_userstate *pdu;
103         int    rc = 0;
104
105         if (!inode) 
106                 return (-EINVAL);
107         pdu = file->private_data;
108         if (libcfs_psdev_ops.p_close != NULL)
109                 rc = libcfs_psdev_ops.p_close(0, (void *)pdu);
110         else
111                 rc = -EPERM;
112         return rc;
113 }
114
115 static int 
116 libcfs_ioctl(struct inode *inode, struct file *file, 
117              unsigned int cmd, unsigned long arg)
118
119         struct cfs_psdev_file    pfile;
120         int    rc = 0;
121
122         if (current->fsuid != 0) 
123                 return -EACCES; 
124         
125         if ( _IOC_TYPE(cmd) != IOC_PORTAL_TYPE || 
126              _IOC_NR(cmd) < IOC_PORTAL_MIN_NR  || 
127              _IOC_NR(cmd) > IOC_PORTAL_MAX_NR ) { 
128                 CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n", 
129                        _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd)); 
130                 return (-EINVAL); 
131         } 
132         
133         /* Handle platform-dependent IOC requests */
134         switch (cmd) { 
135         case IOC_PORTAL_PANIC: 
136                 if (!capable (CAP_SYS_BOOT)) 
137                         return (-EPERM); 
138                 panic("debugctl-invoked panic"); 
139                 return (0);
140         case IOC_PORTAL_MEMHOG: 
141                 if (!capable (CAP_SYS_ADMIN)) 
142                         return -EPERM;
143                 /* go thought */
144         }
145
146         pfile.off = 0;
147         pfile.private_data = file->private_data;
148         if (libcfs_psdev_ops.p_ioctl != NULL) 
149                 rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg); 
150         else
151                 rc = -EPERM;
152         return (rc);
153 }
154
155 static struct file_operations libcfs_fops = { 
156         ioctl:   libcfs_ioctl, 
157         open:    libcfs_psdev_open, 
158         release: libcfs_psdev_release
159 };
160
161 cfs_psdev_t libcfs_dev = { 
162         PORTAL_MINOR, 
163         "portals", 
164         &libcfs_fops
165 };
166
167 EXPORT_SYMBOL(kportal_blockallsigs);
168 EXPORT_SYMBOL(kportal_daemonize);
169
170