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 struct filedesc_to_leader * 172 filedesc_to_leader_alloc(struct filedesc_to_leader *old, 173 struct filedesc *fdp, struct proc *leader); 174 int getvnode(struct filedesc *fdp, int fd, struct file **fpp); 175 void mountcheckdirs(struct vnode *olddp, struct vnode *newdp); 176 void setugidsafety(struct thread *td); 177 178 static __inline struct file * 179 fget_locked(struct filedesc *fdp, int fd) 180 { 181 182 return (fd < 0 || fd >= fdp->fd_nfiles ? NULL : fdp->fd_ofiles[fd]); 183 } 184 185 #endif /* _KERNEL */ 186 187 #endif /* !_SYS_FILEDESC_H_ */ 188