--- /dev/null
+/*
+ * Copyright 2010, Sine Nomine Associates and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License. For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#include <afsconfig.h>
+#include "afs/param.h"
+
+/* ioctl-based emulation for the AFS syscall, for Solaris 11 and onwards. */
+
+#ifdef AFS_SUN511_ENV
+
+#include "afs/sysincludes.h" /* Standard vendor system headers */
+#include "afsincludes.h" /* Afs-based standard headers */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/errno.h>
+#include <sys/open.h>
+#include <sys/cred.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+
+#define DEVAFS_MINOR 0
+
+static int
+devafs_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
+{
+ if (getminor(*devp) != DEVAFS_MINOR) {
+ return EINVAL;
+ }
+ if (otyp != OTYP_CHR) {
+ return EINVAL;
+ }
+ return 0;
+}
+
+static int
+devafs_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
+{
+ if (getminor(dev) != DEVAFS_MINOR) {
+ return EINVAL;
+ }
+ if (otyp != OTYP_CHR) {
+ return EINVAL;
+ }
+ return 0;
+}
+
+static int
+devafs_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
+ int *rval_p)
+{
+ int error;
+ struct afssysa ua;
+ rval_t rv;
+
+ if (getminor(dev) != DEVAFS_MINOR) {
+ return EINVAL;
+ }
+
+ switch (cmd) {
+ case VIOC_SYSCALL: {
+ struct afssysargs sargs;
+ error = ddi_copyin((const void *)arg, &sargs, sizeof(sargs), mode);
+ if (error) {
+ return EFAULT;
+ }
+ ua.syscall = sargs.syscall;
+ ua.parm1 = sargs.param1;
+ ua.parm2 = sargs.param2;
+ ua.parm3 = sargs.param3;
+ ua.parm4 = sargs.param4;
+ ua.parm5 = sargs.param5;
+ ua.parm6 = sargs.param6;
+
+ break;
+ }
+ case VIOC_SYSCALL32: {
+ struct afssysargs32 sargs32;
+ error = ddi_copyin((const void *)arg, &sargs32, sizeof(sargs32), mode);
+ if (error) {
+ return EFAULT;
+ }
+ ua.syscall = sargs32.syscall;
+ ua.parm1 = sargs32.param1;
+ ua.parm2 = sargs32.param2;
+ ua.parm3 = sargs32.param3;
+ ua.parm4 = sargs32.param4;
+ ua.parm5 = sargs32.param5;
+ ua.parm6 = sargs32.param6;
+
+ break;
+ }
+ default:
+ return EINVAL;
+ }
+
+ rv.r_val1 = 0;
+ error = Afs_syscall(&ua, &rv);
+
+ if (!error) {
+ error = rv.r_val1;
+ }
+
+ return error;
+}
+
+static struct cb_ops devafs_cb_ops = {
+ /* .cb_open = */ devafs_open,
+ /* .cb_close = */ devafs_close,
+ /* .cb_strategy = */ nodev,
+ /* .cb_print = */ nodev,
+ /* .cb_dump = */ nodev,
+ /* .cb_read = */ nodev,
+ /* .cb_write = */ nodev,
+ /* .cb_ioctl = */ devafs_ioctl,
+ /* .cb_devmap = */ nodev,
+ /* .cb_mmap = */ nodev,
+ /* .cb_segmap = */ nodev,
+ /* .cb_chpoll = */ nochpoll,
+ /* .cb_prop_op = */ ddi_prop_op,
+ /* .cb_str = */ NULL,
+ /* .cb_flag = */ D_NEW | D_MP | D_64BIT,
+ /* .cb_rev = */ CB_REV,
+ /* .cb_aread = */ nodev,
+ /* .cb_awrite = */ nodev,
+};
+
+static dev_info_t *devafs_dip = NULL;
+
+static int
+devafs_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
+{
+ switch (cmd) {
+ case DDI_INFO_DEVT2DEVINFO:
+ *resultp = devafs_dip;
+ return DDI_SUCCESS;
+ case DDI_INFO_DEVT2INSTANCE:
+ *resultp = 0; /* we only have one instance */
+ return DDI_SUCCESS;
+ default:
+ return DDI_FAILURE;
+ }
+}
+
+static int
+devafs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+ int error;
+ switch (cmd) {
+ case DDI_ATTACH:
+ osi_Assert(devafs_dip == NULL);
+
+ error = ddi_create_minor_node(dip, "afs", S_IFCHR, DEVAFS_MINOR,
+ DDI_PSEUDO, 0);
+ if (error != DDI_SUCCESS) {
+ return DDI_FAILURE;
+ }
+
+ devafs_dip = dip;
+
+ ddi_report_dev(dip);
+
+ return DDI_SUCCESS;
+ case DDI_RESUME:
+ return DDI_FAILURE;
+ default:
+ return DDI_FAILURE;
+ }
+}
+
+static int
+devafs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+ switch (cmd) {
+ case DDI_DETACH:
+ osi_Assert(devafs_dip != NULL);
+
+ devafs_dip = NULL;
+
+ ddi_prop_remove_all(dip);
+ ddi_remove_minor_node(dip, NULL);
+
+ return DDI_SUCCESS;
+ case DDI_SUSPEND:
+ return DDI_FAILURE;
+ default:
+ return DDI_FAILURE;
+ }
+}
+
+static struct dev_ops afs_devops = {
+ /* .devo_rev = */ DEVO_REV,
+ /* .devo_refcnt = */ 0,
+ /* .devo_getinfo = */ devafs_getinfo,
+ /* .devo_identify = */ nulldev,
+ /* .devo_probe = */ nulldev,
+ /* .devo_attach = */ devafs_attach,
+ /* .devo_detach = */ devafs_detach,
+ /* .devo_reset = */ nodev,
+ /* .devo_cb_ops = */ &devafs_cb_ops,
+ /* .devo_bus_ops = */ NULL,
+ /* .devo_power = */ NULL,
+ /* .devo_quiesce = */ ddi_quiesce_not_needed,
+};
+
+extern struct mod_ops mod_driverops;
+
+struct modldrv afs_modldrv = {
+ &mod_driverops,
+ "/dev/afs driver",
+ &afs_devops,
+};
+
+#endif /* AFS_SUN511_ENV */
};
#endif
+#ifndef AFS_SUN511_ENV
static struct sysent afssysent = {
6,
0,
Afs_syscall
};
+#endif /* AFS_SUN511_ENV */
/* inter-module dependencies */
char _depends_on[] = "drv/ip drv/udp strmod/rpcmod";
* Info/Structs to link the afs module into the kernel
*/
extern struct mod_ops mod_fsops;
-extern struct mod_ops mod_syscallops;
static struct modlfs afsmodlfs = {
&mod_fsops,
#endif
};
+#ifdef AFS_SUN511_ENV
+
+extern struct modldrv afs_modldrv;
+
+#else /* AFS_SUN511_ENV */
+
+extern struct mod_ops mod_syscallops;
static struct modlsys afsmodlsys = {
&mod_syscallops,
"afs syscall interface",
* land here from sysent or sysent32
*/
-#if defined(AFS_SUN57_64BIT_ENV)
+# if defined(AFS_SUN57_64BIT_ENV)
extern struct mod_ops mod_syscallops32;
static struct modlsys afsmodlsys32 = {
"afs syscall interface(32 bit)",
&afssysent
};
-#endif
+# endif
+#endif /* !AFS_SUN511_ENV */
static struct modlinkage afs_modlinkage = {
MODREV_1,
+ (void *)&afsmodlfs,
+#ifdef AFS_SUN511_ENV
+ (void *)&afs_modldrv,
+#else
(void *)&afsmodlsys,
-#ifdef AFS_SUN57_64BIT_ENV
+# ifdef AFS_SUN57_64BIT_ENV
(void *)&afsmodlsys32,
-#endif
- (void *)&afsmodlfs,
+# endif
+#endif /* !AFS_SUN511_ENV */
NULL
};
#endif /* AFS_SUN52_ENV */
#endif /* AFS_SUN55_ENV */
#endif /* !AFS_NONFSTRANS */
-#if !defined(AFS_SUN58_ENV)
+
+#ifndef AFS_SUN511_ENV
+ /* syscall initialization stff */
+
+# if !defined(AFS_SUN58_ENV)
/*
* Re-read the /etc/name_to_sysnum file to make sure afs isn't added after
* reboot. Ideally we would like to call modctl_read_sysbinding_file() but
* proper slot entry and we also actually have to properly initialize the
* global sysent[AFS_SYSCALL] entry!
*/
-#ifdef AFS_SUN53_ENV
-#ifndef SYSBINDFILE
-#define SYSBINDFILE "/etc/name_to_sysnum"
-#endif /* SYSBINDFILE */
+# ifdef AFS_SUN53_ENV
+# ifndef SYSBINDFILE
+# define SYSBINDFILE "/etc/name_to_sysnum"
+# endif /* SYSBINDFILE */
read_binding_file(SYSBINDFILE, sb_hashtab);
-#else /* !AFS_SUN53_ENV */
+# else /* !AFS_SUN53_ENV */
read_binding_file(sysbind, sb_hashtab);
-#endif /* AFS_SUN53_ENV */
+# endif /* AFS_SUN53_ENV */
make_syscallname("afs", AFS_SYSCALL);
if (sysent[AFS_SYSCALL].sy_call == nosys) {
sysent[AFS_SYSCALL].sy_lock =
(krwlock_t *) kobj_zalloc(sizeof(krwlock_t), KM_SLEEP);
rw_init(sysent[AFS_SYSCALL].sy_lock, "afs_syscall",
-#ifdef AFS_SUN57_ENV
+# ifdef AFS_SUN57_ENV
RW_DEFAULT, NULL);
-#else /* !AFS_SUN57_ENV */
+# else /* !AFS_SUN57_ENV */
RW_DEFAULT, DEFAULT_WT);
-#endif /* AFS_SUN57_ENV */
+# endif /* AFS_SUN57_ENV */
}
}
-#endif /* !AFS_SUN58_ENV */
+# endif /* !AFS_SUN58_ENV */
+#endif /* !AFS_SUN511_ENV */
osi_Init(); /* initialize global lock, etc */
cred->cr_rgid = gid;
}
#endif
+
+#ifdef AFS_SUN5_ENV
+
+/** The 32 bit OS expects the members of this structure to be 32 bit
+ * quantities and the 64 bit OS expects them as 64 bit quanties. Hence
+ * to accomodate both, *long* is used instead of afs_int32
+ */
+
+# ifdef AFS_SUN57_ENV
+struct afssysa {
+ long syscall;
+ long parm1;
+ long parm2;
+ long parm3;
+ long parm4;
+ long parm5;
+ long parm6;
+};
+# else
+struct afssysa {
+ afs_int32 syscall;
+ afs_int32 parm1;
+ afs_int32 parm2;
+ afs_int32 parm3;
+ afs_int32 parm4;
+ afs_int32 parm5;
+ afs_int32 parm6;
+};
+# endif
+extern int Afs_syscall(struct afssysa *uap, rval_t *rvp);
+#endif /* AFS_SUN5_ENV */
+
#endif /* _AFS_H_ */
#ifdef AFS_SUN5_ENV
extern int afs_sinited;
-/** The 32 bit OS expects the members of this structure to be 32 bit
- * quantities and the 64 bit OS expects them as 64 bit quanties. Hence
- * to accomodate both, *long* is used instead of afs_int32
- */
-
-# ifdef AFS_SUN57_ENV
-struct afssysa {
- long syscall;
- long parm1;
- long parm2;
- long parm3;
- long parm4;
- long parm5;
- long parm6;
-};
-# else
-struct afssysa {
- afs_int32 syscall;
- afs_int32 parm1;
- afs_int32 parm2;
- afs_int32 parm3;
- afs_int32 parm4;
- afs_int32 parm5;
- afs_int32 parm6;
-};
-# endif
-
Afs_syscall(struct afssysa *uap, rval_t * rvp)
{
int *retval = &rvp->r_val1;
case $1 in
'start')
-#
-# Make sure afs exists in /etc/name_to_sysnum
-#
-if grep -s "afs" /etc/name_to_sysnum > /dev/null; then
- echo "Entry for afs already exists in /etc/name_to_sysnum"
-else
- echo "Creating entry for afs in /etc/name_to_sysnum"
- cp /etc/name_to_sysnum /etc/name_to_sysnum.orig
- sed '/nfs/i\
-afs 65' /etc/name_to_sysnum > /tmp/name_to_sysnum
- mv /tmp/name_to_sysnum /etc/name_to_sysnum
- echo "Rebooting now for new /etc/name_to_sysnum to take effect"
- reboot
-fi
-
## Check to see that /bin/isalist exists and is executable
if [ ! -x /bin/isalist ] ;then
echo "/bin/isalist not executable"
case `/bin/isalist` in
*amd64* )
nfssrv=/kernel/misc/amd64/nfssrv
- afs=/kernel/fs/amd64/afs ;;
+ afs=/kernel/drv/amd64/afs ;;
*sparcv9* )
nfssrv=/kernel/misc/sparcv9/nfssrv
- afs=/kernel/fs/sparcv9/afs ;;
+ afs=/kernel/drv/sparcv9/afs ;;
* )
nfssrv=/kernel/misc/nfssrv
- afs=/kernel/fs/afs ;;
+ afs=/kernel/drv/afs ;;
esac
## Load AFS kernel extensions
if [ -f $afs ]; then
- echo "Loading AFS kernel extensions"
- modload $afs
+ if [ -f /kernel/drv/afs.conf ] ; then
+ echo "Kernel afs.conf already exists"
+ else
+ echo "Creating kernel afs.conf"
+ echo 'name="afs" parent="pseudo";' > /kernel/drv/afs.conf
+ fi
+
+ # load the module
+ if grep '^afs ' /etc/name_to_major >/dev/null ; then
+ echo "Loading AFS kernel extensions"
+ modload $afs
+ # this can sometimes be necessary to get the /devices afs device to
+ # attach
+ update_drv afs
+ else
+ echo "Installing AFS driver and loading kernel extensions"
+ add_drv -m '* 0666 root root' afs
+ fi
+
+ # Create the /dev/afs link
+ if grep name=afs /etc/devlink.tab >/dev/null ; then
+ echo "Entry for afs already exists in /etc/devlink.tab"
+ else
+ echo "Adding entry for afs in /etc/devlink.tab"
+ echo "type=ddi_pseudo;name=afs;addr=0;minor=afs \D" >> /dev/devlink.tab
+ devfsadm
+ fi
else
echo "$afs does not exist. Skipping AFS startup."
exit 1
#
# Stop the AFS inetd and server processes
-# Note that the afsd processes cannot be killed
+# We do not kill the afsd process here. It should be possible to do now, but we
+# don't do it yet. Note that you need to parse 'modinfo | grep afs' output and
+# give the id to modunload, in order to unload the kernel module.
#
echo "Killing inetd.afs"
#endif
error=syscall_data.retval;
}
+# elif defined(AFS_SUN511_ENV)
+ {
+ int rval;
+ rval = ioctl_sun_afs_syscall(AFSCALL_CALL, param1, param2, param3,
+ param4, param5, param6, &error);
+ if (rval) {
+ error = rval;
+ }
+ }
# else /* AFS_DARWIN80_ENV */
error =
syscall(AFS_SYSCALL, AFSCALL_CALL, param1, param2, param3, param4,
#define SYSCALL_DEV_FNAME "/dev/openafs_ioctl"
#endif
+#ifdef AFS_SUN511_ENV
+# define VIOC_SYSCALL_TYPE 'C'
+# define VIOC_SYSCALL _IOW(VIOC_SYSCALL_TYPE, 1, struct afssysargs)
+# define VIOC_SYSCALL32 _IOW(VIOC_SYSCALL_TYPE, 2, struct afssysargs32)
+# define SYSCALL_DEV_FNAME "/dev/afs"
+
+struct afssysargs {
+ afs_uint64 param6;
+ afs_uint64 param5;
+ afs_uint64 param4;
+ afs_uint64 param3;
+ afs_uint64 param2;
+ afs_uint64 param1;
+ afs_uint32 syscall;
+};
+
+struct afssysargs32 {
+ afs_uint32 param6;
+ afs_uint32 param5;
+ afs_uint32 param4;
+ afs_uint32 param3;
+ afs_uint32 param2;
+ afs_uint32 param1;
+ afs_uint32 syscall;
+};
+#endif /* AFS_SUN511_ENV */
+
#ifdef AFS_CACHE_VNODE_PATH
#define AFS_CACHE_CELLS_INODE -2
#define AFS_CACHE_ITEMS_INODE -3
#define RXK_LISTENER_ENV 1
#define AFS_GCPAGS 1 /* if nonzero, garbage collect PAGs */
-#define AFS_SYSCALL 65
-
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"
#define AFS_USERSPACE_IP_ADDR 1
#define AFS_GCPAGS 0 /* if nonzero, garbage collect PAGs */
+/* so we get _IOW() when we include sys/ioctl.h */
+#define BSD_COMP
+
#define UKERNEL 1 /* user space kernel */
#define AFS_GREEDY43_ENV 1 /* Used only in rx/rx_user.c */
#define AFS_ENV 1
#endif
#define AFS_3DISPARES 1 /* Utilize the 3 available disk inode 'spares' */
-#define AFS_SYSCALL 65
+
+/* so we get _IOW() when we include sys/ioctl.h */
+#define BSD_COMP
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS 1
#define AFS_3DISPARES 1 /* Utilize the 3 available disk inode 'spares' */
#endif /* AFS_NAMEI_ENV */
-#define AFS_SYSCALL 65
+/* so we get _IOW() when we include sys/ioctl.h */
+#define BSD_COMP
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"
#endif
#define AFS_3DISPARES 1 /* Utilize the 3 available disk inode 'spares' */
-#define AFS_SYSCALL 65
+
+/* so we get _IOW() when we include sys/ioctl.h */
+#define BSD_COMP
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS 1
osi_gcpags.o \
osi_groups.o \
osi_inode.o \
+<sunx86_511 sun4x_511>
+ osi_ioctl.o \
+<all>
osi_file.o \
osi_sleep.o \
osi_vcache.o \
return 0;
}
#endif
+
+#ifdef AFS_SUN511_ENV
+int
+ioctl_sun_afs_syscall(long syscall, uintptr_t param1, uintptr_t param2,
+ uintptr_t param3, uintptr_t param4, uintptr_t param5,
+ uintptr_t param6, int *error)
+{
+ void *ioctldata;
+ long callnum;
+ int fd, code;
+
+# ifdef _ILP32
+ struct afssysargs32 sargs32;
+ sargs32.syscall = syscall;
+ sargs32.param1 = param1;
+ sargs32.param2 = param2;
+ sargs32.param3 = param3;
+ sargs32.param4 = param4;
+ sargs32.param5 = param5;
+ sargs32.param6 = param6;
+
+ ioctldata = &sargs32;
+ callnum = VIOC_SYSCALL32;
+# else /* _ILP32 */
+ struct afssysargs sargs;
+ sargs.syscall = syscall;
+ sargs.param1 = param1;
+ sargs.param2 = param2;
+ sargs.param3 = param3;
+ sargs.param4 = param4;
+ sargs.param5 = param5;
+ sargs.param6 = param6;
+
+ ioctldata = &sargs;
+ callnum = VIOC_SYSCALL;
+# endif /* !_ILP32 */
+
+ fd = open(SYSCALL_DEV_FNAME, O_RDWR);
+ if (fd < 0) {
+ return -1;
+ }
+
+ *error = 0;
+
+ code = ioctl(fd, callnum, ioctldata);
+ close(fd);
+
+ if (code) {
+ errno = code;
+ *error = code;
+ }
+
+ return 0;
+}
+#endif /* AFS_SUN511_ENV */
follow, 0, 0, &errcode);
if (rval)
errcode = rval;
+#elif defined(AFS_SUN511_ENV)
+ rval = ioctl_sun_afs_syscall(AFSCALL_PIOCTL, (uintptr_t)path, cmd,
+ (uintptr_t)cmarg, follow, 0, 0, &errcode);
+ if (rval) {
+ errcode = rval;
+ }
#else
errcode = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, path, cmd, cmarg, follow);
#endif
if (rval) {
errorcode = rval;
}
+#elif defined(AFS_SUN511_ENV)
+ int rval;
+
+ rval = ioctl_sun_afs_syscall(AFSCALL_SETPAG,0,0,0,0,0,0,&errcode);
+ if (rval) {
+ errcode = rval;
+ }
#else
errcode = syscall(AFS_SYSCALL, AFSCALL_SETPAG);
#endif
#ifdef AFS_DARWIN80_ENV
extern int ioctl_afs_syscall(long, long, long, long, long, long, long, int *);
#endif
+#ifdef AFS_SUN511_ENV
+extern int ioctl_sun_afs_syscall(long, uintptr_t, uintptr_t, uintptr_t,
+ uintptr_t, uintptr_t, uintptr_t, int*);
+#endif
/* pioctl.c */
extern int lpioctl(char *, int, void *, int);
}
#endif
-#ifndef AFS_NT40_ENV
+#ifdef AFS_NT40_ENV
+/* no volser_syscall */
+#elif defined(AFS_SUN511_ENV)
+int
+volser_syscall(afs_uint32 a3, afs_uint32 a4, void *a5)
+{
+ int err, code;
+ code = ioctl_sun_afs_syscall(28 /* AFSCALL_CALL */, a3, a4, a5, 0, 0, 0,
+ &err);
+ if (code) {
+ err = code;
+ }
+ return err;
+}
+#else
int
volser_syscall(afs_uint32 a3, afs_uint32 a4, void *a5)
{