1 /*
2 *
3 * Copyright (c) 2003 The Regents of the University of California. All
4 * rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * - Neither the name of the University nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31
32 /*
33 * FUSD: the Framework for User-Space Devices
34 *
35 * Jeremy Elson <jelson@circlemud.org>
36 * Copyright (c) Sensoria Corporation 2001
37 *
38 * Private header file used by the Linux Kernel Module
39 *
40 * $Id: kfusd.h,v 1.51 2004-04-25 03:30:23 girod Exp $
41 */
42
43 #ifndef __KFUSD_H__
44 #define __KFUSD_H__
45
46 #include "fusd_msg.h"
47
48 /* magic numbers for structure checking; unique w.r.t
49 * /usr/src/linux/Documentation/magic-number.txt */
50 #define FUSD_DEV_MAGIC 0x8b43a124
51 #define FUSD_FILE_MAGIC 0x613aa8ff
52
53 /* number of times each device can be opened simultaneously */
54 #define MIN_FILEARRAY_SIZE 8 /* initialize allocation */
55 #define MAX_FILEARRAY_SIZE 1024 /* maximum it can grow to */
56
57 /* maximum read/write size we're willing to service */
58 #define MAX_RW_SIZE (1024*128)
59
60 /* maximum number of major and minor devices */
61 #define MAX_MAJORS 256
62 #define MAX_MINORS 256
63
64 /********************** Structure Definitions *******************************/
65
66 /* Container for a fusd msg */
67 typedef struct fusd_msgC_s_t fusd_msgC_t;
68
69 struct fusd_msgC_s_t {
70 fusd_msg_t fusd_msg; /* the message itself */
71 fusd_msgC_t *next; /* pointer to next one in the list */
72
73 /* 1-bit flags */
74 unsigned int peeked:1; /* has the first half of this been read? */
75 };
76
77 /* magical forward declarations to break the circular dependency */
78 struct fusd_dev_t_s;
79 typedef struct fusd_dev_t_s fusd_dev_t;
80
81 /* state kept per opened file (i.e., an instance of a device) */
82 typedef struct {
83 /* general state management */
84 int magic; /* magic number for sanity checking */
85 fusd_dev_t *fusd_dev; /* fusd device associated with this file */
86 long fusd_dev_version; /* version number of fusd device */
87 void *private_data; /* the user's private data (we ignore it) */
88 struct file *file; /* kernel's file pointer for this file */
89 pid_t pid; /* PID of the last user of this FD */
90 int index; /* our index in our device's file array */
91 struct semaphore file_sem; /* Semaphore for file structure */
92 int cached_poll_state; /* Latest result from a poll diff req */
93 int last_poll_sent; /* Last polldiff request we sent */
94 int poll_failure; /* errno from a failed poll_diff */
95 int in_select; /* for debug only (/dev/fusd/status) */
96
97 /* structures used for messaging */
98 wait_queue_head_t file_wait; /* Wait on this for a user->kernel msg */
99 wait_queue_head_t poll_wait; /* Given to kernel for poll() queue */
100 long transid_outstanding; /* transid of msg we are waiting for */
101 int subcmd_outstanding; /* subcmd of msg we are waiting for */
102 pid_t sys_restarting_pid; /* PID we just returned -ERESTARTSYS to */
103 int sys_restarting_subcmd; /* subcmd of restarting syscall */
104 fusd_msg_t *msg_in; /* A reply we've just received */
105 } fusd_file_t;
106
107
108 /* state kept per device registered under fusd */
109 struct fusd_dev_t_s {
110 int magic; /* Magic number for sanity checking */
111 long version; /* Instance number of this device */
112 int last_version; /* Indicates version of last change */
113 int zombie; /* Is the device dead? */
114 pid_t pid; /* PID of device driver */
115 char *name; /* Name of the device under devfs (/dev) */
116 void *private_data; /* User's private data */
117 #ifdef CONFIG_DEVFS_FS
118 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
119 devfs_handle_t handle; /* The devfs-provided handle */
120 #else
121 /* handle not required for >= 2.6.0 */
122 #endif
123 #endif
124 dev_t device; /* the device (major/minor) */
125 int hash; /* the hash of the device name */
126
127 fusd_file_t **files; /* Array of this device's open files */
128 int array_size; /* Size of the array pointed to by 'files' */
129 int num_files; /* Number of array entries that are valid */
130 int open_in_progress; /* File is referencing this struct,
131 but not yet part of the file array */
132 /* messaging */
133 fusd_msgC_t *msg_head; /* linked list head for message queue */
134 fusd_msgC_t *msg_tail; /* linked list tail for message queue */
135
136 /* synchronization */
137 wait_queue_head_t dev_wait; /* Wait queue for kernel->user msgs */
138 struct semaphore dev_sem; /* Sempahore for device structure */
139
140 /* pointer to allow a dev to be placed on a dev_list */
141 struct list_head devlist;
142
143 /* Flag indicating whether MAKEDEV is done */
144 uint8_t makedev_done;
145 };
146
147
148 /**** Function Prototypes ****/
149
150 STATIC int maybe_free_fusd_dev(fusd_dev_t *fusd_dev);
151
152 STATIC int find_fusd_file(fusd_dev_t *fusd_dev, fusd_file_t *fusd_file);
153 STATIC int free_fusd_file(fusd_dev_t *fusd_dev, fusd_file_t *fusd_file);
154
155 STATIC int fusd_fops_call_send(fusd_file_t *fusd_file_arg,
156 fusd_msg_t *fusd_msg);
157 STATIC int fusd_fops_call_wait(fusd_file_t *fusd_file_arg,
158 fusd_msg_t **reply);
159 STATIC void fusd_fops_call_done(fusd_file_t *fusd_file);
160
161 STATIC void fusd_forge_close(fusd_msg_t *msg, fusd_dev_t *fusd_dev);
162
163
164
165
166
167 /**** Utility functions & macros ****/
168
169 #ifdef CONFIG_FUSD_USE_WAKEUPSYNC
170 #define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible_sync(x)
171 #else
172 #define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible(x)
173 #endif /* CONFIG_FUSD_USE_WAKEUPSYNC */
174
175 #ifdef CONFIG_FUSD_DEBUG
176 static void rdebug_real(char *fmt, ...)
177 __attribute__ ((format (printf, 1, 2)));
178
179 #define RDEBUG(message_level, args...) do { \
180 if (fusd_debug_level >= message_level) rdebug_real(args); \
181 } while(0)
182 #else
183 #define RDEBUG(message_level, args...)
184 #endif /* CONFIG_FUSD_DEBUG */
185
186
187 #define ZOMBIE(fusd_dev) ((fusd_dev)->zombie)
188
189
190 #define GET_FUSD_DEV(candidate, fusd_dev) do { \
191 fusd_dev = candidate; \
192 if (fusd_dev == NULL || fusd_dev->magic != FUSD_DEV_MAGIC) \
193 goto invalid_dev; \
194 } while (0)
195
196 #define GET_FUSD_FILE_AND_DEV(candidate, fusd_file, fusd_dev) do { \
197 fusd_file = candidate; \
198 if (fusd_file == NULL || fusd_file->magic != FUSD_FILE_MAGIC) \
199 goto invalid_file; \
200 GET_FUSD_DEV(fusd_file->fusd_dev, fusd_dev); \
201 if (fusd_dev->version != fusd_file->fusd_dev_version) \
202 goto invalid_file; \
203 } while (0)
204
205
206 #define LOCK_FUSD_DEV(fusd_dev) \
207 do { down(&fusd_dev->dev_sem); \
208 if (ZOMBIE(fusd_dev)) { up(&fusd_dev->dev_sem); goto zombie_dev; } \
209 } while (0)
210
211 /* rawlock does not do a zombie check */
212 #define RAWLOCK_FUSD_DEV(fusd_dev) \
213 do { down(&fusd_dev->dev_sem); } while (0)
214
215 #define UNLOCK_FUSD_DEV(fusd_dev) \
216 do { up(&fusd_dev->dev_sem); } while (0)
217
218
219 #define LOCK_FUSD_FILE(fusd_file) \
220 do { down(&fusd_file->file_sem); \
221 } while (0)
222
223 #define UNLOCK_FUSD_FILE(fusd_file) \
224 do { up(&fusd_file->file_sem); } while (0)
225
226 #define FREE_FUSD_MSGC(fusd_msgc) do { \
227 if ((fusd_msgc)->fusd_msg.data != NULL) KFREE(fusd_msgc->fusd_msg.data); \
228 KFREE(fusd_msgc); \
229 } while (0)
230
231 #define NAME(fusd_dev) ((fusd_dev)->name == NULL ? \
232 "<noname>" : (fusd_dev)->name)
233
234 #ifdef CONFIG_FUSD_MEMDEBUG
235 static int fusd_mem_init(void);
236 static void fusd_mem_cleanup(void);
237 static void fusd_mem_add(void *ptr, int line, int size);
238 static void fusd_mem_del(void *ptr);
239 static void *fusd_kmalloc(size_t size, int type, int line);
240 static void fusd_kfree(void *ptr);
241 static void *fusd_vmalloc(size_t size, int line);
242 static void fusd_vfree(void *ptr);
243 # define KMALLOC(size, type) fusd_kmalloc(size, type, __LINE__)
244 # define KFREE(ptr) fusd_kfree(ptr)
245 # define VMALLOC(size) fusd_vmalloc(size, __LINE__)
246 # define VFREE(ptr) fusd_vfree(ptr)
247 #else /* no memory debugging */
248 # define KMALLOC(size, type) kmalloc(size, type)
249 # define KFREE(ptr) kfree(ptr)
250 # define VMALLOC(size) vmalloc(size)
251 # define VFREE(ptr) vfree(ptr)
252 #endif /* CONFIG_FUSD_MEMDEBUG */
253
254
255
256 /* Functions like this should be in the kernel, but they are not. Sigh. */
257 #ifdef CONFIG_SMP
258
259 DECLARE_MUTEX(atomic_ops);
260
261 static __inline__ int atomic_inc_and_ret(int *i)
262 {
263 int val;
264
265 down(&atomic_ops);
266 val = (++(*i));
267 up(&atomic_ops);
268 return val;
269 }
270 #else
271 static __inline__ int atomic_inc_and_ret(int *i)
272 {
273 return (++(*i));
274 }
275 #endif
276
277
278 #endif /* __KFUSD_H__ */
279
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.