source: rtems-libbsd/freebsd/sys/sys/filedesc.h @ 72d5fa1

55-freebsd-126-freebsd-12
Last change on this file since 72d5fa1 was 72d5fa1, checked in by Sebastian Huber <sebastian.huber@…>, on 11/10/17 at 10:01:39

Fix reference counting for file descriptors

Update #3132.

  • Property mode set to 100644
File size: 10.6 KB
Line 
1/*-
2 * Copyright (c) 1990, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *      @(#)filedesc.h  8.1 (Berkeley) 6/2/93
30 * $FreeBSD$
31 */
32
33#ifndef _SYS_FILEDESC_H_
34#define _SYS_FILEDESC_H_
35
36#include <sys/caprights.h>
37#include <sys/queue.h>
38#include <sys/event.h>
39#include <sys/lock.h>
40#include <sys/priority.h>
41#include <sys/seq.h>
42#include <sys/sx.h>
43
44#include <machine/_limits.h>
45
46struct filecaps {
47        cap_rights_t     fc_rights;     /* per-descriptor capability rights */
48        u_long          *fc_ioctls;     /* per-descriptor allowed ioctls */
49        int16_t          fc_nioctls;    /* fc_ioctls array size */
50        uint32_t         fc_fcntls;     /* per-descriptor allowed fcntls */
51};
52
53struct filedescent {
54        struct file     *fde_file;      /* file structure for open file */
55        struct filecaps  fde_caps;      /* per-descriptor rights */
56        uint8_t          fde_flags;     /* per-process open file flags */
57        seq_t            fde_seq;       /* keep file and caps in sync */
58};
59#define fde_rights      fde_caps.fc_rights
60#define fde_fcntls      fde_caps.fc_fcntls
61#define fde_ioctls      fde_caps.fc_ioctls
62#define fde_nioctls     fde_caps.fc_nioctls
63#define fde_change_size (offsetof(struct filedescent, fde_seq))
64
65struct fdescenttbl {
66        int     fdt_nfiles;             /* number of open files allocated */
67        struct  filedescent fdt_ofiles[0];      /* open files */
68};
69#define fd_seq(fdt, fd) (&(fdt)->fdt_ofiles[(fd)].fde_seq)
70
71/*
72 * This structure is used for the management of descriptors.  It may be
73 * shared by multiple processes.
74 */
75#define NDSLOTTYPE      u_long
76
77#ifndef __rtems__
78struct filedesc {
79        struct  fdescenttbl *fd_files;  /* open files table */
80        struct  vnode *fd_cdir;         /* current directory */
81        struct  vnode *fd_rdir;         /* root directory */
82        struct  vnode *fd_jdir;         /* jail root directory */
83        NDSLOTTYPE *fd_map;             /* bitmap of free fds */
84        int     fd_lastfile;            /* high-water mark of fd_ofiles */
85        int     fd_freefile;            /* approx. next free file */
86        u_short fd_cmask;               /* mask for file creation */
87        int     fd_refcnt;              /* thread reference count */
88        int     fd_holdcnt;             /* hold count on structure + mutex */
89        struct  sx fd_sx;               /* protects members of this struct */
90        struct  kqlist fd_kqlist;       /* list of kqueues on this filedesc */
91        int     fd_holdleaderscount;    /* block fdfree() for shared close() */
92        int     fd_holdleaderswakeup;   /* fdfree() needs wakeup */
93};
94#else /* __rtems__ */
95struct filedesc;
96#endif /* __rtems__ */
97
98/*
99 * Structure to keep track of (process leader, struct fildedesc) tuples.
100 * Each process has a pointer to such a structure when detailed tracking
101 * is needed, e.g., when rfork(RFPROC | RFMEM) causes a file descriptor
102 * table to be shared by processes having different "p_leader" pointers
103 * and thus distinct POSIX style locks.
104 *
105 * fdl_refcount and fdl_holdcount are protected by struct filedesc mtx.
106 */
107#ifndef __rtems__
108struct filedesc_to_leader {
109        int             fdl_refcount;   /* references from struct proc */
110        int             fdl_holdcount;  /* temporary hold during closef */
111        int             fdl_wakeup;     /* fdfree() waits on closef() */
112        struct proc     *fdl_leader;    /* owner of POSIX locks */
113        /* Circular list: */
114        struct filedesc_to_leader *fdl_prev;
115        struct filedesc_to_leader *fdl_next;
116};
117#define fd_nfiles       fd_files->fdt_nfiles
118#define fd_ofiles       fd_files->fdt_ofiles
119#else /* __rtems__ */
120struct filedesc_to_leader;
121#endif /* __rtems__ */
122
123/*
124 * Per-process open flags.
125 */
126#define UF_EXCLOSE      0x01            /* auto-close on exec */
127
128#ifdef _KERNEL
129#ifdef __rtems__
130#include <sys/file.h>
131#include <rtems/libio_.h>
132#endif /* __rtems__ */
133
134/* Lock a file descriptor table. */
135#define FILEDESC_LOCK_INIT(fdp) sx_init(&(fdp)->fd_sx, "filedesc structure")
136#define FILEDESC_LOCK_DESTROY(fdp)      sx_destroy(&(fdp)->fd_sx)
137#define FILEDESC_LOCK(fdp)      (&(fdp)->fd_sx)
138#ifndef __rtems__
139#define FILEDESC_XLOCK(fdp)     sx_xlock(&(fdp)->fd_sx)
140#define FILEDESC_XUNLOCK(fdp)   sx_xunlock(&(fdp)->fd_sx)
141#define FILEDESC_SLOCK(fdp)     sx_slock(&(fdp)->fd_sx)
142#define FILEDESC_SUNLOCK(fdp)   sx_sunlock(&(fdp)->fd_sx)
143#else /* __rtems__ */
144#define FILEDESC_XLOCK(fdp)     do { } while (0)
145#define FILEDESC_XUNLOCK(fdp)   do { } while (0)
146#define FILEDESC_SLOCK(fdp)     do { } while (0)
147#define FILEDESC_SUNLOCK(fdp)   do { } while (0)
148#endif /* __rtems__ */
149
150#define FILEDESC_LOCK_ASSERT(fdp)       sx_assert(&(fdp)->fd_sx, SX_LOCKED | \
151                                            SX_NOTRECURSED)
152#define FILEDESC_XLOCK_ASSERT(fdp)      sx_assert(&(fdp)->fd_sx, SX_XLOCKED | \
153                                            SX_NOTRECURSED)
154#define FILEDESC_UNLOCK_ASSERT(fdp)     sx_assert(&(fdp)->fd_sx, SX_UNLOCKED)
155
156/* Operation types for kern_dup(). */
157enum {
158        FDDUP_NORMAL,           /* dup() behavior. */
159        FDDUP_FCNTL,            /* fcntl()-style errors. */
160        FDDUP_FIXED,            /* Force fixed allocation. */
161        FDDUP_MUSTREPLACE,      /* Target must exist. */
162        FDDUP_LASTMODE,
163};
164
165/* Flags for kern_dup(). */
166#define FDDUP_FLAG_CLOEXEC      0x1     /* Atomically set UF_EXCLOSE. */
167
168/* For backward compatibility. */
169#define falloc(td, resultfp, resultfd, flags) \
170        falloc_caps(td, resultfp, resultfd, flags, NULL)
171
172struct thread;
173
174void    filecaps_init(struct filecaps *fcaps);
175int     filecaps_copy(const struct filecaps *src, struct filecaps *dst,
176            bool locked);
177void    filecaps_move(struct filecaps *src, struct filecaps *dst);
178#ifndef __rtems__
179void    filecaps_free(struct filecaps *fcaps);
180#else /* __rtems__ */
181#define filecaps_free(fcaps) do { } while (0)
182#endif /* __rtems__ */
183
184int     closef(struct file *fp, struct thread *td);
185int     dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
186            int openerror, int *indxp);
187#ifndef __rtems__
188int     falloc_caps(struct thread *td, struct file **resultfp, int *resultfd,
189            int flags, struct filecaps *fcaps);
190#else /* __rtems__ */
191static inline int
192falloc_caps(struct thread *td, struct file **resultfp, int *resultfd,
193    int flags, struct filecaps *fcaps)
194{
195        rtems_libio_t *iop;
196
197        (void)td;
198        (void)flags;
199        (void)fcaps;
200
201        iop = rtems_libio_allocate();
202        *resultfp = rtems_bsd_iop_to_fp(iop);
203
204        if (iop != NULL) {
205                iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
206                rtems_filesystem_location_add_to_mt_entry(&iop->pathinfo);
207                *resultfd = rtems_libio_iop_to_descriptor(iop);
208                return (0);
209        } else {
210                return (ENFILE);
211        }
212}
213#endif /* __rtems__ */
214int     falloc_noinstall(struct thread *td, struct file **resultfp);
215void    _finstall(struct filedesc *fdp, struct file *fp, int fd, int flags,
216            struct filecaps *fcaps);
217int     finstall(struct thread *td, struct file *fp, int *resultfd, int flags,
218            struct filecaps *fcaps);
219int     fdalloc(struct thread *td, int minfd, int *result);
220int     fdallocn(struct thread *td, int minfd, int *fds, int n);
221int     fdcheckstd(struct thread *td);
222#ifndef __rtems__
223void    fdclose(struct thread *td, struct file *fp, int idx);
224#else /* __rtems__ */
225/*
226 * WARNING: Use of fdrop() after fclose() corrupts the file descriptor.  See
227 * fdrop() comment.
228 */
229static inline void
230fdclose(struct thread *td, struct file *fp, int idx)
231{
232        (void)td;
233        (void)idx;
234
235        rtems_libio_free(&fp->f_io);
236}
237#endif /* __rtems__ */
238void    fdcloseexec(struct thread *td);
239void    fdsetugidsafety(struct thread *td);
240struct  filedesc *fdcopy(struct filedesc *fdp);
241int     fdcopy_remapped(struct filedesc *fdp, const int *fds, size_t nfds,
242            struct filedesc **newfdp);
243void    fdinstall_remapped(struct thread *td, struct filedesc *fdp);
244void    fdunshare(struct thread *td);
245void    fdescfree(struct thread *td);
246void    fdescfree_remapped(struct filedesc *fdp);
247struct  filedesc *fdinit(struct filedesc *fdp, bool prepfiles);
248struct  filedesc *fdshare(struct filedesc *fdp);
249struct filedesc_to_leader *
250        filedesc_to_leader_alloc(struct filedesc_to_leader *old,
251            struct filedesc *fdp, struct proc *leader);
252int     getvnode(struct thread *td, int fd, cap_rights_t *rightsp,
253            struct file **fpp);
254void    mountcheckdirs(struct vnode *olddp, struct vnode *newdp);
255
256int     fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
257            struct file **fpp, struct filecaps *havecapsp);
258int     fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
259            struct file **fpp, struct filecaps *havecapsp);
260
261/* Return a referenced file from an unlocked descriptor. */
262#ifndef __rtems__
263int     fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
264            struct file **fpp, seq_t *seqp);
265#else /* __rtems__ */
266static inline int
267fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
268    struct file **fpp, seq_t *seqp)
269{
270        struct file *fp;
271
272        (void)fdp;
273        (void)needrightsp;
274        (void)seqp;
275        fp = rtems_bsd_get_file(fd);
276        *fpp = fp;
277        return (fp != NULL ? 0 : EBADF);
278}
279#endif /* __rtems__ */
280
281#ifndef __rtems__
282/* Requires a FILEDESC_{S,X}LOCK held and returns without a ref. */
283static __inline struct file *
284fget_locked(struct filedesc *fdp, int fd)
285{
286
287        FILEDESC_LOCK_ASSERT(fdp);
288
289        if (fd < 0 || fd > fdp->fd_lastfile)
290                return (NULL);
291
292        return (fdp->fd_ofiles[fd].fde_file);
293}
294
295static __inline struct filedescent *
296fdeget_locked(struct filedesc *fdp, int fd)
297{
298        struct filedescent *fde;
299
300        FILEDESC_LOCK_ASSERT(fdp);
301
302        if (fd < 0 || fd > fdp->fd_lastfile)
303                return (NULL);
304
305        fde = &fdp->fd_ofiles[fd];
306        if (fde->fde_file == NULL)
307                return (NULL);
308
309        return (fde);
310}
311
312#ifdef CAPABILITIES
313static __inline bool
314fd_modified(struct filedesc *fdp, int fd, seq_t seq)
315{
316
317        return (!seq_consistent(fd_seq(fdp->fd_files, fd), seq));
318}
319#endif
320#endif /* __rtems__ */
321
322/* cdir/rdir/jdir manipulation functions. */
323void    pwd_chdir(struct thread *td, struct vnode *vp);
324int     pwd_chroot(struct thread *td, struct vnode *vp);
325void    pwd_ensure_dirs(void);
326
327#endif /* _KERNEL */
328
329#endif /* !_SYS_FILEDESC_H_ */
Note: See TracBrowser for help on using the repository browser.