Subject: Code review of Ultrix getmnt() sought.
To: None <port-pmax@sun-lamp.cs.berkeley.edu>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: port-pmax
Date: 08/22/1994 16:45:35
[[An earlier mailing of this bounced, because I can't spell sun-lamp.
Apologies to those who see it twice, or late.]]
Below is a first pass at an Ultrix getmnt().
It's not yet ready for inclusion in an official source tree.
There's a bunch of things it doesn't do; but it works well enough
for Ultrix mount and df to list the mounted filesystems
and the free space on each of them.
Things I'd like some help on are: which source file to
put this in, given that it's both Ultrix-compatibility
specific, and closely tied to the VFS code (compare it
with getfsstat() in kern/vfs_syscalls.c).
Also I don't know where in the VFS to find a major/minor
device number of a mounted special file, if that's what
the mount is.
I have no idea how Ultrix matches a path argument, if
one is given, to a mount point; but I expect it goes
through namei(), which this doesn't. Neither mount
nor df nor unmount seem to ask Ultrix getmnt()
for a specific path, so I haven't bothered...
--------
#ifdef COMPAT_ULTRIX
struct ult_fs_data {
u_int flags; /* how mounted */
u_int mtsize; /* max transfer size in bytes */
u_int otsize; /* optimal transfer size in bytes */
u_int bsize; /* fs block size in bytes for vm code */
u_int fstype; /* see ../h/fs_types.h */
u_int gtot; /* total number of gnodes */
u_int gfree; /* # of free gnodes */
u_int btot; /* total number of 1K blocks */
u_int bfree; /* # of free 1K blocks */
u_int bfreen; /* user consumable 1K blocks */
u_int pgthresh; /* min size in bytes before paging*/
int uid; /* uid that mounted me */
short /*dev_t*/ dev; /* major/minor of fs */
short exroot; /* root mapping from exports */
#define ULT_MAXPATHLEN 1024/* in case NetBSD MAXPATHLEN changes */
char devname[ULT_MAXPATHLEN + 4]; /* name of dev */
char path[ULT_MAXPATHLEN + 4]; /* name of mount point */
u_int nupdate; /* number of writes */
/* 2112 bytes */
u_int fd_spare[112]; /* this structure is exactly */
/* 14 * 4 + 2 * 1028 + 112 *4 = 2560 */
/* bytes - KEEP IT THAT WAY - rr */
/* since we malloc memory in 512 byte */
/* chunks, the last 113 u_int's are */
/* FREE */
};
/*
* Get statistics on mounted filesystems.
*/
struct ult_getmnt_args {
long *start;
struct ult_fs_data *buf;
long bufsize, mode;
char *path;
};
#define ULT_NOSTAT_MANY 1
#define ULT_STAT_MANY 2
#define ULT_NOSTAT_ONE 4
#define ULT_STAT_ONE 3
/* construct Ultrix_compat structure */
static
make_ult_mntent(sp, tem)
register struct statfs *sp;
register struct ult_fs_data *tem;
{
tem->mtsize = sp->f_bsize; /*XXX should be max transfer size */
tem->flags = sp->f_flags; /*XXX should translate */
tem->otsize = sp->f_iosize;
tem->bsize = sp->f_bsize;
tem->fstype = sp->f_type ; /*XXX*/ /* translate */
tem->gtot = 0; /* kept where? Superblock? */
tem->gfree = sp->f_ffree;
tem->bfreen = sp->f_bfree;
tem->pgthresh = 0; /* not relevant */
tem->uid = 0 ; /* kept where ?*/
tem->dev = 0 ; /* ?? */
tem->exroot = 0 ; /* ?? */
strncpy(tem->path, sp->f_mntonname, ULT_MAXPATHLEN);
strncpy(tem->devname , sp->f_mntfromname, ULT_MAXPATHLEN);
}
ult_getmnt(p, uap, retval)
struct proc *p;
register struct ult_getmnt_args *uap;
int *retval;
{
register struct mount *mp, *nmp;
register struct statfs *sp;
caddr_t sfsp;
register long count, maxcount, error = 0;
int mntflags = MNT_NOWAIT;
register int skip;
int start;
char *path = 0;
if (uap->mode == ULT_STAT_ONE || uap->mode == ULT_STAT_MANY)
mntflags = MNT_WAIT;
maxcount = uap->bufsize / sizeof(struct ult_fs_data);
sfsp = (caddr_t)uap->buf;
if (uap->mode == ULT_STAT_ONE || uap->mode == ULT_NOSTAT_ONE)
{
/* just get the one that matches */
MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
if (error = copyinstr(uap->path, path, MAXPATHLEN, (u_int*)0))
goto bad;
maxcount = 1;
} else {
if (error = copyin((caddr_t)uap->start, &start, sizeof(*uap->start)))
goto bad;
skip = start;
/* skip to the |start|th element in internal list */
for (mp = mountlist.tqh_first; mp != NULL && skip > 0; mp = nmp) {
nmp = mp->mnt_list.tqe_next;
skip--;
}
}
for (count = 0, mp = mountlist.tqh_first; mp != NULL && count < maxcount; mp = nmp) {
nmp = mp->mnt_list.tqe_next;
if (sfsp && count < maxcount &&
((mp->mnt_flag & MNT_MLOCK) == 0)) {
struct ult_fs_data tem;
sp = &mp->mnt_stat;
/*
* If requested, refresh the fsstat cache.
*/
if ((mntflags & MNT_WAIT) &&
(error = VFS_STATFS(mp, sp, p)))
continue;
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if (!path || (strcmp(path, sp->f_mntonname) == 0))
{
make_ult_mntent(sp, &tem);
if (error = copyout((caddr_t)&tem, sfsp, sizeof(tem)))
goto bad;
sfsp += sizeof(tem);
count++;
}
}
}
if (sfsp && count > maxcount)
*retval = maxcount;
else
*retval = count;
return (0);
bad:
if (path)
FREE(path, M_NAMEI);
return(error);
}
#endif /*COMPAT_ULTRIX*/
------------------------------------------------------------------------------