aboutsummaryrefslogtreecommitdiff
path: root/sys/sys/filedesc.h
blob: ef784f7ebaac73d3cc0e34c9d6d9c7ad2ec0be80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*	$OpenBSD: filedesc.h,v 1.44 2020/01/30 15:33:04 visa Exp $	*/
/*	$NetBSD: filedesc.h,v 1.14 1996/04/09 20:55:28 cgd Exp $	*/

/*
 * Copyright (c) 1990, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)filedesc.h	8.1 (Berkeley) 6/2/93
 */

#include <sys/mutex.h>
#include <sys/rwlock.h>
/*
 * This structure is used for the management of descriptors.  It may be
 * shared by multiple processes.
 *
 * A process is initially started out with NDFILE descriptors stored within
 * this structure, selected to be enough for typical applications based on
 * the historical limit of 20 open files (and the usage of descriptors by
 * shells).  If these descriptors are exhausted, a larger descriptor table
 * may be allocated, up to a process' resource limit; the internal arrays
 * are then unused.  The initial expansion is set to NDEXTENT; each time
 * it runs out, it is doubled until the resource limit is reached. NDEXTENT
 * should be selected to be the biggest multiple of OFILESIZE (see below)
 * that will fit in a power-of-two sized piece of memory.
 */
#define NDFILE		20
#define NDEXTENT	50		/* 250 bytes in 256-byte alloc. */
#define NDENTRIES	32		/* 32 fds per entry */
#define NDENTRYMASK	(NDENTRIES - 1)
#define NDENTRYSHIFT	5		/* bits per entry */
#define NDREDUCE(x)	(((x) + NDENTRIES - 1) >> NDENTRYSHIFT)
#define NDHISLOTS(x)	(NDREDUCE(NDREDUCE(x)))
#define NDLOSLOTS(x)	(NDHISLOTS(x) << NDENTRYSHIFT)

struct kqueue;

/*
 * Locking:
 *	a	atomic operations
 *	f	fd_lock
 *	f/w	fd_lock when writing
 *	k	kernel lock
 *	m	fd_fplock
 */
struct filedesc {
	struct	file **fd_ofiles;	/* [f/w,m] file structures for
					 *     open files */
	char	*fd_ofileflags;		/* [f] per-process open file flags */
	struct	vnode *fd_cdir;		/* [k] current directory */
	struct	vnode *fd_rdir;		/* [k] root directory */
	int	fd_nfiles;		/* [f] number of open files allocated */
	int	fd_openfd;		/* [f] number of files currently open */
	u_int	*fd_himap;		/* [f] each bit points to 32 fds */
	u_int	*fd_lomap;		/* [f] bitmap of free fds */
	int	fd_lastfile;		/* [f] high-water mark of fd_ofiles */
	int	fd_freefile;		/* [f] approx. next free file */
	u_short	fd_cmask;		/* [f/w] mask for file creation */
	u_short	fd_refcnt;		/* [k] reference count */
	struct rwlock fd_lock;		/* lock for the file descs */
	struct mutex fd_fplock;		/* lock for reading fd_ofiles without
					 * fd_lock */
	LIST_HEAD(, kqueue) fd_kqlist;	/* [f] kqueues attached to this
					 *     filedesc */
	int fd_flags;			/* [a] flags on this filedesc */
};

/*
 * Basic allocation of descriptors:
 * one of the above, plus arrays for NDFILE descriptors.
 */
struct filedesc0 {
	struct	filedesc fd_fd;
	/*
	 * These arrays are used when the number of open files is
	 * <= NDFILE, and are then pointed to by the pointers above.
	 */
	struct	file *fd_dfiles[NDFILE];
	char	fd_dfileflags[NDFILE];
	/*
	 * There arrays are used when the number of open files is
	 * <= 1024, and are then pointed to by the pointers above.
	 */
	u_int   fd_dhimap[NDENTRIES >> NDENTRYSHIFT];
	u_int   fd_dlomap[NDENTRIES];
};

/*
 * Per-process open flags.
 */
#define	UF_EXCLOSE 	0x01		/* auto-close on exec */
#define	UF_PLEDGED 	0x02		/* open after pledge(2) */

/*
 * Flags on the file descriptor table.
 */
#define FD_ADVLOCK	0x01		/* May hold a POSIX adv. lock. */

/*
 * Storage required per open file descriptor.
 */
#define OFILESIZE (sizeof(struct file *) + sizeof(char))

#ifdef _KERNEL
/*
 * Kernel global variables and routines.
 */
void	filedesc_init(void);
int	dupfdopen(struct proc *, int, int);
int	fdalloc(struct proc *p, int want, int *result);
void	fdexpand(struct proc *);
struct	file *fnew(struct proc *_p);
int	falloc(struct proc *_p, struct file **_rfp, int *_rfd);
struct	filedesc *fdinit(void);
struct	filedesc *fdshare(struct process *);
struct	filedesc *fdcopy(struct process *);
void	fdfree(struct proc *p);
int	fdrelease(struct proc *p, int);
void	fdinsert(struct filedesc *, int, int, struct file *);
void	fdremove(struct filedesc *, int);
void	fdcloseexec(struct proc *);
struct file *fd_iterfile(struct file *, struct proc *);
struct file *fd_getfile(struct filedesc *, int);
struct file *fd_getfile_mode(struct filedesc *, int, int);
int	fd_checkclosed(struct filedesc *, int, struct file *);

int	closef(struct file *, struct proc *);
int	getsock(struct proc *, int, struct file **);

#define	fdplock(fdp)	do { NET_ASSERT_UNLOCKED(); rw_enter_write(&(fdp)->fd_lock); } while (0)
#define	fdpunlock(fdp)	rw_exit_write(&(fdp)->fd_lock)
#define	fdpassertlocked(fdp)	rw_assert_wrlock(&(fdp)->fd_lock)
#endif