Annotation of sys/compat/ultrix/ultrix_fs.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ultrix_fs.c,v 1.14 2006/03/05 21:48:56 miod Exp $ */
! 2: /* $NetBSD: ultrix_fs.c,v 1.4 1996/04/07 17:23:06 jonathan Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995
! 6: * Jonathan Stone (hereinafter referred to as the author)
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. The name of the author may not be used to endorse or promote products
! 17: * derived from this software without specific prior written permission.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
! 20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 22: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
! 23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 29: * SUCH DAMAGE.
! 30: */
! 31:
! 32: #include <sys/param.h>
! 33: #include <sys/systm.h>
! 34: #include <sys/malloc.h>
! 35: #include <sys/exec.h>
! 36: #include <sys/namei.h>
! 37: #include <sys/mount.h>
! 38: #include <net/if.h>
! 39: #include <netinet/in.h>
! 40:
! 41: #include <nfs/rpcv2.h>
! 42: #include <nfs/nfsproto.h>
! 43: #include <nfs/nfs.h>
! 44:
! 45: #include <sys/syscallargs.h>
! 46: #include <compat/ultrix/ultrix_syscallargs.h>
! 47:
! 48: #include <uvm/uvm_extern.h>
! 49:
! 50: #define ULTRIX_MAXPATHLEN 1024
! 51:
! 52: /**
! 53: ** Ultrix filesystem operations: mount(), getmnt().
! 54: ** These are included purely so one can place an (ECOFF or ELF)
! 55: ** NetBSD/pmax kernel in an Ultrix root filesystem, boot it,
! 56: ** and over-write the Ultrix root parition with NetBSD binaries.
! 57: **/
! 58:
! 59: /*
! 60: * Ultrix file system data structure, as modified by
! 61: * Ultrix getmntent(). This structure is padded to 2560 bytes, for
! 62: * compatibility with the size the Ultrix kernel and user apps expect.
! 63: */
! 64: struct ultrix_fs_data {
! 65: u_int32_t ufsd_flags; /* how mounted */
! 66: u_int32_t ufsd_mtsize; /* max transfer size in bytes */
! 67: u_int32_t ufsd_otsize; /* optimal transfer size in bytes */
! 68: u_int32_t ufsd_bsize; /* fs block size (bytes) for vm code */
! 69: u_int32_t ufsd_fstype; /* see ../h/fs_types.h */
! 70: u_int32_t ufsd_gtot; /* total number of gnodes */
! 71: u_int32_t ufsd_gfree; /* # of free gnodes */
! 72: u_int32_t ufsd_btot; /* total number of 1K blocks */
! 73: u_int32_t ufsd_bfree; /* # of free 1K blocks */
! 74: u_int32_t ufsd_bfreen; /* user consumable 1K blocks */
! 75: u_int32_t ufsd_pgthresh; /* min size in bytes before paging*/
! 76: int32_t ufsd_uid; /* uid that mounted me */
! 77: int16_t ufsd_dev; /* major/minor of fs */
! 78: int16_t ufsd_exroot; /* root mapping from exports */
! 79: char ufsd_devname[ULTRIX_MAXPATHLEN + 4]; /* name of dev */
! 80: char ufsd_path[ULTRIX_MAXPATHLEN + 4]; /* name of mnt point */
! 81: u_int32_t ufsd_nupdate; /* number of writes */
! 82: u_int32_t ufsd_pad[112]; /* pad to 2560 bytes. */
! 83: };
! 84:
! 85: /*
! 86: * Get statistics on mounted filesystems.
! 87: */
! 88: #if 0
! 89: struct ultrix_getmnt_args {
! 90: int32_t *start;
! 91: struct ultrix_fs_data *buf;
! 92: int32_t bufsize;
! 93: int32_t mode;
! 94: char *path;
! 95: };
! 96:
! 97: #endif
! 98: /*
! 99: * Ultrix getmnt() flags.
! 100: * The operation getmnt() should perform is incoded in the flag
! 101: * argument. There are two independent attributes.
! 102: *
! 103: * ULTRIX_NOSTAT_xxx will never hang, but it may not return
! 104: * up-to-date statistics. (For NFS clients, it returns whatever is
! 105: * in the cache.) ULTRIX_STAT_xxx returns up-to-date info but may
! 106: * hang (e.g., on dead NFS servers).
! 107: *
! 108: * ULTRIX_xxSTAT_ONE returns statistics on just one filesystem, determined
! 109: * by the parth argument. ULTRIX_xxSTAT_MANY ignores the path argument and
! 110: * returns info on as many filesystems fit in the structure.
! 111: * the start argument, which should be zero on the first call,
! 112: * can be used to iterate over all filesystems.
! 113: *
! 114: */
! 115: #define ULTRIX_NOSTAT_MANY 1
! 116: #define ULTRIX_STAT_MANY 2
! 117: #define ULTRIX_STAT_ONE 3
! 118: #define ULTRIX_NOSTAT_ONE 4
! 119:
! 120: /*
! 121: * Ultrix gnode-layer filesystem codes.
! 122: */
! 123: #define ULTRIX_FSTYPE_UNKNOWN 0x0
! 124: #define ULTRIX_FSTYPE_ULTRIX 0x1 /* Ultrix UFS: basically 4.2bsd FFS */
! 125: #define ULTRIX_FSTYPE_NFS 0x5 /* NFS v2 */
! 126:
! 127: /*
! 128: * Ultrix mount(2) options
! 129: */
! 130: #define ULTRIX_NM_RONLY 0x0001 /* mount read-only */
! 131: #define ULTRIX_NM_SOFT 0x0002 /* soft mount (hard is default) */
! 132: #define ULTRIX_NM_WSIZE 0x0004 /* set write size */
! 133: #define ULTRIX_NM_RSIZE 0x0008 /* set read size */
! 134: #define ULTRIX_NM_TIMEO 0x0010 /* set initial timeout */
! 135: #define ULTRIX_NM_RETRANS 0x0020 /* set number of request retries */
! 136: #define ULTRIX_NM_HOSTNAME 0x0040 /* set hostname for error printf */
! 137: #define ULTRIX_NM_PGTHRESH 0x0080 /* set page threshold for exec */
! 138: #define ULTRIX_NM_INT 0x0100 /* allow hard mount keyboard interrupts */
! 139: #define ULTRIX_NM_NOAC 0x0200 /* don't cache attributes */
! 140:
! 141:
! 142: /*
! 143: * Construct an Ultrix getmnt() ultrix_fs_data from the native NetBSD
! 144: * struct statfs.
! 145: */
! 146: static void
! 147: make_ultrix_mntent(sp, tem)
! 148: register struct statfs *sp;
! 149: register struct ultrix_fs_data *tem;
! 150: {
! 151:
! 152: bzero(tem, sizeof (*tem));
! 153:
! 154: tem->ufsd_flags = sp->f_flags; /* XXX translate */
! 155: tem->ufsd_mtsize = sp->f_bsize; /* XXX max transfer size */
! 156: tem->ufsd_otsize = sp->f_iosize;
! 157: tem->ufsd_bsize = sp->f_bsize;
! 158: /*
! 159: * Translate file system type. NetBSD/1.1 has f_type zero,
! 160: * and uses an fstype string instead.
! 161: * For now, map types not in Ultrix (kernfs, null, procfs...)
! 162: * to UFS, since Ultrix mout will try and call mount_unknown
! 163: * for ULTRIX_FSTYPE_UNKNOWN, but lacks a mount_unknown binary.
! 164: */
! 165: tem->ufsd_fstype = ULTRIX_FSTYPE_NFS;
! 166: if (strcmp(sp->f_fstypename, "ffs") == 0)
! 167: tem->ufsd_fstype = ULTRIX_FSTYPE_ULTRIX;
! 168:
! 169: tem->ufsd_gtot = sp->f_files; /* total "gnodes" */
! 170: tem->ufsd_gfree = sp->f_ffree; /* free "gnodes" */
! 171: tem->ufsd_btot = sp->f_blocks; /* total 1k blocks */
! 172: #ifdef needsmorethought /* XXX */
! 173: /* tem->ufsd_bfree = sp->f_bfree; */ /* free 1k blocks */
! 174: /* tem->ufsd_bfree = sp->f_bavail; */ /* free 1k blocks */
! 175: #endif
! 176:
! 177: tem->ufsd_bfreen = sp->f_bavail; /* blocks available to users */
! 178: tem->ufsd_pgthresh = 0; /* not relevant */
! 179: tem->ufsd_uid = 0; /* XXX kept where ?*/
! 180: tem->ufsd_dev = 0; /* ?? */
! 181: tem->ufsd_exroot = 0; /* ?? */
! 182: strlcpy(tem->ufsd_path, sp->f_mntonname, sizeof(tem->ufsd_path));
! 183: strlcpy(tem->ufsd_devname, sp->f_mntfromname,
! 184: sizeof(tem->ufsd_devname));
! 185: #if 0
! 186: /* In NetBSD-1.1, filesystem type is unused and always 0 */
! 187: printf("mntent: %s type %d\n", tem->ufsd_devname, tem->ufsd_fstype);
! 188: printf("mntent: %s tot %d free %d user%d\n",
! 189: tem->ufsd_devname, sp->f_blocks, sp->f_bfree, sp->f_bavail);
! 190: #endif
! 191: }
! 192:
! 193: int
! 194: ultrix_sys_getmnt(p, v, retval)
! 195: struct proc *p;
! 196: void *v;
! 197: int *retval;
! 198: {
! 199: struct ultrix_sys_getmnt_args *uap = v;
! 200: struct mount *mp, *nmp;
! 201: struct statfs *sp;
! 202: struct ultrix_fs_data *sfsp;
! 203: char *path;
! 204: int mntflags;
! 205: int skip;
! 206: int start;
! 207: long count, maxcount;
! 208: int error = 0;
! 209:
! 210: path = NULL;
! 211: error = 0;
! 212: maxcount = SCARG(uap, bufsize) / sizeof(struct ultrix_fs_data);
! 213: sfsp = SCARG(uap, buf);
! 214:
! 215: if (SCARG(uap, mode) == ULTRIX_STAT_ONE ||
! 216: SCARG(uap, mode) == ULTRIX_STAT_MANY)
! 217: mntflags = MNT_WAIT;
! 218: else
! 219: mntflags = MNT_NOWAIT;
! 220:
! 221: if (SCARG(uap, mode) == ULTRIX_STAT_ONE || SCARG(uap, mode) == ULTRIX_NOSTAT_ONE) {
! 222: /*
! 223: * Only get info on mountpoints that matches the path
! 224: * provided.
! 225: */
! 226: MALLOC(path, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
! 227: if ((error = copyinstr(SCARG(uap, path), path,
! 228: MAXPATHLEN, NULL)) != 0)
! 229: goto bad;
! 230: maxcount = 1;
! 231: } else {
! 232: /*
! 233: * Get info on any mountpoints, somewhat like readdir().
! 234: * Find out how many mount list entries to skip, and skip
! 235: * them.
! 236: */
! 237: if ((error = copyin((caddr_t)SCARG(uap, start), &start,
! 238: sizeof(*SCARG(uap, start)))) != 0)
! 239: goto bad;
! 240: for (skip = start, mp = CIRCLEQ_FIRST(&mountlist);
! 241: mp != CIRCLEQ_END(&mountlist) && skip-- > 0; mp = nmp)
! 242: nmp = CIRCLEQ_NEXT(mp, mnt_list);
! 243: }
! 244:
! 245: for (count = 0, mp = CIRCLEQ_FIRST(&mountlist);
! 246: mp != CIRCLEQ_END(&mountlist) && count < maxcount; mp = nmp) {
! 247: nmp = CIRCLEQ_NEXT(mp, mnt_list);
! 248: if (sfsp != NULL) {
! 249: struct ultrix_fs_data tem;
! 250: sp = &mp->mnt_stat;
! 251:
! 252: /*
! 253: * If requested, refresh the fsstat cache.
! 254: */
! 255: if ((mntflags & MNT_WAIT) != 0 &&
! 256: (error = VFS_STATFS(mp, sp, p)) != 0)
! 257: continue;
! 258:
! 259: /*
! 260: * XXX what does this do? -- cgd
! 261: */
! 262: sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
! 263: if (path == NULL ||
! 264: strcmp(path, sp->f_mntonname) == 0) {
! 265: make_ultrix_mntent(sp, &tem);
! 266: if ((error = copyout((caddr_t)&tem, sfsp,
! 267: sizeof(tem))) != 0)
! 268: goto bad;
! 269: sfsp++;
! 270: count++;
! 271: }
! 272: }
! 273: }
! 274:
! 275: if (sfsp != NULL && count > maxcount)
! 276: *retval = maxcount;
! 277: else
! 278: *retval = count;
! 279:
! 280: bad:
! 281: if (path)
! 282: FREE(path, M_TEMP);
! 283: return (error);
! 284: }
! 285:
! 286:
! 287:
! 288: /* Old-style inet sockaddr (no len field) as passed to Ultrix mount(2) */
! 289: struct osockaddr_in {
! 290: short sin_family;
! 291: u_short sin_port;
! 292: struct in_addr sin_addr;
! 293: char sin_zero[8];
! 294: };
! 295:
! 296:
! 297: /*
! 298: * fstype-dependent structure passed to Ultrix mount(2) when
! 299: * mounting NFS filesystems
! 300: */
! 301: struct ultrix_nfs_args {
! 302: struct osockaddr_in *addr; /* file server address */
! 303: void *fh; /* file handle to be mounted */
! 304: int flags; /* flags */
! 305: int wsize; /* write size in bytes */
! 306: int rsize; /* read size in bytes */
! 307: int timeo; /* initial timeout in .1 secs */
! 308: int retrans; /* times to retry send */
! 309: char *hostname; /* server's hostname */
! 310: char *optstr; /* string of nfs mount options*/
! 311: int gfs_flags; /* gnode flags (ugh) */
! 312: int pg_thresh; /* paging threshold ? */
! 313: };
! 314:
! 315:
! 316: /*
! 317: * fstype-dependent structure passed to Ultrix mount(2) when
! 318: * mounting local (4.2bsd FFS) filesystems
! 319: */
! 320: struct ultrix_ufs_args {
! 321: u_long ufs_flags; /* mount flags?*/
! 322: u_long ufs_pgthresh; /* minimum file size to page */
! 323: };
! 324:
! 325: int
! 326: ultrix_sys_mount(p, v, retval)
! 327: struct proc *p;
! 328: void *v;
! 329: int *retval;
! 330: {
! 331: struct ultrix_sys_mount_args *uap = v;
! 332:
! 333: int error;
! 334: int otype = SCARG(uap, type);
! 335: char fsname[MFSNAMELEN];
! 336: char * fstype;
! 337: struct sys_mount_args nuap;
! 338: caddr_t sg = stackgap_init(p->p_emul);
! 339: caddr_t usp = stackgap_alloc(&sg, 1024 /* XXX */);
! 340:
! 341: bzero(&nuap, sizeof(nuap));
! 342: SCARG(&nuap, flags) = 0;
! 343:
! 344: /*
! 345: * Translate Ultrix integer mount codes for UFS and NFS to
! 346: * NetBSD fstype strings. Other Ultrix filesystem types
! 347: * (msdos, DEC ods-2) are not supported.
! 348: */
! 349: if (otype == ULTRIX_FSTYPE_ULTRIX)
! 350: fstype = "ufs";
! 351: else if (otype == ULTRIX_FSTYPE_NFS)
! 352: fstype = "nfs";
! 353: else
! 354: return (EINVAL);
! 355:
! 356: /* Translate the Ultrix mount-readonly option parameter */
! 357: if (SCARG(uap, rdonly))
! 358: SCARG(&nuap, flags) |= MNT_RDONLY;
! 359:
! 360: /* Copy string-ified version of mount type back out to user space */
! 361: SCARG(&nuap, type) = (char *)usp;
! 362: if ((error = copyout(fstype, (void *)SCARG(&nuap, type),
! 363: strlen(fstype)+1)) != 0) {
! 364: return (error);
! 365: }
! 366: usp += strlen(fstype)+1;
! 367:
! 368: #ifdef later
! 369: parse ultrix mount option string and set NetBSD flags
! 370: #endif
! 371: SCARG(&nuap, path) = SCARG(uap, dir);
! 372:
! 373: if (otype == ULTRIX_FSTYPE_ULTRIX) {
! 374: /* attempt to mount a native, rather than 4.2bsd, ffs */
! 375: struct ufs_args ua;
! 376:
! 377: ua.fspec = SCARG(uap, special);
! 378: bzero(&ua.export_info, sizeof(ua.export_info));
! 379: SCARG(&nuap, data) = usp;
! 380:
! 381: if ((error = copyout(&ua, SCARG(&nuap, data),
! 382: sizeof ua)) !=0) {
! 383: return(error);
! 384: }
! 385: /*
! 386: * Ultrix mount has no MNT_UPDATE flag.
! 387: * Attempt to see if this is the root we're mounting,
! 388: * and if so, set MNT_UPDATE so we can mount / read-write.
! 389: */
! 390: fsname[0] = 0;
! 391: if ((error = copyinstr((caddr_t)SCARG(&nuap, path), fsname,
! 392: sizeof fsname, (u_int *)0)) != 0)
! 393: return(error);
! 394: if (strcmp(fsname, "/") == 0) {
! 395: SCARG(&nuap, flags) |= MNT_UPDATE;
! 396: printf("COMPAT_ULTRIX: mount with MNT_UPDATE on %s\n",
! 397: fsname);
! 398: }
! 399: } else if (otype == ULTRIX_FSTYPE_NFS) {
! 400: struct ultrix_nfs_args una;
! 401: struct nfs_args na;
! 402: struct osockaddr_in osa;
! 403: struct sockaddr_in *sap = (struct sockaddr_in *)& osa;
! 404:
! 405: bzero(&osa, sizeof(osa));
! 406: bzero(&una, sizeof(una));
! 407: if ((error = copyin(SCARG(uap, data), &una, sizeof una)) !=0) {
! 408: return (error);
! 409: }
! 410: /*
! 411: * This is the only syscall boundary the
! 412: * address of the server passes, so do backwards
! 413: * compatibility on 4.3style sockaddrs here.
! 414: */
! 415: if ((error = copyin(una.addr, &osa, sizeof osa)) != 0) {
! 416: printf("ultrix_mount: nfs copyin osa\n");
! 417: return (error);
! 418: }
! 419: sap->sin_family = (u_char)osa.sin_family;
! 420: sap->sin_len = sizeof(*sap);
! 421: /* allocate space above caller's stack for nfs_args */
! 422: SCARG(&nuap, data) = usp;
! 423: usp += sizeof (na);
! 424: /* allocate space above caller's stack for server sockaddr */
! 425: na.version = NFS_ARGSVERSION;
! 426: na.addr = (struct sockaddr *)usp;
! 427: usp += sizeof(*sap);
! 428: na.addrlen = sap->sin_len;
! 429: na.sotype = SOCK_DGRAM;
! 430: na.proto = IPPROTO_UDP;
! 431: na.fh = una.fh;
! 432: na.fhsize = NFSX_V2FH;
! 433: na.flags = /*una.flags;*/ NFSMNT_NOCONN;
! 434: na.wsize = una.wsize;
! 435: na.rsize = una.rsize;
! 436: na.timeo = una.timeo;
! 437: na.retrans = una.retrans;
! 438: na.hostname = una.hostname;
! 439: if ((error = copyout(sap, na.addr, sizeof (*sap) )) != 0)
! 440: return (error);
! 441: if ((error = copyout(&na, SCARG(&nuap, data), sizeof na)) != 0)
! 442: return (error);
! 443: }
! 444: return (sys_mount(p, &nuap, retval));
! 445: }
CVSweb