2021-10-11 18:20:23 -03:00

276 lines
6.4 KiB
C

/* @(#)tmp_vfsops.c 1.1 92/07/30 SMI */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <sys/kmem_alloc.h>
#include <vm/anon.h>
#include <tmpfs/tmpnode.h>
#include <tmpfs/tmp.h>
#include <tmpfs/tmpdir.h>
/*
* tmpfs vfs operations.
*/
static int tmp_mount();
static int tmp_unmount();
static int tmp_root();
static int tmp_statfs();
static int tmp_sync();
static int tmp_vget();
static int tmp_mountroot();
static int tmp_swapvp();
struct vfsops tmp_vfsops = {
tmp_mount,
tmp_unmount,
tmp_root,
tmp_statfs,
tmp_sync,
tmp_vget,
tmp_mountroot,
tmp_swapvp
};
/*
* patchable variables, otherwise tmpfs_maxkmem set on first tmp_mount.
*/
u_int tmpfs_maxprockmem = TMPMAXPROCKMEM; /* percent of kernel memory */
/* this tmpfs can use */
u_int tmpfs_maxkmem = 0; /* patch at the risk of your life */
#define TMPMAPSIZE 32/NBBY
static char tmpfs_minmap[TMPMAPSIZE]; /* map for minor dev num allocation */
static struct tmount *tmpfs_mountp = 0; /* linked list of tmpfs mount structs */
/*ARGSUSED*/
static int
tmp_mount(vfsp, path, data)
struct vfs *vfsp;
char *path;
caddr_t data;
{
int error;
register struct tmount *tmx;
struct tmount *tm;
struct tmpnode *tp;
struct ucred rootcred;
extern int physmem;
extern long tmpimapalloc();
u_int len;
if (tmpfs_maxkmem == 0) { /* first mount or (god forbid) patch */
tmpfs_maxkmem = MAX(PAGESIZE,
(ptob(physmem) * tmpfs_maxprockmem)/100);
}
/* allocate and initialize tmount structure */
tm = (struct tmount *)
new_kmem_zalloc(sizeof (struct tmount), KMEM_SLEEP);
#ifdef TMPFSDEBUG
if (tmpfsdebug)
printf("tmp_mount: vfsp %x tm %x path %s\n", vfsp, tm, path);
#endif TMPFSDEBUG
/* link the structure into the list */
tmx = tmpfs_mountp;
if (tmx == (struct tmount *)NULL)
tmpfs_mountp = tm;
else {
for (; tmx->tm_next; tmx = tmx->tm_next)
;
tmx->tm_next = tm;
}
tm->tm_vfsp = vfsp;
if ((tm->tm_mntno = vfs_getnum(tmpfs_minmap, TMPMAPSIZE)) == -1) {
kmem_free((char *)tm, sizeof (struct tmount));
return (EAGAIN); /* why not 'mount table full'? */
}
/*
* Kludge Alert!
* inodes 0 and 1 have traditionally been unused.
* the next two calls have the effect of invalidating 0 and 1
* for tmpfs use
*/
(void)tmpimapalloc(tm);
(void)tmpimapalloc(tm);
vfsp->vfs_data = (caddr_t)tm;
vfsp->vfs_fsid.val[0] = tm->tm_mntno;
vfsp->vfs_fsid.val[1] = MOUNT_TMP;
(void) copystr(path, tm->tm_mntpath, sizeof (tm->tm_mntpath) - 1, &len);
bzero(tm->tm_mntpath + len, sizeof (tm->tm_mntpath) - len);
/* allocate and initialize root tmpnode structure */
tp = tmpnode_alloc(tm, VDIR);
if (tp == NULL) {
kmem_free((char *)tm, sizeof (struct tmount));
return (ENOSPC);
}
tmpnode_unlock(tp);
tm->tm_rootnode = tp;
newnode(tp, S_IFDIR | 0777, 0, 0); /* XXX Permissions? */
tp->tn_vnode.v_flag |= VROOT;
rootcred.cr_uid = 0;
rootcred.cr_gid = 0;
if ((error = tdirenter(tm, tp, ".", tp, &rootcred)) ||
(error = tdirenter(tm, tp, "..", tp, &rootcred))) {
tmpnode_free(tm, tp);
kmem_free((char *)tm, sizeof (struct tmount));
return (error); /* XXX Could we lose some memory? */
}
return (0);
}
static int
tmp_sync()
{
return (0);
}
/*
* global statistics
*/
int tmp_anonmem; /* amount of anon space reserved for all tmpfs */
int tmp_kmemspace; /* amount of kernel heap used by all tmpfs */
int tmp_files; /* number of files or directories in all tmpfs */
int tmp_anonalloc; /* approximate # of anon pages allocated to tmpfs */
static int
tmp_unmount(vfsp)
struct vfs *vfsp;
{
register struct tmount *tm = VFSP_TO_TM(vfsp);
register struct tmount *tmx;
void vfs_putnum();
#ifdef TMPFSDEBUG
if (tmpfsdebug)
printf("tmp_unmount: tm %x\n", tm);
#endif TMPFSDEBUG
/*
* Don't close down the tmpfs if there are ANY opened files
*/
if (tmpnode_checkopen(tm))
return (EBUSY);
/*
* Remove from tmp mount list
*/
if ((tmx = tmpfs_mountp) == tm)
tmpfs_mountp = tm->tm_next;
else
for (; tmx; tmx = tmx->tm_next)
if (tmx->tm_next == tm)
tmx->tm_next = tm->tm_next;
vfs_putnum(tmpfs_minmap, (int)tm->tm_mntno);
/*
* must free all kmemalloc'd and anonalloc'd memory associated with
* this filesystem
*/
(void)tmpnode_freeall(tm); /* frees all files and directories */
if ((tm->tm_anonmem != 0) || (tm->tm_files != 0) ||
(tm->tm_directories != 0) || (tm->tm_direntries != 0) ||
(tm->tm_kmemspace != 0)) {
#ifdef TMPFSDEBUG
if (tm || tmpdebugerrs) { /* always true for now */
printf("tmpnode_freeall bad bookkeeping tm %x\n", tm);
printf("files = %d\n", tm->tm_files);
printf("directories = %d\n", tm->tm_directories);
printf("direntries = %d\n", tm->tm_direntries);
printf("anonmem = %d\n", tm->tm_anonmem);
printf("kmemspace = %d\n", tm->tm_kmemspace);
}
#endif TMPFSDEBUG
}
kmem_free((char *)tm, sizeof (struct tmount));
return (0);
}
static int
tmp_root(vfsp, vpp)
struct vfs *vfsp;
struct vnode **vpp;
{
struct tmount *tm = VFSP_TO_TM(vfsp);
struct tmpnode *tp = tm->tm_rootnode;
tmpnode_get(tp);
tmpnode_unlock(tp);
*vpp = TP_TO_VP(tp);
#ifdef TMPFSDEBUG
if (tmpfsdebug)
printf("tmp_root: tm %x tp %x vpp\n", tm, tp, *vpp);
#endif TMPFSDEBUG
return (0);
}
static int
tmp_statfs(vfsp, sbp)
struct vfs *vfsp;
struct statfs *sbp;
{
struct tmount *tm = VFSP_TO_TM(vfsp);
extern int tmpfs_hiwater;
#ifdef TMPFSDEBUG
if (tmpfsdebug)
printf("tmp_statfs: tm %x sbp %x\n", tm, sbp);
#endif TMPFSDEBUG
sbp->f_bsize = PAGESIZE;
sbp->f_blocks = anoninfo.ani_free - btop(tmpfs_hiwater) +
btop(tmp_anonmem);
sbp->f_bfree = sbp->f_blocks - btop(tm->tm_anonmem);
sbp->f_bavail = sbp->f_bfree;
/*
* The maximum number of files available is the number of tmpnodes we
* can allocate from the remaining kernel memory available to tmpfs.
*/
sbp->f_ffree = (tmpfs_maxkmem - tmp_kmemspace)/sizeof (struct tmpnode);
sbp->f_files = sbp->f_ffree + tmp_files;
if (sbp->f_bfree < 0) {
sbp->f_blocks -= sbp->f_bfree;
sbp->f_files -= sbp->f_bfree;
sbp->f_bfree = sbp->f_bavail = sbp->f_ffree = 0;
}
sbp->f_fsid = vfsp->vfs_fsid;
return (0);
}
/*ARGSUSED*/
static int
tmp_vget(vfsp, vpp, fidp)
struct vfs *vfsp;
struct vnode **vpp;
struct fid *fidp;
{
#ifdef TMPFSDEBUG
if (tmpfsdebug)
printf("tmp_vget: vfsp %x fidp %x\n", vfsp, fidp);
#endif TMPFSDEBUG
*vpp = NULL;
return (0);
}
static int
tmp_mountroot()
{
return (EINVAL);
}
static int
tmp_swapvp()
{
return (EINVAL);
}