]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sys/filedesc.h
This commit was generated by cvs2svn to compensate for changes in r141098,
[FreeBSD/FreeBSD.git] / sys / sys / filedesc.h
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  * 4. 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/queue.h>
37 #include <sys/event.h>
38 #include <sys/priority.h>
39 #include <sys/_lock.h>
40 #include <sys/_mutex.h>
41
42 #include <machine/_limits.h>
43
44 /*
45  * This structure is used for the management of descriptors.  It may be
46  * shared by multiple processes.
47  */
48 #define NDSLOTTYPE      u_long
49
50 struct filedesc {
51         struct  file **fd_ofiles;       /* file structures for open files */
52         char    *fd_ofileflags;         /* per-process open file flags */
53         struct  vnode *fd_cdir;         /* current directory */
54         struct  vnode *fd_rdir;         /* root directory */
55         struct  vnode *fd_jdir;         /* jail root directory */
56         int     fd_nfiles;              /* number of open files allocated */
57         NDSLOTTYPE *fd_map;             /* bitmap of free fds */
58         int     fd_lastfile;            /* high-water mark of fd_ofiles */
59         int     fd_freefile;            /* approx. next free file */
60         u_short fd_cmask;               /* mask for file creation */
61         u_short fd_refcnt;              /* thread reference count */
62         u_short fd_holdcnt;             /* hold count on structure + mutex */
63
64         struct  mtx fd_mtx;             /* protects members of this struct */
65         int     fd_locked;              /* long lock flag */
66         int     fd_wanted;              /* "" */
67         struct  kqlist fd_kqlist;       /* list of kqueues on this filedesc */
68         int     fd_holdleaderscount;    /* block fdfree() for shared close() */
69         int     fd_holdleaderswakeup;   /* fdfree() needs wakeup */
70 };
71
72 /*
73  * Structure to keep track of (process leader, struct fildedesc) tuples.
74  * Each process has a pointer to such a structure when detailed tracking
75  * is needed, e.g., when rfork(RFPROC | RFMEM) causes a file descriptor
76  * table to be shared by processes having different "p_leader" pointers
77  * and thus distinct POSIX style locks.
78  *
79  * fdl_refcount and fdl_holdcount are protected by struct filedesc mtx.
80  */
81 struct filedesc_to_leader {
82         int             fdl_refcount;   /* references from struct proc */
83         int             fdl_holdcount;  /* temporary hold during closef */
84         int             fdl_wakeup;     /* fdfree() waits on closef() */
85         struct proc     *fdl_leader;    /* owner of POSIX locks */
86         /* Circular list: */
87         struct filedesc_to_leader *fdl_prev;
88         struct filedesc_to_leader *fdl_next;
89 };
90
91 /*
92  * Per-process open flags.
93  */
94 #define UF_EXCLOSE      0x01            /* auto-close on exec */
95
96 #ifdef _KERNEL
97
98 /* Lock a file descriptor table. */
99 #define FILEDESC_LOCK(fd)                                                               \
100         do {                                                                            \
101                 mtx_lock(&(fd)->fd_mtx);                                                \
102                 (fd)->fd_wanted++;                                                      \
103                 while ((fd)->fd_locked)                                                 \
104                         msleep(&(fd)->fd_locked, &(fd)->fd_mtx, PLOCK, "fdesc", 0);     \
105                 (fd)->fd_locked = 2;                                                    \
106                 (fd)->fd_wanted--;                                                      \
107                 mtx_unlock(&(fd)->fd_mtx);                                              \
108         } while (0);
109
110 #define FILEDESC_UNLOCK(fd)                                                             \
111         do {                                                                            \
112                 mtx_lock(&(fd)->fd_mtx);                                                \
113                 KASSERT((fd)->fd_locked == 2,                                           \
114                     ("fdesc locking mistake %d should be %d", (fd)->fd_locked, 2));     \
115                 (fd)->fd_locked = 0;                                                    \
116                 if ((fd)->fd_wanted)                                                    \
117                         wakeup(&(fd)->fd_locked);                                       \
118                 mtx_unlock(&(fd)->fd_mtx);                                              \
119         } while (0);
120
121 #define FILEDESC_LOCK_FAST(fd)                                                          \
122         do {                                                                            \
123                 mtx_lock(&(fd)->fd_mtx);                                                \
124                 (fd)->fd_wanted++;                                                      \
125                 while ((fd)->fd_locked)                                                 \
126                         msleep(&(fd)->fd_locked, &(fd)->fd_mtx, PLOCK, "fdesc", 0);     \
127                 (fd)->fd_locked = 1;                                                    \
128                 (fd)->fd_wanted--;                                                      \
129         } while (0);
130
131 #define FILEDESC_UNLOCK_FAST(fd)                                                        \
132         do {                                                                            \
133                 KASSERT((fd)->fd_locked == 1,                                           \
134                     ("fdesc locking mistake %d should be %d", (fd)->fd_locked, 1));     \
135                 (fd)->fd_locked = 0;                                                    \
136                 if ((fd)->fd_wanted)                                                    \
137                         wakeup(&(fd)->fd_locked);                                       \
138                 mtx_unlock(&(fd)->fd_mtx);                                              \
139         } while (0);
140
141 #ifdef INVARIANT_SUPPORT
142 #define FILEDESC_LOCK_ASSERT(fd, arg)                                                   \
143         do {                                                                            \
144                 if ((arg) == MA_OWNED)                                                  \
145                         KASSERT((fd)->fd_locked != 0, ("fdesc locking mistake"));       \
146                 else                                                                    \
147                         KASSERT((fd)->fd_locked == 0, ("fdesc locking mistake"));       \
148         } while (0);
149 #else
150 #define FILEDESC_LOCK_ASSERT(fd, arg)
151 #endif
152
153 #define FILEDESC_LOCK_DESC      "filedesc structure"
154
155 struct thread;
156
157 int     closef(struct file *fp, struct thread *td);
158 int     dupfdopen(struct thread *td, struct filedesc *fdp, int indx, int dfd,
159             int mode, int error);
160 int     falloc(struct thread *td, struct file **resultfp, int *resultfd);
161 int     fdalloc(struct thread *td, int minfd, int *result);
162 int     fdavail(struct thread *td, int n);
163 int     fdcheckstd(struct thread *td);
164 void    fdclose(struct filedesc *fdp, struct file *fp, int idx, struct thread *td);
165 void    fdcloseexec(struct thread *td);
166 struct  filedesc *fdcopy(struct filedesc *fdp);
167 void    fdunshare(struct proc *p, struct thread *td);
168 void    fdfree(struct thread *td);
169 struct  filedesc *fdinit(struct filedesc *fdp);
170 struct  filedesc *fdshare(struct filedesc *fdp);
171 void    fdused(struct filedesc *fdp, int fd);
172 struct filedesc_to_leader *
173         filedesc_to_leader_alloc(struct filedesc_to_leader *old,
174             struct filedesc *fdp, struct proc *leader);
175 int     getvnode(struct filedesc *fdp, int fd, struct file **fpp);
176 void    mountcheckdirs(struct vnode *olddp, struct vnode *newdp);
177 void    setugidsafety(struct thread *td);
178
179 static __inline struct file *
180 fget_locked(struct filedesc *fdp, int fd)
181 {
182
183         return (fd < 0 || fd >= fdp->fd_nfiles ? NULL : fdp->fd_ofiles[fd]);
184 }
185
186 #endif /* _KERNEL */
187
188 #endif /* !_SYS_FILEDESC_H_ */