#include "afsincludes.h" /* Afs-based standard headers */
#include "afs/afs_stats.h" /* afs statistics */
#include "afs/vice.h"
+#include "afs/afs_bypasscache.h"
#include "rx/rx_globals.h"
struct VenusFid afs_rootFid;
short afs_waitForeverCount = 0;
afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
+#ifdef AFS_DISCON_ENV
+afs_int32 afs_is_disconnected;
+afs_int32 afs_is_logging;
+afs_int32 afs_is_discon_rw;
+/* On reconnection, turn this knob on until it finishes,
+ * then turn it off.
+ */
+afs_int32 afs_in_sync = 0;
+#endif
+
+/*!
+ * \defgroup pioctl Path IOCTL functions
+ *
+ * DECL_PIOCTL is a macro defined to contain the following parameters for functions:
+ *
+ * \param[in] avc the AFS vcache structure in use by pioctl
+ * \param[in] afun not in use
+ * \param[in] areq the AFS vrequest structure
+ * \param[in] ain as defined by the function
+ * \param[in] aout as defined by the function
+ * \param[in] ainSize size of ain
+ * \param[in] aoutSize size of aout
+ * \param[in] acred UNIX credentials structure underlying the operation
+ */
+
#define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
struct AFS_UCRED **acred)
DECL_PIOCTL(PSetCellStatus);
DECL_PIOCTL(PFlushVolumeData);
DECL_PIOCTL(PGetVnodeXStatus);
+DECL_PIOCTL(PGetVnodeXStatus2);
DECL_PIOCTL(PSetSysName);
DECL_PIOCTL(PSetSPrefs);
DECL_PIOCTL(PSetSPrefs33);
DECL_PIOCTL(PRxStatProc);
DECL_PIOCTL(PRxStatPeer);
DECL_PIOCTL(PPrefetchFromTape);
-DECL_PIOCTL(PResidencyCmd);
+DECL_PIOCTL(PFsCmd);
DECL_PIOCTL(PCallBackAddr);
+DECL_PIOCTL(PDiscon);
+DECL_PIOCTL(PNFSNukeCreds);
+DECL_PIOCTL(PNewUuid);
+DECL_PIOCTL(PPrecache);
+#if defined(AFS_CACHE_BYPASS)
+DECL_PIOCTL(PSetCachingThreshold);
+DECL_PIOCTL(PSetCachingBlkSize);
+#endif
/*
* A macro that says whether we're going to need HandleClientContext().
static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
struct AFS_UCRED *acred);
+typedef int (*pioctlFunction) (struct vcache *, int, struct vrequest *,
+ char *, char *, afs_int32, afs_int32 *,
+ struct AFS_UCRED **);
-static int (*(VpioctlSw[])) () = {
+static pioctlFunction VpioctlSw[] = {
PBogus, /* 0 */
PSetAcl, /* 1 */
PGetAcl, /* 2 */
PBogus, /* 64 -- arla: force cache check */
PBogus, /* 65 -- arla: break callback */
PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
- PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
+ PFsCmd, /* 67 -- RXOSD: generic commnd interface */
PBogus, /* 68 -- arla: fetch stats */
+ PGetVnodeXStatus2, /* 69 - get caller access and some vcache status */
};
-static int (*(CpioctlSw[])) () = {
+static pioctlFunction CpioctlSw[] = {
PBogus, /* 0 */
PNewAlias, /* 1 -- create new cell alias */
PListAliases, /* 2 -- list cell aliases */
PCallBackAddr, /* 3 -- request addr for callback rxcon */
+ PBogus, /* 4 */
+ PDiscon, /* 5 -- get/set discon mode */
+ PBogus, /* 6 */
+ PBogus, /* 7 */
+ PBogus, /* 8 */
+ PNewUuid, /* 9 */
+ PBogus, /* 0 */
+ PBogus, /* 0 */
+ PPrecache, /* 12 */
};
-#define PSetClientContext 99 /* Special pioctl to setup caller's creds */
-int afs_nobody = NFS_NOBODY;
-
-#if (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)) || defined(AFS_HPUX_64BIT_ENV) || defined(AFS_SUN57_64BIT_ENV) || (defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)) || defined(NEED_IOCTL32)
-static void
-afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
-{
- dst->in = (char *)(unsigned long)src->in;
- dst->out = (char *)(unsigned long)src->out;
- dst->in_size = src->in_size;
- dst->out_size = src->out_size;
-}
-#endif
-
-/*
- * If you need to change copyin_afs_ioctl(), you may also need to change
- * copyin_iparam().
- */
-
-static int
-copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
-{
- int code;
-#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
- struct afs_ioctl32 dst32;
-
- if (!(IS64U)) {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL) */
-
-
-#if defined(AFS_HPUX_64BIT_ENV)
- struct afs_ioctl32 dst32;
-
- if (is_32bit(u.u_procp)) { /* is_32bit() in proc_iface.h */
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_HPUX_64BIT_ENV) */
-
-#if defined(AFS_SUN57_64BIT_ENV)
- struct afs_ioctl32 dst32;
-
- if (get_udatamodel() == DATAMODEL_ILP32) {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_SUN57_64BIT_ENV) */
-
-#if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
- struct afs_ioctl32 dst32;
-
- if (!ABI_IS_64BIT(get_current_abi())) {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
-
-#if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
- struct afs_ioctl32 dst32;
-
-#ifdef AFS_SPARC64_LINUX26_ENV
- if (test_thread_flag(TIF_32BIT))
-#elif AFS_SPARC64_LINUX24_ENV
- if (current->thread.flags & SPARC_FLAG_32BIT)
-#elif defined(AFS_SPARC64_LINUX20_ENV)
- if (current->tss.flags & SPARC_FLAG_32BIT)
-
-#elif defined(AFS_AMD64_LINUX26_ENV)
- if (test_thread_flag(TIF_IA32))
-#elif defined(AFS_AMD64_LINUX20_ENV)
- if (current->thread.flags & THREAD_IA32)
-
-#elif defined(AFS_PPC64_LINUX26_ENV)
- if (current->thread_info->flags & _TIF_32BIT)
-#elif defined(AFS_PPC64_LINUX20_ENV)
- if (current->thread.flags & PPC_FLAG_32BIT)
-
-#elif defined(AFS_S390X_LINUX26_ENV)
- if (test_thread_flag(TIF_31BIT))
-#elif defined(AFS_S390X_LINUX20_ENV)
- if (current->thread.flags & S390_FLAG_31BIT)
-
+static int (*(OpioctlSw[])) () = {
+ PBogus, /* 0 */
+ PNFSNukeCreds, /* 1 -- nuke all creds for NFS client */
+#if defined(AFS_CACHE_BYPASS)
+ PSetCachingThreshold /* 2 -- get/set cache-bypass size threshold */
#else
-#error pioctl32 not done for this linux
+ PNoop /* 2 -- get/set cache-bypass size threshold */
#endif
- {
- AFS_COPYIN(cmarg, (caddr_t) & dst32, sizeof dst32, code);
- if (!code)
- afs_ioctl32_to_afs_ioctl(&dst32, dst);
- return code;
- }
-#endif /* defined(AFS_LINUX_64BIT_KERNEL) */
+};
- AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
- return code;
-}
+#define PSetClientContext 99 /* Special pioctl to setup caller's creds */
+int afs_nobody = NFS_NOBODY;
int
HandleIoctl(register struct vcache *avc, register afs_int32 acom,
interface call.
*/
/* AFS_HPUX102 and up uses VNODE ioctl instead */
-#ifndef AFS_HPUX102_ENV
+#if !defined(AFS_HPUX102_ENV) && !defined(AFS_DARWIN80_ENV)
#if !defined(AFS_SGI_ENV)
#ifdef AFS_AIX32_ENV
#ifdef AFS_AIX51_ENV
#ifdef __64BIT__
-kioctl(fdes, com, arg, ext, arg2, arg3)
+int
+kioctl(int fdes, int com, caddr_t arg, caddr_t ext, caddr_t arg2,
+ caddr_t arg3)
#else /* __64BIT__ */
-kioctl32(fdes, com, arg, ext, arg2, arg3)
+int
+kioctl32(int fdes, int com, caddr_t arg, caddr_t ext, caddr_t arg2,
+ caddr_t arg3)
#endif /* __64BIT__ */
- caddr_t arg2, arg3;
#else
-kioctl(fdes, com, arg, ext)
+int
+kioctl(int fdes, int com, caddr_t arg, caddr_t ext)
#endif
- int fdes, com;
- caddr_t arg, ext;
{
struct a {
int fd, com;
int arg;
};
-afs_xioctl(uap, rvp)
- struct afs_ioctl_sys *uap;
- rval_t *rvp;
+int
+afs_xioctl(struct afs_ioctl_sys *uap, rval_t *rvp)
{
#elif defined(AFS_OSF_ENV)
-afs_xioctl(p, args, retval)
- struct proc *p;
- void *args;
- long *retval;
+int
+afs_xioctl(struct proc *p, void *args, long *retval)
{
struct a {
long fd;
#elif defined(AFS_FBSD50_ENV)
#define arg data
int
-afs_xioctl(td, uap, retval)
- struct thread *td;
- register struct ioctl_args *uap;
- register_t *retval;
+afs_xioctl(struct thread *td, register struct ioctl_args *uap,
+ register_t *retval)
{
struct proc *p = td->td_proc;
#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
};
int
-afs_xioctl(p, uap, retval)
- struct proc *p;
- register struct ioctl_args *uap;
- register_t *retval;
+afs_xioctl(struct proc *p, register struct ioctl_args *uap, register_t *retval)
{
#elif defined(AFS_LINUX22_ENV)
struct afs_ioctl_sys {
}
#elif defined(AFS_OSF_ENV)
-afs_pioctl(p, args, retval)
- struct proc *p;
- void *args;
- int *retval;
+afs_pioctl(struct proc *p, void *args, int *retval)
{
struct a {
char *path;
#elif defined(AFS_FBSD50_ENV)
int
-afs_pioctl(td, args, retval)
- struct thread *td;
- void *args;
- int *retval;
+afs_pioctl(struct thread *td, void *args, int *retval)
{
struct a {
char *path;
#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
int
-afs_pioctl(p, args, retval)
- struct proc *p;
- void *args;
- int *retval;
+afs_pioctl(struct proc *p, void *args, int *retval)
{
struct a {
char *path;
} *uap = (struct a *)args;
AFS_STATCNT(afs_pioctl);
+#ifdef AFS_DARWIN80_ENV
+ return (afs_syscall_pioctl
+ (uap->path, uap->cmd, uap->cmarg, uap->follow,
+ kauth_cred_get()));
+#else
return (afs_syscall_pioctl
(uap->path, uap->cmd, uap->cmarg, uap->follow,
p->p_cred->pc_ucred));
+#endif
}
#endif
int
#ifdef AFS_SUN5_ENV
-afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
- rval_t *rvp;
- struct AFS_UCRED *credp;
+afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow,
+ rval_t *vvp, struct AFS_UCRED *credp)
#else
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_syscall_pioctl(path, com, cmarg, follow, credp)
- struct AFS_UCRED *credp;
+afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow,
+ struct AFS_UCRED *credp)
#else
-afs_syscall_pioctl(path, com, cmarg, follow)
+afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
#endif
#endif
- char *path;
- unsigned int com;
- caddr_t cmarg;
- int follow;
{
struct afs_ioctl data;
#ifdef AFS_NEED_CLIENTCONTEXT
- struct AFS_UCRED *tmpcred;
+ struct AFS_UCRED *tmpcred = NULL;
#endif
struct AFS_UCRED *foreigncreds = NULL;
register afs_int32 code = 0;
}
if ((com & 0xff) == PSetClientContext) {
#ifdef AFS_NEED_CLIENTCONTEXT
-#if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
code = HandleClientContext(&data, &com, &foreigncreds, credp);
#else
code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
* like afs_osi_suser(cred) which, I think, is better since it
* generalizes and supports multi cred environments...
*/
-#ifdef AFS_SUN5_ENV
+#if defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
tmpcred = credp;
credp = foreigncreds;
#elif defined(AFS_AIX41_ENV)
} else
vp = NULL;
+#if defined(AFS_SUN510_ENV)
+ if (vp && !IsAfsVnode(vp)) {
+ struct vnode *realvp;
+ if
+#ifdef AFS_SUN511_ENV
+ (VOP_REALVP(vp, &realvp, NULL) == 0)
+#else
+ (VOP_REALVP(vp, &realvp) == 0)
+#endif
+{
+ struct vnode *oldvp = vp;
+
+ VN_HOLD(realvp);
+ vp = realvp;
+ AFS_RELE(oldvp);
+ }
+ }
+#endif
/* now make the call if we were passed no file, or were passed an AFS file */
if (!vp || IsAfsVnode(vp)) {
#if defined(AFS_SUN5_ENV)
set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
#elif defined(AFS_SGI_ENV)
OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
-#elif !defined(AFS_SUN5_ENV)
+#elif defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
+ credp = tmpcred; /* restore original credentials */
+#else
osi_curcred() = tmpcred; /* restore original credentials */
#endif /* AFS_HPUX101_ENV */
crfree(foreigncreds);
register afs_int32 function, device;
afs_int32 inSize, outSize, outSizeMax;
char *inData, *outData;
- int (*(*pioctlSw)) ();
+ pioctlFunction *pioctlSw;
int pioctlSwSize;
struct afs_fakestat_state fakestate;
pioctlSw = CpioctlSw;
pioctlSwSize = sizeof(CpioctlSw);
break;
+ case 'O': /* Coordinated/common pioctls */
+ pioctlSw = OpioctlSw;
+ pioctlSwSize = sizeof(OpioctlSw);
+ break;
default:
afs_PutFakeStat(&fakestate);
return EINVAL;
return afs_CheckCode(code, &treq, 41);
}
+/*!
+ * VIOCGETFID (22) - Get file ID quickly
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout fid of requested file
+ *
+ * \retval EINVAL Error if some of the initial arguments aren't set
+ *
+ * \post get the file id of some file
+ */
DECL_PIOCTL(PGetFID)
{
AFS_STATCNT(PGetFID);
return 0;
}
+/*!
+ * VIOCSETAL (1) - Set access control list
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the ACL being set
+ * \param[out] aout the ACL being set returned
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ *
+ * \post Changed ACL, via direct writing to the wire
+ */
+int dummy_PSetAcl(char *ain, char *aout)
+{
+ return 0;
+}
+
DECL_PIOCTL(PSetAcl)
{
register afs_int32 code;
AFS_STATCNT(PSetAcl);
if (!avc)
return EINVAL;
- if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1000)
+ if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1024 /* AFSOPAQUEMAX */)
return EINVAL;
acl.AFSOpaque_val = ain;
int afs_defaultAsynchrony = 0;
+/*!
+ * VIOC_STOREBEHIND (47) Adjust store asynchrony
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain sbstruct (store behind structure) input
+ * \param[out] aout resulting sbstruct
+ *
+ * \retval EPERM Error if the user doesn't have super-user credentials
+ * \retval EACCES Error if there isn't enough access to not check the mode bits
+ *
+ * \post sets asynchrony based on a file, from a struct sbstruct "I THINK"
+ */
DECL_PIOCTL(PStoreBehind)
{
afs_int32 code = 0;
return code;
}
+/*!
+ * VIOC_GCPAGS (48) - Disable automatic PAG gc'ing
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout not in use
+ *
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ *
+ * \post set the gcpags to GCPAGS_USERDISABLED
+ */
DECL_PIOCTL(PGCPAGs)
{
if (!afs_osi_suser(*acred)) {
return 0;
}
+/*!
+ * VIOCGETAL (2) - Get access control list
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout the ACL
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ * \retval ERANGE Error if the vnode of the file id is too large
+ * \retval -1 Error if getting the ACL failed
+ *
+ * \post Obtain the ACL, based on file ID
+ *
+ * \notes there is a hack to tell which type of ACL is being returned, checks the top 2-bytes to judge what type of ACL it is, only for dfs xlat or ACLs
+ */
DECL_PIOCTL(PGetAcl)
{
struct AFSOpaque acl;
return code;
}
+/*!
+ * PNoop returns success. Used for functions which are not implemented or are no longer in use.
+ *
+ * \ingroup pioctl
+ *
+ * \notes Functions involved in this: 17 (VIOCENGROUP) -- used to be enable group; 18 (VIOCDISGROUP) -- used to be disable group; 2 (?) -- get/set cache-bypass size threshold
+ */
DECL_PIOCTL(PNoop)
{
AFS_STATCNT(PNoop);
return 0;
}
+/*!
+ * PBogus returns fail. Used for functions which are not implemented or are no longer in use.
+ *
+ * \ingroup pioctl
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ *
+ * \notes Functions involved in this: 0 (?); 4 (?); 6 (?); 7 (VIOCSTAT); 8 (?); 13 (VIOCGETTIME) -- used to be quick check time; 15 (VIOCPREFETCH) -- prefetch is now special-cased; see pioctl code!; 16 (VIOCNOP) -- used to be testing code; 19 (VIOCLISTGROUPS) -- used to be list group; 23 (VIOCWAITFOREVER) -- used to be waitforever; 57 (VIOC_FPRIOSTATUS) -- arla: set file prio; 58 (VIOC_FHGET) -- arla: fallback getfh; 59 (VIOC_FHOPEN) -- arla: fallback fhopen; 60 (VIOC_XFSDEBUG) -- arla: controls xfsdebug; 61 (VIOC_ARLADEBUG) -- arla: controls arla debug; 62 (VIOC_AVIATOR) -- arla: debug interface; 63 (VIOC_XFSDEBUG_PRINT) -- arla: print xfs status; 64 (VIOC_CALCULATE_CACHE) -- arla: force cache check; 65 (VIOC_BREAKCELLBACK) -- arla: break callback; 68 (?) -- arla: fetch stats;
+ */
DECL_PIOCTL(PBogus)
{
AFS_STATCNT(PBogus);
return EINVAL;
}
+/*!
+ * VIOC_FILE_CELL_NAME (30) - Get cell in which file lives
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use (avc used to pass in file id)
+ * \param[out] aout cell name
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ * \retval ESRCH Error if the file isn't part of a cell
+ *
+ * \post Get a cell based on a passed in file id
+ */
DECL_PIOCTL(PGetFileCell)
{
register struct cell *tcell;
return 0;
}
+/*!
+ * VIOC_GET_WS_CELL (31) - Get cell in which workstation lives
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout cell name
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval ESRCH Error if the machine isn't part of a cell, for whatever reason
+ *
+ * \post Get the primary cell that the machine is a part of.
+ */
DECL_PIOCTL(PGetWSCell)
{
struct cell *tcell = NULL;
return 0;
}
+/*!
+ * VIOC_GET_PRIMARY_CELL (33) - Get primary cell for caller
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use (user id found via areq)
+ * \param[out] aout cell name
+ *
+ * \retval ESRCH Error if the user id doesn't have a primary cell specified
+ *
+ * \post Get the primary cell for a certain user, based on the user's uid
+ */
DECL_PIOCTL(PGetUserCell)
{
register afs_int32 i;
return 0;
}
+/*!
+ * VIOCSETTOK (3) - Set authentication tokens
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the krb tickets from which to set the afs tokens
+ * \param[out] aout not in use
+ *
+ * \retval EINVAL Error if the ticket is either too long or too short
+ * \retval EIO Error if the AFS initState is below 101
+ * \retval ESRCH Error if the cell for which the Token is being set can't be found
+ *
+ * \post Set the Tokens for a specific cell name, unless there is none set, then default to primary
+ *
+ */
DECL_PIOCTL(PSetTokens)
{
afs_int32 i;
#else
struct proc *p = curproc; /* XXX */
#endif
+#ifndef AFS_DARWIN80_ENV
uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
p->p_pid, p->p_comm);
+#endif
if (!setpag(p, acred, -1, &pag, 1)) {
#else
#ifdef AFS_OSF_ENV
afs_osi_Free(tu->stp, tu->stLen);
}
tu->stp = (char *)afs_osi_Alloc(stLen);
+ if (tu->stp == NULL) {
+ return ENOMEM;
+ }
tu->stLen = stLen;
memcpy(tu->stp, stp, stLen);
tu->ct = clear;
}
}
+/*!
+ * VIOCGETVOLSTAT (4) - Get volume status
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout status of the volume
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ *
+ * \post The status of a volume (based on the FID of the volume), or an offline message /motd
+ */
DECL_PIOCTL(PGetVolumeStatus)
{
char volName[32];
return code;
}
+/*!
+ * VIOCSETVOLSTAT (5) - Set volume status
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain values to set the status at, offline message, message of the day, volume name, minimum quota, maximum quota
+ * \param[out] aout status of a volume, offlines messages, minimum quota, maximumm quota
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ * \retval EROFS Error if the volume is read only, or a backup volume
+ * \retval ENODEV Error if the volume can't be accessed
+ * \retval E2BIG Error if the volume name, offline message, and motd are too big
+ *
+ * \post Set the status of a volume, including any offline messages, a minimum quota, and a maximum quota
+ */
DECL_PIOCTL(PSetVolumeStatus)
{
char volName[32];
return code;
}
+/*!
+ * VIOCFLUSH (6) - Invalidate cache entry
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout not in use
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ *
+ * \post Flush any information the cache manager has on an entry
+ */
DECL_PIOCTL(PFlush)
{
AFS_STATCNT(PFlush);
/* now find the disk cache entries */
afs_TryToSmush(avc, *acred, 1);
osi_dnlc_purgedp(avc);
- afs_symhint_inval(avc);
if (avc->linkData && !(avc->states & CCore)) {
afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1);
avc->linkData = NULL;
return 0;
}
+/*!
+ * VIOC_AFS_STAT_MT_PT (29) - Stat mount point
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the last component in a path, related to mountpoint that we're looking for information about
+ * \param[out] aout volume, cell, link data
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ * \retval ENOTDIR Error if the 'mount point' argument isn't a directory
+ * \retval EIO Error if the link data can't be accessed
+ *
+ * \post Get the volume, and cell, as well as the link data for a mount point
+ */
DECL_PIOCTL(PNewStatMount)
{
register afs_int32 code;
return code;
}
+/*!
+ * VIOCGETTOK (8) - Get authentication tokens
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain userid
+ * \param[out] aout token
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval EDOM Error if the input parameter is out of the bounds of the available tokens
+ * \retval ENOTCONN Error if there aren't tokens for this cell
+ *
+ * \post If the input paramater exists, get the token that corresponds to the parameter value, if there is no token at this value, get the token for the first cell
+ *
+ * \notes "it's a weird interface (from comments in the code)"
+ */
+
DECL_PIOCTL(PGetTokens)
{
register struct cell *tcell;
return 0;
}
+/*!
+ * VIOCUNLOG (9) - Invalidate tokens
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout not in use
+ *
+ * \retval EIO Error if the afs daemon hasn't been started yet
+ *
+ * \post remove tokens from a user, specified by the user id
+ *
+ * \notes sets the token's time to 0, which then causes it to be removed
+ * \notes Unlog is the same as un-pag in OpenAFS
+ */
DECL_PIOCTL(PUnlog)
{
register afs_int32 i;
return 0;
}
+/*!
+ * VIOC_AFS_MARINER_HOST (32) - Get/set mariner (cache manager monitor) host
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain host address to be set
+ * \param[out] aout old host address
+ *
+ * \post depending on whether or not a variable is set, either get the host for the cache manager monitor, or set the old address and give it a new address
+ *
+ * \notes Errors turn off mariner
+ */
DECL_PIOCTL(PMariner)
{
afs_int32 newHostAddr;
return 0;
}
+/*!
+ * VIOCCKSERV (10) - Check that servers are up
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain name of the cell
+ * \param[out] aout current down server list
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ * \retval ENOENT Error if we are unable to obtain the cell
+ *
+ * \post Either a fast check (where it doesn't contact servers) or a local check (checks local cell only)
+ */
DECL_PIOCTL(PCheckServers)
{
register char *cp = 0;
pcheck = (struct chservinfo *)ain;
if (pcheck->tinterval >= 0) {
cp = aout;
- memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
+ memcpy(cp, (char *)&afs_probe_interval, sizeof(afs_int32));
*aoutSize = sizeof(afs_int32);
if (pcheck->tinterval > 0) {
if (!afs_osi_suser(*acred))
return EACCES;
- PROBE_INTERVAL = pcheck->tinterval;
+ afs_probe_interval = pcheck->tinterval;
}
return 0;
}
return 0;
}
+/*!
+ * VIOCCKBACK (11) - Check backup volume mappings
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout not in use
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ *
+ * \post Check the root volume, and then check the names if the volume check variable is set to force, has expired, is busy, or if the mount points variable is set
+ */
DECL_PIOCTL(PCheckVolNames)
{
AFS_STATCNT(PCheckVolNames);
return 0;
}
+/*!
+ * VIOCCKCONN (12) - Check connections for a user
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout not in use
+ *
+ * \retval EACCESS Error if no user is specififed, the user has no tokens set, or if the user's tokens are bad
+ *
+ * \post check to see if a user has the correct authentication. If so, allow access.
+ *
+ * \notes Check the connections to all the servers specified
+ */
DECL_PIOCTL(PCheckAuth)
{
int i;
return 0;
}
+/*!
+ * VIOCWHEREIS (14) - Find out where a volume is located
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout volume location
+ *
+ * \retval EINVAL Error if some of the default arguments don't exist
+ * \retval ENODEV Error if there is no such volume
+ *
+ * \post fine a volume, based on a volume file id
+ *
+ * \notes check each of the servers specified
+ */
DECL_PIOCTL(PFindVolume)
{
register struct volume *tvp;
return ENODEV;
}
+/*!
+ * VIOCACCESS (20) - Access using PRS_FS bits
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain PRS_FS bits
+ * \param[out] aout not in use
+ *
+ * \retval EINVAL Error if some of the initial arguments aren't set
+ * \retval EACCES Error if access is denied
+ *
+ * \post check to make sure access is allowed
+ */
DECL_PIOCTL(PViceAccess)
{
register afs_int32 code;
return EACCES;
}
+DECL_PIOCTL(PPrecache)
+{
+ afs_int32 newValue;
+
+ /*AFS_STATCNT(PPrecache);*/
+ if (!afs_osi_suser(*acred))
+ return EACCES;
+ memcpy((char *)&newValue, ain, sizeof(afs_int32));
+ afs_preCache = newValue*1024;
+ return 0;
+}
+
+/*!
+ * VIOCSETCACHESIZE (24) - Set venus cache size in 1000 units
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the size the venus cache should be set to
+ * \param[out] aout not in use
+ *
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ * \retval EROFS Error if the cache is set to be in memory
+ *
+ * \post Set the cache size based on user input. If no size is given, set it to the default OpenAFS cache size.
+ *
+ * \notes recompute the general cache parameters for every single block allocated
+ */
DECL_PIOCTL(PSetCacheSize)
{
afs_int32 newValue;
}
#define MAXGCSTATS 16
+/*!
+ * VIOCGETCACHEPARMS (40) - Get cache stats
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain afs index flags
+ * \param[out] aout cache blocks, blocks used, blocks files (in an array)
+ *
+ * \post Get the cache blocks, and how many of the cache blocks there are
+ */
DECL_PIOCTL(PGetCacheSize)
{
afs_int32 results[MAXGCSTATS];
-
+ afs_int32 flags;
+ register struct dcache * tdc;
+ int i, size;
+
AFS_STATCNT(PGetCacheSize);
+
+ if (sizeof(afs_int32) == ainSize){
+ memcpy((char *)&flags, ain, sizeof(afs_int32));
+ } else if (0 == ainSize){
+ flags = 0;
+ } else {
+ return EINVAL;
+ }
+
memset((char *)results, 0, sizeof(results));
results[0] = afs_cacheBlocks;
results[1] = afs_blocksUsed;
+ results[2] = afs_cacheFiles;
+
+ if (1 == flags){
+ for (i = 0; i < afs_cacheFiles; i++) {
+ if (afs_indexFlags[i] & IFFree) results[3]++;
+ }
+ } else if (2 == flags){
+ for (i = 0; i < afs_cacheFiles; i++) {
+ if (afs_indexFlags[i] & IFFree) results[3]++;
+ if (afs_indexFlags[i] & IFEverUsed) results[4]++;
+ if (afs_indexFlags[i] & IFDataMod) results[5]++;
+ if (afs_indexFlags[i] & IFDirtyPages) results[6]++;
+ if (afs_indexFlags[i] & IFAnyPages) results[7]++;
+ if (afs_indexFlags[i] & IFDiscarded) results[8]++;
+
+ tdc = afs_indexTable[i];
+ if (tdc){
+ results[9]++;
+ size = tdc->validPos;
+ if ( 0 < size && size < (1<<12) ) results[10]++;
+ else if (size < (1<<14) ) results[11]++;
+ else if (size < (1<<16) ) results[12]++;
+ else if (size < (1<<18) ) results[13]++;
+ else if (size < (1<<20) ) results[14]++;
+ else if (size >= (1<<20) ) results[15]++;
+ }
+ }
+ }
memcpy(aout, (char *)results, sizeof(results));
*aoutSize = sizeof(results);
return 0;
}
+/*!
+ * VIOCFLUSHCB (25) - Flush callback only
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout not in use
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ * \retval 0 0 returned if the volume is set to read-only
+ *
+ * \post Flushes callbacks, by setting the length of callbacks to one, setting the next callback to be sent to the CB_DROPPED value, and then dequeues everything else.
+ */
DECL_PIOCTL(PRemoveCallBack)
{
register struct conn *tc;
return 0;
}
+/*!
+ * VIOCNEWCELL (26) - Configure new cell
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the name of the cell, the hosts that will be a part of the cell, whether or not it's linked with another cell, the other cell it's linked with, the file server port, and the volume server port
+ * \param[out] aout not in use
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval EACCES Error if the user doesn't have super-user cedentials
+ * \retval EINVAL Error if some 'magic' var doesn't have a certain bit set
+ *
+ * \post creates a new cell
+ */
DECL_PIOCTL(PNewCell)
{
/* create a new cell */
return code;
}
+/*!
+ * VIOCGETCELL (27) - Get cell info
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain The cell index of a specific cell
+ * \param[out] aout list of servers in the cell
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval EDOM Error if there is no cell asked about
+ *
+ * \post Lists the cell's server names and and addresses
+ */
DECL_PIOCTL(PListCells)
{
afs_int32 whichCell;
return EDOM;
}
+/*!
+ * VIOC_AFS_DELETE_MT_PT (28) - Delete mount point
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the name of the file in this dir to remove
+ * \param[out] aout not in use
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ * \retval ENOTDIR Error if the argument to remove is not a directory
+ * \retval ENOENT Error if there is no cache to remove the mount point from or if a vcache doesn't exist
+ *
+ * \post Ensure that everything is OK before deleting the mountpoint. If not, don't delete. Delete a mount point based on a file id.
+ */
DECL_PIOCTL(PRemoveMount)
{
register afs_int32 code;
return code;
}
+/*!
+ * VIOC_VENUSLOG (34) - Enable/Disable venus logging
+ *
+ * \ingroup pioctl
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ *
+ * \notes Obsoleted, perhaps should be PBogus
+ */
DECL_PIOCTL(PVenusLogging)
{
return EINVAL; /* OBSOLETE */
}
+/*!
+ * VIOC_GETCELLSTATUS (35) - Get cell status info
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain The cell you want status information on
+ * \param[out] aout cell state (as a struct)
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval ENOENT Error if the cell doesn't exist
+ *
+ * \post Returns the state of the cell as defined in a struct cell
+ */
DECL_PIOCTL(PGetCellStatus)
{
register struct cell *tcell;
return 0;
}
+/*!
+ * VIOC_SETCELLSTATUS (36) - Set corresponding info
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain The cell you want to set information about, and the values you want to set
+ * \param[out] aout not in use
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ *
+ * \post Set the state of the cell in a defined struct cell, based on whether or not SetUID is allowed
+ */
DECL_PIOCTL(PSetCellStatus)
{
register struct cell *tcell;
return 0;
}
+/*!
+ * VIOC_FLUSHVOLUME (37) - Flush whole volume's data
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use (args in avc)
+ * \param[out] aout not in use
+ *
+ * \retval EINVAL Error if some of the standard args aren't set
+ * \retval EIO Error if the afs daemon hasn't started yet
+ *
+ * \post Wipe everything on the volume. This is done dependent on which platform this is for.
+ *
+ * \notes Does not flush a file that a user has open and is using, because it will be re-created on next write. Also purges the dnlc, because things are screwed up.
+ */
DECL_PIOCTL(PFlushVolumeData)
{
register afs_int32 i;
register struct vcache *tvc;
register struct volume *tv;
afs_int32 cell, volume;
+ struct afs_q *tq, *uq;
+#ifdef AFS_DARWIN80_ENV
+ vnode_t vp;
+#endif
AFS_STATCNT(PFlushVolumeData);
if (!avc)
* Clear stat'd flag from all vnodes from this volume; this will invalidate all
* the vcaches associated with the volume.
*/
+ loop:
ObtainReadLock(&afs_xvcache);
- for (i = 0; i < VCSIZE; i++) {
- for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
+ i = VCHashV(&avc->fid);
+ for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
+ uq = QPrev(tq);
+ tvc = QTOVH(tq);
if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
+ if (tvc->states & CVInit) {
+ ReleaseReadLock(&afs_xvcache);
+ afs_osi_Sleep(&tvc->states);
+ goto loop;
+ }
+#ifdef AFS_DARWIN80_ENV
+ if (tvc->states & CDeadVnode) {
+ ReleaseReadLock(&afs_xvcache);
+ afs_osi_Sleep(&tvc->states);
+ goto loop;
+ }
+#endif
#if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
VN_HOLD(AFSTOV(tvc));
#else
+#ifdef AFS_DARWIN80_ENV
+ vp = AFSTOV(tvc);
+ if (vnode_get(vp))
+ continue;
+ if (vnode_ref(vp)) {
+ AFS_GUNLOCK();
+ vnode_put(vp);
+ AFS_GLOCK();
+ continue;
+ }
+#else
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
osi_vnhold(tvc, 0);
#else
VREFCOUNT_INC(tvc); /* AIX, apparently */
#endif
#endif
+#endif
ReleaseReadLock(&afs_xvcache);
#ifdef AFS_BOZONLOCK_ENV
afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
#ifdef AFS_BOZONLOCK_ENV
afs_BozonUnlock(&tvc->pvnLock, tvc);
#endif
+#ifdef AFS_DARWIN80_ENV
+ vnode_put(AFSTOV(tvc));
+#endif
ObtainReadLock(&afs_xvcache);
+ uq = QPrev(tq);
/* our tvc ptr is still good until now */
AFS_FAST_RELE(tvc);
}
}
- }
ReleaseReadLock(&afs_xvcache);
}
-
+/*!
+ * VIOCGETVCXSTATUS (41) - gets vnode x status
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use (avc used)
+ * \param[out] aout vcxstat: the file id, the data version, any lock, the parent vnode, the parent unique id, the trunc position, the callback, cbExpires, what access is being made, what files are open, any users executing/writing, the flock ount, the states, the move stat
+ *
+ * \retval EINVAL Error if some of the initial default arguments aren't set
+ * \retval EACCES Error if access to check the mode bits is denied
+ *
+ * \post gets stats for the vnode, a struct listed in vcxstat
+ */
DECL_PIOCTL(PGetVnodeXStatus)
{
register afs_int32 code;
mode = PRSFS_READ;
if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
return EACCES;
+
+ memset(&stat, 0, sizeof(struct vcxstat));
stat.fid = avc->fid;
hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
stat.lock = avc->lock;
}
-/* We require root for local sysname changes, but not for remote */
-/* (since we don't really believe remote uids anyway) */
- /* outname[] shouldn't really be needed- this is left as an excercise */
- /* for the reader. */
+DECL_PIOCTL(PGetVnodeXStatus2)
+{
+ register afs_int32 code;
+ struct vcxstat2 stat;
+ afs_int32 mode;
+
+ if (!avc)
+ return EINVAL;
+ code = afs_VerifyVCache(avc, areq);
+ if (code)
+ return code;
+ if (vType(avc) == VDIR)
+ mode = PRSFS_LOOKUP;
+ else
+ mode = PRSFS_READ;
+ if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
+ return EACCES;
+
+ memset(&stat, 0, sizeof(struct vcxstat2));
+
+ stat.cbExpires = avc->cbExpires;
+ stat.anyAccess = avc->anyAccess;
+ stat.mvstat = avc->mvstat;
+ stat.callerAccess = afs_GetAccessBits(avc, ~0, areq);
+
+ memcpy(aout, (char *)&stat, sizeof(struct vcxstat2));
+ *aoutSize = sizeof(struct vcxstat2);
+ return 0;
+}
+
+
+/*!
+ * VIOC_AFS_SYSNAME (38) - Change @sys value
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain new value for @sys
+ * \param[out] aout count, entry, list (debug values?)
+ *
+ * \retval EINVAL Error if afsd isn't running, the new sysname is too large, the new sysname causes issues (starts with a .0 or ..0), there is no PAG set in the credentials, the user of a PAG can't be found, (!(exporter = au->exporter)) "NOT SURE ON THIS"
+ * \retval ENODEV Error if there isn't already a system named that ("I THINK")
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ *
+ * \post Set the value of @sys if these things work: if the input isn't too long or if input doesn't start with .0 or ..0
+ *
+ * \notes We require root for local sysname changes, but not for remote (since we don't really believe remote uids anyway) outname[] shouldn't really be needed- this is left as an exercise for the reader.
+ */
DECL_PIOCTL(PSetSysName)
{
char *cp, *cp2 = NULL, inname[MAXSYSNAME], outname[MAXSYSNAME];
- int setsysname, foundname = 0;
+ afs_int32 setsysname;
+ int foundname = 0;
register struct afs_exporter *exporter;
register struct unixuser *au;
register afs_int32 pag, error;
- int t, count, num = 0;
- char **sysnamelist[MAXSYSNAME];
+ int t, count, num = 0, allpags = 0;
+ char **sysnamelist;
AFS_STATCNT(PSetSysName);
if (!afs_globalVFS) {
#endif
}
memset(inname, 0, MAXSYSNAME);
- memcpy((char *)&setsysname, ain, sizeof(afs_int32));
+ memcpy(&setsysname, ain, sizeof(afs_int32));
ain += sizeof(afs_int32);
+ if (setsysname & 0x8000) {
+ allpags = 1;
+ setsysname &= ~0x8000;
+ }
if (setsysname) {
/* Check my args */
ain += t + 1;
num = count;
}
- if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
+ if ((*acred)->cr_gid == RMTUSER_REQ ||
+ (*acred)->cr_gid == RMTUSER_REQ_PRIV) { /* Handles all exporters */
+ if (allpags && (*acred)->cr_gid != RMTUSER_REQ_PRIV) {
+ return EPERM;
+ }
pag = PagInCred(*acred);
if (pag == NOPAG) {
return EINVAL; /* Better than panicing */
afs_PutUser(au, READ_LOCK);
return EINVAL; /* Better than panicing */
}
- error = EXP_SYSNAME(exporter, (setsysname ? cp2 : NULL), sysnamelist,
- &num);
+ error = EXP_SYSNAME(exporter, (setsysname ? cp2 : NULL), &sysnamelist,
+ &num, allpags);
if (error) {
if (error == ENODEV)
foundname = 0; /* sysname not set yet! */
}
} else {
foundname = num;
- strcpy(outname, (*sysnamelist)[0]);
+ strcpy(outname, sysnamelist[0]);
}
afs_PutUser(au, READ_LOCK);
+ if (setsysname)
+ afs_sysnamegen++;
} else {
/* Not xlating, so local case */
if (!afs_sysname)
if (!setsysname) { /* user just wants the info */
strcpy(outname, afs_sysname);
foundname = afs_sysnamecount;
- *sysnamelist = afs_sysnamelist;
+ sysnamelist = afs_sysnamelist;
} else { /* Local guy; only root can change sysname */
if (!afs_osi_suser(*acred))
return EACCES;
+ /* allpags makes no sense for local use */
+ if (allpags)
+ return EINVAL;
+
/* clear @sys entries from the dnlc, once afs_lookup can
* do lookups of @sys entries and thinks it can trust them */
/* privs ok, store the entry, ... */
}
}
afs_sysnamecount = setsysname;
+ afs_sysnamegen++;
}
}
if (!setsysname) {
strcpy(cp, outname); /* ... the entry, ... */
cp += strlen(outname) + 1;
for (count = 1; count < foundname; ++count) { /* ... or list. */
- if (!(*sysnamelist)[count])
+ if (!sysnamelist[count])
osi_Panic
("PSetSysName: no afs_sysnamelist entry to read\n");
- t = strlen((*sysnamelist)[count]);
+ t = strlen(sysnamelist[count]);
if (t >= MAXSYSNAME)
osi_Panic("PSetSysName: sysname entry garbled\n");
- strcpy(cp, (*sysnamelist)[count]);
+ strcpy(cp, sysnamelist[count]);
cp += t + 1;
}
}
static int debugsetsp = 0;
static int
-afs_setsprefs(sp, num, vlonly)
- struct spref *sp;
- unsigned int num;
- unsigned int vlonly;
+afs_setsprefs(struct spref *sp, unsigned int num, unsigned int vlonly)
{
struct srvAddr *sa;
int i, j, k, matches, touchedSize;
return 0;
}
- /* Note that this may only be performed by the local root user.
- */
+/*!
+ * VIOC_SETPREFS (46) - Set server ranks
+ *
+ * \param[in] ain the sprefs value you want the sprefs to be set to
+ * \param[out] aout not in use
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ * \retval EINVAL Error if the struct setsprefs is too large or if it multiplied by the number of servers is too large
+ *
+ * \post set the sprefs using the afs_setsprefs() function
+ */
DECL_PIOCTL(PSetSPrefs)
{
struct setspref *ssp;
return 0;
}
+/*
+ * VIOC_SETPREFS33 (42) - Set server ranks (deprecated)
+ *
+ * \param[in] ain the server preferences to be set
+ * \param[out] aout not in use
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ *
+ * \post set the server preferences, calling a function
+ *
+ * \notes this may only be performed by the local root user.
+ */
DECL_PIOCTL(PSetSPrefs33)
{
struct spref *sp;
return 0;
}
-/* some notes on the following code...
- * in the hash table of server structs, all servers with the same IP address
- * will be on the same overflow chain.
- * This could be sped slightly in some circumstances by having it cache the
- * immediately previous slot in the hash table and some supporting information
- * Only reports file servers now.
+/*
+ * VIOC_GETSPREFS (43) - Get server ranks
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the server preferences to get
+ * \param[out] aout the server preferences information
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval ENOENT Error if the sprefrequest is too large
+ *
+ * \post Get the sprefs
+ *
+ * \notes in the hash table of server structs, all servers with the same IP address; will be on the same overflow chain; This could be sped slightly in some circumstances by having it cache the immediately previous slot in the hash table and some supporting information; Only reports file servers now.
*/
DECL_PIOCTL(PGetSPrefs)
{
/* Enable/Disable the specified exporter. Must be root to disable an exporter */
int afs_NFSRootOnly = 1;
+/*!
+ * VIOC_EXPORTAFS (39) - Export afs to nfs clients
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain a struct Vic * EIOctl containing export values needed to change between nfs and afs
+ * \param[out] aout a struct of the exporter states (exporter->exp_states)
+ *
+ * \retval ENODEV Error if the exporter doesn't exist
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ *
+ * \post Changes the state of various values to reflect the change of the export values between nfs and afs.
+ *
+ * \notes Legacy code obtained from IBM.
+ */
DECL_PIOCTL(PExportAfs)
{
afs_int32 export, newint =
0, type, changestate, handleValue, convmode, pwsync, smounts;
+ afs_int32 rempags = 0, pagcb = 0;
register struct afs_exporter *exporter;
AFS_STATCNT(PExportAfs);
exporter = exporter_find(type);
if (newint) {
export = handleValue & 3;
- changestate = handleValue & 0xff;
+ changestate = handleValue & 0xfff;
smounts = (handleValue >> 2) & 3;
pwsync = (handleValue >> 4) & 3;
convmode = (handleValue >> 6) & 3;
+ rempags = (handleValue >> 8) & 3;
+ pagcb = (handleValue >> 10) & 3;
} else {
changestate = (handleValue >> 16) & 0x1;
convmode = (handleValue >> 16) & 0x2;
exporter->exp_states &= ~EXP_SUBMOUNTS;
}
}
+ if (rempags & 2) {
+ if (rempags & 1)
+ exporter->exp_states |= EXP_CLIPAGS;
+ else
+ exporter->exp_states &= ~EXP_CLIPAGS;
+ }
+ if (pagcb & 2) {
+ if (pagcb & 1)
+ exporter->exp_states |= EXP_CALLBACK;
+ else
+ exporter->exp_states &= ~EXP_CALLBACK;
+ }
handleValue = exporter->exp_states;
memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
*aoutSize = sizeof(afs_int32);
return 0;
}
+/*!
+ * VIOC_GAG (44) - Silence Cache Manager
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the flags to either gag or de-gag the cache manager
+ * \param[out] aout not in use
+ *
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ *
+ * \post set the gag flags, then show these flags
+ */
DECL_PIOCTL(PGag)
{
struct gaginfo *gagflags;
return 0;
}
-
+/*!
+ * VIOC_TWIDDLE (45) - Adjust RX knobs
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the previous settings of the 'knobs'
+ * \param[out] aout not in use
+ *
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ *
+ * \post build out the struct rxp, from a struct rx
+ */
DECL_PIOCTL(PTwiddleRx)
{
struct rxparams *rxp;
return 0;
}
+/*!
+ * VIOC_GETINITPARAMS (49) - Get initial cache manager parameters
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout initial cache manager params
+ *
+ * \retval E2BIG Error if the initial parameters are bigger than some PIGGYSIZE
+ *
+ * \post return the initial cache manager parameters
+ */
DECL_PIOCTL(PGetInitParams)
{
if (sizeof(struct cm_initparams) > PIGGYSIZE)
}
#endif
+/*!
+ * VIOC_GETRXKCRYPT (55) - Get rxkad encryption flag
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain not in use
+ * \param[out] aout value of cryptall
+ *
+ * \post get the value of cryptall (presumably whether or not things should be encrypted)
+ */
DECL_PIOCTL(PGetRxkcrypt)
{
memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
return 0;
}
+/*!
+ * VIOC_SETRXKCRYPT (56) - Set rxkad encryption flag
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the argument whether or not things should be encrypted
+ * \param[out] aout not in use
+ *
+ * \retval EPERM Error if the user doesn't have super-user credentials
+ * \retval EINVAL Error if the input is too big, or if the input is outside the bounds of what it can be set to
+ *
+ * \post set whether or not things should be encrypted
+ *
+ * \notes may need to be modified at a later date to take into account other values for cryptall (beyond true or false)
+ */
DECL_PIOCTL(PSetRxkcrypt)
{
afs_int32 tmpval;
{
char *ain, *inData;
afs_uint32 hostaddr;
- afs_int32 uid, g0, g1, i, code, pag, exporter_type;
+ afs_int32 uid, g0, g1, i, code, pag, exporter_type, isroot = 0;
struct afs_exporter *exporter, *outexporter;
struct AFS_UCRED *newcred;
struct unixuser *au;
+ afs_uint32 comp = *com & 0xff00;
+ afs_uint32 h, l;
#if defined(AFS_SGIMP_ENV)
osi_Assert(ISAFS_GLOCK());
u.u_error = 0;
#endif
/* check for acceptable opcodes for normal folks, which are, so far,
- * set tokens and unlog.
+ * get/set tokens, sysname, and unlog.
*/
if (i != 9 && i != 3 && i != 38 && i != 8) {
osi_FreeLargeSpace(inData);
* code fails for remote client roots.
*/
uid = afs_nobody; /* NFS_NOBODY == -2 */
+ isroot = 1;
}
newcred = crget();
-#if defined(AFS_LINUX26_ENV)
- newcred->cr_group_info = groups_alloc(0);
-#endif
#ifdef AFS_AIX41_ENV
setuerror(0);
#endif
- newcred->cr_gid = RMTUSER_REQ;
+ newcred->cr_gid = isroot ? RMTUSER_REQ_PRIV : RMTUSER_REQ;
#ifdef AFS_AIX51_ENV
newcred->cr_groupset.gs_union.un_groups[0] = g0;
newcred->cr_groupset.gs_union.un_groups[1] = g1;
+#elif defined(AFS_LINUX26_ENV)
+#ifdef AFS_LINUX26_ONEGROUP_ENV
+ newcred->cr_group_info = groups_alloc(1); /* not that anything sets this */
+ l = (((g0-0x3f00) & 0x3fff) << 14) | ((g1-0x3f00) & 0x3fff);
+ h = ((g0-0x3f00) >> 14);
+ h = ((g1-0x3f00) >> 14) + h + h + h;
+ GROUP_AT(newcred->cr_group_info, 0) = ((h << 28) | l);
+#else
+ newcred->cr_group_info = groups_alloc(2);
+ GROUP_AT(newcred->cr_group_info, 0) = g0;
+ GROUP_AT(newcred->cr_group_info, 1) = g1;
+#endif
#else
newcred->cr_groups[0] = g0;
newcred->cr_groups[1] = g1;
#endif
#ifdef AFS_AIX_ENV
newcred->cr_ngrps = 2;
-#else
-#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
+#elif !defined(AFS_LINUX26_ENV)
+#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
newcred->cr_ngroups = 2;
#else
for (i = 2; i < NGROUPS; i++)
} else if (!code) {
EXP_RELE(outexporter);
}
+ if (!code)
+ *com = (*com) | comp;
return code;
}
#endif /* AFS_NEED_CLIENTCONTEXT */
-/* get all interface addresses of this client */
+/*!
+ * VIOC_GETCPREFS (50) - Get client interface
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain sprefrequest input
+ * \param[out] aout spref information
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval EINVAL Error if some of the standard args aren't set
+ *
+ * \post get all interface addresses and other information of the client interface
+ */
DECL_PIOCTL(PGetCPrefs)
{
struct sprefrequest *spin; /* input */
return 0;
}
+/*!
+ * VIOC_SETCPREFS (51) - Set client interface
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the interfaces you want set
+ * \param[out] aout not in use
+ *
+ * \retval EIO Error if the afs daemon hasn't started yet
+ * \retval EINVAL Error if the input is too large for the struct
+ * \retval ENOMEM Error if there are too many servers
+ *
+ * \post set the callbak interfaces addresses to those of the hosts
+ */
DECL_PIOCTL(PSetCPrefs)
{
struct setspref *sin;
return 0;
}
+/*!
+ * VIOC_AFS_FLUSHMOUNT (52) - Flush mount symlink data
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the last part of a path to a mount point, which tells us what to flush
+ * \param[out] aout not in use
+ *
+ * \retval EINVAL Error if some of the initial arguments aren't set
+ * \retval ENOTDIR Error if the initial argument for the mount point isn't a directory
+ * \retval ENOENT Error if the dcache entry isn't set
+ *
+ * \post remove all of the mount data from the dcache regarding a certain mount point
+ */
DECL_PIOCTL(PFlushMount)
{
register afs_int32 code;
/* now find the disk cache entries */
afs_TryToSmush(tvc, *acred, 1);
osi_dnlc_purgedp(tvc);
- afs_symhint_inval(tvc);
if (tvc->linkData && !(tvc->states & CCore)) {
afs_osi_Free(tvc->linkData, strlen(tvc->linkData) + 1);
tvc->linkData = NULL;
return code;
}
+/*!
+ * VIOC_RXSTAT_PROC (53) - Control process RX statistics
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the flags that control which stats to use
+ * \param[out] aout not in use
+ *
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ * \retval EINVAL Error if the flag input is too long
+ *
+ * \post either enable process RPCStats, disable process RPCStats, or clear the process RPCStats
+ */
DECL_PIOCTL(PRxStatProc)
{
int code = 0;
}
+/*!
+ * VIOC_RXSTAT_PEER (54) - Control peer RX statistics
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain the flags that control which statistics to use
+ * \param[out] aout not in use
+ *
+ * \retval EACCES Error if the user doesn't have super-user credentials
+ * \retval EINVAL Error if the flag input is too long
+ *
+ * \post either enable peer RPCStatws, disable peer RPCStats, or clear the peer RPCStats
+ */
DECL_PIOCTL(PRxStatPeer)
{
int code = 0;
return code;
}
-DECL_PIOCTL(PResidencyCmd)
+DECL_PIOCTL(PFsCmd)
{
register afs_int32 code;
struct conn *tc;
struct vcache *tvc;
- struct ResidencyCmdInputs *Inputs;
- struct ResidencyCmdOutputs *Outputs;
+ struct FsCmdInputs *Inputs;
+ struct FsCmdOutputs *Outputs;
struct VenusFid tfid;
struct AFSFid *Fid;
- Inputs = (struct ResidencyCmdInputs *)ain;
- Outputs = (struct ResidencyCmdOutputs *)aout;
+ Inputs = (struct FsCmdInputs *)ain;
+ Outputs = (struct FsCmdOutputs *)aout;
if (!avc)
return EINVAL;
- if (!ain || ainSize != sizeof(struct ResidencyCmdInputs))
+ if (!ain || ainSize != sizeof(struct FsCmdInputs))
return EINVAL;
Fid = &Inputs->fid;
if (tc) {
RX_AFS_GUNLOCK();
code =
- RXAFS_ResidencyCmd(tc->id, Fid, Inputs,
- (struct ResidencyCmdOutputs *)aout);
+ RXAFS_FsCmd(tc->id, Fid, Inputs,
+ (struct FsCmdOutputs *)aout);
RX_AFS_GLOCK();
} else
code = -1;
afs_PutVCache(tvc);
if (!code) {
- *aoutSize = sizeof(struct ResidencyCmdOutputs);
+ *aoutSize = sizeof(struct FsCmdOutputs);
}
return code;
}
+DECL_PIOCTL(PNewUuid)
+{
+ /*AFS_STATCNT(PNewUuid); */
+ if (!afs_resourceinit_flag) /* afs deamons havn't started yet */
+ return EIO; /* Inappropriate ioctl for device */
+
+ if (!afs_osi_suser(acred))
+ return EACCES;
+
+ ObtainWriteLock(&afs_xinterface, 555);
+ afs_uuid_create(&afs_cb_interface.uuid);
+ ReleaseWriteLock(&afs_xinterface);
+ ForceAllNewConnections();
+ return 0;
+}
+
+#if defined(AFS_CACHE_BYPASS)
+
+DECL_PIOCTL(PSetCachingThreshold)
+{
+ afs_int32 getting;
+ afs_int32 setting;
+
+ setting = getting = 1;
+
+ if (ain == NULL || ainSize < sizeof(afs_int32))
+ setting = 0;
+
+ if (aout == NULL)
+ getting = 0;
+
+ if (setting == 0 && getting == 0)
+ return EINVAL;
+
+ /*
+ * If setting, set first, and return the value now in effect
+ */
+ if (setting) {
+ afs_int32 threshold;
+
+ if (!afs_osi_suser(*acred))
+ return EPERM;
+ memcpy((char *)&threshold, ain, sizeof(afs_int32));
+ cache_bypass_threshold = threshold;
+ afs_warn("Cache Bypass Threshold set to: %d\n", threshold);
+ /* TODO: move to separate pioctl, or enhance pioctl */
+ cache_bypass_strategy = LARGE_FILES_BYPASS_CACHE;
+ }
+
+ if (getting) {
+ /* Return the current size threshold */
+ afs_int32 oldThreshold = cache_bypass_threshold;
+ memcpy(aout, (char *)&oldThreshold, sizeof(afs_int32));
+ *aoutSize = sizeof(afs_int32);
+ }
+
+ return(0);
+}
+
+#endif /* defined(AFS_CACHE_BYPASS) */
+
DECL_PIOCTL(PCallBackAddr)
{
#ifndef UKERNEL
#endif /* UKERNEL */
return 0;
}
+
+DECL_PIOCTL(PDiscon)
+{
+#ifdef AFS_DISCON_ENV
+ static afs_int32 mode = 1; /* Start up in 'off' */
+ afs_int32 force = 0;
+ int code = 0;
+
+ if (ainSize) {
+
+ if (!afs_osi_suser(*acred))
+ return EPERM;
+
+ if (ain[0])
+ mode = ain[0] - 1;
+ if (ain[1])
+ afs_ConflictPolicy = ain[1] - 1;
+ if (ain[2])
+ force = 1;
+
+ /*
+ * All of these numbers are hard coded in fs.c. If they
+ * change here, they should change there and vice versa
+ */
+ switch (mode) {
+ case 0: /* Disconnect ("offline" mode), breaking all callbacks */
+ if (!AFS_IS_DISCONNECTED) {
+ ObtainWriteLock(&afs_discon_lock, 999);
+ afs_DisconGiveUpCallbacks();
+ afs_RemoveAllConns();
+ afs_is_disconnected = 1;
+ afs_is_discon_rw = 1;
+ ReleaseWriteLock(&afs_discon_lock);
+ }
+ break;
+ case 1: /* Fully connected, ("online" mode). */
+ ObtainWriteLock(&afs_discon_lock, 998);
+
+ afs_in_sync = 1;
+ code = afs_ResyncDisconFiles(areq, *acred);
+ afs_in_sync = 0;
+
+ if (code && !force) {
+ printf("Files not synchronized properly, still in discon state. \
+ Please retry or use \"force\".\n");
+ } else {
+ afs_is_disconnected = 0;
+ afs_is_discon_rw = 0;
+ printf("\nSync succeeded. You are back online.\n");
+ }
+
+ ReleaseWriteLock(&afs_discon_lock);
+ break;
+ default:
+ return EINVAL;
+ }
+ } else {
+ return EINVAL;
+ }
+
+ memcpy(aout, &mode, sizeof(afs_int32));
+ *aoutSize = sizeof(afs_int32);
+ return 0;
+#else
+ return EINVAL;
+#endif
+}
+
+DECL_PIOCTL(PNFSNukeCreds)
+{
+ afs_uint32 addr, code;
+ register afs_int32 i;
+ register struct unixuser *tu;
+
+ AFS_STATCNT(PUnlog);
+ if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
+ return EIO; /* Inappropriate ioctl for device */
+
+ if (ainSize < sizeof(afs_int32))
+ return EINVAL;
+ memcpy(&addr, ain, sizeof(afs_int32));
+
+ if ((*acred)->cr_gid == RMTUSER_REQ_PRIV && !addr) {
+ tu = afs_GetUser(areq->uid, -1, SHARED_LOCK);
+ if (!tu->exporter || !(addr = EXP_GETHOST(tu->exporter))) {
+ afs_PutUser(tu, SHARED_LOCK);
+ return EACCES;
+ }
+ afs_PutUser(tu, SHARED_LOCK);
+ } else if (!afs_osi_suser(acred)) {
+ return EACCES;
+ }
+
+ ObtainWriteLock(&afs_xuser, 227);
+ for (i = 0; i < NUSERS; i++) {
+ for (tu = afs_users[i]; tu; tu = tu->next) {
+ if (tu->exporter && EXP_CHECKHOST(tu->exporter, addr)) {
+ tu->vid = UNDEFVID;
+ tu->states &= ~UHasTokens;
+ /* security is not having to say you're sorry */
+ memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
+ tu->refCount++;
+ ReleaseWriteLock(&afs_xuser);
+ afs_ResetUserConns(tu);
+ tu->refCount--;
+ ObtainWriteLock(&afs_xuser, 228);
+#ifdef UKERNEL
+ /* set the expire times to 0, causes
+ * afs_GCUserData to remove this entry
+ */
+ tu->ct.EndTimestamp = 0;
+ tu->tokenTime = 0;
+#endif /* UKERNEL */
+ }
+ }
+ }
+ ReleaseWriteLock(&afs_xuser);
+ return 0;
+}