xref: /freebsd/share/man/man9/make_dev.9 (revision c48ca725a83c0c8b27210d50977835c0b916bf07)
1.\"
2.\" SPDX-License-Identifier: BSD-2-Clause
3.\"
4.\" Copyright (c) 1999 Chris Costello
5.\" All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\"    notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\"    notice, this list of conditions and the following disclaimer in the
14.\"    documentation and/or other materials provided with the distribution.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.Dd January 19, 2025
29.Dt MAKE_DEV 9
30.Os
31.Sh NAME
32.Nm make_dev ,
33.Nm make_dev_cred ,
34.Nm make_dev_credf ,
35.Nm make_dev_p ,
36.Nm make_dev_s ,
37.Nm make_dev_alias ,
38.Nm make_dev_alias_p ,
39.Nm destroy_dev ,
40.Nm destroy_dev_sched ,
41.Nm destroy_dev_sched_cb ,
42.Nm destroy_dev_drain ,
43.Nm dev_depends
44.Nd create and destroy character devices including devfs registration
45.Sh SYNOPSIS
46.In sys/param.h
47.In sys/conf.h
48.Ft void
49.Fn make_dev_args_init "struct make_dev_args *args"
50.Ft int
51.Fn make_dev_s "struct make_dev_args *args" "struct cdev **cdev" "const char *fmt" ...
52.Ft int
53.Fn make_dev_alias_p "int flags" "struct cdev **cdev" "struct cdev *pdev" "const char *fmt" ...
54.Ft void
55.Fn destroy_dev "struct cdev *dev"
56.Ft void
57.Fn destroy_dev_sched "struct cdev *dev"
58.Ft void
59.Fn destroy_dev_sched_cb "struct cdev *dev" "void (*cb)(void *)" "void *arg"
60.Ft void
61.Fn destroy_dev_drain "struct cdevsw *csw"
62.Ft void
63.Fn dev_depends "struct cdev *pdev" "struct cdev *cdev"
64.Pp
65LEGACY INTERFACES
66.Ft struct cdev *
67.Fn make_dev "struct cdevsw *cdevsw" "int unit" "uid_t uid" "gid_t gid" "int perms" "const char *fmt" ...
68.Ft struct cdev *
69.Fn make_dev_cred "struct cdevsw *cdevsw" "int unit" "struct ucred *cr" "uid_t uid" "gid_t gid" "int perms" "const char *fmt" ...
70.Ft struct cdev *
71.Fn make_dev_credf "int flags" "struct cdevsw *cdevsw" "int unit" "struct ucred *cr" "uid_t uid" "gid_t gid" "int perms" "const char *fmt" ...
72.Ft int
73.Fn make_dev_p "int flags" "struct cdev **cdev" "struct cdevsw *devsw" "struct ucred *cr" "uid_t uid" "gid_t gid" "int mode" "const char *fmt" ...
74.Ft struct cdev *
75.Fn make_dev_alias "struct cdev *pdev" "const char *fmt" ...
76.Sh DESCRIPTION
77The
78.Fn make_dev_s
79function creates a
80.Fa cdev
81structure for a new device, which is returned into the
82.Fa cdev
83argument.
84It also notifies
85.Xr devfs 4
86of the presence of the new device, that causes corresponding nodes
87to be created.
88Besides this, a
89.Xr devctl 4
90notification is sent.
91The function takes the structure
92.Va struct make_dev_args args ,
93which specifies the parameters for the device creation:
94.Pp
95.Bd -literal -offset indent -compact
96struct make_dev_args {
97	size_t		 mda_size;
98	int		 mda_flags;
99	struct cdevsw	*mda_devsw;
100	struct ucred	*mda_cr;
101	uid_t		 mda_uid;
102	gid_t		 mda_gid;
103	int		 mda_mode;
104	int		 mda_unit;
105	void		*mda_si_drv1;
106	void		*mda_si_drv2;
107};
108.Ed
109.Pp
110Before use and filling with the desired values, the structure must be
111initialized by the
112.Fn make_dev_args_init
113function, which ensures that future kernel interface expansion does
114not affect driver source code or binary interface.
115.Pp
116The created device will be owned by
117.Va args.mda_uid ,
118with the group ownership as
119.Va args.mda_gid .
120The name is the expansion of
121.Va fmt
122and following arguments as
123.Xr printf 9
124would print it.
125The name determines its path under
126.Pa /dev
127or other
128.Xr devfs 4
129mount point and may contain slash
130.Ql /
131characters to denote subdirectories.
132The permissions of the file specified in
133.Va args.mda_mode
134are defined in
135.In sys/stat.h :
136.Pp
137.Bd -literal -offset indent -compact
138#define S_IRWXU 0000700    /* RWX mask for owner */
139#define S_IRUSR 0000400    /* R for owner */
140#define S_IWUSR 0000200    /* W for owner */
141#define S_IXUSR 0000100    /* X for owner */
142
143#define S_IRWXG 0000070    /* RWX mask for group */
144#define S_IRGRP 0000040    /* R for group */
145#define S_IWGRP 0000020    /* W for group */
146#define S_IXGRP 0000010    /* X for group */
147
148#define S_IRWXO 0000007    /* RWX mask for other */
149#define S_IROTH 0000004    /* R for other */
150#define S_IWOTH 0000002    /* W for other */
151#define S_IXOTH 0000001    /* X for other */
152
153#define S_ISUID 0004000    /* set user id on execution */
154#define S_ISGID 0002000    /* set group id on execution */
155#define S_ISVTX 0001000    /* sticky bit */
156#ifndef _POSIX_SOURCE
157#define S_ISTXT 0001000
158#endif
159.Ed
160.Pp
161The
162.Va args.mda_cr
163argument specifies credentials that will be stored in the
164.Fa si_cred
165member of the initialized
166.Fa struct cdev .
167.Pp
168The
169.Va args.mda_flags
170argument alters the operation of
171.Fn make_dev_s .
172The following values are currently accepted:
173.Pp
174.Bl -tag -width "MAKEDEV_CHECKNAME" -compact -offset indent
175.It Dv MAKEDEV_REF
176reference the created device
177.It Dv MAKEDEV_NOWAIT
178do not sleep, the call may fail
179.It Dv MAKEDEV_WAITOK
180allow the function to sleep to satisfy malloc
181.It Dv MAKEDEV_ETERNAL
182created device will be never destroyed
183.It Dv MAKEDEV_CHECKNAME
184return an error if the device name is invalid or already exists
185.El
186.Pp
187Only
188.Dv MAKEDEV_NOWAIT ,
189.Dv MAKEDEV_WAITOK
190and
191.Dv MAKEDEV_CHECKNAME
192values are accepted for the
193.Fn make_dev_alias_p
194function.
195.Pp
196The
197.Dv MAKEDEV_WAITOK
198flag is assumed if none of
199.Dv MAKEDEV_WAITOK ,
200.Dv MAKEDEV_NOWAIT
201is specified.
202.Pp
203The
204.Xr dev_clone 9
205event handler shall specify the
206.Dv MAKEDEV_REF
207flag when creating a device in response to lookup, to avoid a race where
208the created device is immediately destroyed after
209.Fn devfs_lookup
210drops its reference to
211.Fa cdev .
212.Pp
213The
214.Dv MAKEDEV_ETERNAL
215flag allows the kernel to not acquire some locks when translating system
216calls into the cdevsw methods calls.
217It is responsibility of the driver author to make sure that
218.Fn destroy_dev
219is never called on the returned cdev.
220For the convenience, use the
221.Dv MAKEDEV_ETERNAL_KLD
222flag for the code that can be compiled into kernel or loaded
223(and unloaded) as loadable module.
224.Pp
225A panic will occur if the
226.Dv MAKEDEV_CHECKNAME
227flag is not specified
228and the device name is invalid or already exists.
229.Pp
230The
231.Fn make_dev_p
232use of the form:
233.Bd -literal -offset indent
234struct cdev *dev;
235int res;
236res = make_dev_p(flags, &dev, cdevsw, cred, uid, gid, perms, name);
237.Ed
238.Pp
239is equivalent to the code:
240.Bd -literal -offset indent
241struct cdev *dev;
242struct make_dev_args args;
243int res;
244
245make_dev_args_init(&args);
246args.mda_flags = flags;
247args.mda_devsw = cdevsw;
248args.mda_cr = cred;
249args.mda_uid = uid;
250args.mda_gid = gid;
251args.mda_mode = perms;
252res = make_dev_s(&args, &dev, name);
253.Ed
254.Pp
255Similarly, the
256.Fn make_dev_credf
257function call is equivalent to:
258.Bd -literal -offset indent
259(void) make_dev_s(&args, &dev, name);
260.Ed
261.Pp
262In other words,
263.Fn make_dev_credf
264does not allow the caller to obtain the return value, and in
265kernels compiled with the
266.Va INVARIANTS
267options, the function asserts that the device creation succeeded.
268.Pp
269The
270.Fn make_dev_cred
271function is equivalent to the call:
272.Bd -literal -offset indent
273make_dev_credf(0, cdevsw, unit, cr, uid, gid, perms, fmt, ...);
274.Ed
275.Pp
276The
277.Fn make_dev
278function call is the same as:
279.Bd -literal -offset indent
280make_dev_credf(0, cdevsw, unit, NULL, uid, gid, perms, fmt, ...);
281.Ed
282.Pp
283The
284.Fn make_dev_alias_p
285function takes the returned
286.Ft cdev
287from
288.Fn make_dev
289and makes another (aliased) name for this device.
290It is an error to call
291.Fn make_dev_alias_p
292prior to calling
293.Fn make_dev .
294.Pp
295The
296.Fn make_dev_alias
297function is similar to
298.Fn make_dev_alias_p
299but it returns the resulting aliasing
300.Ft *cdev
301and may not return an error.
302.Pp
303The
304.Fa cdev
305returned by
306.Fn make_dev_s
307and
308.Fn make_dev_alias_p
309has two fields,
310.Fa si_drv1
311and
312.Fa si_drv2 ,
313that are available to store state.
314Both fields are of type
315.Ft void * ,
316and can be initialized simultaneously with the
317.Va cdev
318allocation by filling
319.Va args.mda_si_drv1
320and
321.Va args.mda_si_drv2
322members of the
323.Fn make_dev_s
324argument structure, or filled after the
325.Va cdev
326is allocated, if using legacy interfaces.
327In the latter case, the driver should handle the race of
328accessing uninitialized
329.Va si_drv1
330and
331.Va si_drv2
332itself.
333These are designed to replace the
334.Fa unit
335argument to
336.Fn make_dev ,
337which can be obtained with
338.Fn dev2unit .
339.Pp
340The
341.Fn destroy_dev
342function takes the returned
343.Fa cdev
344from
345.Fn make_dev
346and destroys the registration for that device.
347The notification is sent to
348.Xr devctl 4
349about the destruction event.
350Do not call
351.Fn destroy_dev
352on devices that were created with
353.Fn make_dev_alias .
354.Pp
355The
356.Fn dev_depends
357function establishes a parent-child relationship between two devices.
358The net effect is that a
359.Fn destroy_dev
360of the parent device will also result in the destruction of the
361child device(s),
362if any exist.
363A device may simultaneously be a parent and a child,
364so it is possible to build a complete hierarchy.
365.Pp
366The
367.Fn destroy_dev_sched_cb
368function schedules execution of the
369.Fn destroy_dev
370for the specified
371.Fa cdev
372in the safe context.
373After
374.Fn destroy_dev
375is finished, and if the supplied
376.Fa cb
377is not
378.Dv NULL ,
379the callback
380.Fa cb
381is called, with argument
382.Fa arg .
383The
384.Fn destroy_dev_sched
385function is the same as:
386.Bd -literal -offset indent
387destroy_dev_sched_cb(cdev, NULL, NULL);
388.Ed
389.Pp
390The
391.Fn d_close
392driver method cannot call
393.Fn destroy_dev
394directly.
395Doing so causes deadlock when
396.Fn destroy_dev
397waits for all threads to leave the driver methods.
398Also, because
399.Fn destroy_dev
400sleeps, no non-sleepable locks may be held over the call.
401The
402.Fn destroy_dev_sched
403family of functions overcome these issues.
404.Pp
405The device driver may call the
406.Fn destroy_dev_drain
407function to wait until all devices that have supplied
408.Fa csw
409as cdevsw, are destroyed.
410This is useful when driver knows that
411.Fn destroy_dev_sched
412is called for all instantiated devices, but need to postpone module
413unload until
414.Fn destroy_dev
415is actually finished for all of them.
416.Sh RETURN VALUES
417If successful,
418.Fn make_dev_s
419and
420.Fn make_dev_p
421will return 0, otherwise they will return an error.
422If successful,
423.Fn make_dev_credf
424will return a valid
425.Fa cdev
426pointer, otherwise it will return
427.Dv NULL .
428.Sh ERRORS
429The
430.Fn make_dev_s ,
431.Fn make_dev_p
432and
433.Fn make_dev_alias_p
434calls will fail and the device will be not registered if:
435.Bl -tag -width Er
436.It Bq Er ENOMEM
437The
438.Dv MAKEDEV_NOWAIT
439flag was specified and a memory allocation request could not be satisfied.
440.It Bq Er ENAMETOOLONG
441The
442.Dv MAKEDEV_CHECKNAME
443flag was specified and the provided device name is longer than
444.Dv SPECNAMELEN .
445.It Bq Er EINVAL
446The
447.Dv MAKEDEV_CHECKNAME
448flag was specified and the provided device name is empty, contains a
449.Qq \&.
450or
451.Qq ..
452path component or ends with
453.Ql / .
454.It Bq Er EINVAL
455The
456.Dv MAKEDEV_CHECKNAME
457flag was specified and the provided device name contains invalid characters.
458.It Bq Er EEXIST
459The
460.Dv MAKEDEV_CHECKNAME
461flag was specified and the provided device name already exists.
462.El
463.Sh SEE ALSO
464.Xr devctl 4 ,
465.Xr devfs 4 ,
466.Xr dev_clone 9
467.Sh HISTORY
468The
469.Fn make_dev
470and
471.Fn destroy_dev
472functions first appeared in
473.Fx 4.0 .
474The function
475.Fn make_dev_alias
476first appeared in
477.Fx 4.1 .
478The function
479.Fn dev_depends
480first appeared in
481.Fx 5.0 .
482The functions
483.Fn make_dev_credf ,
484.Fn destroy_dev_sched ,
485.Fn destroy_dev_sched_cb
486first appeared in
487.Fx 7.0 .
488The function
489.Fn make_dev_p
490first appeared in
491.Fx 8.2 .
492The function
493.Fn make_dev_s
494first appeared in
495.Fx 11.0 .
496