COMMAND

    tmpfs

SYSTEMS AFFECTED

    SunOS 4.1.4

PROBLEM

    Yamamori Takenori found SunOS4.1.4 another tmpfs bug.

        (/tmp is mounted as tmpfs)
        $ cd /tmp
        $ mkdir aaa
        $ chmod -w aaa
        $ cd aaa
        $ ln -s bbb ccc    # should be symbolic-link (not hard-link)

    and then

        panic: kmem_free: block already free

SOLUTION

    Takenori made a tmpfs-bug-fix program for other problem. Modloaded
    this program  on the  SunOS4.1.4 kernel  fixed this  bug.  URL for
    fix:


        http://www.tt.rim.or.jp/~yamamori/sun/tmpfs-symlink-fix.tar.gz

    Fix follows:

    /* tmpfs-symlink-fix.c */

    #define KERNEL
                         /* change here */
    #define sun4c
    #define __sun4c__   /* for the use of gcc's fix-include */
    /* #define sun4m */
    /* #define __sun4m__ */


    #include <sys/types.h>
    #include <sys/conf.h>
    #include <sys/buf.h>
    #include <sys/param.h>
    #include <sys/errno.h>
    #include <sys/user.h>
    #include <sys/time.h>
    #include <sys/vfs.h>
    #include <sys/vnode.h>
    #include <sys/ucred.h>
    #include <sys/syslog.h>
    #include <sundev/mbvar.h>
    #include <sun/autoconf.h>
    #include <sun/vddrv.h>

    extern  struct vnodeops tmp_vnodeops;

    static struct vdldrv vd = {
      VDMAGIC_PSEUDO,      /* Drv_magic */
      "tmpfs-symlink-fix"  /* Drv_name  */
      /* unused members */
    };

    static int (*real_tmp_symlink)();

    int
    wrap_tmp_symlink(
      struct vnode *vn,
      char *l_name,
      int *va,
      char *t_name,
      struct ucred *cred
    ) {

      struct vnode *vn1;
      int err;

    #ifdef DEBUG
      printf("tmp_symlink: l_name=%s t_name=%s va=%x\n", l_name, t_name, *va);
    #endif

      if ((err = VOP_MKDIR(vn, l_name, va, &vn1, cred)) != 0) {
        return err;
      }
      VOP_RMDIR(vn, l_name, cred);
      return real_tmp_symlink(vn, l_name, va, t_name, cred);
    }


    int
    xxxinit(
      unsigned int function_code,
      struct vddrv *vdp,
      addr_t vdi,
      struct vdstat *vds
    ) {

      int x;

      switch(function_code) {
        case VDLOAD:
          vdp->vdd_vdtab = (struct vdlinkage*)&vd;

          x = splhigh();
          real_tmp_symlink = tmp_vnodeops.vn_symlink;
          tmp_vnodeops.vn_symlink = wrap_tmp_symlink;
          splx(x);

          log(LOG_INFO, "tmpfs symlink-fix module loaded\n");
          return 0;

        case VDUNLOAD:
          x = splhigh();
          tmp_vnodeops.vn_symlink = real_tmp_symlink;
          splx(x);

          log(LOG_INFO, "tmpfs symlink-fix module unloaded\n");
          return 0;

        case VDSTAT:
          return 0;

        default:
          return EIO;
      }
    }