Document all functions, global and static variables, and sysctls.
Includes some minor whitespace changes, and re-ordering to be able to document properly (e.g, grouping of variables and the SYSCTL macro calls for them, where the documentation has been added.) Reviewed by: phk (but all errors are mine)
This commit is contained in:
parent
6f60771b6d
commit
eb8e6d5276
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=91690
@ -57,6 +57,10 @@
|
||||
|
||||
#include "opt_vfs_aio.h"
|
||||
|
||||
/*
|
||||
* Counter for allocating reference ids to new jobs. Wrapped to 1 on
|
||||
* overflow.
|
||||
*/
|
||||
static long jobrefid;
|
||||
|
||||
#define JOBST_NULL 0x0
|
||||
@ -98,59 +102,68 @@ static long jobrefid;
|
||||
#define AIOD_LIFETIME_DEFAULT (30 * hz)
|
||||
#endif
|
||||
|
||||
SYSCTL_NODE(_vfs, OID_AUTO, aio, CTLFLAG_RW, 0, "Async IO management");
|
||||
|
||||
static int max_aio_procs = MAX_AIO_PROCS;
|
||||
static int num_aio_procs = 0;
|
||||
static int target_aio_procs = TARGET_AIO_PROCS;
|
||||
static int max_queue_count = MAX_AIO_QUEUE;
|
||||
static int num_queue_count = 0;
|
||||
static int num_buf_aio = 0;
|
||||
static int num_aio_resv_start = 0;
|
||||
static int aiod_timeout;
|
||||
static int aiod_lifetime;
|
||||
static int unloadable = 0;
|
||||
|
||||
static int max_aio_per_proc = MAX_AIO_PER_PROC;
|
||||
static int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC;
|
||||
static int max_buf_aio = MAX_BUF_AIO;
|
||||
|
||||
SYSCTL_NODE(_vfs, OID_AUTO, aio, CTLFLAG_RW, 0, "AIO mgmt");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc,
|
||||
CTLFLAG_RW, &max_aio_per_proc, 0, "");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue_per_proc,
|
||||
CTLFLAG_RW, &max_aio_queue_per_proc, 0, "");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_procs,
|
||||
CTLFLAG_RW, &max_aio_procs, 0, "");
|
||||
CTLFLAG_RW, &max_aio_procs, 0,
|
||||
"Maximum number of kernel threads to use for handling async IO ");
|
||||
|
||||
static int num_aio_procs = 0;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, num_aio_procs,
|
||||
CTLFLAG_RD, &num_aio_procs, 0, "");
|
||||
CTLFLAG_RD, &num_aio_procs, 0,
|
||||
"Number of presently active kernel threads for async IO");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, num_queue_count,
|
||||
CTLFLAG_RD, &num_queue_count, 0, "");
|
||||
/*
|
||||
* The code will adjust the actual number of AIO processes towards this
|
||||
* number when it gets a chance.
|
||||
*/
|
||||
static int target_aio_procs = TARGET_AIO_PROCS;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, target_aio_procs, CTLFLAG_RW, &target_aio_procs,
|
||||
0, "Preferred number of ready kernel threads for async IO");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue,
|
||||
CTLFLAG_RW, &max_queue_count, 0, "");
|
||||
static int max_queue_count = MAX_AIO_QUEUE;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue, CTLFLAG_RW, &max_queue_count, 0,
|
||||
"Maximum number of aio requests to queue, globally");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, target_aio_procs,
|
||||
CTLFLAG_RW, &target_aio_procs, 0, "");
|
||||
static int num_queue_count = 0;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, num_queue_count, CTLFLAG_RD, &num_queue_count, 0,
|
||||
"Number of queued aio requests");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_buf_aio,
|
||||
CTLFLAG_RW, &max_buf_aio, 0, "");
|
||||
static int num_buf_aio = 0;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, num_buf_aio, CTLFLAG_RD, &num_buf_aio, 0,
|
||||
"Number of aio requests presently handled by the buf subsystem");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, num_buf_aio,
|
||||
CTLFLAG_RD, &num_buf_aio, 0, "");
|
||||
/* Number of async I/O thread in the process of being started */
|
||||
/* XXX This should be local to _aio_aqueue() */
|
||||
static int num_aio_resv_start = 0;
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime,
|
||||
CTLFLAG_RW, &aiod_lifetime, 0, "");
|
||||
static int aiod_timeout;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_timeout, CTLFLAG_RW, &aiod_timeout, 0,
|
||||
"Timeout value for synchronous aio operations");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_timeout,
|
||||
CTLFLAG_RW, &aiod_timeout, 0, "");
|
||||
static int aiod_lifetime;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime, CTLFLAG_RW, &aiod_lifetime, 0,
|
||||
"Maximum lifetime for idle aiod");
|
||||
|
||||
static int unloadable = 0;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, unloadable, CTLFLAG_RW, &unloadable, 0,
|
||||
"Allow unload of aio (not recommended)");
|
||||
|
||||
|
||||
static int max_aio_per_proc = MAX_AIO_PER_PROC;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc, CTLFLAG_RW, &max_aio_per_proc,
|
||||
0, "Maximum active aio requests per process (stored in the process)");
|
||||
|
||||
static int max_aio_queue_per_proc = MAX_AIO_QUEUE_PER_PROC;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue_per_proc, CTLFLAG_RW,
|
||||
&max_aio_queue_per_proc, 0,
|
||||
"Maximum queued aio requests per process (stored in the process)");
|
||||
|
||||
static int max_buf_aio = MAX_BUF_AIO;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_buf_aio, CTLFLAG_RW, &max_buf_aio, 0,
|
||||
"Maximum buf aio requests per process (stored in the process)");
|
||||
|
||||
struct aiocblist {
|
||||
TAILQ_ENTRY(aiocblist) list; /* List of jobs */
|
||||
TAILQ_ENTRY(aiocblist) plist; /* List of jobs for proc */
|
||||
@ -227,7 +240,8 @@ struct kaioinfo {
|
||||
#define KAIO_RUNDOWN 0x1 /* process is being run down */
|
||||
#define KAIO_WAKEUP 0x2 /* wakeup process when there is a significant event */
|
||||
|
||||
static TAILQ_HEAD(,aiothreadlist) aio_freeproc, aio_activeproc;
|
||||
static TAILQ_HEAD(,aiothreadlist) aio_activeproc; /* Active daemons */
|
||||
static TAILQ_HEAD(,aiothreadlist) aio_freeproc; /* Idle daemons */
|
||||
static TAILQ_HEAD(,aiocblist) aio_jobs; /* Async job list */
|
||||
static TAILQ_HEAD(,aiocblist) aio_bufjobs; /* Phys I/O job list */
|
||||
|
||||
@ -249,12 +263,23 @@ static int filt_aioattach(struct knote *kn);
|
||||
static void filt_aiodetach(struct knote *kn);
|
||||
static int filt_aio(struct knote *kn, long hint);
|
||||
|
||||
static vm_zone_t kaio_zone, aiop_zone, aiocb_zone, aiol_zone;
|
||||
static vm_zone_t aiolio_zone;
|
||||
/*
|
||||
* Zones for:
|
||||
* kaio Per process async io info
|
||||
* aiop async io thread data
|
||||
* aiocb async io jobs
|
||||
* aiol list io job pointer - internal to aio_suspend XXX
|
||||
* aiolio list io jobs
|
||||
*/
|
||||
static vm_zone_t kaio_zone, aiop_zone, aiocb_zone, aiol_zone, aiolio_zone;
|
||||
|
||||
/* kqueue filters for aio */
|
||||
static struct filterops aio_filtops =
|
||||
{ 0, filt_aioattach, filt_aiodetach, filt_aio };
|
||||
|
||||
/*
|
||||
* Main operations function for use as a kernel module.
|
||||
*/
|
||||
static int
|
||||
aio_modload(struct module *module, int cmd, void *arg)
|
||||
{
|
||||
@ -321,6 +346,9 @@ aio_onceonly(void)
|
||||
jobrefid = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for unload of AIO when used as a module.
|
||||
*/
|
||||
static int
|
||||
aio_unload(void)
|
||||
{
|
||||
@ -784,8 +812,10 @@ aio_daemon(void *uproc)
|
||||
mycp->p_fd = NULL;
|
||||
|
||||
/* The daemon resides in its own pgrp. */
|
||||
MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
|
||||
MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
|
||||
MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
|
||||
M_WAITOK | M_ZERO);
|
||||
MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
PGRPSESS_XLOCK();
|
||||
enterpgrp(mycp, mycp->p_pid, newpgrp, newsess);
|
||||
@ -1931,6 +1961,7 @@ aio_error(struct thread *td, struct aio_error_args *uap)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* syscall - asynchronous read from a file (REALTIME) */
|
||||
int
|
||||
aio_read(struct thread *td, struct aio_read_args *uap)
|
||||
{
|
||||
@ -1938,6 +1969,7 @@ aio_read(struct thread *td, struct aio_read_args *uap)
|
||||
return aio_aqueue(td, uap->aiocbp, LIO_READ);
|
||||
}
|
||||
|
||||
/* syscall - asynchronous write to a file (REALTIME) */
|
||||
int
|
||||
aio_write(struct thread *td, struct aio_write_args *uap)
|
||||
{
|
||||
@ -1945,6 +1977,7 @@ aio_write(struct thread *td, struct aio_write_args *uap)
|
||||
return aio_aqueue(td, uap->aiocbp, LIO_WRITE);
|
||||
}
|
||||
|
||||
/* syscall - XXX undocumented */
|
||||
int
|
||||
lio_listio(struct thread *td, struct lio_listio_args *uap)
|
||||
{
|
||||
@ -2210,6 +2243,7 @@ aio_physwakeup(struct buf *bp)
|
||||
}
|
||||
}
|
||||
|
||||
/* syscall - wait for the next completion of an aio request */
|
||||
int
|
||||
aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap)
|
||||
{
|
||||
@ -2285,6 +2319,7 @@ aio_waitcomplete(struct thread *td, struct aio_waitcomplete_args *uap)
|
||||
}
|
||||
}
|
||||
|
||||
/* kqueue attach function */
|
||||
static int
|
||||
filt_aioattach(struct knote *kn)
|
||||
{
|
||||
@ -2304,6 +2339,7 @@ filt_aioattach(struct knote *kn)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* kqueue detach function */
|
||||
static void
|
||||
filt_aiodetach(struct knote *kn)
|
||||
{
|
||||
@ -2312,6 +2348,7 @@ filt_aiodetach(struct knote *kn)
|
||||
SLIST_REMOVE(&aiocbe->klist, kn, knote, kn_selnext);
|
||||
}
|
||||
|
||||
/* kqueue filter function */
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
filt_aio(struct knote *kn, long hint)
|
||||
|
@ -63,6 +63,10 @@ struct buf_ops buf_ops_bio = {
|
||||
bwrite
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX buf is global because kern_shutdown.c and ffs_checkoverlap has
|
||||
* carnal knowledge of buffers. This knowledge should be moved to vfs_bio.c.
|
||||
*/
|
||||
struct buf *buf; /* buffer header pool */
|
||||
struct swqueue bswlist;
|
||||
struct mtx buftimelock; /* Interlock on setting prio and timo */
|
||||
@ -78,10 +82,82 @@ static void vfs_setdirty(struct buf *bp);
|
||||
static void vfs_vmio_release(struct buf *bp);
|
||||
static void vfs_backgroundwritedone(struct buf *bp);
|
||||
static int flushbufqueues(void);
|
||||
static void buf_daemon __P((void));
|
||||
|
||||
int vmiodirenable = TRUE;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, vmiodirenable, CTLFLAG_RW, &vmiodirenable, 0,
|
||||
"Use the VM system for directory writes");
|
||||
int runningbufspace;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, runningbufspace, CTLFLAG_RD, &runningbufspace, 0,
|
||||
"Amount of presently outstanding async buffer io");
|
||||
static int bufspace;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, bufspace, CTLFLAG_RD, &bufspace, 0,
|
||||
"KVA memory used for bufs");
|
||||
static int maxbufspace;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, maxbufspace, CTLFLAG_RD, &maxbufspace, 0,
|
||||
"Maximum allowed value of bufspace (including buf_daemon)");
|
||||
static int bufmallocspace;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, bufmallocspace, CTLFLAG_RD, &bufmallocspace, 0,
|
||||
"Amount of malloced memory for buffers");
|
||||
static int maxbufmallocspace;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, maxmallocbufspace, CTLFLAG_RW, &maxbufmallocspace, 0,
|
||||
"Maximum amount of malloced memory for buffers");
|
||||
static int lobufspace;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, lobufspace, CTLFLAG_RD, &lobufspace, 0,
|
||||
"Minimum amount of buffers we want to have");
|
||||
static int hibufspace;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, hibufspace, CTLFLAG_RD, &hibufspace, 0,
|
||||
"Maximum allowed value of bufspace (excluding buf_daemon)");
|
||||
static int bufreusecnt;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, bufreusecnt, CTLFLAG_RW, &bufreusecnt, 0,
|
||||
"Number of times we have reused a buffer");
|
||||
static int buffreekvacnt;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, buffreekvacnt, CTLFLAG_RW, &buffreekvacnt, 0,
|
||||
"Number of times we have freed the KVA space from some buffer");
|
||||
static int bufdefragcnt;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, bufdefragcnt, CTLFLAG_RW, &bufdefragcnt, 0,
|
||||
"Number of times we have had to repeat buffer allocation to defragment");
|
||||
static int lorunningspace;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, lorunningspace, CTLFLAG_RW, &lorunningspace, 0,
|
||||
"Minimum preferred space used for in-progress I/O");
|
||||
static int hirunningspace;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, hirunningspace, CTLFLAG_RW, &hirunningspace, 0,
|
||||
"Maximum amount of space to use for in-progress I/O");
|
||||
static int numdirtybuffers;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, numdirtybuffers, CTLFLAG_RD, &numdirtybuffers, 0,
|
||||
"Number of buffers that are dirty (has unwritten changes) at the moment");
|
||||
static int lodirtybuffers;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, lodirtybuffers, CTLFLAG_RW, &lodirtybuffers, 0,
|
||||
"How many buffers we want to have free before bufdaemon can sleep");
|
||||
static int hidirtybuffers;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, hidirtybuffers, CTLFLAG_RW, &hidirtybuffers, 0,
|
||||
"When the number of dirty buffers is considered severe");
|
||||
static int numfreebuffers;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, numfreebuffers, CTLFLAG_RD, &numfreebuffers, 0,
|
||||
"Number of free buffers");
|
||||
static int lofreebuffers;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, lofreebuffers, CTLFLAG_RW, &lofreebuffers, 0,
|
||||
"XXX Unused");
|
||||
static int hifreebuffers;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, hifreebuffers, CTLFLAG_RW, &hifreebuffers, 0,
|
||||
"XXX Complicatedly unused");
|
||||
static int getnewbufcalls;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, getnewbufcalls, CTLFLAG_RW, &getnewbufcalls, 0,
|
||||
"Number of calls to getnewbuf");
|
||||
static int getnewbufrestarts;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, getnewbufrestarts, CTLFLAG_RW, &getnewbufrestarts, 0,
|
||||
"Number of times getnewbuf has had to restart a buffer aquisition");
|
||||
static int dobkgrdwrite = 1;
|
||||
SYSCTL_INT(_debug, OID_AUTO, dobkgrdwrite, CTLFLAG_RW, &dobkgrdwrite, 0,
|
||||
"Do background writes (honoring the BX_BKGRDWRITE flag)?");
|
||||
|
||||
/*
|
||||
* Wakeup point for bufdaemon, as well as indicator of whether it is already
|
||||
* active. Set to 1 when the bufdaemon is already "on" the queue, 0 when it
|
||||
* is idling.
|
||||
*/
|
||||
static int bd_request;
|
||||
|
||||
static void buf_daemon __P((void));
|
||||
/*
|
||||
* bogus page -- for I/O to/from partially complete buffers
|
||||
* this is a temporary solution to the problem, but it is not
|
||||
@ -90,69 +166,54 @@ static void buf_daemon __P((void));
|
||||
* but the code is intricate enough already.
|
||||
*/
|
||||
vm_page_t bogus_page;
|
||||
int vmiodirenable = TRUE;
|
||||
int runningbufspace;
|
||||
|
||||
/*
|
||||
* Offset for bogus_page.
|
||||
* XXX bogus_offset should be local to bufinit
|
||||
*/
|
||||
static vm_offset_t bogus_offset;
|
||||
|
||||
static int bufspace, maxbufspace,
|
||||
bufmallocspace, maxbufmallocspace, lobufspace, hibufspace;
|
||||
static int bufreusecnt, bufdefragcnt, buffreekvacnt;
|
||||
/*
|
||||
* Synchronization (sleep/wakeup) variable for active buffer space requests.
|
||||
* Set when wait starts, cleared prior to wakeup().
|
||||
* Used in runningbufwakeup() and waitrunningbufspace().
|
||||
*/
|
||||
static int runningbufreq;
|
||||
|
||||
/*
|
||||
* Synchronization (sleep/wakeup) variable for buffer requests.
|
||||
* Can contain the VFS_BIO_NEED flags defined below; setting/clearing is done
|
||||
* by and/or.
|
||||
* Used in numdirtywakeup(), bufspacewakeup(), bufcountwakeup(), bwillwrite(),
|
||||
* getnewbuf(), and getblk().
|
||||
*/
|
||||
static int needsbuffer;
|
||||
static int lorunningspace, hirunningspace, runningbufreq;
|
||||
static int numdirtybuffers, lodirtybuffers, hidirtybuffers;
|
||||
static int numfreebuffers, lofreebuffers, hifreebuffers;
|
||||
static int getnewbufcalls;
|
||||
static int getnewbufrestarts;
|
||||
|
||||
SYSCTL_INT(_vfs, OID_AUTO, numdirtybuffers, CTLFLAG_RD,
|
||||
&numdirtybuffers, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, lodirtybuffers, CTLFLAG_RW,
|
||||
&lodirtybuffers, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, hidirtybuffers, CTLFLAG_RW,
|
||||
&hidirtybuffers, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, numfreebuffers, CTLFLAG_RD,
|
||||
&numfreebuffers, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, lofreebuffers, CTLFLAG_RW,
|
||||
&lofreebuffers, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, hifreebuffers, CTLFLAG_RW,
|
||||
&hifreebuffers, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, runningbufspace, CTLFLAG_RD,
|
||||
&runningbufspace, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, lorunningspace, CTLFLAG_RW,
|
||||
&lorunningspace, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, hirunningspace, CTLFLAG_RW,
|
||||
&hirunningspace, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, maxbufspace, CTLFLAG_RD,
|
||||
&maxbufspace, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, hibufspace, CTLFLAG_RD,
|
||||
&hibufspace, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, lobufspace, CTLFLAG_RD,
|
||||
&lobufspace, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, bufspace, CTLFLAG_RD,
|
||||
&bufspace, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, maxmallocbufspace, CTLFLAG_RW,
|
||||
&maxbufmallocspace, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, bufmallocspace, CTLFLAG_RD,
|
||||
&bufmallocspace, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, getnewbufcalls, CTLFLAG_RW,
|
||||
&getnewbufcalls, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, getnewbufrestarts, CTLFLAG_RW,
|
||||
&getnewbufrestarts, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, vmiodirenable, CTLFLAG_RW,
|
||||
&vmiodirenable, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, bufdefragcnt, CTLFLAG_RW,
|
||||
&bufdefragcnt, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, buffreekvacnt, CTLFLAG_RW,
|
||||
&buffreekvacnt, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, bufreusecnt, CTLFLAG_RW,
|
||||
&bufreusecnt, 0, "");
|
||||
|
||||
/*
|
||||
* Mask for index into the buffer hash table, which needs to be power of 2 in
|
||||
* size. Set in kern_vfs_bio_buffer_alloc.
|
||||
*/
|
||||
static int bufhashmask;
|
||||
static LIST_HEAD(bufhashhdr, buf) *bufhashtbl, invalhash;
|
||||
struct bqueues bufqueues[BUFFER_QUEUES] = { { 0 } };
|
||||
char *buf_wmesg = BUF_WMESG;
|
||||
|
||||
extern int vm_swap_size;
|
||||
/*
|
||||
* Hash table for all buffers, with a linked list hanging from each table
|
||||
* entry. Set in kern_vfs_bio_buffer_alloc, initialized in buf_init.
|
||||
*/
|
||||
static LIST_HEAD(bufhashhdr, buf) *bufhashtbl;
|
||||
|
||||
/*
|
||||
* Somewhere to store buffers when they are not in another list, to always
|
||||
* have them in a list (and thus being able to use the same set of operations
|
||||
* on them.)
|
||||
*/
|
||||
static struct bufhashhdr invalhash;
|
||||
/* Queues for free buffers with various properties */
|
||||
static struct bqueues bufqueues[BUFFER_QUEUES] = { { 0 } };
|
||||
/*
|
||||
* Single global constant for BUF_WMESG, to avoid getting multiple references.
|
||||
* buf_wmesg is referred from macros.
|
||||
*/
|
||||
char *buf_wmesg = BUF_WMESG;
|
||||
|
||||
#define VFS_BIO_NEED_ANY 0x01 /* any freeable buffer */
|
||||
#define VFS_BIO_NEED_DIRTYFLUSH 0x02 /* waiting for dirty buffer flush */
|
||||
@ -301,6 +362,7 @@ vfs_buf_test_cache(struct buf *bp,
|
||||
}
|
||||
}
|
||||
|
||||
/* Wake up the buffer deamon if necessary */
|
||||
static __inline__
|
||||
void
|
||||
bd_wakeup(int dirtybuflevel)
|
||||
@ -400,6 +462,7 @@ kern_vfs_bio_buffer_alloc(caddr_t v, int physmem_est)
|
||||
return(v);
|
||||
}
|
||||
|
||||
/* Initialize the buffer subsystem. Called before use of any buffers. */
|
||||
void
|
||||
bufinit(void)
|
||||
{
|
||||
@ -656,9 +719,6 @@ breadn(struct vnode * vp, daddr_t blkno, int size,
|
||||
* here.
|
||||
*/
|
||||
|
||||
int dobkgrdwrite = 1;
|
||||
SYSCTL_INT(_debug, OID_AUTO, dobkgrdwrite, CTLFLAG_RW, &dobkgrdwrite, 0, "");
|
||||
|
||||
int
|
||||
bwrite(struct buf * bp)
|
||||
{
|
||||
@ -811,7 +871,8 @@ vfs_backgroundwritedone(bp)
|
||||
* If BX_BKGRDINPROG is not set in the original buffer it must
|
||||
* have been released and re-instantiated - which is not legal.
|
||||
*/
|
||||
KASSERT((origbp->b_xflags & BX_BKGRDINPROG), ("backgroundwritedone: lost buffer2"));
|
||||
KASSERT((origbp->b_xflags & BX_BKGRDINPROG),
|
||||
("backgroundwritedone: lost buffer2"));
|
||||
origbp->b_xflags &= ~BX_BKGRDINPROG;
|
||||
if (origbp->b_xflags & BX_BKGRDWAIT) {
|
||||
origbp->b_xflags &= ~BX_BKGRDWAIT;
|
||||
@ -931,7 +992,8 @@ void
|
||||
bdirty(bp)
|
||||
struct buf *bp;
|
||||
{
|
||||
KASSERT(bp->b_qindex == QUEUE_NONE, ("bdirty: buffer %p still on queue %d", bp, bp->b_qindex));
|
||||
KASSERT(bp->b_qindex == QUEUE_NONE,
|
||||
("bdirty: buffer %p still on queue %d", bp, bp->b_qindex));
|
||||
bp->b_flags &= ~(B_RELBUF);
|
||||
bp->b_iocmd = BIO_WRITE;
|
||||
|
||||
@ -959,7 +1021,8 @@ void
|
||||
bundirty(bp)
|
||||
struct buf *bp;
|
||||
{
|
||||
KASSERT(bp->b_qindex == QUEUE_NONE, ("bundirty: buffer %p still on queue %d", bp, bp->b_qindex));
|
||||
KASSERT(bp->b_qindex == QUEUE_NONE,
|
||||
("bundirty: buffer %p still on queue %d", bp, bp->b_qindex));
|
||||
|
||||
if (bp->b_flags & B_DELWRI) {
|
||||
bp->b_flags &= ~B_DELWRI;
|
||||
@ -1038,7 +1101,8 @@ brelse(struct buf * bp)
|
||||
|
||||
GIANT_REQUIRED;
|
||||
|
||||
KASSERT(!(bp->b_flags & (B_CLUSTER|B_PAGING)), ("brelse: inappropriate B_PAGING or B_CLUSTER bp %p", bp));
|
||||
KASSERT(!(bp->b_flags & (B_CLUSTER|B_PAGING)),
|
||||
("brelse: inappropriate B_PAGING or B_CLUSTER bp %p", bp));
|
||||
|
||||
s = splbio();
|
||||
|
||||
@ -1228,7 +1292,8 @@ brelse(struct buf * bp)
|
||||
LIST_INSERT_HEAD(&invalhash, bp, b_hash);
|
||||
bp->b_dev = NODEV;
|
||||
/* buffers with junk contents */
|
||||
} else if (bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF) || (bp->b_ioflags & BIO_ERROR)) {
|
||||
} else if (bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF) ||
|
||||
(bp->b_ioflags & BIO_ERROR)) {
|
||||
bp->b_flags |= B_INVAL;
|
||||
bp->b_xflags &= ~BX_BKGRDWRITE;
|
||||
if (bp->b_xflags & BX_BKGRDINPROG)
|
||||
@ -1360,6 +1425,7 @@ bqrelse(struct buf * bp)
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/* Give pages used by the bp back to the VM system (where possible) */
|
||||
static void
|
||||
vfs_vmio_release(bp)
|
||||
struct buf *bp;
|
||||
@ -1392,7 +1458,8 @@ vfs_vmio_release(bp)
|
||||
* no valid data. We also free the page if the
|
||||
* buffer was used for direct I/O
|
||||
*/
|
||||
if ((bp->b_flags & B_ASYNC) == 0 && !m->valid && m->hold_count == 0) {
|
||||
if ((bp->b_flags & B_ASYNC) == 0 && !m->valid &&
|
||||
m->hold_count == 0) {
|
||||
vm_page_busy(m);
|
||||
vm_page_protect(m, VM_PROT_NONE);
|
||||
vm_page_free(m);
|
||||
@ -1884,7 +1951,7 @@ buf_daemon()
|
||||
|
||||
/*
|
||||
* Only clear bd_request if we have reached our low water
|
||||
* mark. The buf_daemon normally waits 5 seconds and
|
||||
* mark. The buf_daemon normally waits 1 second and
|
||||
* then incrementally flushes any dirty buffers that have
|
||||
* built up, within reason.
|
||||
*
|
||||
@ -2191,7 +2258,7 @@ getblk(struct vnode * vp, daddr_t blkno, int size, int slpflag, int slptimeo)
|
||||
|
||||
/*
|
||||
* The buffer is locked. B_CACHE is cleared if the buffer is
|
||||
* invalid. Ohterwise, for a non-VMIO buffer, B_CACHE is set
|
||||
* invalid. Otherwise, for a non-VMIO buffer, B_CACHE is set
|
||||
* and for a VMIO buffer B_CACHE is adjusted according to the
|
||||
* backing VM cache.
|
||||
*/
|
||||
@ -3251,6 +3318,7 @@ vm_hold_load_pages(struct buf * bp, vm_offset_t from, vm_offset_t to)
|
||||
bp->b_npages = index;
|
||||
}
|
||||
|
||||
/* Return pages associated with this buf to the vm system */
|
||||
void
|
||||
vm_hold_free_pages(struct buf * bp, vm_offset_t from, vm_offset_t to)
|
||||
{
|
||||
@ -3286,6 +3354,7 @@ vm_hold_free_pages(struct buf * bp, vm_offset_t from, vm_offset_t to)
|
||||
#ifdef DDB
|
||||
#include <ddb/ddb.h>
|
||||
|
||||
/* DDB command to show buffer data */
|
||||
DB_SHOW_COMMAND(buffer, db_show_buffer)
|
||||
{
|
||||
/* get args */
|
||||
|
@ -96,7 +96,7 @@ static u_long nchash; /* size of hash table */
|
||||
SYSCTL_ULONG(_debug, OID_AUTO, nchash, CTLFLAG_RD, &nchash, 0, "");
|
||||
static u_long ncnegfactor = 16; /* ratio of negative entries */
|
||||
SYSCTL_ULONG(_debug, OID_AUTO, ncnegfactor, CTLFLAG_RW, &ncnegfactor, 0, "");
|
||||
static u_long numneg; /* number of cache entries allocated */
|
||||
static u_long numneg; /* number of cache entries allocated */
|
||||
SYSCTL_ULONG(_debug, OID_AUTO, numneg, CTLFLAG_RD, &numneg, 0, "");
|
||||
static u_long numcache; /* number of cache entries allocated */
|
||||
SYSCTL_ULONG(_debug, OID_AUTO, numcache, CTLFLAG_RD, &numcache, 0, "");
|
||||
@ -110,6 +110,8 @@ struct nchstats nchstats; /* cache effectiveness statistics */
|
||||
|
||||
static int doingcache = 1; /* 1 => enable the cache */
|
||||
SYSCTL_INT(_debug, OID_AUTO, vfscache, CTLFLAG_RW, &doingcache, 0, "");
|
||||
|
||||
/* Export size information to userland */
|
||||
SYSCTL_INT(_debug, OID_AUTO, vnsize, CTLFLAG_RD, 0, sizeof(struct vnode), "");
|
||||
SYSCTL_INT(_debug, OID_AUTO, ncsize, CTLFLAG_RD, 0, sizeof(struct namecache), "");
|
||||
|
||||
@ -625,15 +627,22 @@ struct __getcwd_args {
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX All of these sysctls would probably be more productive dead.
|
||||
*/
|
||||
static int disablecwd;
|
||||
SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0, "");
|
||||
SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0,
|
||||
"Disable the getcwd syscall");
|
||||
|
||||
/* Various statistics for the getcwd syscall */
|
||||
static u_long numcwdcalls; STATNODE(CTLFLAG_RD, numcwdcalls, &numcwdcalls);
|
||||
static u_long numcwdfail1; STATNODE(CTLFLAG_RD, numcwdfail1, &numcwdfail1);
|
||||
static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2);
|
||||
static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3);
|
||||
static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4);
|
||||
static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound);
|
||||
|
||||
/* Implementation of the getcwd syscall */
|
||||
int
|
||||
__getcwd(td, uap)
|
||||
struct thread *td;
|
||||
@ -731,8 +740,8 @@ __getcwd(td, uap)
|
||||
SYSCTL_UINT(_vfs_cache, OID_AUTO, name, CTLFLAG_RD, &name, 0, "")
|
||||
|
||||
static int disablefullpath;
|
||||
SYSCTL_INT(_debug, OID_AUTO, disablefullpath, CTLFLAG_RW,
|
||||
&disablefullpath, 0, "");
|
||||
SYSCTL_INT(_debug, OID_AUTO, disablefullpath, CTLFLAG_RW, &disablefullpath, 0,
|
||||
"Disable the vn_fullpath function");
|
||||
|
||||
STATNODE(numfullpathcalls);
|
||||
STATNODE(numfullpathfail1);
|
||||
@ -741,6 +750,10 @@ STATNODE(numfullpathfail3);
|
||||
STATNODE(numfullpathfail4);
|
||||
STATNODE(numfullpathfound);
|
||||
|
||||
/*
|
||||
* Retrieve the full filesystem path that correspond to a vnode from the name
|
||||
* cache (if available)
|
||||
*/
|
||||
int
|
||||
vn_fullpath(struct thread *td, struct vnode *vn, char **retbuf, char **freebuf)
|
||||
{
|
||||
|
@ -57,7 +57,8 @@
|
||||
#if defined(CLUSTERDEBUG)
|
||||
#include <sys/sysctl.h>
|
||||
static int rcluster= 0;
|
||||
SYSCTL_INT(_debug, OID_AUTO, rcluster, CTLFLAG_RW, &rcluster, 0, "");
|
||||
SYSCTL_INT(_debug, OID_AUTO, rcluster, CTLFLAG_RW, &rcluster, 0,
|
||||
"Debug VFS clustering code");
|
||||
#endif
|
||||
|
||||
static MALLOC_DEFINE(M_SEGMENT, "cluster_save buffer", "cluster_save buffer");
|
||||
@ -69,10 +70,16 @@ static struct buf *
|
||||
daddr_t blkno, long size, int run, struct buf *fbp));
|
||||
|
||||
static int write_behind = 1;
|
||||
SYSCTL_INT(_vfs, OID_AUTO, write_behind, CTLFLAG_RW, &write_behind, 0, "");
|
||||
SYSCTL_INT(_vfs, OID_AUTO, write_behind, CTLFLAG_RW, &write_behind, 0,
|
||||
"Cluster write-behind; 0: disable, 1: enable, 2: backed off");
|
||||
|
||||
/* Page expended to mark partially backed buffers */
|
||||
extern vm_page_t bogus_page;
|
||||
|
||||
/*
|
||||
* Number of physical bufs (pbufs) this subsystem is allowed.
|
||||
* Manipulated by vm_pager.c
|
||||
*/
|
||||
extern int cluster_pbuf_freecnt;
|
||||
|
||||
/*
|
||||
@ -81,7 +88,8 @@ extern int cluster_pbuf_freecnt;
|
||||
#define MAXRA 32
|
||||
|
||||
/*
|
||||
* This replaces bread.
|
||||
* Read data to a buf, including read-ahead if we find this to be beneficial.
|
||||
* cluster_read replaces bread.
|
||||
*/
|
||||
int
|
||||
cluster_read(vp, filesize, lblkno, size, cred, totread, seqcount, bpp)
|
||||
|
@ -71,6 +71,10 @@ MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
|
||||
|
||||
#define ROOTNAME "root_device"
|
||||
|
||||
/*
|
||||
* The vnode of the system's root (/ in the filesystem, without chroot
|
||||
* active.)
|
||||
*/
|
||||
struct vnode *rootvnode;
|
||||
|
||||
/*
|
||||
@ -293,6 +297,9 @@ vfs_mountroot_ask(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local helper function for vfs_mountroot_ask.
|
||||
*/
|
||||
static void
|
||||
gets(char *cp)
|
||||
{
|
||||
@ -367,6 +374,7 @@ setrootbyname(char *name)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Show the dev_t for a disk specified by name */
|
||||
#ifdef DDB
|
||||
DB_SHOW_COMMAND(disk, db_getdiskbyname)
|
||||
{
|
||||
|
@ -109,6 +109,11 @@ static struct vnodeopv_desc default_vnodeop_opv_desc =
|
||||
|
||||
VNODEOP_SET(default_vnodeop_opv_desc);
|
||||
|
||||
/*
|
||||
* Series of placeholder functions for various error returns for
|
||||
* VOPs.
|
||||
*/
|
||||
|
||||
int
|
||||
vop_eopnotsupp(struct vop_generic_args *ap)
|
||||
{
|
||||
@ -147,6 +152,9 @@ vop_null(struct vop_generic_args *ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to make a defined VOP fall back to the default VOP.
|
||||
*/
|
||||
int
|
||||
vop_defaultop(struct vop_generic_args *ap)
|
||||
{
|
||||
@ -154,6 +162,9 @@ vop_defaultop(struct vop_generic_args *ap)
|
||||
return (VOCALL(default_vnodeop_p, ap->a_desc->vdesc_offset, ap));
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to panic on some bad VOPs in some filesystems.
|
||||
*/
|
||||
int
|
||||
vop_panic(struct vop_generic_args *ap)
|
||||
{
|
||||
@ -161,6 +172,18 @@ vop_panic(struct vop_generic_args *ap)
|
||||
panic("filesystem goof: vop_panic[%s]", ap->a_desc->vdesc_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* vop_std<something> and vop_no<something> are default functions for use by
|
||||
* filesystems that need the "default reasonable" implementation for a
|
||||
* particular operation.
|
||||
*
|
||||
* The documentation for the operations they implement exists (if it exists)
|
||||
* in the VOP_<SOMETHING>(9) manpage (all uppercase).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Default vop for filesystems that do not support name lookup
|
||||
*/
|
||||
static int
|
||||
vop_nolookup(ap)
|
||||
struct vop_lookup_args /* {
|
||||
@ -198,6 +221,14 @@ vop_nostrategy (struct vop_strategy_args *ap)
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* vop_stdpathconf:
|
||||
*
|
||||
* Standard implementation of POSIX pathconf, to get information about limits
|
||||
* for a filesystem.
|
||||
* Override per filesystem for the case where the filesystem has smaller
|
||||
* limits.
|
||||
*/
|
||||
int
|
||||
vop_stdpathconf(ap)
|
||||
struct vop_pathconf_args /* {
|
||||
@ -256,6 +287,7 @@ vop_stdlock(ap)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* See above. */
|
||||
int
|
||||
vop_stdunlock(ap)
|
||||
struct vop_unlock_args /* {
|
||||
@ -270,6 +302,7 @@ vop_stdunlock(ap)
|
||||
ap->a_td));
|
||||
}
|
||||
|
||||
/* See above. */
|
||||
int
|
||||
vop_stdislocked(ap)
|
||||
struct vop_islocked_args /* {
|
||||
@ -281,6 +314,7 @@ vop_stdislocked(ap)
|
||||
return (lockstatus(&ap->a_vp->v_lock, ap->a_td));
|
||||
}
|
||||
|
||||
/* Mark the vnode inactive */
|
||||
int
|
||||
vop_stdinactive(ap)
|
||||
struct vop_inactive_args /* {
|
||||
@ -512,6 +546,7 @@ vop_stdgetwritemount(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Create the VM system backing object for this vnode */
|
||||
int
|
||||
vop_stdcreatevobject(ap)
|
||||
struct vop_createvobject_args /* {
|
||||
@ -570,6 +605,7 @@ vop_stdcreatevobject(ap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Destroy the VM system object associated with this vnode */
|
||||
int
|
||||
vop_stddestroyvobject(ap)
|
||||
struct vop_destroyvobject_args /* {
|
||||
@ -627,6 +663,7 @@ vop_stdgetvobject(ap)
|
||||
return (vp->v_object ? 0 : EINVAL);
|
||||
}
|
||||
|
||||
/* XXX Needs good comment and VOP_BMAP(9) manpage */
|
||||
int
|
||||
vop_stdbmap(ap)
|
||||
struct vop_bmap_args /* {
|
||||
@ -650,6 +687,7 @@ vop_stdbmap(ap)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */
|
||||
int
|
||||
vop_stdgetpages(ap)
|
||||
struct vop_getpages_args /* {
|
||||
@ -665,6 +703,7 @@ vop_stdgetpages(ap)
|
||||
ap->a_count, ap->a_reqpage);
|
||||
}
|
||||
|
||||
/* XXX Needs good comment and more info in the manpage (VOP_PUTPAGES(9)). */
|
||||
int
|
||||
vop_stdputpages(ap)
|
||||
struct vop_putpages_args /* {
|
||||
@ -685,7 +724,7 @@ vop_stdputpages(ap)
|
||||
|
||||
/*
|
||||
* vfs default ops
|
||||
* used to fill the vfs fucntion table to get reasonable default return values.
|
||||
* used to fill the vfs function table to get reasonable default return values.
|
||||
*/
|
||||
int
|
||||
vfs_stdmount (mp, path, data, ndp, td)
|
||||
@ -698,7 +737,7 @@ vfs_stdmount (mp, path, data, ndp, td)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
vfs_stdunmount (mp, mntflags, td)
|
||||
struct mount *mp;
|
||||
int mntflags;
|
||||
@ -707,7 +746,7 @@ vfs_stdunmount (mp, mntflags, td)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
vfs_stdroot (mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
@ -715,7 +754,7 @@ vfs_stdroot (mp, vpp)
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
vfs_stdstatfs (mp, sbp, td)
|
||||
struct mount *mp;
|
||||
struct statfs *sbp;
|
||||
@ -732,7 +771,7 @@ vfs_stdvptofh (vp, fhp)
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
vfs_stdstart (mp, flags, td)
|
||||
struct mount *mp;
|
||||
int flags;
|
||||
|
@ -56,6 +56,11 @@ MALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes");
|
||||
* The highest defined VFS number.
|
||||
*/
|
||||
int maxvfsconf = VFS_GENERIC + 1;
|
||||
|
||||
/*
|
||||
* Single-linked list of configured VFSes.
|
||||
* New entries are added/deleted by vfs_register()/vfs_unregister()
|
||||
*/
|
||||
struct vfsconf *vfsconf;
|
||||
|
||||
/*
|
||||
@ -81,10 +86,19 @@ static int vnodeopv_num;
|
||||
|
||||
/* Table of known descs (list of vnode op handlers "vop_access_desc") */
|
||||
static struct vnodeop_desc **vfs_op_descs;
|
||||
static int *vfs_op_desc_refs; /* reference counts */
|
||||
/* Reference counts for vfs_op_descs */
|
||||
static int *vfs_op_desc_refs;
|
||||
/* Number of descriptions */
|
||||
static int num_op_descs;
|
||||
/* Number of entries in each description */
|
||||
static int vfs_opv_numops;
|
||||
|
||||
/*
|
||||
* Recalculate the operations vector/description (those parts of it that can
|
||||
* be recalculated, that is.)
|
||||
* XXX It may be preferable to replace this function with an invariant check
|
||||
* and a set of functions that should keep the table invariant.
|
||||
*/
|
||||
static void
|
||||
vfs_opv_recalc(void)
|
||||
{
|
||||
@ -143,6 +157,7 @@ vfs_opv_recalc(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a set of vnode operations (a description) to the table above. */
|
||||
void
|
||||
vfs_add_vnodeops(const void *data)
|
||||
{
|
||||
@ -210,6 +225,7 @@ vfs_add_vnodeops(const void *data)
|
||||
vfs_opv_recalc();
|
||||
}
|
||||
|
||||
/* Remove a vnode type from the vnode description table above. */
|
||||
void
|
||||
vfs_rm_vnodeops(const void *data)
|
||||
{
|
||||
@ -302,6 +318,7 @@ vfsinit(void *dummy)
|
||||
}
|
||||
SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL)
|
||||
|
||||
/* Register a new file system type in the global table */
|
||||
int
|
||||
vfs_register(struct vfsconf *vfc)
|
||||
{
|
||||
@ -347,6 +364,7 @@ vfs_register(struct vfsconf *vfc)
|
||||
}
|
||||
|
||||
|
||||
/* Remove registration of a file system type */
|
||||
int
|
||||
vfs_unregister(struct vfsconf *vfc)
|
||||
{
|
||||
@ -382,6 +400,10 @@ vfs_unregister(struct vfsconf *vfc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard kernel module handling code for file system modules.
|
||||
* Referenced from VFS_SET().
|
||||
*/
|
||||
int
|
||||
vfs_modevent(module_t mod, int type, void *data)
|
||||
{
|
||||
|
@ -71,6 +71,10 @@ MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
|
||||
|
||||
#define ROOTNAME "root_device"
|
||||
|
||||
/*
|
||||
* The vnode of the system's root (/ in the filesystem, without chroot
|
||||
* active.)
|
||||
*/
|
||||
struct vnode *rootvnode;
|
||||
|
||||
/*
|
||||
@ -293,6 +297,9 @@ vfs_mountroot_ask(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local helper function for vfs_mountroot_ask.
|
||||
*/
|
||||
static void
|
||||
gets(char *cp)
|
||||
{
|
||||
@ -367,6 +374,7 @@ setrootbyname(char *name)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Show the dev_t for a disk specified by name */
|
||||
#ifdef DDB
|
||||
DB_SHOW_COMMAND(disk, db_getdiskbyname)
|
||||
{
|
||||
|
@ -266,14 +266,14 @@ vn_close(vp, flags, cred, td)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sequential heuristic - detect sequential operation
|
||||
*/
|
||||
static __inline
|
||||
int
|
||||
sequential_heuristic(struct uio *uio, struct file *fp)
|
||||
{
|
||||
|
||||
/*
|
||||
* Sequential heuristic - detect sequential operation
|
||||
*/
|
||||
if ((uio->uio_offset == 0 && fp->f_seqcount > 0) ||
|
||||
uio->uio_offset == fp->f_nextoff) {
|
||||
/*
|
||||
@ -499,6 +499,9 @@ vn_statfile(fp, sb, td)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stat a vnode; implementation for the stat syscall
|
||||
*/
|
||||
int
|
||||
vn_stat(vp, sb, td)
|
||||
struct vnode *vp;
|
||||
@ -891,6 +894,9 @@ vfs_write_resume(mp)
|
||||
wakeup(&mp->mnt_flag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement kqueues for files by translating it to vnode operation.
|
||||
*/
|
||||
static int
|
||||
vn_kqfilter(struct file *fp, struct knote *kn)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user