2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include "afs/param.h"
15 #include "afs/sysincludes.h" /* Standard vendor system headers */
17 #include "h/syscallargs.h"
19 #include "afsincludes.h" /* Afs-based standard headers */
20 #include "afs/afs_stats.h" /* afs statistics */
22 #include "rx/rx_globals.h"
24 struct VenusFid afs_rootFid;
25 afs_int32 afs_waitForever=0;
26 short afs_waitForeverCount = 0;
27 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
29 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
30 char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
31 struct AFS_UCRED **acred)
33 /* Prototypes for pioctl routines */
36 DECL_PIOCTL(PStoreBehind);
41 DECL_PIOCTL(PGetFileCell);
42 DECL_PIOCTL(PGetWSCell);
43 DECL_PIOCTL(PGetUserCell);
44 DECL_PIOCTL(PSetTokens);
45 DECL_PIOCTL(PGetVolumeStatus);
46 DECL_PIOCTL(PSetVolumeStatus);
48 DECL_PIOCTL(PNewStatMount);
49 DECL_PIOCTL(PGetTokens);
51 DECL_PIOCTL(PMariner);
52 DECL_PIOCTL(PCheckServers);
53 DECL_PIOCTL(PCheckVolNames);
54 DECL_PIOCTL(PCheckAuth);
55 DECL_PIOCTL(PFindVolume);
56 DECL_PIOCTL(PViceAccess);
57 DECL_PIOCTL(PSetCacheSize);
58 DECL_PIOCTL(PGetCacheSize);
59 DECL_PIOCTL(PRemoveCallBack);
60 DECL_PIOCTL(PNewCell);
61 DECL_PIOCTL(PNewAlias);
62 DECL_PIOCTL(PListCells);
63 DECL_PIOCTL(PListAliases);
64 DECL_PIOCTL(PRemoveMount);
65 DECL_PIOCTL(PVenusLogging);
66 DECL_PIOCTL(PGetCellStatus);
67 DECL_PIOCTL(PSetCellStatus);
68 DECL_PIOCTL(PFlushVolumeData);
69 DECL_PIOCTL(PGetVnodeXStatus);
70 DECL_PIOCTL(PSetSysName);
71 DECL_PIOCTL(PSetSPrefs);
72 DECL_PIOCTL(PSetSPrefs33);
73 DECL_PIOCTL(PGetSPrefs);
74 DECL_PIOCTL(PExportAfs);
76 DECL_PIOCTL(PTwiddleRx);
77 DECL_PIOCTL(PGetInitParams);
78 DECL_PIOCTL(PGetRxkcrypt);
79 DECL_PIOCTL(PSetRxkcrypt);
80 DECL_PIOCTL(PGetCPrefs);
81 DECL_PIOCTL(PSetCPrefs);
82 DECL_PIOCTL(PFlushMount);
83 DECL_PIOCTL(PRxStatProc);
84 DECL_PIOCTL(PRxStatPeer);
85 DECL_PIOCTL(PPrefetchFromTape);
86 DECL_PIOCTL(PResidencyCmd);
88 /* Prototypes for private routines */
89 static int HandleClientContext(struct afs_ioctl *ablob, int *com,
90 struct AFS_UCRED **acred, struct AFS_UCRED *credp);
91 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata);
92 int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
93 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred);
94 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred);
97 static int (*(VpioctlSw[]))() = {
102 PGetVolumeStatus, /* 4 */
103 PSetVolumeStatus, /* 5 */
108 PCheckServers, /* 10 */
109 PCheckVolNames, /* 11 */
111 PBogus, /* 13 -- used to be quick check time */
113 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
114 PBogus, /* 16 -- used to be testing code */
115 PNoop, /* 17 -- used to be enable group */
116 PNoop, /* 18 -- used to be disable group */
117 PBogus, /* 19 -- used to be list group */
118 PViceAccess, /* 20 */
119 PUnlog, /* 21 -- unlog *is* unpag in this system */
120 PGetFID, /* 22 -- get file ID */
121 PBogus, /* 23 -- used to be waitforever */
122 PSetCacheSize, /* 24 */
123 PRemoveCallBack, /* 25 -- flush only the callback */
126 PRemoveMount, /* 28 -- delete mount point */
127 PNewStatMount, /* 29 -- new style mount point stat */
128 PGetFileCell, /* 30 -- get cell name for input file */
129 PGetWSCell, /* 31 -- get cell name for workstation */
130 PMariner, /* 32 - set/get mariner host */
131 PGetUserCell, /* 33 -- get cell name for user */
132 PVenusLogging, /* 34 -- Enable/Disable logging */
133 PGetCellStatus, /* 35 */
134 PSetCellStatus, /* 36 */
135 PFlushVolumeData, /* 37 -- flush all data from a volume */
136 PSetSysName, /* 38 - Set system name */
137 PExportAfs, /* 39 - Export Afs to remote nfs clients */
138 PGetCacheSize, /* 40 - get cache size and usage */
139 PGetVnodeXStatus, /* 41 - get vcache's special status */
140 PSetSPrefs33, /* 42 - Set CM Server preferences... */
141 PGetSPrefs, /* 43 - Get CM Server preferences... */
142 PGag, /* 44 - turn off/on all CM messages */
143 PTwiddleRx, /* 45 - adjust some RX params */
144 PSetSPrefs, /* 46 - Set CM Server preferences... */
145 PStoreBehind, /* 47 - set degree of store behind to be done */
146 PGCPAGs, /* 48 - disable automatic pag gc-ing */
147 PGetInitParams, /* 49 - get initial cm params */
148 PGetCPrefs, /* 50 - get client interface addresses */
149 PSetCPrefs, /* 51 - set client interface addresses */
150 PFlushMount, /* 52 - flush mount symlink data */
151 PRxStatProc, /* 53 - control process RX statistics */
152 PRxStatPeer, /* 54 - control peer RX statistics */
153 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
154 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
155 PBogus, /* 57 -- arla: set file prio */
156 PBogus, /* 58 -- arla: fallback getfh */
157 PBogus, /* 59 -- arla: fallback fhopen */
158 PBogus, /* 60 -- arla: controls xfsdebug */
159 PBogus, /* 61 -- arla: controls arla debug */
160 PBogus, /* 62 -- arla: debug interface */
161 PBogus, /* 63 -- arla: print xfs status */
162 PBogus, /* 64 -- arla: force cache check */
163 PBogus, /* 65 -- arla: break callback */
164 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
165 PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
166 PBogus, /* 68 -- arla: fetch stats */
169 static int (*(CpioctlSw[]))() = {
171 PNewAlias, /* 1 -- create new cell alias */
172 PListAliases, /* 2 -- list cell aliases */
175 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
176 int afs_nobody = NFS_NOBODY;
179 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
181 dst->in = (char *)(unsigned long)src->in;
182 dst->out = (char *)(unsigned long)src->out;
183 dst->in_size = src->in_size;
184 dst->out_size = src->out_size;
188 * If you need to change copyin_afs_ioctl(), you may also need to change
193 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
197 #if defined(AFS_HPUX_64BIT_ENV)
198 struct afs_ioctl32 dst32;
200 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
202 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
204 afs_ioctl32_to_afs_ioctl(&dst32, dst);
207 #endif /* defined(AFS_HPUX_64BIT_ENV) */
209 #if defined(AFS_SUN57_64BIT_ENV)
210 struct afs_ioctl32 dst32;
212 if (get_udatamodel() == DATAMODEL_ILP32) {
213 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
215 afs_ioctl32_to_afs_ioctl(&dst32, dst);
218 #endif /* defined(AFS_SUN57_64BIT_ENV) */
220 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
221 struct afs_ioctl32 dst32;
223 if (!ABI_IS_64BIT(get_current_abi()))
225 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
227 afs_ioctl32_to_afs_ioctl(&dst32, dst);
230 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
232 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
233 struct afs_ioctl32 dst32;
235 #ifdef AFS_SPARC64_LINUX24_ENV
236 if (current->thread.flags & SPARC_FLAG_32BIT)
237 #elif defined(AFS_SPARC64_LINUX20_ENV)
238 if (current->tss.flags & SPARC_FLAG_32BIT)
239 #elif defined(AFS_AMD64_LINUX20_ENV)
240 if (current->thread.flags & THREAD_IA32)
242 #error Not done for this linux type
245 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
247 afs_ioctl32_to_afs_ioctl(&dst32, dst);
250 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
252 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
256 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata)
258 register afs_int32 code;
261 AFS_STATCNT(HandleIoctl);
263 switch(acom & 0xff) {
265 avc->states |= CSafeStore;
269 /* case 2 used to be abort store, but this is no longer provided,
270 since it is impossible to implement under normal Unix.
274 /* return the name of the cell this file is open on */
275 register struct cell *tcell;
276 register afs_int32 i;
278 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
280 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
282 if (i > adata->out_size) {
283 /* 0 means we're not interested in the output */
284 if (adata->out_size != 0) code = EFAULT;
288 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
290 afs_PutCell(tcell, READ_LOCK);
296 case 49: /* VIOC_GETINITPARAMS */
297 if (adata->out_size < sizeof(struct cm_initparams)) {
301 AFS_COPYOUT(&cm_initParams, adata->out,
302 sizeof(struct cm_initparams), code);
314 return code; /* so far, none implemented */
319 /* For aix we don't temporarily bypass ioctl(2) but rather do our
320 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
321 * is now called from afs_gn_ioctl.
323 int afs_ioctl(struct vcache *tvc, int cmd, int arg)
325 struct afs_ioctl data;
328 AFS_STATCNT(afs_ioctl);
329 if (((cmd >> 8) & 0xff) == 'V') {
330 /* This is a VICEIOCTL call */
331 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
334 error = HandleIoctl(tvc, cmd, &data);
337 /* No-op call; just return. */
341 #endif /* AFS_AIX_ENV */
343 #if defined(AFS_SGI_ENV)
344 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
350 struct afs_ioctl data;
356 AFS_STATCNT(afs_ioctl);
357 if (((cmd >> 8) & 0xff) == 'V') {
358 /* This is a VICEIOCTL call */
359 error = copyin_afs_ioctl(arg, &data);
362 locked = ISAFS_GLOCK();
365 error = HandleIoctl(tvc, cmd, &data);
370 /* No-op call; just return. */
374 #endif /* AFS_SGI_ENV */
376 /* unlike most calls here, this one uses u.u_error to return error conditions,
377 since this is really an intercepted chapter 2 call, rather than a vnode
380 /* AFS_HPUX102 and up uses VNODE ioctl instead */
381 #ifndef AFS_HPUX102_ENV
382 #if !defined(AFS_SGI_ENV)
386 kioctl(fdes, com, arg, ext, arg2, arg3)
387 #else /* __64BIT__ */
388 kioctl32(fdes, com, arg, ext, arg2, arg3)
389 #endif /* __64BIT__ */
392 kioctl(fdes, com, arg, ext)
403 } u_uap, *uap = &u_uap;
405 #if defined(AFS_SUN5_ENV)
407 struct afs_ioctl_sys {
413 afs_xioctl (uap, rvp)
414 struct afs_ioctl_sys *uap;
417 #elif defined(AFS_OSF_ENV)
418 afs_xioctl (p, args, retval)
427 } *uap = (struct a *)args;
428 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
436 afs_xioctl(p, uap, retval)
438 register struct ioctl_args *uap;
441 #elif defined(AFS_LINUX22_ENV)
442 struct afs_ioctl_sys {
446 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
447 unsigned int com, unsigned long arg)
449 struct afs_ioctl_sys ua, *uap = &ua;
451 int afs_xioctl (void)
457 } *uap = (struct a *)u.u_ap;
458 #endif /* AFS_SUN5_ENV */
460 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
462 #elif !defined(AFS_LINUX22_ENV)
463 register struct file *fd;
465 #if defined(AFS_XBSD_ENV)
466 register struct filedesc *fdp;
468 register struct vcache *tvc;
469 register int ioctlDone = 0, code = 0;
471 AFS_STATCNT(afs_xioctl);
472 #if defined(AFS_XBSD_ENV)
474 if ((u_int)uap->fd >= fdp->fd_nfiles ||
475 (fd = fdp->fd_ofiles[uap->fd]) == NULL)
477 if ((fd->f_flag & (FREAD | FWRITE)) == 0)
480 #if defined(AFS_DARWIN_ENV)
481 if ((code=fdgetf(p, uap->fd, &fd)))
484 #ifdef AFS_LINUX22_ENV
497 if (setuerror(getf(uap->fd, &fd))) {
503 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
505 #else /* AFS_OSF_ENV */
507 #if defined(AFS_SUN57_ENV)
509 if (!fd) return(EBADF);
510 #elif defined(AFS_SUN54_ENV)
512 if (!fd) return(EBADF);
514 if (code = getf(uap->fd, &fd)) {
520 if (!fd) return(EBADF);
527 /* first determine whether this is any sort of vnode */
528 #if defined(AFS_LINUX22_ENV)
533 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
535 if (fd->f_type == DTYPE_VNODE) {
537 /* good, this is a vnode; next see if it is an AFS vnode */
538 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
539 tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
540 #elif defined(AFS_OBSD_ENV)
541 tvc = IsAfsVnode((struct vnode *) fd->f_data) ?
542 VTOAFS((struct vnode *) fd->f_data) : NULL;
544 tvc = VTOAFS((struct vnode*)fd->f_data); /* valid, given a vnode */
546 #endif /* AFS_LINUX22_ENV */
547 if (tvc && IsAfsVnode(AFSTOV(tvc))) {
549 tvc = VTOAFS(afs_gntovn((struct gnode *) tvc));
550 if (!tvc) { /* shouldn't happen with held gnodes */
555 /* This is an AFS vnode */
556 if (((uap->com >> 8) & 0xff) == 'V') {
557 register struct afs_ioctl *datap;
559 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
560 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
562 osi_FreeSmallSpace(datap);
564 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
567 #if defined(AFS_SUN5_ENV)
582 #else /* AFS_OSF_ENV */
586 #ifdef AFS_LINUX22_ENV
596 code = HandleIoctl(tvc, uap->com, datap);
597 osi_FreeSmallSpace(datap);
611 #if defined(AFS_LINUX22_ENV)
623 code = okioctl(fdes, com, arg, ext, arg2, arg3);
624 #else /* __64BIT__ */
625 code = okioctl32(fdes, com, arg, ext, arg2, arg3);
626 #endif /* __64BIT__ */
627 #else /* !AFS_AIX51_ENV */
628 code = okioctl(fdes, com, arg, ext);
629 #endif /* AFS_AIX51_ENV */
631 #else /* !AFS_AIX41_ENV */
633 okioctl(fdes, com, arg, ext);
634 #elif defined(AFS_SUN5_ENV)
635 #if defined(AFS_SUN57_ENV)
637 #elif defined(AFS_SUN54_ENV)
642 code = ioctl(uap, rvp);
643 #elif defined(AFS_FBSD_ENV)
644 return ioctl(p, uap);
645 #elif defined(AFS_OBSD_ENV)
646 code = sys_ioctl(p, uap, retval);
647 #elif defined(AFS_DARWIN_ENV)
648 return ioctl(p, uap, retval);
649 #elif defined(AFS_OSF_ENV)
650 code = ioctl(p, args, retval);
657 #elif !defined(AFS_LINUX22_ENV)
671 #ifdef AFS_LINUX22_ENV
674 #if defined(KERNEL_HAVE_UERROR)
677 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
678 return (getuerror() ? -1 : u.u_ioctlrv);
680 return getuerror() ? -1 : 0;
683 #endif /* AFS_LINUX22_ENV */
684 #endif /* AFS_SUN5_ENV */
685 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
689 #endif /* AFS_SGI_ENV */
690 #endif /* AFS_HPUX102_ENV */
692 #if defined(AFS_SGI_ENV)
693 /* "pioctl" system call entry point; just pass argument to the parameterized
702 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
706 AFS_STATCNT(afs_pioctl);
708 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
717 #elif defined(AFS_OSF_ENV)
718 afs_pioctl(p, args, retval)
728 } *uap = (struct a *) args;
730 AFS_STATCNT(afs_pioctl);
731 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
734 #elif defined(AFS_FBSD50_ENV)
736 afs_pioctl(td, args, retval)
746 } *uap = (struct a *) args;
748 AFS_STATCNT(afs_pioctl);
749 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, td->td_ucred));
752 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
754 afs_pioctl(p, args, retval)
764 } *uap = (struct a *) args;
766 AFS_STATCNT(afs_pioctl);
767 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
772 /* macro to avoid adding any more #ifdef's to pioctl code. */
773 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
774 #define PIOCTL_FREE_CRED() crfree(credp)
776 #define PIOCTL_FREE_CRED()
781 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
783 struct AFS_UCRED *credp;
785 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
786 afs_syscall_pioctl(path, com, cmarg, follow, credp)
787 struct AFS_UCRED *credp;
789 afs_syscall_pioctl(path, com, cmarg, follow)
797 struct afs_ioctl data;
798 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
799 register afs_int32 code = 0;
805 struct ucred *credp = crref(); /* don't free until done! */
807 #ifdef AFS_LINUX22_ENV
808 cred_t *credp = crref(); /* don't free until done! */
812 AFS_STATCNT(afs_syscall_pioctl);
813 if (follow) follow = 1; /* compat. with old venus */
814 code = copyin_afs_ioctl(cmarg, &data);
817 #if defined(KERNEL_HAVE_UERROR)
822 if ((com & 0xff) == PSetClientContext) {
823 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
824 return EINVAL; /* Not handling these yet. */
825 #elif defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
826 code = HandleClientContext(&data, &com, &foreigncreds, credp);
828 code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
832 crfree(foreigncreds);
835 #if defined(KERNEL_HAVE_UERROR)
836 return (setuerror(code), code);
842 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
845 * We could have done without temporary setting the u.u_cred below
846 * (foreigncreds could be passed as param the pioctl modules)
847 * but calls such as afs_osi_suser() doesn't allow that since it
848 * references u.u_cred directly. We could, of course, do something
849 * like afs_osi_suser(cred) which, I think, is better since it
850 * generalizes and supports multi cred environments...
854 credp = foreigncreds;
857 tmpcred = crref(); /* XXX */
860 #if defined(AFS_HPUX101_ENV)
861 tmpcred = p_cred(u.u_procp);
862 set_p_cred(u.u_procp, foreigncreds);
865 tmpcred = OSI_GET_CURRENT_CRED();
866 OSI_SET_CURRENT_CRED(foreigncreds);
869 tmpcred = osi_curcred();
870 osi_curcred() = foreigncreds;
873 u.u_cred = foreigncreds;
874 #endif /* AFS_SGI64_ENV */
875 #endif /* AFS_HPUX101_ENV */
881 if ((com & 0xff) == 15) {
882 /* special case prefetch so entire pathname eval occurs in helper process.
883 otherwise, the pioctl call is essentially useless */
884 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
885 code = Prefetch(path, &data, follow,
886 foreigncreds ? foreigncreds : credp);
888 code = Prefetch(path, &data, follow, osi_curcred());
891 #if defined(KERNEL_HAVE_UERROR)
899 code = lookupname(path, USR, follow, NULL, &vp,
900 foreigncreds ? foreigncreds : credp);
902 #ifdef AFS_LINUX22_ENV
903 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &dp);
905 vp = (struct vnode *)dp->d_inode;
907 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &vp);
908 #endif /* AFS_LINUX22_ENV */
909 #endif /* AFS_AIX41_ENV */
913 #if defined(KERNEL_HAVE_UERROR)
921 /* now make the call if we were passed no file, or were passed an AFS file */
922 if (!vp || IsAfsVnode(vp)) {
924 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
925 * So, we must test in this part of the code. Also, must arrange to
926 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
927 * we hold gnodes, whose references hold our vcache entries.
930 gp = vp; /* remember for "put" */
931 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
936 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
940 struct ucred *cred1, *cred2;
943 cred1 = cred2 = foreigncreds;
945 cred1 = cred2 = credp;
947 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
948 if (cred1 != cred2) {
949 /* something changed the creds */
954 #if defined(AFS_HPUX101_ENV)
956 struct ucred *cred = p_cred(u.u_procp);
957 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
963 credp = OSI_GET_CURRENT_CRED();
964 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
967 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
968 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
970 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
972 #endif /* AFS_SGI_ENV */
973 #endif /* AFS_HPUX101_ENV */
974 #endif /* AFS_AIX41_ENV */
975 #endif /* AFS_SUN5_ENV */
977 #if defined(KERNEL_HAVE_UERROR)
980 code = EINVAL; /* not in /afs */
991 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
994 crset(tmpcred); /* restore original credentials */
996 #if defined(AFS_HPUX101_ENV)
997 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
998 #elif defined(AFS_SGI_ENV)
999 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
1000 #elif !defined(AFS_SUN5_ENV)
1001 osi_curcred() = tmpcred; /* restore original credentials */
1002 #endif /* AFS_HPUX101_ENV */
1003 crfree(foreigncreds);
1006 #endif /* LINUX, DARWIN, FBSD */
1008 #ifdef AFS_LINUX22_ENV
1011 AFS_RELE(vp); /* put vnode back */
1015 #ifdef AFS_LINUX22_ENV
1018 #if defined(KERNEL_HAVE_UERROR)
1021 return (getuerror());
1029 int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
1030 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1033 struct vrequest treq;
1034 register afs_int32 code;
1035 register afs_int32 function, device;
1036 afs_int32 inSize, outSize;
1037 char *inData, *outData;
1038 int (*(*pioctlSw))();
1040 struct afs_fakestat_state fakestate;
1042 avc = avp ? VTOAFS(avp) : NULL;
1043 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1044 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1045 AFS_STATCNT(HandlePioctl);
1046 if ((code = afs_InitReq(&treq, *acred))) return code;
1047 afs_InitFakeStat(&fakestate);
1049 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1051 afs_PutFakeStat(&fakestate);
1055 device = (acom & 0xff00) >> 8;
1057 case 'V': /* Original pioctls */
1058 pioctlSw = VpioctlSw;
1059 pioctlSwSize = sizeof(VpioctlSw);
1061 case 'C': /* Coordinated/common pioctls */
1062 pioctlSw = CpioctlSw;
1063 pioctlSwSize = sizeof(CpioctlSw);
1066 afs_PutFakeStat(&fakestate);
1069 function = acom & 0xff;
1070 if (function >= (pioctlSwSize / sizeof(char *))) {
1071 afs_PutFakeStat(&fakestate);
1072 return EINVAL; /* out of range */
1074 inSize = ablob->in_size;
1076 /* Do all range checking before continuing */
1077 if (inSize >= PIGGYSIZE || inSize < 0 || ablob->out_size < 0)
1080 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1082 AFS_COPYIN(ablob->in, inData, inSize, code);
1083 inData[inSize]='\0';
1087 osi_FreeLargeSpace(inData);
1088 afs_PutFakeStat(&fakestate);
1091 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1093 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1094 osi_FreeLargeSpace(inData);
1095 if (code == 0 && ablob->out_size > 0) {
1096 if (outSize > ablob->out_size) outSize = ablob->out_size;
1097 if (outSize >= PIGGYSIZE) code = E2BIG;
1099 outData[outSize]='\0';
1100 AFS_COPYOUT(outData, ablob->out, outSize, code);
1103 osi_FreeLargeSpace(outData);
1104 afs_PutFakeStat(&fakestate);
1105 return afs_CheckCode(code, &treq, 41);
1108 DECL_PIOCTL(PGetFID)
1110 AFS_STATCNT(PGetFID);
1111 if (!avc) return EINVAL;
1112 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1113 *aoutSize = sizeof(struct VenusFid);
1117 DECL_PIOCTL(PSetAcl)
1119 register afs_int32 code;
1121 struct AFSOpaque acl;
1122 struct AFSVolSync tsync;
1123 struct AFSFetchStatus OutStatus;
1126 AFS_STATCNT(PSetAcl);
1129 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1132 acl.AFSOpaque_val = ain;
1134 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1136 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1138 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1139 &acl, &OutStatus, &tsync);
1145 (afs_Analyze(tconn, code, &avc->fid, areq,
1146 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1148 /* now we've forgotten all of the access info */
1149 ObtainWriteLock(&afs_xcbhash, 455);
1151 afs_DequeueCallback(avc);
1152 avc->states &= ~(CStatd | CUnique);
1153 ReleaseWriteLock(&afs_xcbhash);
1154 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1155 osi_dnlc_purgedp(avc);
1159 int afs_defaultAsynchrony = 0;
1161 DECL_PIOCTL(PStoreBehind)
1164 struct sbstruct *sbr;
1166 sbr = (struct sbstruct *)ain;
1167 if (sbr->sb_default != -1) {
1168 if (afs_osi_suser(*acred))
1169 afs_defaultAsynchrony = sbr->sb_default;
1173 if (avc && (sbr->sb_thisfile != -1)) {
1174 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1175 areq, DONT_CHECK_MODE_BITS))
1176 avc->asynchrony = sbr->sb_thisfile;
1180 *aoutSize = sizeof(struct sbstruct);
1181 sbr = (struct sbstruct *)aout;
1182 sbr->sb_default = afs_defaultAsynchrony;
1184 sbr->sb_thisfile = avc->asynchrony;
1190 DECL_PIOCTL(PGCPAGs)
1192 if (!afs_osi_suser(*acred)) {
1195 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1199 DECL_PIOCTL(PGetAcl)
1201 struct AFSOpaque acl;
1202 struct AFSVolSync tsync;
1203 struct AFSFetchStatus OutStatus;
1209 AFS_STATCNT(PGetAcl);
1210 if (!avc) return EINVAL;
1211 Fid.Volume = avc->fid.Fid.Volume;
1212 Fid.Vnode = avc->fid.Fid.Vnode;
1213 Fid.Unique = avc->fid.Fid.Unique;
1214 if (avc->states & CForeign) {
1216 * For a dfs xlator acl we have a special hack so that the
1217 * xlator will distinguish which type of acl will return. So
1218 * we currently use the top 2-bytes (vals 0-4) to tell which
1219 * type of acl to bring back. Horrible hack but this will
1220 * cause the least number of changes to code size and interfaces.
1222 if (Fid.Vnode & 0xc0000000)
1224 Fid.Vnode |= (ainSize << 30);
1226 acl.AFSOpaque_val = aout;
1228 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1231 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1233 code = RXAFS_FetchACL(tconn->id, &Fid,
1234 &acl, &OutStatus, &tsync);
1240 (afs_Analyze(tconn, code, &avc->fid, areq,
1241 AFS_STATS_FS_RPCIDX_FETCHACL,
1242 SHARED_LOCK, NULL));
1245 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1258 AFS_STATCNT(PBogus);
1262 DECL_PIOCTL(PGetFileCell)
1264 register struct cell *tcell;
1266 AFS_STATCNT(PGetFileCell);
1267 if (!avc) return EINVAL;
1268 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1269 if (!tcell) return ESRCH;
1270 strcpy(aout, tcell->cellName);
1271 afs_PutCell(tcell, READ_LOCK);
1272 *aoutSize = strlen(aout) + 1;
1276 DECL_PIOCTL(PGetWSCell)
1278 struct cell *tcell = NULL;
1280 AFS_STATCNT(PGetWSCell);
1281 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1282 return EIO; /* Inappropriate ioctl for device */
1284 tcell = afs_GetPrimaryCell(READ_LOCK);
1285 if (!tcell) /* no primary cell? */
1287 strcpy(aout, tcell->cellName);
1288 *aoutSize = strlen(aout) + 1;
1289 afs_PutCell(tcell, READ_LOCK);
1293 DECL_PIOCTL(PGetUserCell)
1295 register afs_int32 i;
1296 register struct unixuser *tu;
1297 register struct cell *tcell;
1299 AFS_STATCNT(PGetUserCell);
1300 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1301 return EIO; /* Inappropriate ioctl for device */
1303 /* return the cell name of the primary cell for this user */
1304 i = UHash(areq->uid);
1305 ObtainWriteLock(&afs_xuser,224);
1306 for(tu = afs_users[i]; tu; tu = tu->next) {
1307 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1309 ReleaseWriteLock(&afs_xuser);
1314 tcell = afs_GetCell(tu->cell, READ_LOCK);
1315 afs_PutUser(tu, WRITE_LOCK);
1316 if (!tcell) return ESRCH;
1318 strcpy(aout, tcell->cellName);
1319 afs_PutCell(tcell, READ_LOCK);
1320 *aoutSize = strlen(aout)+1; /* 1 for the null */
1324 ReleaseWriteLock(&afs_xuser);
1331 DECL_PIOCTL(PSetTokens)
1334 register struct unixuser *tu;
1335 struct ClearToken clear;
1336 register struct cell *tcell;
1339 struct vrequest treq;
1340 afs_int32 flag, set_parent_pag = 0;
1342 AFS_STATCNT(PSetTokens);
1343 if (!afs_resourceinit_flag) {
1346 memcpy((char *)&i, ain, sizeof(afs_int32));
1347 ain += sizeof(afs_int32);
1348 stp = ain; /* remember where the ticket is */
1349 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1350 if (i > MAXKTCTICKETLEN) return EINVAL;
1352 ain += i; /* skip over ticket */
1353 memcpy((char *)&i, ain, sizeof(afs_int32));
1354 ain += sizeof(afs_int32);
1355 if (i != sizeof(struct ClearToken)) {
1358 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1359 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1360 ain += sizeof(struct ClearToken);
1361 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1362 /* still stuff left? we've got primary flag and cell name. Set these */
1363 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1364 ain += sizeof(afs_int32); /* skip id field */
1365 /* rest is cell name, look it up */
1366 /* some versions of gcc appear to need != 0 in order to get this right */
1367 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1371 tcell = afs_GetCellByName(ain, READ_LOCK);
1372 if (!tcell) goto nocell;
1375 /* default to primary cell, primary id */
1376 flag = 1; /* primary id */
1377 tcell = afs_GetPrimaryCell(READ_LOCK);
1378 if (!tcell) goto nocell;
1381 afs_PutCell(tcell, READ_LOCK);
1382 if (set_parent_pag) {
1384 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1385 #if defined(AFS_DARWIN_ENV)
1386 struct proc *p = current_proc(); /* XXX */
1388 struct proc *p = curproc; /* XXX */
1390 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1391 p->p_pid, p->p_comm);
1392 if (!setpag(p, acred, -1, &pag, 1)) {
1395 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1397 if (!setpag(acred, -1, &pag, 1)) {
1400 afs_InitReq(&treq, *acred);
1404 /* now we just set the tokens */
1405 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1406 tu->vid = clear.ViceId;
1407 if (tu->stp != NULL) {
1408 afs_osi_Free(tu->stp, tu->stLen);
1410 tu->stp = (char *) afs_osi_Alloc(stLen);
1412 memcpy(tu->stp, stp, stLen);
1415 afs_stats_cmfullperf.authent.TicketUpdates++;
1416 afs_ComputePAGStats();
1417 #endif /* AFS_NOSTATS */
1418 tu->states |= UHasTokens;
1419 tu->states &= ~UTokensBad;
1420 afs_SetPrimary(tu, flag);
1421 tu->tokenTime =osi_Time();
1422 afs_ResetUserConns(tu);
1423 afs_PutUser(tu, WRITE_LOCK);
1438 DECL_PIOCTL(PGetVolumeStatus)
1441 char offLineMsg[256];
1443 register struct conn *tc;
1444 register afs_int32 code;
1445 struct VolumeStatus volstat;
1447 char *Name, *OfflineMsg, *MOTD;
1450 AFS_STATCNT(PGetVolumeStatus);
1451 if (!avc) return EINVAL;
1453 OfflineMsg = offLineMsg;
1456 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1458 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1460 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1461 &Name, &OfflineMsg, &MOTD);
1467 (afs_Analyze(tc, code, &avc->fid, areq,
1468 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1469 SHARED_LOCK, NULL));
1471 if (code) return code;
1472 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1474 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1475 cp += sizeof(VolumeStatus);
1476 strcpy(cp, volName);
1477 cp += strlen(volName)+1;
1478 strcpy(cp, offLineMsg);
1479 cp += strlen(offLineMsg)+1;
1481 cp += strlen(motd)+1;
1482 *aoutSize = (cp - aout);
1486 DECL_PIOCTL(PSetVolumeStatus)
1489 char offLineMsg[256];
1491 register struct conn *tc;
1492 register afs_int32 code;
1493 struct AFSFetchVolumeStatus volstat;
1494 struct AFSStoreVolumeStatus storeStat;
1495 register struct volume *tvp;
1499 AFS_STATCNT(PSetVolumeStatus);
1500 if (!avc) return EINVAL;
1502 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1504 if (tvp->states & (VRO | VBackup)) {
1505 afs_PutVolume(tvp, READ_LOCK);
1508 afs_PutVolume(tvp, READ_LOCK);
1511 /* Copy the junk out, using cp as a roving pointer. */
1513 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1514 cp += sizeof(AFSFetchVolumeStatus);
1515 if (strlen(cp) >= sizeof(volName))
1517 strcpy(volName, cp);
1518 cp += strlen(volName)+1;
1519 if (strlen(cp) >= sizeof(offLineMsg))
1521 strcpy(offLineMsg, cp);
1522 cp += strlen(offLineMsg)+1;
1523 if (strlen(cp) >= sizeof(motd))
1527 if (volstat.MinQuota != -1) {
1528 storeStat.MinQuota = volstat.MinQuota;
1529 storeStat.Mask |= AFS_SETMINQUOTA;
1531 if (volstat.MaxQuota != -1) {
1532 storeStat.MaxQuota = volstat.MaxQuota;
1533 storeStat.Mask |= AFS_SETMAXQUOTA;
1536 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1538 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1540 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1541 &storeStat, volName, offLineMsg, motd);
1547 (afs_Analyze(tc, code, &avc->fid, areq,
1548 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1549 SHARED_LOCK, NULL));
1551 if (code) return code;
1552 /* we are sending parms back to make compat. with prev system. should
1553 change interface later to not ask for current status, just set new status */
1555 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1556 cp += sizeof(VolumeStatus);
1557 strcpy(cp, volName);
1558 cp += strlen(volName)+1;
1559 strcpy(cp, offLineMsg);
1560 cp += strlen(offLineMsg)+1;
1562 cp += strlen(motd)+1;
1563 *aoutSize = cp - aout;
1569 AFS_STATCNT(PFlush);
1570 if (!avc) return EINVAL;
1571 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1572 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1574 ObtainWriteLock(&avc->lock,225);
1575 ObtainWriteLock(&afs_xcbhash, 456);
1576 afs_DequeueCallback(avc);
1577 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1578 ReleaseWriteLock(&afs_xcbhash);
1579 /* now find the disk cache entries */
1580 afs_TryToSmush(avc, *acred, 1);
1581 osi_dnlc_purgedp(avc);
1582 afs_symhint_inval(avc);
1583 if (avc->linkData && !(avc->states & CCore)) {
1584 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1585 avc->linkData = NULL;
1587 ReleaseWriteLock(&avc->lock);
1588 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1589 afs_BozonUnlock(&avc->pvnLock, avc);
1594 DECL_PIOCTL(PNewStatMount)
1596 register afs_int32 code;
1597 register struct vcache *tvc;
1598 register struct dcache *tdc;
1599 struct VenusFid tfid;
1601 struct sysname_info sysState;
1602 afs_size_t offset, len;
1604 AFS_STATCNT(PNewStatMount);
1605 if (!avc) return EINVAL;
1606 code = afs_VerifyVCache(avc, areq);
1607 if (code) return code;
1608 if (vType(avc) != VDIR) {
1611 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1612 if (!tdc) return ENOENT;
1613 Check_AtSys(avc, ain, &sysState, areq);
1614 ObtainReadLock(&tdc->lock);
1616 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1617 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1618 ReleaseReadLock(&tdc->lock);
1619 afs_PutDCache(tdc); /* we're done with the data */
1620 bufp = sysState.name;
1624 tfid.Cell = avc->fid.Cell;
1625 tfid.Fid.Volume = avc->fid.Fid.Volume;
1626 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1627 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1629 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1635 if (tvc->mvstat != 1) {
1640 ObtainWriteLock(&tvc->lock,226);
1641 code = afs_HandleLink(tvc, areq);
1643 if (tvc->linkData) {
1644 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1647 /* we have the data */
1648 strcpy(aout, tvc->linkData);
1649 *aoutSize = strlen(tvc->linkData)+1;
1654 ReleaseWriteLock(&tvc->lock);
1657 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1661 DECL_PIOCTL(PGetTokens)
1663 register struct cell *tcell;
1664 register afs_int32 i;
1665 register struct unixuser *tu;
1670 AFS_STATCNT(PGetTokens);
1671 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1672 return EIO; /* Inappropriate ioctl for device */
1674 /* weird interface. If input parameter is present, it is an integer and
1675 we're supposed to return the parm'th tokens for this unix uid.
1676 If not present, we just return tokens for cell 1.
1677 If counter out of bounds, return EDOM.
1678 If no tokens for the particular cell, return ENOTCONN.
1679 Also, if this mysterious parm is present, we return, along with the
1680 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1681 at the end, in that order.
1683 if ((newStyle = (ainSize > 0))) {
1684 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1686 i = UHash(areq->uid);
1687 ObtainReadLock(&afs_xuser);
1688 for(tu = afs_users[i]; tu; tu=tu->next) {
1690 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1691 if (iterator-- == 0) break; /* are we done yet? */
1695 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1700 * No need to hold a read lock on each user entry
1704 ReleaseReadLock(&afs_xuser);
1709 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1710 tu->states |= (UTokensBad | UNeedsReset);
1711 afs_PutUser(tu, READ_LOCK);
1714 /* use iterator for temp */
1716 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1717 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1718 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1719 cp += sizeof(afs_int32);
1720 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1722 iterator = sizeof(struct ClearToken);
1723 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1724 cp += sizeof(afs_int32);
1725 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1726 cp += sizeof(struct ClearToken);
1728 /* put out primary id and cell name, too */
1729 iterator = (tu->states & UPrimary ? 1 : 0);
1730 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1731 cp += sizeof(afs_int32);
1732 tcell = afs_GetCell(tu->cell, READ_LOCK);
1734 strcpy(cp, tcell->cellName);
1735 cp += strlen(tcell->cellName)+1;
1736 afs_PutCell(tcell, READ_LOCK);
1740 *aoutSize = cp - aout;
1741 afs_PutUser(tu, READ_LOCK);
1747 register afs_int32 i;
1748 register struct unixuser *tu;
1750 AFS_STATCNT(PUnlog);
1751 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1752 return EIO; /* Inappropriate ioctl for device */
1754 i = UHash(areq->uid);
1755 ObtainWriteLock(&afs_xuser,227);
1756 for(tu=afs_users[i]; tu; tu=tu->next) {
1757 if (tu->uid == areq->uid) {
1759 tu->states &= ~UHasTokens;
1760 /* security is not having to say you're sorry */
1761 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1763 ReleaseWriteLock(&afs_xuser);
1764 /* We have to drop the lock over the call to afs_ResetUserConns, since
1765 * it obtains the afs_xvcache lock. We could also keep the lock, and
1766 * modify ResetUserConns to take parm saying we obtained the lock
1767 * already, but that is overkill. By keeping the "tu" pointer
1768 * held over the released lock, we guarantee that we won't lose our
1769 * place, and that we'll pass over every user conn that existed when
1770 * we began this call.
1772 afs_ResetUserConns(tu);
1774 ObtainWriteLock(&afs_xuser,228);
1776 /* set the expire times to 0, causes
1777 * afs_GCUserData to remove this entry
1779 tu->ct.EndTimestamp = 0;
1781 #endif /* UKERNEL */
1784 ReleaseWriteLock(&afs_xuser);
1788 DECL_PIOCTL(PMariner)
1790 afs_int32 newHostAddr;
1791 afs_int32 oldHostAddr;
1793 AFS_STATCNT(PMariner);
1795 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1797 oldHostAddr = 0xffffffff; /* disabled */
1799 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1800 if (newHostAddr == 0xffffffff) {
1801 /* disable mariner operations */
1804 else if (newHostAddr) {
1806 afs_marinerHost = newHostAddr;
1808 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1809 *aoutSize = sizeof(afs_int32);
1813 DECL_PIOCTL(PCheckServers)
1815 register char *cp = 0;
1817 register struct server *ts;
1818 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1820 struct chservinfo *pcheck;
1822 AFS_STATCNT(PCheckServers);
1824 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1825 return EIO; /* Inappropriate ioctl for device */
1827 if (*lp == 0x12345678) { /* For afs3.3 version */
1828 pcheck=(struct chservinfo *)ain;
1829 if (pcheck->tinterval >= 0) {
1831 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1832 *aoutSize = sizeof(afs_int32);
1833 if (pcheck->tinterval > 0) {
1834 if (!afs_osi_suser(*acred))
1836 PROBE_INTERVAL=pcheck->tinterval;
1842 temp=pcheck->tflags;
1843 cp = pcheck->tbuffer;
1844 } else { /* For pre afs3.3 versions */
1845 memcpy((char *)&temp, ain, sizeof(afs_int32));
1846 cp = ain+sizeof(afs_int32);
1847 if (ainSize > sizeof(afs_int32))
1852 * 1: fast check, don't contact servers.
1853 * 2: local cell only.
1856 /* have cell name, too */
1857 cellp = afs_GetCellByName(cp, READ_LOCK);
1858 if (!cellp) return ENOENT;
1861 if (!cellp && (temp & 2)) {
1862 /* use local cell */
1863 cellp = afs_GetPrimaryCell(READ_LOCK);
1865 if (!(temp & 1)) { /* if not fast, call server checker routine */
1866 afs_CheckServers(1, cellp); /* check down servers */
1867 afs_CheckServers(0, cellp); /* check up servers */
1869 /* now return the current down server list */
1871 ObtainReadLock(&afs_xserver);
1872 for(i=0;i<NSERVERS;i++) {
1873 for(ts = afs_servers[i]; ts; ts=ts->next) {
1874 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1875 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1876 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1877 cp += sizeof(afs_int32);
1881 ReleaseReadLock(&afs_xserver);
1882 if (cellp) afs_PutCell(cellp, READ_LOCK);
1883 *aoutSize = cp - aout;
1887 DECL_PIOCTL(PCheckVolNames)
1889 AFS_STATCNT(PCheckVolNames);
1890 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1891 return EIO; /* Inappropriate ioctl for device */
1893 afs_CheckRootVolume();
1894 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1895 AFS_VOLCHECK_EXPIRED |
1897 AFS_VOLCHECK_MTPTS);
1901 DECL_PIOCTL(PCheckAuth)
1906 struct unixuser *tu;
1909 AFS_STATCNT(PCheckAuth);
1910 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1911 return EIO; /* Inappropriate ioctl for device */
1914 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1915 if (!tu) retValue = EACCES;
1917 /* we have a user */
1918 ObtainReadLock(&afs_xsrvAddr);
1919 ObtainReadLock(&afs_xconn);
1921 /* any tokens set? */
1922 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1923 /* all connections in cell 1 working? */
1924 for(i=0;i<NSERVERS;i++) {
1925 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1926 for (tc = sa->conns; tc; tc=tc->next) {
1927 if (tc->user == tu && (tu->states & UTokensBad))
1932 ReleaseReadLock(&afs_xsrvAddr);
1933 ReleaseReadLock(&afs_xconn);
1934 afs_PutUser(tu, READ_LOCK);
1936 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1937 *aoutSize = sizeof(afs_int32);
1941 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1944 register afs_int32 code;
1945 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1951 AFS_STATCNT(Prefetch);
1952 if (!apath) return EINVAL;
1953 tp = osi_AllocLargeSpace(1024);
1954 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1956 osi_FreeLargeSpace(tp);
1959 if (afs_BBusy()) { /* do this as late as possible */
1960 osi_FreeLargeSpace(tp);
1961 return EWOULDBLOCK; /* pretty close */
1963 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1964 (afs_size_t) 0, (afs_size_t) 0, tp);
1968 DECL_PIOCTL(PFindVolume)
1970 register struct volume *tvp;
1971 register struct server *ts;
1972 register afs_int32 i;
1975 AFS_STATCNT(PFindVolume);
1976 if (!avc) return EINVAL;
1977 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1980 for(i=0;i<MAXHOSTS;i++) {
1981 ts = tvp->serverHost[i];
1983 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1984 cp += sizeof(afs_int32);
1987 /* still room for terminating NULL, add it on */
1988 ainSize = 0; /* reuse vbl */
1989 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
1990 cp += sizeof(afs_int32);
1992 *aoutSize = cp - aout;
1993 afs_PutVolume(tvp, READ_LOCK);
1999 DECL_PIOCTL(PViceAccess)
2001 register afs_int32 code;
2004 AFS_STATCNT(PViceAccess);
2005 if (!avc) return EINVAL;
2006 code = afs_VerifyVCache(avc, areq);
2007 if (code) return code;
2008 memcpy((char *)&temp, ain, sizeof(afs_int32));
2009 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2014 DECL_PIOCTL(PSetCacheSize)
2019 AFS_STATCNT(PSetCacheSize);
2020 if (!afs_osi_suser(*acred))
2022 /* too many things are setup initially in mem cache version */
2023 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2024 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2025 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2027 if (newValue < afs_min_cache)
2028 afs_cacheBlocks = afs_min_cache;
2030 afs_cacheBlocks = newValue;
2032 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2033 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2034 afs_MaybeWakeupTruncateDaemon();
2035 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2036 afs_osi_Wait(1000, 0, 0);
2037 afs_MaybeWakeupTruncateDaemon();
2042 #define MAXGCSTATS 16
2043 DECL_PIOCTL(PGetCacheSize)
2045 afs_int32 results[MAXGCSTATS];
2047 AFS_STATCNT(PGetCacheSize);
2048 memset((char *)results, 0, sizeof(results));
2049 results[0] = afs_cacheBlocks;
2050 results[1] = afs_blocksUsed;
2051 memcpy(aout, (char *)results, sizeof(results));
2052 *aoutSize = sizeof(results);
2056 DECL_PIOCTL(PRemoveCallBack)
2058 register struct conn *tc;
2059 register afs_int32 code = 0;
2060 struct AFSCallBack CallBacks_Array[1];
2061 struct AFSCBFids theFids;
2062 struct AFSCBs theCBs;
2065 AFS_STATCNT(PRemoveCallBack);
2066 if (!avc) return EINVAL;
2067 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2068 ObtainWriteLock(&avc->lock,229);
2069 theFids.AFSCBFids_len = 1;
2070 theCBs.AFSCBs_len = 1;
2071 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2072 theCBs.AFSCBs_val = CallBacks_Array;
2073 CallBacks_Array[0].CallBackType = CB_DROPPED;
2074 if (avc->callback) {
2076 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2078 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2080 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2084 /* don't set code on failure since we wouldn't use it */
2086 (afs_Analyze(tc, code, &avc->fid, areq,
2087 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2088 SHARED_LOCK, NULL));
2090 ObtainWriteLock(&afs_xcbhash, 457);
2091 afs_DequeueCallback(avc);
2093 avc->states &= ~(CStatd | CUnique);
2094 ReleaseWriteLock(&afs_xcbhash);
2095 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2096 osi_dnlc_purgedp(avc);
2098 ReleaseWriteLock(&avc->lock);
2102 DECL_PIOCTL(PNewCell)
2104 /* create a new cell */
2105 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2106 char *newcell=0, *linkedcell=0, *tp= ain;
2107 register afs_int32 code, linkedstate=0, ls;
2108 u_short fsport = 0, vlport = 0;
2111 AFS_STATCNT(PNewCell);
2112 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2113 return EIO; /* Inappropriate ioctl for device */
2115 if (!afs_osi_suser(*acred))
2118 memcpy((char *)&magic, tp, sizeof(afs_int32));
2119 tp += sizeof(afs_int32);
2120 if (magic != 0x12345678)
2123 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2124 * server addresses while the 3.5 fs newcell command passes
2125 * MAXHOSTS. To figure out which is which, check if the cellname
2128 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2129 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2131 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2132 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2133 tp += (scount * sizeof(afs_int32));
2135 lp = (afs_int32 *)tp;
2138 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2139 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2140 tp += (3 * sizeof(afs_int32));
2142 if ((ls = *lp) & 1) {
2143 linkedcell = tp + strlen(newcell)+1;
2144 linkedstate |= CLinkedCell;
2147 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2148 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2153 DECL_PIOCTL(PNewAlias)
2155 /* create a new cell alias */
2157 register afs_int32 code;
2158 char *realName, *aliasName;
2160 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2161 return EIO; /* Inappropriate ioctl for device */
2163 if (!afs_osi_suser(*acred))
2167 tp += strlen(aliasName) + 1;
2170 code = afs_NewCellAlias(aliasName, realName);
2175 DECL_PIOCTL(PListCells)
2177 afs_int32 whichCell;
2178 register struct cell *tcell=0;
2179 register afs_int32 i;
2180 register char *cp, *tp = ain;
2182 AFS_STATCNT(PListCells);
2183 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2184 return EIO; /* Inappropriate ioctl for device */
2186 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2187 tp += sizeof(afs_int32);
2188 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2191 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2192 for(i=0;i<MAXCELLHOSTS;i++) {
2193 if (tcell->cellHosts[i] == 0) break;
2194 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2195 cp += sizeof(afs_int32);
2197 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2198 strcpy(cp, tcell->cellName);
2199 cp += strlen(tcell->cellName)+1;
2200 *aoutSize = cp - aout;
2201 afs_PutCell(tcell, READ_LOCK);
2203 if (tcell) return 0;
2207 DECL_PIOCTL(PListAliases)
2209 afs_int32 whichAlias;
2210 register struct cell_alias *tcalias=0;
2211 register char *cp, *tp = ain;
2213 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2214 return EIO; /* Inappropriate ioctl for device */
2215 if (ainSize < sizeof(afs_int32))
2218 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2219 tp += sizeof(afs_int32);
2221 tcalias = afs_GetCellAlias(whichAlias);
2224 strcpy(cp, tcalias->alias);
2225 cp += strlen(tcalias->alias)+1;
2226 strcpy(cp, tcalias->cell);
2227 cp += strlen(tcalias->cell)+1;
2228 *aoutSize = cp - aout;
2229 afs_PutCellAlias(tcalias);
2231 if (tcalias) return 0;
2235 DECL_PIOCTL(PRemoveMount)
2237 register afs_int32 code;
2239 struct sysname_info sysState;
2240 afs_size_t offset, len;
2241 register struct conn *tc;
2242 register struct dcache *tdc;
2243 register struct vcache *tvc;
2244 struct AFSFetchStatus OutDirStatus;
2245 struct VenusFid tfid;
2246 struct AFSVolSync tsync;
2250 /* "ain" is the name of the file in this dir to remove */
2252 AFS_STATCNT(PRemoveMount);
2253 if (!avc) return EINVAL;
2254 code = afs_VerifyVCache(avc, areq);
2255 if (code) return code;
2256 if (vType(avc) != VDIR) return ENOTDIR;
2258 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2259 if (!tdc) return ENOENT;
2260 Check_AtSys(avc, ain, &sysState, areq);
2261 ObtainReadLock(&tdc->lock);
2263 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2264 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2265 ReleaseReadLock(&tdc->lock);
2266 bufp = sysState.name;
2271 tfid.Cell = avc->fid.Cell;
2272 tfid.Fid.Volume = avc->fid.Fid.Volume;
2273 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2274 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2276 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2283 if (tvc->mvstat != 1) {
2289 ObtainWriteLock(&tvc->lock,230);
2290 code = afs_HandleLink(tvc, areq);
2292 if (tvc->linkData) {
2293 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2298 ReleaseWriteLock(&tvc->lock);
2299 osi_dnlc_purgedp(tvc);
2305 ObtainWriteLock(&avc->lock,231);
2306 osi_dnlc_remove(avc, bufp, tvc);
2308 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2310 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2312 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2313 bufp, &OutDirStatus, &tsync);
2319 (afs_Analyze(tc, code, &avc->fid, areq,
2320 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2321 SHARED_LOCK, NULL));
2324 if (tdc) afs_PutDCache(tdc);
2325 ReleaseWriteLock(&avc->lock);
2329 /* we have the thing in the cache */
2330 ObtainWriteLock(&tdc->lock, 661);
2331 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2332 /* we can do it locally */
2333 code = afs_dir_Delete(&tdc->f.inode, bufp);
2335 ZapDCE(tdc); /* surprise error -- invalid value */
2336 DZap(&tdc->f.inode);
2339 ReleaseWriteLock(&tdc->lock);
2340 afs_PutDCache(tdc); /* drop ref count */
2342 avc->states &= ~CUnique; /* For the dfs xlator */
2343 ReleaseWriteLock(&avc->lock);
2346 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2350 DECL_PIOCTL(PVenusLogging)
2352 return EINVAL; /* OBSOLETE */
2355 DECL_PIOCTL(PGetCellStatus)
2357 register struct cell *tcell;
2360 AFS_STATCNT(PGetCellStatus);
2361 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2362 return EIO; /* Inappropriate ioctl for device */
2364 tcell = afs_GetCellByName(ain, READ_LOCK);
2365 if (!tcell) return ENOENT;
2366 temp = tcell->states;
2367 afs_PutCell(tcell, READ_LOCK);
2368 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2369 *aoutSize = sizeof(afs_int32);
2373 DECL_PIOCTL(PSetCellStatus)
2375 register struct cell *tcell;
2378 if (!afs_osi_suser(*acred))
2380 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2381 return EIO; /* Inappropriate ioctl for device */
2383 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2384 if (!tcell) return ENOENT;
2385 memcpy((char *)&temp, ain, sizeof(afs_int32));
2387 tcell->states |= CNoSUID;
2389 tcell->states &= ~CNoSUID;
2390 afs_PutCell(tcell, WRITE_LOCK);
2394 DECL_PIOCTL(PFlushVolumeData)
2396 register afs_int32 i;
2397 register struct dcache *tdc;
2398 register struct vcache *tvc;
2399 register struct volume *tv;
2400 afs_int32 cell, volume;
2402 AFS_STATCNT(PFlushVolumeData);
2405 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2406 return EIO; /* Inappropriate ioctl for device */
2408 volume = avc->fid.Fid.Volume; /* who to zap */
2409 cell = avc->fid.Cell;
2412 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2413 * the vcaches associated with the volume.
2415 ObtainReadLock(&afs_xvcache);
2416 for(i = 0; i < VCSIZE; i++) {
2417 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2418 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2419 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2420 VN_HOLD(AFSTOV(tvc));
2422 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
2428 ReleaseReadLock(&afs_xvcache);
2429 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2430 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2432 ObtainWriteLock(&tvc->lock,232);
2434 ObtainWriteLock(&afs_xcbhash, 458);
2435 afs_DequeueCallback(tvc);
2436 tvc->states &= ~(CStatd | CDirty);
2437 ReleaseWriteLock(&afs_xcbhash);
2438 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2439 osi_dnlc_purgedp(tvc);
2440 afs_TryToSmush(tvc, *acred, 1);
2441 ReleaseWriteLock(&tvc->lock);
2442 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2443 afs_BozonUnlock(&tvc->pvnLock, tvc);
2445 ObtainReadLock(&afs_xvcache);
2446 /* our tvc ptr is still good until now */
2451 ReleaseReadLock(&afs_xvcache);
2454 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2455 for(i=0;i<afs_cacheFiles;i++) {
2456 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2457 tdc = afs_GetDSlot(i, NULL);
2458 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2459 ReleaseReadLock(&tdc->tlock);
2460 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2461 if (! (afs_indexFlags[i] & IFDataMod)) {
2462 /* if the file is modified, but has a ref cnt of only 1, then
2463 someone probably has the file open and is writing into it.
2464 Better to skip flushing such a file, it will be brought back
2465 immediately on the next write anyway.
2467 If we *must* flush, then this code has to be rearranged to call
2468 afs_storeAllSegments() first */
2469 afs_FlushDCache(tdc);
2473 ReleaseReadLock(&tdc->tlock);
2475 afs_PutDCache(tdc); /* bumped by getdslot */
2477 MReleaseWriteLock(&afs_xdcache);
2479 ObtainReadLock(&afs_xvolume);
2480 for (i=0;i<NVOLS;i++) {
2481 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2482 if (tv->volume == volume) {
2483 afs_ResetVolumeInfo(tv);
2488 ReleaseReadLock(&afs_xvolume);
2490 /* probably, a user is doing this, probably, because things are screwed up.
2491 * maybe it's the dnlc's fault? */
2498 DECL_PIOCTL(PGetVnodeXStatus)
2500 register afs_int32 code;
2501 struct vcxstat stat;
2504 /* AFS_STATCNT(PGetVnodeXStatus); */
2505 if (!avc) return EINVAL;
2506 code = afs_VerifyVCache(avc, areq);
2507 if (code) return code;
2508 if (vType(avc) == VDIR)
2509 mode = PRSFS_LOOKUP;
2512 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2514 stat.fid = avc->fid;
2515 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2516 stat.lock = avc->lock;
2517 stat.parentVnode = avc->parentVnode;
2518 stat.parentUnique = avc->parentUnique;
2519 hset(stat.flushDV, avc->flushDV);
2520 hset(stat.mapDV, avc->mapDV);
2521 stat.truncPos = avc->truncPos;
2522 { /* just grab the first two - won't break anything... */
2523 struct axscache *ac;
2525 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2526 stat.randomUid[i] = ac->uid;
2527 stat.randomAccess[i] = ac->axess;
2530 stat.callback = afs_data_pointer_to_int32(avc->callback);
2531 stat.cbExpires = avc->cbExpires;
2532 stat.anyAccess = avc->anyAccess;
2533 stat.opens = avc->opens;
2534 stat.execsOrWriters = avc->execsOrWriters;
2535 stat.flockCount = avc->flockCount;
2536 stat.mvstat = avc->mvstat;
2537 stat.states = avc->states;
2538 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2539 *aoutSize = sizeof(struct vcxstat);
2544 /* We require root for local sysname changes, but not for remote */
2545 /* (since we don't really believe remote uids anyway) */
2546 /* outname[] shouldn't really be needed- this is left as an excercise */
2547 /* for the reader. */
2548 DECL_PIOCTL(PSetSysName)
2550 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2551 int setsysname, foundname=0;
2552 register struct afs_exporter *exporter;
2553 register struct unixuser *au;
2554 register afs_int32 pag, error;
2558 AFS_STATCNT(PSetSysName);
2559 if (!afs_globalVFS) {
2560 /* Afsd is NOT running; disable it */
2561 #if defined(KERNEL_HAVE_UERROR)
2562 return (setuerror(EINVAL), EINVAL);
2567 memset(inname, 0, MAXSYSNAME);
2568 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2569 ain += sizeof(afs_int32);
2573 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2575 for(cp = ain,count = 0;count < setsysname;count++) {
2576 /* won't go past end of ain since maxsysname*num < ain length */
2578 if (t >= MAXSYSNAME || t <= 0)
2580 /* check for names that can shoot us in the foot */
2581 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2587 /* inname gets first entry in case we're being a translater */
2589 memcpy(inname, ain, t+1); /* include terminating null */
2592 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2593 pag = PagInCred(*acred);
2595 return EINVAL; /* Better than panicing */
2597 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2598 return EINVAL; /* Better than panicing */
2600 if (!(exporter = au->exporter)) {
2601 afs_PutUser(au, READ_LOCK);
2602 return EINVAL; /* Better than panicing */
2604 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2606 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2608 afs_PutUser(au, READ_LOCK);
2613 afs_PutUser(au, READ_LOCK);
2616 /* Not xlating, so local case */
2617 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2618 if (!setsysname) { /* user just wants the info */
2619 strcpy(outname, afs_sysname);
2620 foundname = afs_sysnamecount;
2621 } else { /* Local guy; only root can change sysname */
2622 if (!afs_osi_suser(*acred))
2625 /* clear @sys entries from the dnlc, once afs_lookup can
2626 do lookups of @sys entries and thinks it can trust them */
2627 /* privs ok, store the entry, ... */
2628 strcpy(afs_sysname, inname);
2629 if (setsysname > 1) { /* ... or list */
2631 for(count=1; count < setsysname;++count) {
2632 if (!afs_sysnamelist[count])
2633 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2635 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2639 afs_sysnamecount = setsysname;
2643 cp = aout; /* not changing so report back the count and ... */
2644 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2645 cp += sizeof(afs_int32);
2647 strcpy(cp, outname); /* ... the entry, ... */
2648 cp += strlen(outname)+1;
2649 for(count=1; count < foundname; ++count) { /* ... or list. */
2650 /* Note: we don't support @sys lists for exporters */
2651 if (!afs_sysnamelist[count])
2652 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2653 t = strlen(afs_sysnamelist[count]);
2654 if (t >= MAXSYSNAME)
2655 osi_Panic("PSetSysName: sysname entry garbled\n");
2656 strcpy(cp, afs_sysnamelist[count]);
2660 *aoutSize = cp - aout;
2665 /* sequential search through the list of touched cells is not a good
2666 * long-term solution here. For small n, though, it should be just
2667 * fine. Should consider special-casing the local cell for large n.
2668 * Likewise for PSetSPrefs.
2670 * s - number of ids in array l[] -- NOT index of last id
2671 * l - array of cell ids which have volumes that need to be sorted
2672 * vlonly - sort vl servers or file servers?
2674 static void *ReSortCells_cb(struct cell *cell, void *arg)
2676 afs_int32 *p = (afs_int32 *) arg;
2677 afs_int32 *l = p + 1;
2680 for (i=0; i<s; i++) {
2681 if (l[i] == cell->cellNum) {
2682 ObtainWriteLock(&cell->lock, 690);
2683 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2684 ReleaseWriteLock(&cell->lock);
2691 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2699 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2701 memcpy(p+1, l, s * sizeof(afs_int32));
2702 afs_TraverseCells(&ReSortCells_cb, p);
2703 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2707 ObtainReadLock(&afs_xvolume);
2708 for (i= 0; i< NVOLS; i++) {
2709 for (j=afs_volumes[i];j;j=j->next) {
2711 if (j->cell == l[k]) {
2712 ObtainWriteLock(&j->lock,233);
2713 afs_SortServers(j->serverHost, MAXHOSTS);
2714 ReleaseWriteLock(&j->lock);
2719 ReleaseReadLock(&afs_xvolume);
2723 static int debugsetsp = 0;
2724 static int afs_setsprefs(sp, num, vlonly)
2727 unsigned int vlonly;
2730 int i,j,k,matches,touchedSize;
2731 struct server *srvr = NULL;
2732 afs_int32 touched[34];
2736 for (k=0; k < num; sp++, k++) {
2738 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2741 ObtainReadLock(&afs_xserver);
2743 i = SHash(sp->host.s_addr);
2744 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2745 if (sa->sa_ip == sp->host.s_addr) {
2747 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2748 || (sa->sa_portal == AFS_FSPORT);
2749 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2756 if (sa && matches) { /* found one! */
2758 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2760 sa->sa_iprank = sp->rank + afs_randomMod15();
2761 afs_SortOneServer(sa->server);
2764 /* if we don't know yet what cell it's in, this is moot */
2765 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2766 /* is it in our list of touched cells ? */ ;
2767 if (j < 0) { /* no, it's not */
2768 touched[touchedSize++] = srvr->cell->cellNum;
2769 if (touchedSize >= 32) { /* watch for ovrflow */
2770 ReleaseReadLock(&afs_xserver);
2771 ReSortCells(touchedSize, touched, vlonly);
2773 ObtainReadLock(&afs_xserver);
2779 ReleaseReadLock(&afs_xserver);
2780 /* if we didn't find one, start to create one. */
2781 /* Note that it doesn't have a cell yet... */
2783 afs_uint32 temp = sp->host.s_addr;
2784 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2785 WRITE_LOCK, (afsUUID *)0,0);
2786 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2787 afs_PutServer(srvr, WRITE_LOCK);
2789 } /* for all cited preferences */
2791 ReSortCells(touchedSize, touched, vlonly);
2795 /* Note that this may only be performed by the local root user.
2797 DECL_PIOCTL(PSetSPrefs)
2799 struct setspref *ssp;
2800 AFS_STATCNT(PSetSPrefs);
2802 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2803 return EIO; /* Inappropriate ioctl for device */
2805 if (!afs_osi_suser(*acred))
2808 if (ainSize < sizeof(struct setspref))
2811 ssp = (struct setspref *)ain;
2812 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2815 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2816 (ssp->flags & DBservers));
2820 DECL_PIOCTL(PSetSPrefs33)
2823 AFS_STATCNT(PSetSPrefs);
2824 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2825 return EIO; /* Inappropriate ioctl for device */
2828 if (!afs_osi_suser(*acred))
2831 sp = (struct spref *)ain;
2832 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2836 /* some notes on the following code...
2837 * in the hash table of server structs, all servers with the same IP address
2838 * will be on the same overflow chain.
2839 * This could be sped slightly in some circumstances by having it cache the
2840 * immediately previous slot in the hash table and some supporting information
2841 * Only reports file servers now.
2843 DECL_PIOCTL(PGetSPrefs)
2845 struct sprefrequest *spin; /* input */
2846 struct sprefinfo *spout; /* output */
2847 struct spref *srvout; /* one output component */
2848 int i,j; /* counters for hash table traversal */
2849 struct server *srvr; /* one of CM's server structs */
2851 int vlonly; /* just return vlservers ? */
2854 AFS_STATCNT(PGetSPrefs);
2855 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2856 return EIO; /* Inappropriate ioctl for device */
2859 if (ainSize < sizeof (struct sprefrequest_33)) {
2863 spin = ((struct sprefrequest *) ain);
2866 if (ainSize > sizeof (struct sprefrequest_33)) {
2867 vlonly = (spin->flags & DBservers);
2871 /* struct sprefinfo includes 1 server struct... that size gets added
2872 * in during the loop that follows.
2874 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2875 spout = (struct sprefinfo *) aout;
2876 spout->next_offset = spin->offset;
2877 spout->num_servers = 0;
2878 srvout = spout->servers;
2880 ObtainReadLock(&afs_xserver);
2881 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2882 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2883 if (spin->offset > (unsigned short)i) {
2884 continue; /* catch up to where we left off */
2886 spout->next_offset++;
2889 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2890 || (sa->sa_portal == AFS_FSPORT);
2892 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2893 /* only report ranks for vl servers */
2897 srvout->host.s_addr = sa->sa_ip;
2898 srvout->rank = sa->sa_iprank;
2899 *aoutSize += sizeof(struct spref);
2900 spout->num_servers++;
2903 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2904 ReleaseReadLock(&afs_xserver); /* no more room! */
2909 ReleaseReadLock(&afs_xserver);
2911 spout->next_offset = 0; /* start over from the beginning next time */
2915 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2916 int afs_NFSRootOnly = 1;
2917 DECL_PIOCTL(PExportAfs)
2919 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2920 register struct afs_exporter *exporter;
2922 AFS_STATCNT(PExportAfs);
2923 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2924 type = handleValue >> 24;
2929 exporter = exporter_find(type);
2931 export = handleValue & 3;
2932 changestate = handleValue & 0xff;
2933 smounts = (handleValue >> 2) & 3;
2934 pwsync = (handleValue >> 4) & 3;
2935 convmode = (handleValue >> 6) & 3;
2937 changestate = (handleValue >> 16) & 0x1;
2938 convmode = (handleValue >> 16) & 0x2;
2939 pwsync = (handleValue >> 16) & 0x4;
2940 smounts = (handleValue >> 16) & 0x8;
2941 export = handleValue & 0xff;
2944 /* Failed finding desired exporter; */
2948 handleValue = exporter->exp_states;
2949 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2950 *aoutSize = sizeof(afs_int32);
2952 if (!afs_osi_suser(*acred))
2953 return EACCES; /* Only superuser can do this */
2957 exporter->exp_states |= EXP_EXPORTED;
2959 exporter->exp_states &= ~EXP_EXPORTED;
2963 exporter->exp_states |= EXP_UNIXMODE;
2965 exporter->exp_states &= ~EXP_UNIXMODE;
2969 exporter->exp_states |= EXP_PWSYNC;
2971 exporter->exp_states &= ~EXP_PWSYNC;
2975 afs_NFSRootOnly = 0;
2976 exporter->exp_states |= EXP_SUBMOUNTS;
2978 afs_NFSRootOnly = 1;
2979 exporter->exp_states &= ~EXP_SUBMOUNTS;
2982 handleValue = exporter->exp_states;
2983 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2984 *aoutSize = sizeof(afs_int32);
2987 exporter->exp_states |= EXP_EXPORTED;
2989 exporter->exp_states &= ~EXP_EXPORTED;
2991 exporter->exp_states |= EXP_UNIXMODE;
2993 exporter->exp_states &= ~EXP_UNIXMODE;
2995 exporter->exp_states |= EXP_PWSYNC;
2997 exporter->exp_states &= ~EXP_PWSYNC;
2999 afs_NFSRootOnly = 0;
3000 exporter->exp_states |= EXP_SUBMOUNTS;
3002 afs_NFSRootOnly = 1;
3003 exporter->exp_states &= ~EXP_SUBMOUNTS;
3013 struct gaginfo *gagflags;
3015 if (!afs_osi_suser(*acred))
3018 gagflags = (struct gaginfo *) ain;
3019 afs_showflags = gagflags->showflags;
3025 DECL_PIOCTL(PTwiddleRx)
3027 struct rxparams *rxp;
3029 if (!afs_osi_suser(*acred))
3032 rxp = (struct rxparams *) ain;
3034 if (rxp->rx_initReceiveWindow)
3035 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3036 if (rxp->rx_maxReceiveWindow)
3037 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3038 if (rxp->rx_initSendWindow)
3039 rx_initSendWindow = rxp->rx_initSendWindow;
3040 if (rxp->rx_maxSendWindow)
3041 rx_maxSendWindow = rxp->rx_maxSendWindow;
3042 if (rxp->rxi_nSendFrags)
3043 rxi_nSendFrags = rxp->rxi_nSendFrags;
3044 if (rxp->rxi_nRecvFrags)
3045 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3046 if (rxp->rxi_OrphanFragSize)
3047 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3048 if (rxp->rx_maxReceiveSize)
3050 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3051 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3053 if (rxp->rx_MyMaxSendSize)
3054 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3059 DECL_PIOCTL(PGetInitParams)
3061 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3064 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3065 *aoutSize = sizeof(struct cm_initparams);
3069 #ifdef AFS_SGI65_ENV
3070 /* They took crget() from us, so fake it. */
3071 static cred_t *crget(void)
3074 cr = crdup(get_current_cred());
3075 memset((char*)cr, 0, sizeof(cred_t));
3076 #if CELL || CELL_PREPARE
3083 DECL_PIOCTL(PGetRxkcrypt)
3085 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3086 *aoutSize=sizeof(afs_int32);
3090 DECL_PIOCTL(PSetRxkcrypt)
3094 if (!afs_osi_suser(*acred))
3096 if (ainSize != sizeof(afs_int32) || ain == NULL)
3098 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3099 /* if new mappings added later this will need to be changed */
3100 if (tmpval != 0 && tmpval != 1)
3107 * Create new credentials to correspond to a remote user with given
3108 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3109 * provide pioctl (and other) services to foreign clients (i.e. nfs
3110 * clients) by using this call to `become' the client.
3113 #define PIOCTL_HEADER 6
3114 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3116 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3117 return EINVAL; /* NFS trans not supported for Ultrix */
3120 afs_uint32 hostaddr;
3121 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3122 struct afs_exporter *exporter, *outexporter;
3123 struct AFS_UCRED *newcred;
3124 struct unixuser *au;
3126 #if defined(AFS_SGIMP_ENV)
3127 osi_Assert(ISAFS_GLOCK());
3129 AFS_STATCNT(HandleClientContext);
3130 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3131 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3132 return EINVAL; /* Too small to be good */
3134 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3135 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3137 osi_FreeLargeSpace(inData);
3141 /* Extract information for remote user */
3142 hostaddr = *((afs_uint32 *)ain);
3143 ain += sizeof(hostaddr);
3144 uid = *((afs_uint32 *)ain);
3146 g0 = *((afs_uint32 *)ain);
3148 g1 = *((afs_uint32 *)ain);
3150 *com = *((afs_uint32 *)ain);
3151 ain += sizeof(afs_int32);
3152 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3155 * Of course, one must be root for most of these functions, but
3156 * we'll allow (for knfs) you to set things if the pag is 0 and
3157 * you're setting tokens or unlogging.
3160 if (!afs_osi_suser(credp)) {
3162 #ifndef AFS_SGI64_ENV
3163 /* Since SGI's suser() returns explicit failure after the call.. */
3167 /* check for acceptable opcodes for normal folks, which are, so far,
3168 * set tokens and unlog.
3170 if (i != 9 && i != 3 && i != 38 && i != 8) {
3171 osi_FreeLargeSpace(inData);
3176 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3177 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3178 osi_FreeLargeSpace(inData);
3181 * We map uid 0 to nobody to match the mapping that the nfs
3182 * server does and to ensure that the suser() calls in the afs
3183 * code fails for remote client roots.
3185 uid = afs_nobody; /* NFS_NOBODY == -2 */
3188 #ifdef AFS_AIX41_ENV
3191 newcred->cr_gid = RMTUSER_REQ;
3192 #ifdef AFS_AIX51_ENV
3193 newcred->cr_groupset.gs_union.un_groups[0] = g0;
3194 newcred->cr_groupset.gs_union.un_groups[1] = g1;
3196 newcred->cr_groups[0] = g0;
3197 newcred->cr_groups[1] = g1;
3200 newcred->cr_ngrps = 2;
3202 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3203 newcred->cr_ngroups = 2;
3205 for (i=2; i<NGROUPS; i++)
3206 newcred->cr_groups[i] = NOGROUP;
3209 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3210 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3212 if (!(exporter = exporter_find(exporter_type))) {
3213 /* Exporter wasn't initialized or an invalid exporter type */
3217 if (exporter->exp_states & EXP_PWSYNC) {
3218 if (uid != credp->cr_uid) {
3220 return ENOEXEC; /* XXX Find a better errno XXX */
3223 newcred->cr_uid = uid; /* Only temporary */
3224 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3225 /* The client's pag is the only unique identifier for it */
3226 newcred->cr_uid = pag;
3228 if (!code && *com == PSETPAG) {
3229 /* Special case for 'setpag' */
3230 afs_uint32 pagvalue = genpag();
3232 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3234 * Note that we leave the 'outexporter' struct held so it won't
3237 au->exporter = outexporter;
3238 if (ablob->out_size >= 4) {
3239 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3241 afs_PutUser(au, WRITE_LOCK);
3242 if (code) return code;
3243 return PSETPAG; /* Special return for setpag */
3245 EXP_RELE(outexporter);
3248 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3251 /* get all interface addresses of this client */
3253 DECL_PIOCTL(PGetCPrefs)
3255 struct sprefrequest *spin; /* input */
3256 struct sprefinfo *spout; /* output */
3257 struct spref *srvout; /* one output component */
3261 AFS_STATCNT(PGetCPrefs);
3262 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
3263 return EIO; /* Inappropriate ioctl for device */
3265 if ( ainSize < sizeof (struct sprefrequest ))
3268 spin = (struct sprefrequest *) ain;
3269 spout = (struct sprefinfo *) aout;
3271 maxNumber = spin->num_servers; /* max addrs this time */
3272 srvout = spout->servers;
3274 ObtainReadLock(&afs_xinterface);
3276 /* copy out the client interface information from the
3277 ** kernel data structure "interface" to the output buffer
3279 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3280 && ( j< maxNumber) ; i++, j++, srvout++)
3281 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3283 spout->num_servers = j;
3284 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3286 if ( i >= afs_cb_interface.numberOfInterfaces )
3287 spout->next_offset = 0; /* start from beginning again */
3289 spout->next_offset = spin->offset + j;
3291 ReleaseReadLock(&afs_xinterface);
3295 DECL_PIOCTL(PSetCPrefs)
3297 struct setspref *sin;
3300 AFS_STATCNT(PSetCPrefs);
3301 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
3302 return EIO; /* Inappropriate ioctl for device */
3304 sin = (struct setspref *)ain;
3306 if ( ainSize < sizeof(struct setspref) )
3308 #if 0 /* num_servers is unsigned */
3309 if ( sin->num_servers < 0 )
3312 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3315 ObtainWriteLock(&afs_xinterface, 412);
3316 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3317 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3318 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3320 ReleaseWriteLock(&afs_xinterface);
3324 DECL_PIOCTL(PFlushMount)
3326 register afs_int32 code;
3327 register struct vcache *tvc;
3328 register struct dcache *tdc;
3329 struct VenusFid tfid;
3331 struct sysname_info sysState;
3332 afs_size_t offset, len;
3334 AFS_STATCNT(PFlushMount);
3335 if (!avc) return EINVAL;
3336 code = afs_VerifyVCache(avc, areq);
3337 if (code) return code;
3338 if (vType(avc) != VDIR) {
3341 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3342 if (!tdc) return ENOENT;
3343 Check_AtSys(avc, ain, &sysState, areq);
3344 ObtainReadLock(&tdc->lock);
3346 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3347 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3348 ReleaseReadLock(&tdc->lock);
3349 afs_PutDCache(tdc); /* we're done with the data */
3350 bufp = sysState.name;
3354 tfid.Cell = avc->fid.Cell;
3355 tfid.Fid.Volume = avc->fid.Fid.Volume;
3356 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3357 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3359 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3365 if (tvc->mvstat != 1) {
3370 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3371 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3373 ObtainWriteLock(&tvc->lock,649);
3374 ObtainWriteLock(&afs_xcbhash, 650);
3375 afs_DequeueCallback(tvc);
3376 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3377 ReleaseWriteLock(&afs_xcbhash);
3378 /* now find the disk cache entries */
3379 afs_TryToSmush(tvc, *acred, 1);
3380 osi_dnlc_purgedp(tvc);
3381 afs_symhint_inval(tvc);
3382 if (tvc->linkData && !(tvc->states & CCore)) {
3383 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3384 tvc->linkData = NULL;
3386 ReleaseWriteLock(&tvc->lock);
3387 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3388 afs_BozonUnlock(&tvc->pvnLock, tvc);
3392 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3396 DECL_PIOCTL(PRxStatProc)
3401 if (!afs_osi_suser(*acred)) {
3405 if (ainSize != sizeof(afs_int32)) {
3409 memcpy((char *)&flags, ain, sizeof(afs_int32));
3410 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3414 if (flags & AFSCALL_RXSTATS_ENABLE) {
3415 rx_enableProcessRPCStats();
3417 if (flags & AFSCALL_RXSTATS_DISABLE) {
3418 rx_disableProcessRPCStats();
3420 if (flags & AFSCALL_RXSTATS_CLEAR) {
3421 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3429 DECL_PIOCTL(PRxStatPeer)
3434 if (!afs_osi_suser(*acred)) {
3438 if (ainSize != sizeof(afs_int32)) {
3442 memcpy((char *)&flags, ain, sizeof(afs_int32));
3443 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3447 if (flags & AFSCALL_RXSTATS_ENABLE) {
3448 rx_enablePeerRPCStats();
3450 if (flags & AFSCALL_RXSTATS_DISABLE) {
3451 rx_disablePeerRPCStats();
3453 if (flags & AFSCALL_RXSTATS_CLEAR) {
3454 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3461 DECL_PIOCTL(PPrefetchFromTape)
3463 register afs_int32 code, code1;
3466 struct rx_call *tcall;
3467 struct AFSVolSync tsync;
3468 struct AFSFetchStatus OutStatus;
3469 struct AFSCallBack CallBack;
3470 struct VenusFid tfid;
3474 AFS_STATCNT(PSetAcl);
3478 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3479 Fid = (struct AFSFid *) ain;
3481 Fid = &avc->fid.Fid;
3482 tfid.Cell = avc->fid.Cell;
3483 tfid.Fid.Volume = Fid->Volume;
3484 tfid.Fid.Vnode = Fid->Vnode;
3485 tfid.Fid.Unique = Fid->Unique;
3487 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3489 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3490 ICL_TYPE_POINTER, tvc,
3491 ICL_TYPE_FID, &tfid,
3492 ICL_TYPE_FID, &avc->fid);
3495 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3496 ICL_TYPE_POINTER, tvc,
3497 ICL_TYPE_FID, &tfid,
3498 ICL_TYPE_FID, &tvc->fid);
3501 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3505 tcall = rx_NewCall(tc->id);
3506 code = StartRXAFS_FetchData(tcall,
3507 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3509 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3510 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3512 code1 = rx_EndCall(tcall, code);
3517 (afs_Analyze(tc, code, &tvc->fid, areq,
3518 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3520 /* This call is done only to have the callback things handled correctly */
3521 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3525 *aoutSize = sizeof(afs_int32);
3530 DECL_PIOCTL(PResidencyCmd)
3532 register afs_int32 code;
3535 struct ResidencyCmdInputs *Inputs;
3536 struct ResidencyCmdOutputs *Outputs;
3537 struct VenusFid tfid;
3540 Inputs = (struct ResidencyCmdInputs *) ain;
3541 Outputs = (struct ResidencyCmdOutputs *) aout;
3542 if (!avc) return EINVAL;
3543 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3547 Fid = &avc->fid.Fid;
3549 tfid.Cell = avc->fid.Cell;
3550 tfid.Fid.Volume = Fid->Volume;
3551 tfid.Fid.Vnode = Fid->Vnode;
3552 tfid.Fid.Unique = Fid->Unique;
3554 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3555 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3556 ICL_TYPE_POINTER, tvc,
3557 ICL_TYPE_INT32, Inputs->command,
3558 ICL_TYPE_FID, &tfid);
3562 if (Inputs->command) {
3564 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3567 code = RXAFS_ResidencyCmd(tc->id, Fid,
3569 (struct ResidencyCmdOutputs *) aout);
3574 (afs_Analyze(tc, code, &tvc->fid, areq,
3575 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3577 /* This call is done to have the callback things handled correctly */
3578 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3579 } else { /* just a status request, return also link data */
3581 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3582 Outputs->chars[0] = 0;
3583 if (vType(tvc) == VLNK) {
3584 ObtainWriteLock(&tvc->lock,555);
3585 if (afs_HandleLink(tvc, areq) == 0)
3586 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3587 ReleaseWriteLock(&tvc->lock);
3594 *aoutSize = sizeof(struct ResidencyCmdOutputs);