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;
}
}