aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt2008-04-22 18:08:23 -0500
committerEric Anholt2008-04-23 12:42:06 -0500
commit47a2b7dc03e35d4eaf8148b87aeea8dd96723b4d (patch)
tree09df677e70bf9e9cce1fbd603f8134cacc4a5e58
parentc82894034f611696c54c5aaf2112be638aa2cb35 (diff)
downloadexternal-libgbm-47a2b7dc03e35d4eaf8148b87aeea8dd96723b4d.tar.gz
external-libgbm-47a2b7dc03e35d4eaf8148b87aeea8dd96723b4d.tar.xz
external-libgbm-47a2b7dc03e35d4eaf8148b87aeea8dd96723b4d.zip
Initial add of mmfs module.
-rw-r--r--.gitignore1
-rw-r--r--linux-core/Makefile3
-rw-r--r--linux-core/Makefile.kernel3
-rw-r--r--linux-core/mmfs.h176
-rw-r--r--linux-core/mmfs_drv.c299
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/mmfs_basic.c68
7 files changed, 551 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore
index 0991da8c..fe64a289 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,6 +58,7 @@ tests/getclient
58tests/getstats 58tests/getstats
59tests/getversion 59tests/getversion
60tests/lock 60tests/lock
61tests/mmfs_basic
61tests/openclose 62tests/openclose
62tests/setversion 63tests/setversion
63tests/updatedraw 64tests/updatedraw
diff --git a/linux-core/Makefile b/linux-core/Makefile
index 3af6f370..f2d44642 100644
--- a/linux-core/Makefile
+++ b/linux-core/Makefile
@@ -58,7 +58,7 @@ endif
58 58
59# Modules for all architectures 59# Modules for all architectures
60MODULE_LIST := drm.o tdfx.o r128.o radeon.o mga.o sis.o savage.o via.o \ 60MODULE_LIST := drm.o tdfx.o r128.o radeon.o mga.o sis.o savage.o via.o \
61 mach64.o nv.o nouveau.o xgi.o 61 mach64.o nv.o nouveau.o xgi.o mmfs.o
62 62
63# Modules only for ix86 architectures 63# Modules only for ix86 architectures
64ifneq (,$(findstring 86,$(MACHINE))) 64ifneq (,$(findstring 86,$(MACHINE)))
@@ -92,6 +92,7 @@ NVHEADERS = nv_drv.h $(DRMHEADERS)
92FFBHEADERS = ffb_drv.h $(DRMHEADERS) 92FFBHEADERS = ffb_drv.h $(DRMHEADERS)
93NOUVEAUHEADERS = nouveau_drv.h nouveau_drm.h nouveau_reg.h $(DRMHEADERS) 93NOUVEAUHEADERS = nouveau_drv.h nouveau_drm.h nouveau_reg.h $(DRMHEADERS)
94XGIHEADERS = xgi_cmdlist.h xgi_drv.h xgi_misc.h xgi_regs.h $(DRMHEADERS) 94XGIHEADERS = xgi_cmdlist.h xgi_drv.h xgi_misc.h xgi_regs.h $(DRMHEADERS)
95MMFSHEADERS = mmfs.h mmfs_priv.h
95 96
96PROGS = dristat drmstat 97PROGS = dristat drmstat
97 98
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index f012262d..093552bf 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -41,6 +41,7 @@ mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o
41nv-objs := nv_drv.o 41nv-objs := nv_drv.o
42xgi-objs := xgi_cmdlist.o xgi_drv.o xgi_fb.o xgi_misc.o xgi_pcie.o \ 42xgi-objs := xgi_cmdlist.o xgi_drv.o xgi_fb.o xgi_misc.o xgi_pcie.o \
43 xgi_fence.o 43 xgi_fence.o
44mmfs-objs := mmfs_drv.o
44 45
45ifeq ($(CONFIG_COMPAT),y) 46ifeq ($(CONFIG_COMPAT),y)
46drm-objs += drm_ioc32.o 47drm-objs += drm_ioc32.o
@@ -52,7 +53,7 @@ nouveau-objs += nouveau_ioc32.o
52xgi-objs += xgi_ioc32.o 53xgi-objs += xgi_ioc32.o
53endif 54endif
54 55
55obj-m += drm.o 56obj-m += drm.o mmfs.o
56obj-$(CONFIG_DRM_TDFX) += tdfx.o 57obj-$(CONFIG_DRM_TDFX) += tdfx.o
57obj-$(CONFIG_DRM_R128) += r128.o 58obj-$(CONFIG_DRM_R128) += r128.o
58obj-$(CONFIG_DRM_RADEON)+= radeon.o 59obj-$(CONFIG_DRM_RADEON)+= radeon.o
diff --git a/linux-core/mmfs.h b/linux-core/mmfs.h
new file mode 100644
index 00000000..bdc148b9
--- /dev/null
+++ b/linux-core/mmfs.h
@@ -0,0 +1,176 @@
1/*
2 * Copyright © 2008 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 *
26 */
27
28/** @file mmfs.h
29 * This file provides ioctl and ioctl argument definitions for using the
30 * mmfs device.
31 */
32#ifdef __KERNEL__
33#include <linux/spinlock.h>
34#include <linux/idr.h>
35
36/** @file mmfs_priv.h
37 * This file provides internal structure definitions for mmfs..
38 */
39
40/**
41 * This structure defines the mmfs memory object, which will be used by the
42 * DRM for its buffer objects.
43 */
44struct mmfs_object {
45 /** File representing the shmem storage */
46 struct file *filp;
47
48 spinlock_t lock;
49
50 size_t size;
51 /** Reference count of this object, protected by object_lock */
52 int refcount;
53};
54
55/**
56 * This structure defines the process (actually per-fd) mapping of object
57 * handles to mmfs objects.
58 */
59struct mmfs_file {
60 /** Mapping of object handles to object pointers. */
61 struct idr object_idr;
62 /**
63 * Lock for synchronization of access to object->refcount and
64 * object_idr. See note in mmfs_unreference_ioctl.
65 */
66 spinlock_t delete_lock;
67};
68
69void mmfs_object_reference(struct mmfs_object *obj);
70void mmfs_object_unreference(struct mmfs_object *obj);
71
72#endif /* __KERNEL__ */
73
74#define MMFS_DEVICE_PATH "/dev/mmfs"
75/* XXX: Choose non-experimental major */
76#define MMFS_DEVICE_MAJOR 246
77
78struct mmfs_alloc_args {
79 /**
80 * Requested size for the object.
81 *
82 * The (page-aligned) allocated size for the object will be returned.
83 */
84 uint32_t size;
85 /** Returned handle for the object. */
86 uint32_t handle;
87};
88
89struct mmfs_unreference_args {
90 /** Handle of the object to be unreferenced. */
91 uint32_t handle;
92};
93
94struct mmfs_link_args {
95 /** Handle for the object being given a name. */
96 uint32_t handle;
97 /** Requested file name to export the object under. */
98 char *name;
99 /** Requested file mode to export the object under. */
100 mode_t mode;
101};
102
103struct mmfs_pread_args {
104 /** Handle for the object being read. */
105 uint32_t handle;
106 /** Offset into the object to read from */
107 off_t offset;
108 /** Length of data to read */
109 size_t size;
110 /** Pointer to write the data into. */
111 void *data;
112};
113
114struct mmfs_pwrite_args {
115 /** Handle for the object being written to. */
116 uint32_t handle;
117 /** Offset into the object to write to */
118 off_t offset;
119 /** Length of data to write */
120 size_t size;
121 /** Pointer to read the data from. */
122 void *data;
123};
124
125struct mmfs_mmap_args {
126 /** Handle for the object being mapped. */
127 uint32_t handle;
128 /** Offset in the object to map. */
129 off_t offset;
130 /**
131 * Length of data to map.
132 *
133 * The value will be page-aligned.
134 */
135 size_t size;
136 /** Returned pointer the data was mapped at */
137 void *addr;
138};
139
140/**
141 * \name Ioctls Definitions
142 */
143/* @{ */
144
145#define MMFS_IOCTL_BASE 'm'
146#define MMFS_IO(nr) _IO(MMFS_IOCTL_BASE, nr)
147#define MMFS_IOR(nr,type) _IOR(MMFS_IOCTL_BASE, nr, type)
148#define MMFS_IOW(nr,type) _IOW(MMFS_IOCTL_BASE, nr, type)
149#define MMFS_IOWR(nr,type) _IOWR(MMFS_IOCTL_BASE, nr, type)
150
151/** This ioctl allocates an object and returns a handle referencing it. */
152#define MMFS_IOCTL_ALLOC MMFS_IOWR(0x00, struct mmfs_alloc_args)
153
154/**
155 * This ioctl releases the reference on the handle returned from
156 * MMFS_IOCTL_ALLOC.
157 */
158#define MMFS_IOCTL_UNREFERENCE MMFS_IOR(0x01, struct mmfs_unreference_args)
159
160/**
161 * This ioctl creates a file in the mmfs filesystem representing an object.
162 *
163 * XXX: Need a way to get handle from fd or name.
164 */
165#define MMFS_IOCTL_LINK MMFS_IOWR(0x02, struct mmfs_link_args)
166
167/** This ioctl copies data from an object into a user address. */
168#define MMFS_IOCTL_PREAD MMFS_IOWR(0x03, struct mmfs_pread_args)
169
170/** This ioctl copies data from a user address into an object. */
171#define MMFS_IOCTL_PWRITE MMFS_IOWR(0x04, struct mmfs_pwrite_args)
172
173/** This ioctl maps data from the object into the user address space. */
174#define MMFS_IOCTL_MMAP MMFS_IOWR(0x05, struct mmfs_mmap_args)
175
176/* }@ */
diff --git a/linux-core/mmfs_drv.c b/linux-core/mmfs_drv.c
new file mode 100644
index 00000000..f4b07117
--- /dev/null
+++ b/linux-core/mmfs_drv.c
@@ -0,0 +1,299 @@
1/*
2 * Copyright © 2008 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 *
26 */
27
28#include <linux/types.h>
29#include <linux/slab.h>
30#include <linux/mm.h>
31#include <linux/uaccess.h>
32#include <linux/fs.h>
33#include <linux/file.h>
34#include <linux/module.h>
35#include "mmfs.h"
36
37/** @file mmfs.c
38 *
39 * This file provides the filesystem for memory manager objects used by the
40 * DRM.
41 *
42 * The goal is to have swap-backed object allocation managed through
43 * struct file. However, file descriptors as handles to a struct file have
44 * two major failings:
45 * - Process limits prevent more than 1024 or so being used at a time by
46 * default.
47 * - Inability to allocate high fds will aggravate the X Server's select()
48 * handling, and likely that of many GL client applications as well.
49 *
50 * This led to a plan of using our own integer IDs (called handles, following
51 * DRM terminology) to mimic fds, and implement the fd syscalls we need as
52 * ioctls. The objects themselves will still include the struct file so
53 * that we can transition to fds if the required kernel infrastructure shows
54 * up at a later data, and as our interface with shmfs for memory allocation.
55 */
56
57static struct mmfs_object *
58mmfs_object_alloc(size_t size)
59{
60 struct mmfs_object *obj;
61
62 BUG_ON((size & (PAGE_SIZE - 1)) != 0);
63
64 obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
65
66 obj->filp = shmem_file_setup("mmfs object", size, 0);
67 if (IS_ERR(obj->filp)) {
68 kfree(obj);
69 return NULL;
70 }
71
72 obj->refcount = 1;
73
74 return obj;
75}
76
77/**
78 * Removes the mapping from handle to filp for this object.
79 */
80static int
81mmfs_handle_delete(struct mmfs_file *mmfs_filp, int handle)
82{
83 struct mmfs_object *obj;
84
85 /* This is gross. The idr system doesn't let us try a delete and
86 * return an error code. It just spews if you fail at deleting.
87 * So, we have to grab a lock around finding the object and then
88 * doing the delete on it and dropping the refcount, or the user
89 * could race us to double-decrement the refcount and cause a
90 * use-after-free later. Given the frequency of our handle lookups,
91 * we may want to use ida for number allocation and a hash table
92 * for the pointers, anyway.
93 */
94 spin_lock(&mmfs_filp->delete_lock);
95
96 /* Check if we currently have a reference on the object */
97 obj = idr_find(&mmfs_filp->object_idr, handle);
98 if (obj == NULL) {
99 spin_unlock(&mmfs_filp->delete_lock);
100 return -EINVAL;
101 }
102
103 /* Release reference and decrement refcount. */
104 idr_remove(&mmfs_filp->object_idr, handle);
105 mmfs_object_unreference(obj);
106
107 spin_unlock(&mmfs_filp->delete_lock);
108
109 return 0;
110}
111
112/**
113 * Allocates a new mmfs object and returns a handle to it.
114 */
115static int
116mmfs_alloc_ioctl(struct inode *inode, struct file *filp,
117 unsigned int cmd, unsigned long arg)
118{
119 struct mmfs_file *mmfs_filp = filp->private_data;
120 struct mmfs_alloc_args args;
121 struct mmfs_object *obj;
122 int handle, ret;
123
124 if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
125 return -EFAULT;
126
127 /* Round requested size up to page size */
128 args.size = (args.size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
129
130 /* Allocate the new object */
131 obj = mmfs_object_alloc(args.size);
132 if (obj == NULL)
133 return -ENOMEM;
134
135 /* Get the user-visible handle using idr.
136 *
137 * I'm not really sure why the idr api needs us to do this in two
138 * repeating steps. It handles internal locking of its data
139 * structure, yet insists that we keep its memory allocation step
140 * separate from its slot-finding step for locking purposes.
141 */
142 do {
143 if (idr_pre_get(&mmfs_filp->object_idr, GFP_KERNEL) == 0) {
144 kfree(obj);
145 return -EFAULT;
146 }
147
148 ret = idr_get_new(&mmfs_filp->object_idr, obj, &handle);
149 } while (ret == -EAGAIN);
150
151 if (ret != 0) {
152 mmfs_object_unreference(obj);
153 return -EFAULT;
154 }
155
156 args.handle = handle;
157
158 if (copy_to_user((void __user *)arg, &args, sizeof(args))) {
159 mmfs_handle_delete(mmfs_filp, args.handle);
160 return -EFAULT;
161 }
162
163 return 0;
164}
165
166/**
167 * Allocates a new mmfs object and returns a handle to it.
168 */
169static int
170mmfs_unreference_ioctl(struct inode *inode, struct file *filp,
171 unsigned int cmd, unsigned long arg)
172{
173 struct mmfs_file *mmfs_filp = filp->private_data;
174 struct mmfs_unreference_args args;
175 int ret;
176
177 if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
178 return -EFAULT;
179
180 ret = mmfs_handle_delete(mmfs_filp, args.handle);
181
182 return ret;
183}
184
185static int
186mmfs_ioctl(struct inode *inode, struct file *filp,
187 unsigned int cmd, unsigned long arg)
188{
189
190 switch (cmd) {
191 case MMFS_IOCTL_ALLOC:
192 return mmfs_alloc_ioctl(inode, filp, cmd, arg);
193 case MMFS_IOCTL_UNREFERENCE:
194 return mmfs_unreference_ioctl(inode, filp, cmd, arg);
195 default:
196 return -EINVAL;
197 }
198}
199
200/**
201 * Sets up the file private for keeping track of our mappings of handles to
202 * mmfs objects.
203 */
204int
205mmfs_open(struct inode *inode, struct file *filp)
206{
207 struct mmfs_file *mmfs_filp;
208
209 if (filp->f_flags & O_EXCL)
210 return -EBUSY; /* No exclusive opens */
211
212 mmfs_filp = kcalloc(1, sizeof(*mmfs_filp), GFP_KERNEL);
213 if (mmfs_filp == NULL)
214 return -ENOMEM;
215 filp->private_data = mmfs_filp;
216
217 idr_init(&mmfs_filp->object_idr);
218
219 return 0;
220}
221
222/** Called at device close to release the file's references on objects. */
223static int
224mmfs_object_release(int id, void *ptr, void *data)
225{
226 struct mmfs_object *obj = ptr;
227
228 mmfs_object_unreference(obj);
229
230 return 0;
231}
232
233/**
234 * Called at close time when the filp is going away.
235 *
236 * Releases any remaining references on objects by this filp.
237 */
238int
239mmfs_close(struct inode *inode, struct file *filp)
240{
241 struct mmfs_file *mmfs_filp = filp->private_data;
242
243 idr_for_each(&mmfs_filp->object_idr, &mmfs_object_release, NULL);
244
245 idr_destroy(&mmfs_filp->object_idr);
246
247 kfree(mmfs_filp);
248 filp->private_data = NULL;
249
250 return 0;
251}
252
253void
254mmfs_object_reference(struct mmfs_object *obj)
255{
256 spin_lock(&obj->lock);
257 obj->refcount++;
258 spin_unlock(&obj->lock);
259}
260
261void
262mmfs_object_unreference(struct mmfs_object *obj)
263{
264 spin_lock(&obj->lock);
265 obj->refcount--;
266 spin_unlock(&obj->lock);
267 if (obj->refcount == 0) {
268 fput(obj->filp);
269 kfree(obj);
270 }
271}
272
273/** File operations structure */
274static const struct file_operations mmfs_dev_fops = {
275 .owner = THIS_MODULE,
276 .open = mmfs_open,
277 .release = mmfs_close,
278 .ioctl = mmfs_ioctl,
279};
280
281static int __init mmfs_init(void)
282{
283 int ret;
284
285 ret = register_chrdev(MMFS_DEVICE_MAJOR, "mmfs", &mmfs_dev_fops);
286 if (ret != 0)
287 return ret;
288
289 return 0;
290}
291
292static void __exit mmfs_exit(void)
293{
294 unregister_chrdev(MMFS_DEVICE_MAJOR, "mmfs");
295}
296
297module_init(mmfs_init);
298module_exit(mmfs_exit);
299MODULE_LICENSE("GPL and additional rights");
diff --git a/tests/Makefile.am b/tests/Makefile.am
index dce1754e..4a7b0119 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,4 +1,5 @@
1AM_CFLAGS = \ 1AM_CFLAGS = \
2 -I $(top_srcdir)/linux-core \
2 -I $(top_srcdir)/shared-core \ 3 -I $(top_srcdir)/shared-core \
3 -I $(top_srcdir)/libdrm 4 -I $(top_srcdir)/libdrm
4 5
@@ -22,7 +23,8 @@ TESTS = auth \
22 getstats \ 23 getstats \
23 lock \ 24 lock \
24 setversion \ 25 setversion \
25 updatedraw 26 updatedraw \
27 mmfs_basic
26 28
27EXTRA_PROGRAMS = $(TESTS) 29EXTRA_PROGRAMS = $(TESTS)
28CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES) 30CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES)
diff --git a/tests/mmfs_basic.c b/tests/mmfs_basic.c
new file mode 100644
index 00000000..907dc585
--- /dev/null
+++ b/tests/mmfs_basic.c
@@ -0,0 +1,68 @@
1/*
2 * Copyright © 2008 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 *
26 */
27
28#include <stdlib.h>
29#include <stdio.h>
30#include <assert.h>
31#include <fcntl.h>
32#include <inttypes.h>
33#include <sys/stat.h>
34#include "mmfs.h"
35
36static void
37create_mmfs_device()
38{
39 struct stat sb;
40 int ret;
41
42 ret = stat(MMFS_DEVICE_PATH, &sb);
43
44 if (ret == 0)
45 return;
46
47 ret = mknod(MMFS_DEVICE_PATH, S_IFCHR | S_IRUSR | S_IWUSR,
48 makedev(MMFS_DEVICE_MAJOR, 0));
49
50 if (ret != 0)
51 errx(1, "mknod()");
52}
53
54
55int main(int argc, char **argv)
56{
57 int fd;
58
59 create_mmfs_device();
60
61 fd = open(MMFS_DEVICE_PATH, O_RDWR);
62 if (fd == -1)
63 errx(1, "open()");
64
65 close(fd);
66
67 return 0;
68}