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 #if defined(KERNEL_HAVE_UERROR)
1018 return (getuerror());
1025 int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
1026 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1029 struct vrequest treq;
1030 register afs_int32 code;
1031 register afs_int32 function, device;
1032 afs_int32 inSize, outSize;
1033 char *inData, *outData;
1034 int (*(*pioctlSw))();
1036 struct afs_fakestat_state fakestate;
1038 avc = avp ? VTOAFS(avp) : NULL;
1039 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1040 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1041 AFS_STATCNT(HandlePioctl);
1042 if ((code = afs_InitReq(&treq, *acred))) return code;
1043 afs_InitFakeStat(&fakestate);
1045 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1047 afs_PutFakeStat(&fakestate);
1051 device = (acom & 0xff00) >> 8;
1053 case 'V': /* Original pioctls */
1054 pioctlSw = VpioctlSw;
1055 pioctlSwSize = sizeof(VpioctlSw);
1057 case 'C': /* Coordinated/common pioctls */
1058 pioctlSw = CpioctlSw;
1059 pioctlSwSize = sizeof(CpioctlSw);
1062 afs_PutFakeStat(&fakestate);
1065 function = acom & 0xff;
1066 if (function >= (pioctlSwSize / sizeof(char *))) {
1067 afs_PutFakeStat(&fakestate);
1068 return EINVAL; /* out of range */
1070 inSize = ablob->in_size;
1072 /* Do all range checking before continuing */
1073 if (inSize >= PIGGYSIZE || inSize < 0 || ablob->out_size < 0)
1076 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1078 AFS_COPYIN(ablob->in, inData, inSize, code);
1079 inData[inSize]='\0';
1083 osi_FreeLargeSpace(inData);
1084 afs_PutFakeStat(&fakestate);
1087 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1089 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1090 osi_FreeLargeSpace(inData);
1091 if (code == 0 && ablob->out_size > 0) {
1092 if (outSize > ablob->out_size) outSize = ablob->out_size;
1093 if (outSize >= PIGGYSIZE) code = E2BIG;
1095 outData[outSize]='\0';
1096 AFS_COPYOUT(outData, ablob->out, outSize, code);
1099 osi_FreeLargeSpace(outData);
1100 afs_PutFakeStat(&fakestate);
1101 return afs_CheckCode(code, &treq, 41);
1104 DECL_PIOCTL(PGetFID)
1106 AFS_STATCNT(PGetFID);
1107 if (!avc) return EINVAL;
1108 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1109 *aoutSize = sizeof(struct VenusFid);
1113 DECL_PIOCTL(PSetAcl)
1115 register afs_int32 code;
1117 struct AFSOpaque acl;
1118 struct AFSVolSync tsync;
1119 struct AFSFetchStatus OutStatus;
1122 AFS_STATCNT(PSetAcl);
1125 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1128 acl.AFSOpaque_val = ain;
1130 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1132 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1134 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1135 &acl, &OutStatus, &tsync);
1141 (afs_Analyze(tconn, code, &avc->fid, areq,
1142 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1144 /* now we've forgotten all of the access info */
1145 ObtainWriteLock(&afs_xcbhash, 455);
1147 afs_DequeueCallback(avc);
1148 avc->states &= ~(CStatd | CUnique);
1149 ReleaseWriteLock(&afs_xcbhash);
1150 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1151 osi_dnlc_purgedp(avc);
1155 int afs_defaultAsynchrony = 0;
1157 DECL_PIOCTL(PStoreBehind)
1160 struct sbstruct *sbr;
1162 sbr = (struct sbstruct *)ain;
1163 if (sbr->sb_default != -1) {
1164 if (afs_osi_suser(*acred))
1165 afs_defaultAsynchrony = sbr->sb_default;
1169 if (avc && (sbr->sb_thisfile != -1)) {
1170 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1171 areq, DONT_CHECK_MODE_BITS))
1172 avc->asynchrony = sbr->sb_thisfile;
1176 *aoutSize = sizeof(struct sbstruct);
1177 sbr = (struct sbstruct *)aout;
1178 sbr->sb_default = afs_defaultAsynchrony;
1180 sbr->sb_thisfile = avc->asynchrony;
1186 DECL_PIOCTL(PGCPAGs)
1188 if (!afs_osi_suser(*acred)) {
1191 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1195 DECL_PIOCTL(PGetAcl)
1197 struct AFSOpaque acl;
1198 struct AFSVolSync tsync;
1199 struct AFSFetchStatus OutStatus;
1205 AFS_STATCNT(PGetAcl);
1206 if (!avc) return EINVAL;
1207 Fid.Volume = avc->fid.Fid.Volume;
1208 Fid.Vnode = avc->fid.Fid.Vnode;
1209 Fid.Unique = avc->fid.Fid.Unique;
1210 if (avc->states & CForeign) {
1212 * For a dfs xlator acl we have a special hack so that the
1213 * xlator will distinguish which type of acl will return. So
1214 * we currently use the top 2-bytes (vals 0-4) to tell which
1215 * type of acl to bring back. Horrible hack but this will
1216 * cause the least number of changes to code size and interfaces.
1218 if (Fid.Vnode & 0xc0000000)
1220 Fid.Vnode |= (ainSize << 30);
1222 acl.AFSOpaque_val = aout;
1224 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1227 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1229 code = RXAFS_FetchACL(tconn->id, &Fid,
1230 &acl, &OutStatus, &tsync);
1236 (afs_Analyze(tconn, code, &avc->fid, areq,
1237 AFS_STATS_FS_RPCIDX_FETCHACL,
1238 SHARED_LOCK, NULL));
1241 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1254 AFS_STATCNT(PBogus);
1258 DECL_PIOCTL(PGetFileCell)
1260 register struct cell *tcell;
1262 AFS_STATCNT(PGetFileCell);
1263 if (!avc) return EINVAL;
1264 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1265 if (!tcell) return ESRCH;
1266 strcpy(aout, tcell->cellName);
1267 afs_PutCell(tcell, READ_LOCK);
1268 *aoutSize = strlen(aout) + 1;
1272 DECL_PIOCTL(PGetWSCell)
1274 struct cell *tcell = NULL;
1276 AFS_STATCNT(PGetWSCell);
1277 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1278 return EIO; /* Inappropriate ioctl for device */
1280 tcell = afs_GetPrimaryCell(READ_LOCK);
1281 if (!tcell) /* no primary cell? */
1283 strcpy(aout, tcell->cellName);
1284 *aoutSize = strlen(aout) + 1;
1285 afs_PutCell(tcell, READ_LOCK);
1289 DECL_PIOCTL(PGetUserCell)
1291 register afs_int32 i;
1292 register struct unixuser *tu;
1293 register struct cell *tcell;
1295 AFS_STATCNT(PGetUserCell);
1296 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1297 return EIO; /* Inappropriate ioctl for device */
1299 /* return the cell name of the primary cell for this user */
1300 i = UHash(areq->uid);
1301 ObtainWriteLock(&afs_xuser,224);
1302 for(tu = afs_users[i]; tu; tu = tu->next) {
1303 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1305 ReleaseWriteLock(&afs_xuser);
1310 tcell = afs_GetCell(tu->cell, READ_LOCK);
1311 afs_PutUser(tu, WRITE_LOCK);
1312 if (!tcell) return ESRCH;
1314 strcpy(aout, tcell->cellName);
1315 afs_PutCell(tcell, READ_LOCK);
1316 *aoutSize = strlen(aout)+1; /* 1 for the null */
1320 ReleaseWriteLock(&afs_xuser);
1327 DECL_PIOCTL(PSetTokens)
1330 register struct unixuser *tu;
1331 struct ClearToken clear;
1332 register struct cell *tcell;
1335 struct vrequest treq;
1336 afs_int32 flag, set_parent_pag = 0;
1338 AFS_STATCNT(PSetTokens);
1339 if (!afs_resourceinit_flag) {
1342 memcpy((char *)&i, ain, sizeof(afs_int32));
1343 ain += sizeof(afs_int32);
1344 stp = ain; /* remember where the ticket is */
1345 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1346 if (i > MAXKTCTICKETLEN) return EINVAL;
1348 ain += i; /* skip over ticket */
1349 memcpy((char *)&i, ain, sizeof(afs_int32));
1350 ain += sizeof(afs_int32);
1351 if (i != sizeof(struct ClearToken)) {
1354 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1355 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1356 ain += sizeof(struct ClearToken);
1357 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1358 /* still stuff left? we've got primary flag and cell name. Set these */
1359 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1360 ain += sizeof(afs_int32); /* skip id field */
1361 /* rest is cell name, look it up */
1362 /* some versions of gcc appear to need != 0 in order to get this right */
1363 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1367 tcell = afs_GetCellByName(ain, READ_LOCK);
1368 if (!tcell) goto nocell;
1371 /* default to primary cell, primary id */
1372 flag = 1; /* primary id */
1373 tcell = afs_GetPrimaryCell(READ_LOCK);
1374 if (!tcell) goto nocell;
1377 afs_PutCell(tcell, READ_LOCK);
1378 if (set_parent_pag) {
1380 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1381 #if defined(AFS_DARWIN_ENV)
1382 struct proc *p = current_proc(); /* XXX */
1384 struct proc *p = curproc; /* XXX */
1386 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1387 p->p_pid, p->p_comm);
1388 if (!setpag(p, acred, -1, &pag, 1)) {
1391 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1393 if (!setpag(acred, -1, &pag, 1)) {
1396 afs_InitReq(&treq, *acred);
1400 /* now we just set the tokens */
1401 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1402 tu->vid = clear.ViceId;
1403 if (tu->stp != NULL) {
1404 afs_osi_Free(tu->stp, tu->stLen);
1406 tu->stp = (char *) afs_osi_Alloc(stLen);
1408 memcpy(tu->stp, stp, stLen);
1411 afs_stats_cmfullperf.authent.TicketUpdates++;
1412 afs_ComputePAGStats();
1413 #endif /* AFS_NOSTATS */
1414 tu->states |= UHasTokens;
1415 tu->states &= ~UTokensBad;
1416 afs_SetPrimary(tu, flag);
1417 tu->tokenTime =osi_Time();
1418 afs_ResetUserConns(tu);
1419 afs_PutUser(tu, WRITE_LOCK);
1434 DECL_PIOCTL(PGetVolumeStatus)
1437 char offLineMsg[256];
1439 register struct conn *tc;
1440 register afs_int32 code;
1441 struct VolumeStatus volstat;
1443 char *Name, *OfflineMsg, *MOTD;
1446 AFS_STATCNT(PGetVolumeStatus);
1447 if (!avc) return EINVAL;
1449 OfflineMsg = offLineMsg;
1452 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1454 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1456 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1457 &Name, &OfflineMsg, &MOTD);
1463 (afs_Analyze(tc, code, &avc->fid, areq,
1464 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1465 SHARED_LOCK, NULL));
1467 if (code) return code;
1468 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1470 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1471 cp += sizeof(VolumeStatus);
1472 strcpy(cp, volName);
1473 cp += strlen(volName)+1;
1474 strcpy(cp, offLineMsg);
1475 cp += strlen(offLineMsg)+1;
1477 cp += strlen(motd)+1;
1478 *aoutSize = (cp - aout);
1482 DECL_PIOCTL(PSetVolumeStatus)
1485 char offLineMsg[256];
1487 register struct conn *tc;
1488 register afs_int32 code;
1489 struct AFSFetchVolumeStatus volstat;
1490 struct AFSStoreVolumeStatus storeStat;
1491 register struct volume *tvp;
1495 AFS_STATCNT(PSetVolumeStatus);
1496 if (!avc) return EINVAL;
1498 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1500 if (tvp->states & (VRO | VBackup)) {
1501 afs_PutVolume(tvp, READ_LOCK);
1504 afs_PutVolume(tvp, READ_LOCK);
1507 /* Copy the junk out, using cp as a roving pointer. */
1509 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1510 cp += sizeof(AFSFetchVolumeStatus);
1511 if (strlen(cp) >= sizeof(volName))
1513 strcpy(volName, cp);
1514 cp += strlen(volName)+1;
1515 if (strlen(cp) >= sizeof(offLineMsg))
1517 strcpy(offLineMsg, cp);
1518 cp += strlen(offLineMsg)+1;
1519 if (strlen(cp) >= sizeof(motd))
1523 if (volstat.MinQuota != -1) {
1524 storeStat.MinQuota = volstat.MinQuota;
1525 storeStat.Mask |= AFS_SETMINQUOTA;
1527 if (volstat.MaxQuota != -1) {
1528 storeStat.MaxQuota = volstat.MaxQuota;
1529 storeStat.Mask |= AFS_SETMAXQUOTA;
1532 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1534 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1536 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1537 &storeStat, volName, offLineMsg, motd);
1543 (afs_Analyze(tc, code, &avc->fid, areq,
1544 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1545 SHARED_LOCK, NULL));
1547 if (code) return code;
1548 /* we are sending parms back to make compat. with prev system. should
1549 change interface later to not ask for current status, just set new status */
1551 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1552 cp += sizeof(VolumeStatus);
1553 strcpy(cp, volName);
1554 cp += strlen(volName)+1;
1555 strcpy(cp, offLineMsg);
1556 cp += strlen(offLineMsg)+1;
1558 cp += strlen(motd)+1;
1559 *aoutSize = cp - aout;
1565 AFS_STATCNT(PFlush);
1566 if (!avc) return EINVAL;
1567 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1568 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1570 ObtainWriteLock(&avc->lock,225);
1571 ObtainWriteLock(&afs_xcbhash, 456);
1572 afs_DequeueCallback(avc);
1573 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1574 ReleaseWriteLock(&afs_xcbhash);
1575 /* now find the disk cache entries */
1576 afs_TryToSmush(avc, *acred, 1);
1577 osi_dnlc_purgedp(avc);
1578 afs_symhint_inval(avc);
1579 if (avc->linkData && !(avc->states & CCore)) {
1580 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1581 avc->linkData = NULL;
1583 ReleaseWriteLock(&avc->lock);
1584 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1585 afs_BozonUnlock(&avc->pvnLock, avc);
1590 DECL_PIOCTL(PNewStatMount)
1592 register afs_int32 code;
1593 register struct vcache *tvc;
1594 register struct dcache *tdc;
1595 struct VenusFid tfid;
1597 struct sysname_info sysState;
1598 afs_size_t offset, len;
1600 AFS_STATCNT(PNewStatMount);
1601 if (!avc) return EINVAL;
1602 code = afs_VerifyVCache(avc, areq);
1603 if (code) return code;
1604 if (vType(avc) != VDIR) {
1607 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1608 if (!tdc) return ENOENT;
1609 Check_AtSys(avc, ain, &sysState, areq);
1610 ObtainReadLock(&tdc->lock);
1612 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1613 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1614 ReleaseReadLock(&tdc->lock);
1615 afs_PutDCache(tdc); /* we're done with the data */
1616 bufp = sysState.name;
1620 tfid.Cell = avc->fid.Cell;
1621 tfid.Fid.Volume = avc->fid.Fid.Volume;
1622 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1623 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1625 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1631 if (tvc->mvstat != 1) {
1636 ObtainWriteLock(&tvc->lock,226);
1637 code = afs_HandleLink(tvc, areq);
1639 if (tvc->linkData) {
1640 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1643 /* we have the data */
1644 strcpy(aout, tvc->linkData);
1645 *aoutSize = strlen(tvc->linkData)+1;
1650 ReleaseWriteLock(&tvc->lock);
1653 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1657 DECL_PIOCTL(PGetTokens)
1659 register struct cell *tcell;
1660 register afs_int32 i;
1661 register struct unixuser *tu;
1666 AFS_STATCNT(PGetTokens);
1667 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1668 return EIO; /* Inappropriate ioctl for device */
1670 /* weird interface. If input parameter is present, it is an integer and
1671 we're supposed to return the parm'th tokens for this unix uid.
1672 If not present, we just return tokens for cell 1.
1673 If counter out of bounds, return EDOM.
1674 If no tokens for the particular cell, return ENOTCONN.
1675 Also, if this mysterious parm is present, we return, along with the
1676 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1677 at the end, in that order.
1679 if ((newStyle = (ainSize > 0))) {
1680 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1682 i = UHash(areq->uid);
1683 ObtainReadLock(&afs_xuser);
1684 for(tu = afs_users[i]; tu; tu=tu->next) {
1686 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1687 if (iterator-- == 0) break; /* are we done yet? */
1691 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1696 * No need to hold a read lock on each user entry
1700 ReleaseReadLock(&afs_xuser);
1705 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1706 tu->states |= (UTokensBad | UNeedsReset);
1707 afs_PutUser(tu, READ_LOCK);
1710 /* use iterator for temp */
1712 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1713 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1714 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1715 cp += sizeof(afs_int32);
1716 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1718 iterator = sizeof(struct ClearToken);
1719 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1720 cp += sizeof(afs_int32);
1721 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1722 cp += sizeof(struct ClearToken);
1724 /* put out primary id and cell name, too */
1725 iterator = (tu->states & UPrimary ? 1 : 0);
1726 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1727 cp += sizeof(afs_int32);
1728 tcell = afs_GetCell(tu->cell, READ_LOCK);
1730 strcpy(cp, tcell->cellName);
1731 cp += strlen(tcell->cellName)+1;
1732 afs_PutCell(tcell, READ_LOCK);
1736 *aoutSize = cp - aout;
1737 afs_PutUser(tu, READ_LOCK);
1743 register afs_int32 i;
1744 register struct unixuser *tu;
1746 AFS_STATCNT(PUnlog);
1747 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1748 return EIO; /* Inappropriate ioctl for device */
1750 i = UHash(areq->uid);
1751 ObtainWriteLock(&afs_xuser,227);
1752 for(tu=afs_users[i]; tu; tu=tu->next) {
1753 if (tu->uid == areq->uid) {
1755 tu->states &= ~UHasTokens;
1756 /* security is not having to say you're sorry */
1757 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1759 ReleaseWriteLock(&afs_xuser);
1760 /* We have to drop the lock over the call to afs_ResetUserConns, since
1761 * it obtains the afs_xvcache lock. We could also keep the lock, and
1762 * modify ResetUserConns to take parm saying we obtained the lock
1763 * already, but that is overkill. By keeping the "tu" pointer
1764 * held over the released lock, we guarantee that we won't lose our
1765 * place, and that we'll pass over every user conn that existed when
1766 * we began this call.
1768 afs_ResetUserConns(tu);
1770 ObtainWriteLock(&afs_xuser,228);
1772 /* set the expire times to 0, causes
1773 * afs_GCUserData to remove this entry
1775 tu->ct.EndTimestamp = 0;
1777 #endif /* UKERNEL */
1780 ReleaseWriteLock(&afs_xuser);
1784 DECL_PIOCTL(PMariner)
1786 afs_int32 newHostAddr;
1787 afs_int32 oldHostAddr;
1789 AFS_STATCNT(PMariner);
1791 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1793 oldHostAddr = 0xffffffff; /* disabled */
1795 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1796 if (newHostAddr == 0xffffffff) {
1797 /* disable mariner operations */
1800 else if (newHostAddr) {
1802 afs_marinerHost = newHostAddr;
1804 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1805 *aoutSize = sizeof(afs_int32);
1809 DECL_PIOCTL(PCheckServers)
1811 register char *cp = 0;
1813 register struct server *ts;
1814 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1816 struct chservinfo *pcheck;
1818 AFS_STATCNT(PCheckServers);
1820 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1821 return EIO; /* Inappropriate ioctl for device */
1823 if (*lp == 0x12345678) { /* For afs3.3 version */
1824 pcheck=(struct chservinfo *)ain;
1825 if (pcheck->tinterval >= 0) {
1827 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1828 *aoutSize = sizeof(afs_int32);
1829 if (pcheck->tinterval > 0) {
1830 if (!afs_osi_suser(*acred))
1832 PROBE_INTERVAL=pcheck->tinterval;
1838 temp=pcheck->tflags;
1839 cp = pcheck->tbuffer;
1840 } else { /* For pre afs3.3 versions */
1841 memcpy((char *)&temp, ain, sizeof(afs_int32));
1842 cp = ain+sizeof(afs_int32);
1843 if (ainSize > sizeof(afs_int32))
1848 * 1: fast check, don't contact servers.
1849 * 2: local cell only.
1852 /* have cell name, too */
1853 cellp = afs_GetCellByName(cp, READ_LOCK);
1854 if (!cellp) return ENOENT;
1857 if (!cellp && (temp & 2)) {
1858 /* use local cell */
1859 cellp = afs_GetPrimaryCell(READ_LOCK);
1861 if (!(temp & 1)) { /* if not fast, call server checker routine */
1862 afs_CheckServers(1, cellp); /* check down servers */
1863 afs_CheckServers(0, cellp); /* check up servers */
1865 /* now return the current down server list */
1867 ObtainReadLock(&afs_xserver);
1868 for(i=0;i<NSERVERS;i++) {
1869 for(ts = afs_servers[i]; ts; ts=ts->next) {
1870 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1871 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1872 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1873 cp += sizeof(afs_int32);
1877 ReleaseReadLock(&afs_xserver);
1878 if (cellp) afs_PutCell(cellp, READ_LOCK);
1879 *aoutSize = cp - aout;
1883 DECL_PIOCTL(PCheckVolNames)
1885 AFS_STATCNT(PCheckVolNames);
1886 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1887 return EIO; /* Inappropriate ioctl for device */
1889 afs_CheckRootVolume();
1890 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1891 AFS_VOLCHECK_EXPIRED |
1893 AFS_VOLCHECK_MTPTS);
1897 DECL_PIOCTL(PCheckAuth)
1902 struct unixuser *tu;
1905 AFS_STATCNT(PCheckAuth);
1906 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
1907 return EIO; /* Inappropriate ioctl for device */
1910 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1911 if (!tu) retValue = EACCES;
1913 /* we have a user */
1914 ObtainReadLock(&afs_xsrvAddr);
1915 ObtainReadLock(&afs_xconn);
1917 /* any tokens set? */
1918 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1919 /* all connections in cell 1 working? */
1920 for(i=0;i<NSERVERS;i++) {
1921 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1922 for (tc = sa->conns; tc; tc=tc->next) {
1923 if (tc->user == tu && (tu->states & UTokensBad))
1928 ReleaseReadLock(&afs_xsrvAddr);
1929 ReleaseReadLock(&afs_xconn);
1930 afs_PutUser(tu, READ_LOCK);
1932 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1933 *aoutSize = sizeof(afs_int32);
1937 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1940 register afs_int32 code;
1941 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1947 AFS_STATCNT(Prefetch);
1948 if (!apath) return EINVAL;
1949 tp = osi_AllocLargeSpace(1024);
1950 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1952 osi_FreeLargeSpace(tp);
1955 if (afs_BBusy()) { /* do this as late as possible */
1956 osi_FreeLargeSpace(tp);
1957 return EWOULDBLOCK; /* pretty close */
1959 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1960 (afs_size_t) 0, (afs_size_t) 0, tp);
1964 DECL_PIOCTL(PFindVolume)
1966 register struct volume *tvp;
1967 register struct server *ts;
1968 register afs_int32 i;
1971 AFS_STATCNT(PFindVolume);
1972 if (!avc) return EINVAL;
1973 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1976 for(i=0;i<MAXHOSTS;i++) {
1977 ts = tvp->serverHost[i];
1979 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1980 cp += sizeof(afs_int32);
1983 /* still room for terminating NULL, add it on */
1984 ainSize = 0; /* reuse vbl */
1985 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
1986 cp += sizeof(afs_int32);
1988 *aoutSize = cp - aout;
1989 afs_PutVolume(tvp, READ_LOCK);
1995 DECL_PIOCTL(PViceAccess)
1997 register afs_int32 code;
2000 AFS_STATCNT(PViceAccess);
2001 if (!avc) return EINVAL;
2002 code = afs_VerifyVCache(avc, areq);
2003 if (code) return code;
2004 memcpy((char *)&temp, ain, sizeof(afs_int32));
2005 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2010 DECL_PIOCTL(PSetCacheSize)
2015 AFS_STATCNT(PSetCacheSize);
2016 if (!afs_osi_suser(*acred))
2018 /* too many things are setup initially in mem cache version */
2019 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2020 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2021 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2023 if (newValue < afs_min_cache)
2024 afs_cacheBlocks = afs_min_cache;
2026 afs_cacheBlocks = newValue;
2028 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2029 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2030 afs_MaybeWakeupTruncateDaemon();
2031 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2032 afs_osi_Wait(1000, 0, 0);
2033 afs_MaybeWakeupTruncateDaemon();
2038 #define MAXGCSTATS 16
2039 DECL_PIOCTL(PGetCacheSize)
2041 afs_int32 results[MAXGCSTATS];
2043 AFS_STATCNT(PGetCacheSize);
2044 memset((char *)results, 0, sizeof(results));
2045 results[0] = afs_cacheBlocks;
2046 results[1] = afs_blocksUsed;
2047 memcpy(aout, (char *)results, sizeof(results));
2048 *aoutSize = sizeof(results);
2052 DECL_PIOCTL(PRemoveCallBack)
2054 register struct conn *tc;
2055 register afs_int32 code = 0;
2056 struct AFSCallBack CallBacks_Array[1];
2057 struct AFSCBFids theFids;
2058 struct AFSCBs theCBs;
2061 AFS_STATCNT(PRemoveCallBack);
2062 if (!avc) return EINVAL;
2063 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2064 ObtainWriteLock(&avc->lock,229);
2065 theFids.AFSCBFids_len = 1;
2066 theCBs.AFSCBs_len = 1;
2067 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2068 theCBs.AFSCBs_val = CallBacks_Array;
2069 CallBacks_Array[0].CallBackType = CB_DROPPED;
2070 if (avc->callback) {
2072 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2074 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2076 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2080 /* don't set code on failure since we wouldn't use it */
2082 (afs_Analyze(tc, code, &avc->fid, areq,
2083 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2084 SHARED_LOCK, NULL));
2086 ObtainWriteLock(&afs_xcbhash, 457);
2087 afs_DequeueCallback(avc);
2089 avc->states &= ~(CStatd | CUnique);
2090 ReleaseWriteLock(&afs_xcbhash);
2091 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2092 osi_dnlc_purgedp(avc);
2094 ReleaseWriteLock(&avc->lock);
2098 DECL_PIOCTL(PNewCell)
2100 /* create a new cell */
2101 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2102 char *newcell=0, *linkedcell=0, *tp= ain;
2103 register afs_int32 code, linkedstate=0, ls;
2104 u_short fsport = 0, vlport = 0;
2107 AFS_STATCNT(PNewCell);
2108 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2109 return EIO; /* Inappropriate ioctl for device */
2111 if (!afs_osi_suser(*acred))
2114 memcpy((char *)&magic, tp, sizeof(afs_int32));
2115 tp += sizeof(afs_int32);
2116 if (magic != 0x12345678)
2119 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2120 * server addresses while the 3.5 fs newcell command passes
2121 * MAXHOSTS. To figure out which is which, check if the cellname
2124 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2125 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2127 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2128 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2129 tp += (scount * sizeof(afs_int32));
2131 lp = (afs_int32 *)tp;
2134 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2135 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2136 tp += (3 * sizeof(afs_int32));
2138 if ((ls = *lp) & 1) {
2139 linkedcell = tp + strlen(newcell)+1;
2140 linkedstate |= CLinkedCell;
2143 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2144 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2149 DECL_PIOCTL(PNewAlias)
2151 /* create a new cell alias */
2153 register afs_int32 code;
2154 char *realName, *aliasName;
2156 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2157 return EIO; /* Inappropriate ioctl for device */
2159 if (!afs_osi_suser(*acred))
2163 tp += strlen(aliasName) + 1;
2166 code = afs_NewCellAlias(aliasName, realName);
2171 DECL_PIOCTL(PListCells)
2173 afs_int32 whichCell;
2174 register struct cell *tcell=0;
2175 register afs_int32 i;
2176 register char *cp, *tp = ain;
2178 AFS_STATCNT(PListCells);
2179 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2180 return EIO; /* Inappropriate ioctl for device */
2182 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2183 tp += sizeof(afs_int32);
2184 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2187 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2188 for(i=0;i<MAXCELLHOSTS;i++) {
2189 if (tcell->cellHosts[i] == 0) break;
2190 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2191 cp += sizeof(afs_int32);
2193 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2194 strcpy(cp, tcell->cellName);
2195 cp += strlen(tcell->cellName)+1;
2196 *aoutSize = cp - aout;
2197 afs_PutCell(tcell, READ_LOCK);
2199 if (tcell) return 0;
2203 DECL_PIOCTL(PListAliases)
2205 afs_int32 whichAlias;
2206 register struct cell_alias *tcalias=0;
2207 register char *cp, *tp = ain;
2209 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2210 return EIO; /* Inappropriate ioctl for device */
2211 if (ainSize < sizeof(afs_int32))
2214 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2215 tp += sizeof(afs_int32);
2217 tcalias = afs_GetCellAlias(whichAlias);
2220 strcpy(cp, tcalias->alias);
2221 cp += strlen(tcalias->alias)+1;
2222 strcpy(cp, tcalias->cell);
2223 cp += strlen(tcalias->cell)+1;
2224 *aoutSize = cp - aout;
2225 afs_PutCellAlias(tcalias);
2227 if (tcalias) return 0;
2231 DECL_PIOCTL(PRemoveMount)
2233 register afs_int32 code;
2235 struct sysname_info sysState;
2236 afs_size_t offset, len;
2237 register struct conn *tc;
2238 register struct dcache *tdc;
2239 register struct vcache *tvc;
2240 struct AFSFetchStatus OutDirStatus;
2241 struct VenusFid tfid;
2242 struct AFSVolSync tsync;
2246 /* "ain" is the name of the file in this dir to remove */
2248 AFS_STATCNT(PRemoveMount);
2249 if (!avc) return EINVAL;
2250 code = afs_VerifyVCache(avc, areq);
2251 if (code) return code;
2252 if (vType(avc) != VDIR) return ENOTDIR;
2254 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2255 if (!tdc) return ENOENT;
2256 Check_AtSys(avc, ain, &sysState, areq);
2257 ObtainReadLock(&tdc->lock);
2259 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2260 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2261 ReleaseReadLock(&tdc->lock);
2262 bufp = sysState.name;
2267 tfid.Cell = avc->fid.Cell;
2268 tfid.Fid.Volume = avc->fid.Fid.Volume;
2269 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2270 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2272 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2279 if (tvc->mvstat != 1) {
2285 ObtainWriteLock(&tvc->lock,230);
2286 code = afs_HandleLink(tvc, areq);
2288 if (tvc->linkData) {
2289 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2294 ReleaseWriteLock(&tvc->lock);
2295 osi_dnlc_purgedp(tvc);
2301 ObtainWriteLock(&avc->lock,231);
2302 osi_dnlc_remove(avc, bufp, tvc);
2304 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2306 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2308 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2309 bufp, &OutDirStatus, &tsync);
2315 (afs_Analyze(tc, code, &avc->fid, areq,
2316 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2317 SHARED_LOCK, NULL));
2320 if (tdc) afs_PutDCache(tdc);
2321 ReleaseWriteLock(&avc->lock);
2325 /* we have the thing in the cache */
2326 ObtainWriteLock(&tdc->lock, 661);
2327 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2328 /* we can do it locally */
2329 code = afs_dir_Delete(&tdc->f.inode, bufp);
2331 ZapDCE(tdc); /* surprise error -- invalid value */
2332 DZap(&tdc->f.inode);
2335 ReleaseWriteLock(&tdc->lock);
2336 afs_PutDCache(tdc); /* drop ref count */
2338 avc->states &= ~CUnique; /* For the dfs xlator */
2339 ReleaseWriteLock(&avc->lock);
2342 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2346 DECL_PIOCTL(PVenusLogging)
2348 return EINVAL; /* OBSOLETE */
2351 DECL_PIOCTL(PGetCellStatus)
2353 register struct cell *tcell;
2356 AFS_STATCNT(PGetCellStatus);
2357 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2358 return EIO; /* Inappropriate ioctl for device */
2360 tcell = afs_GetCellByName(ain, READ_LOCK);
2361 if (!tcell) return ENOENT;
2362 temp = tcell->states;
2363 afs_PutCell(tcell, READ_LOCK);
2364 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2365 *aoutSize = sizeof(afs_int32);
2369 DECL_PIOCTL(PSetCellStatus)
2371 register struct cell *tcell;
2374 if (!afs_osi_suser(*acred))
2376 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2377 return EIO; /* Inappropriate ioctl for device */
2379 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2380 if (!tcell) return ENOENT;
2381 memcpy((char *)&temp, ain, sizeof(afs_int32));
2383 tcell->states |= CNoSUID;
2385 tcell->states &= ~CNoSUID;
2386 afs_PutCell(tcell, WRITE_LOCK);
2390 DECL_PIOCTL(PFlushVolumeData)
2392 register afs_int32 i;
2393 register struct dcache *tdc;
2394 register struct vcache *tvc;
2395 register struct volume *tv;
2396 afs_int32 cell, volume;
2398 AFS_STATCNT(PFlushVolumeData);
2401 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2402 return EIO; /* Inappropriate ioctl for device */
2404 volume = avc->fid.Fid.Volume; /* who to zap */
2405 cell = avc->fid.Cell;
2408 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2409 * the vcaches associated with the volume.
2411 ObtainReadLock(&afs_xvcache);
2412 for(i = 0; i < VCSIZE; i++) {
2413 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2414 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2415 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2416 VN_HOLD(AFSTOV(tvc));
2418 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
2424 ReleaseReadLock(&afs_xvcache);
2425 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2426 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2428 ObtainWriteLock(&tvc->lock,232);
2430 ObtainWriteLock(&afs_xcbhash, 458);
2431 afs_DequeueCallback(tvc);
2432 tvc->states &= ~(CStatd | CDirty);
2433 ReleaseWriteLock(&afs_xcbhash);
2434 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2435 osi_dnlc_purgedp(tvc);
2436 afs_TryToSmush(tvc, *acred, 1);
2437 ReleaseWriteLock(&tvc->lock);
2438 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2439 afs_BozonUnlock(&tvc->pvnLock, tvc);
2441 ObtainReadLock(&afs_xvcache);
2442 /* our tvc ptr is still good until now */
2447 ReleaseReadLock(&afs_xvcache);
2450 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2451 for(i=0;i<afs_cacheFiles;i++) {
2452 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2453 tdc = afs_GetDSlot(i, NULL);
2454 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2455 ReleaseReadLock(&tdc->tlock);
2456 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2457 if (! (afs_indexFlags[i] & IFDataMod)) {
2458 /* if the file is modified, but has a ref cnt of only 1, then
2459 someone probably has the file open and is writing into it.
2460 Better to skip flushing such a file, it will be brought back
2461 immediately on the next write anyway.
2463 If we *must* flush, then this code has to be rearranged to call
2464 afs_storeAllSegments() first */
2465 afs_FlushDCache(tdc);
2469 ReleaseReadLock(&tdc->tlock);
2471 afs_PutDCache(tdc); /* bumped by getdslot */
2473 MReleaseWriteLock(&afs_xdcache);
2475 ObtainReadLock(&afs_xvolume);
2476 for (i=0;i<NVOLS;i++) {
2477 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2478 if (tv->volume == volume) {
2479 afs_ResetVolumeInfo(tv);
2484 ReleaseReadLock(&afs_xvolume);
2486 /* probably, a user is doing this, probably, because things are screwed up.
2487 * maybe it's the dnlc's fault? */
2494 DECL_PIOCTL(PGetVnodeXStatus)
2496 register afs_int32 code;
2497 struct vcxstat stat;
2500 /* AFS_STATCNT(PGetVnodeXStatus); */
2501 if (!avc) return EINVAL;
2502 code = afs_VerifyVCache(avc, areq);
2503 if (code) return code;
2504 if (vType(avc) == VDIR)
2505 mode = PRSFS_LOOKUP;
2508 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2510 stat.fid = avc->fid;
2511 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2512 stat.lock = avc->lock;
2513 stat.parentVnode = avc->parentVnode;
2514 stat.parentUnique = avc->parentUnique;
2515 hset(stat.flushDV, avc->flushDV);
2516 hset(stat.mapDV, avc->mapDV);
2517 stat.truncPos = avc->truncPos;
2518 { /* just grab the first two - won't break anything... */
2519 struct axscache *ac;
2521 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2522 stat.randomUid[i] = ac->uid;
2523 stat.randomAccess[i] = ac->axess;
2526 stat.callback = afs_data_pointer_to_int32(avc->callback);
2527 stat.cbExpires = avc->cbExpires;
2528 stat.anyAccess = avc->anyAccess;
2529 stat.opens = avc->opens;
2530 stat.execsOrWriters = avc->execsOrWriters;
2531 stat.flockCount = avc->flockCount;
2532 stat.mvstat = avc->mvstat;
2533 stat.states = avc->states;
2534 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2535 *aoutSize = sizeof(struct vcxstat);
2540 /* We require root for local sysname changes, but not for remote */
2541 /* (since we don't really believe remote uids anyway) */
2542 /* outname[] shouldn't really be needed- this is left as an excercise */
2543 /* for the reader. */
2544 DECL_PIOCTL(PSetSysName)
2546 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2547 int setsysname, foundname=0;
2548 register struct afs_exporter *exporter;
2549 register struct unixuser *au;
2550 register afs_int32 pag, error;
2554 AFS_STATCNT(PSetSysName);
2555 if (!afs_globalVFS) {
2556 /* Afsd is NOT running; disable it */
2557 #if defined(KERNEL_HAVE_UERROR)
2558 return (setuerror(EINVAL), EINVAL);
2563 memset(inname, 0, MAXSYSNAME);
2564 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2565 ain += sizeof(afs_int32);
2569 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2571 for(cp = ain,count = 0;count < setsysname;count++) {
2572 /* won't go past end of ain since maxsysname*num < ain length */
2574 if (t >= MAXSYSNAME || t <= 0)
2576 /* check for names that can shoot us in the foot */
2577 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2583 /* inname gets first entry in case we're being a translater */
2585 memcpy(inname, ain, t+1); /* include terminating null */
2588 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2589 pag = PagInCred(*acred);
2591 return EINVAL; /* Better than panicing */
2593 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2594 return EINVAL; /* Better than panicing */
2596 if (!(exporter = au->exporter)) {
2597 afs_PutUser(au, READ_LOCK);
2598 return EINVAL; /* Better than panicing */
2600 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2602 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2604 afs_PutUser(au, READ_LOCK);
2609 afs_PutUser(au, READ_LOCK);
2612 /* Not xlating, so local case */
2613 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2614 if (!setsysname) { /* user just wants the info */
2615 strcpy(outname, afs_sysname);
2616 foundname = afs_sysnamecount;
2617 } else { /* Local guy; only root can change sysname */
2618 if (!afs_osi_suser(*acred))
2621 /* clear @sys entries from the dnlc, once afs_lookup can
2622 do lookups of @sys entries and thinks it can trust them */
2623 /* privs ok, store the entry, ... */
2624 strcpy(afs_sysname, inname);
2625 if (setsysname > 1) { /* ... or list */
2627 for(count=1; count < setsysname;++count) {
2628 if (!afs_sysnamelist[count])
2629 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2631 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2635 afs_sysnamecount = setsysname;
2639 cp = aout; /* not changing so report back the count and ... */
2640 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2641 cp += sizeof(afs_int32);
2643 strcpy(cp, outname); /* ... the entry, ... */
2644 cp += strlen(outname)+1;
2645 for(count=1; count < foundname; ++count) { /* ... or list. */
2646 /* Note: we don't support @sys lists for exporters */
2647 if (!afs_sysnamelist[count])
2648 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2649 t = strlen(afs_sysnamelist[count]);
2650 if (t >= MAXSYSNAME)
2651 osi_Panic("PSetSysName: sysname entry garbled\n");
2652 strcpy(cp, afs_sysnamelist[count]);
2656 *aoutSize = cp - aout;
2661 /* sequential search through the list of touched cells is not a good
2662 * long-term solution here. For small n, though, it should be just
2663 * fine. Should consider special-casing the local cell for large n.
2664 * Likewise for PSetSPrefs.
2666 * s - number of ids in array l[] -- NOT index of last id
2667 * l - array of cell ids which have volumes that need to be sorted
2668 * vlonly - sort vl servers or file servers?
2670 static void *ReSortCells_cb(struct cell *cell, void *arg)
2672 afs_int32 *p = (afs_int32 *) arg;
2673 afs_int32 *l = p + 1;
2676 for (i=0; i<s; i++) {
2677 if (l[i] == cell->cellNum) {
2678 ObtainWriteLock(&cell->lock, 690);
2679 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2680 ReleaseWriteLock(&cell->lock);
2687 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2695 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2697 memcpy(p+1, l, s * sizeof(afs_int32));
2698 afs_TraverseCells(&ReSortCells_cb, p);
2699 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2703 ObtainReadLock(&afs_xvolume);
2704 for (i= 0; i< NVOLS; i++) {
2705 for (j=afs_volumes[i];j;j=j->next) {
2707 if (j->cell == l[k]) {
2708 ObtainWriteLock(&j->lock,233);
2709 afs_SortServers(j->serverHost, MAXHOSTS);
2710 ReleaseWriteLock(&j->lock);
2715 ReleaseReadLock(&afs_xvolume);
2719 static int debugsetsp = 0;
2720 static int afs_setsprefs(sp, num, vlonly)
2723 unsigned int vlonly;
2726 int i,j,k,matches,touchedSize;
2727 struct server *srvr = NULL;
2728 afs_int32 touched[34];
2732 for (k=0; k < num; sp++, k++) {
2734 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2737 ObtainReadLock(&afs_xserver);
2739 i = SHash(sp->host.s_addr);
2740 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2741 if (sa->sa_ip == sp->host.s_addr) {
2743 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2744 || (sa->sa_portal == AFS_FSPORT);
2745 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2752 if (sa && matches) { /* found one! */
2754 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2756 sa->sa_iprank = sp->rank + afs_randomMod15();
2757 afs_SortOneServer(sa->server);
2760 /* if we don't know yet what cell it's in, this is moot */
2761 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2762 /* is it in our list of touched cells ? */ ;
2763 if (j < 0) { /* no, it's not */
2764 touched[touchedSize++] = srvr->cell->cellNum;
2765 if (touchedSize >= 32) { /* watch for ovrflow */
2766 ReleaseReadLock(&afs_xserver);
2767 ReSortCells(touchedSize, touched, vlonly);
2769 ObtainReadLock(&afs_xserver);
2775 ReleaseReadLock(&afs_xserver);
2776 /* if we didn't find one, start to create one. */
2777 /* Note that it doesn't have a cell yet... */
2779 afs_uint32 temp = sp->host.s_addr;
2780 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2781 WRITE_LOCK, (afsUUID *)0,0);
2782 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2783 afs_PutServer(srvr, WRITE_LOCK);
2785 } /* for all cited preferences */
2787 ReSortCells(touchedSize, touched, vlonly);
2791 /* Note that this may only be performed by the local root user.
2793 DECL_PIOCTL(PSetSPrefs)
2795 struct setspref *ssp;
2796 AFS_STATCNT(PSetSPrefs);
2798 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2799 return EIO; /* Inappropriate ioctl for device */
2801 if (!afs_osi_suser(*acred))
2804 if (ainSize < sizeof(struct setspref))
2807 ssp = (struct setspref *)ain;
2808 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2811 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2812 (ssp->flags & DBservers));
2816 DECL_PIOCTL(PSetSPrefs33)
2819 AFS_STATCNT(PSetSPrefs);
2820 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2821 return EIO; /* Inappropriate ioctl for device */
2824 if (!afs_osi_suser(*acred))
2827 sp = (struct spref *)ain;
2828 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2832 /* some notes on the following code...
2833 * in the hash table of server structs, all servers with the same IP address
2834 * will be on the same overflow chain.
2835 * This could be sped slightly in some circumstances by having it cache the
2836 * immediately previous slot in the hash table and some supporting information
2837 * Only reports file servers now.
2839 DECL_PIOCTL(PGetSPrefs)
2841 struct sprefrequest *spin; /* input */
2842 struct sprefinfo *spout; /* output */
2843 struct spref *srvout; /* one output component */
2844 int i,j; /* counters for hash table traversal */
2845 struct server *srvr; /* one of CM's server structs */
2847 int vlonly; /* just return vlservers ? */
2850 AFS_STATCNT(PGetSPrefs);
2851 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
2852 return EIO; /* Inappropriate ioctl for device */
2855 if (ainSize < sizeof (struct sprefrequest_33)) {
2859 spin = ((struct sprefrequest *) ain);
2862 if (ainSize > sizeof (struct sprefrequest_33)) {
2863 vlonly = (spin->flags & DBservers);
2867 /* struct sprefinfo includes 1 server struct... that size gets added
2868 * in during the loop that follows.
2870 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2871 spout = (struct sprefinfo *) aout;
2872 spout->next_offset = spin->offset;
2873 spout->num_servers = 0;
2874 srvout = spout->servers;
2876 ObtainReadLock(&afs_xserver);
2877 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2878 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2879 if (spin->offset > (unsigned short)i) {
2880 continue; /* catch up to where we left off */
2882 spout->next_offset++;
2885 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2886 || (sa->sa_portal == AFS_FSPORT);
2888 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2889 /* only report ranks for vl servers */
2893 srvout->host.s_addr = sa->sa_ip;
2894 srvout->rank = sa->sa_iprank;
2895 *aoutSize += sizeof(struct spref);
2896 spout->num_servers++;
2899 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2900 ReleaseReadLock(&afs_xserver); /* no more room! */
2905 ReleaseReadLock(&afs_xserver);
2907 spout->next_offset = 0; /* start over from the beginning next time */
2911 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2912 int afs_NFSRootOnly = 1;
2913 DECL_PIOCTL(PExportAfs)
2915 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2916 register struct afs_exporter *exporter;
2918 AFS_STATCNT(PExportAfs);
2919 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2920 type = handleValue >> 24;
2925 exporter = exporter_find(type);
2927 export = handleValue & 3;
2928 changestate = handleValue & 0xff;
2929 smounts = (handleValue >> 2) & 3;
2930 pwsync = (handleValue >> 4) & 3;
2931 convmode = (handleValue >> 6) & 3;
2933 changestate = (handleValue >> 16) & 0x1;
2934 convmode = (handleValue >> 16) & 0x2;
2935 pwsync = (handleValue >> 16) & 0x4;
2936 smounts = (handleValue >> 16) & 0x8;
2937 export = handleValue & 0xff;
2940 /* Failed finding desired exporter; */
2944 handleValue = exporter->exp_states;
2945 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2946 *aoutSize = sizeof(afs_int32);
2948 if (!afs_osi_suser(*acred))
2949 return EACCES; /* Only superuser can do this */
2953 exporter->exp_states |= EXP_EXPORTED;
2955 exporter->exp_states &= ~EXP_EXPORTED;
2959 exporter->exp_states |= EXP_UNIXMODE;
2961 exporter->exp_states &= ~EXP_UNIXMODE;
2965 exporter->exp_states |= EXP_PWSYNC;
2967 exporter->exp_states &= ~EXP_PWSYNC;
2971 afs_NFSRootOnly = 0;
2972 exporter->exp_states |= EXP_SUBMOUNTS;
2974 afs_NFSRootOnly = 1;
2975 exporter->exp_states &= ~EXP_SUBMOUNTS;
2978 handleValue = exporter->exp_states;
2979 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2980 *aoutSize = sizeof(afs_int32);
2983 exporter->exp_states |= EXP_EXPORTED;
2985 exporter->exp_states &= ~EXP_EXPORTED;
2987 exporter->exp_states |= EXP_UNIXMODE;
2989 exporter->exp_states &= ~EXP_UNIXMODE;
2991 exporter->exp_states |= EXP_PWSYNC;
2993 exporter->exp_states &= ~EXP_PWSYNC;
2995 afs_NFSRootOnly = 0;
2996 exporter->exp_states |= EXP_SUBMOUNTS;
2998 afs_NFSRootOnly = 1;
2999 exporter->exp_states &= ~EXP_SUBMOUNTS;
3009 struct gaginfo *gagflags;
3011 if (!afs_osi_suser(*acred))
3014 gagflags = (struct gaginfo *) ain;
3015 afs_showflags = gagflags->showflags;
3021 DECL_PIOCTL(PTwiddleRx)
3023 struct rxparams *rxp;
3025 if (!afs_osi_suser(*acred))
3028 rxp = (struct rxparams *) ain;
3030 if (rxp->rx_initReceiveWindow)
3031 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3032 if (rxp->rx_maxReceiveWindow)
3033 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3034 if (rxp->rx_initSendWindow)
3035 rx_initSendWindow = rxp->rx_initSendWindow;
3036 if (rxp->rx_maxSendWindow)
3037 rx_maxSendWindow = rxp->rx_maxSendWindow;
3038 if (rxp->rxi_nSendFrags)
3039 rxi_nSendFrags = rxp->rxi_nSendFrags;
3040 if (rxp->rxi_nRecvFrags)
3041 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3042 if (rxp->rxi_OrphanFragSize)
3043 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3044 if (rxp->rx_maxReceiveSize)
3046 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3047 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3049 if (rxp->rx_MyMaxSendSize)
3050 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3055 DECL_PIOCTL(PGetInitParams)
3057 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3060 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3061 *aoutSize = sizeof(struct cm_initparams);
3065 #ifdef AFS_SGI65_ENV
3066 /* They took crget() from us, so fake it. */
3067 static cred_t *crget(void)
3070 cr = crdup(get_current_cred());
3071 memset((char*)cr, 0, sizeof(cred_t));
3072 #if CELL || CELL_PREPARE
3079 DECL_PIOCTL(PGetRxkcrypt)
3081 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3082 *aoutSize=sizeof(afs_int32);
3086 DECL_PIOCTL(PSetRxkcrypt)
3090 if (!afs_osi_suser(*acred))
3092 if (ainSize != sizeof(afs_int32) || ain == NULL)
3094 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3095 /* if new mappings added later this will need to be changed */
3096 if (tmpval != 0 && tmpval != 1)
3103 * Create new credentials to correspond to a remote user with given
3104 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3105 * provide pioctl (and other) services to foreign clients (i.e. nfs
3106 * clients) by using this call to `become' the client.
3109 #define PIOCTL_HEADER 6
3110 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3112 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3113 return EINVAL; /* NFS trans not supported for Ultrix */
3116 afs_uint32 hostaddr;
3117 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3118 struct afs_exporter *exporter, *outexporter;
3119 struct AFS_UCRED *newcred;
3120 struct unixuser *au;
3122 #if defined(AFS_SGIMP_ENV)
3123 osi_Assert(ISAFS_GLOCK());
3125 AFS_STATCNT(HandleClientContext);
3126 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3127 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3128 return EINVAL; /* Too small to be good */
3130 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3131 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3133 osi_FreeLargeSpace(inData);
3137 /* Extract information for remote user */
3138 hostaddr = *((afs_uint32 *)ain);
3139 ain += sizeof(hostaddr);
3140 uid = *((afs_uint32 *)ain);
3142 g0 = *((afs_uint32 *)ain);
3144 g1 = *((afs_uint32 *)ain);
3146 *com = *((afs_uint32 *)ain);
3147 ain += sizeof(afs_int32);
3148 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3151 * Of course, one must be root for most of these functions, but
3152 * we'll allow (for knfs) you to set things if the pag is 0 and
3153 * you're setting tokens or unlogging.
3156 if (!afs_osi_suser(credp)) {
3158 #ifndef AFS_SGI64_ENV
3159 /* Since SGI's suser() returns explicit failure after the call.. */
3163 /* check for acceptable opcodes for normal folks, which are, so far,
3164 * set tokens and unlog.
3166 if (i != 9 && i != 3 && i != 38 && i != 8) {
3167 osi_FreeLargeSpace(inData);
3172 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3173 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3174 osi_FreeLargeSpace(inData);
3177 * We map uid 0 to nobody to match the mapping that the nfs
3178 * server does and to ensure that the suser() calls in the afs
3179 * code fails for remote client roots.
3181 uid = afs_nobody; /* NFS_NOBODY == -2 */
3184 #ifdef AFS_AIX41_ENV
3187 newcred->cr_gid = RMTUSER_REQ;
3188 #ifdef AFS_AIX51_ENV
3189 newcred->cr_groupset.gs_union.un_groups[0] = g0;
3190 newcred->cr_groupset.gs_union.un_groups[1] = g1;
3192 newcred->cr_groups[0] = g0;
3193 newcred->cr_groups[1] = g1;
3196 newcred->cr_ngrps = 2;
3198 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3199 newcred->cr_ngroups = 2;
3201 for (i=2; i<NGROUPS; i++)
3202 newcred->cr_groups[i] = NOGROUP;
3205 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3206 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3208 if (!(exporter = exporter_find(exporter_type))) {
3209 /* Exporter wasn't initialized or an invalid exporter type */
3213 if (exporter->exp_states & EXP_PWSYNC) {
3214 if (uid != credp->cr_uid) {
3216 return ENOEXEC; /* XXX Find a better errno XXX */
3219 newcred->cr_uid = uid; /* Only temporary */
3220 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3221 /* The client's pag is the only unique identifier for it */
3222 newcred->cr_uid = pag;
3224 if (!code && *com == PSETPAG) {
3225 /* Special case for 'setpag' */
3226 afs_uint32 pagvalue = genpag();
3228 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3230 * Note that we leave the 'outexporter' struct held so it won't
3233 au->exporter = outexporter;
3234 if (ablob->out_size >= 4) {
3235 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3237 afs_PutUser(au, WRITE_LOCK);
3238 if (code) return code;
3239 return PSETPAG; /* Special return for setpag */
3241 EXP_RELE(outexporter);
3244 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3247 /* get all interface addresses of this client */
3249 DECL_PIOCTL(PGetCPrefs)
3251 struct sprefrequest *spin; /* input */
3252 struct sprefinfo *spout; /* output */
3253 struct spref *srvout; /* one output component */
3257 AFS_STATCNT(PGetCPrefs);
3258 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
3259 return EIO; /* Inappropriate ioctl for device */
3261 if ( ainSize < sizeof (struct sprefrequest ))
3264 spin = (struct sprefrequest *) ain;
3265 spout = (struct sprefinfo *) aout;
3267 maxNumber = spin->num_servers; /* max addrs this time */
3268 srvout = spout->servers;
3270 ObtainReadLock(&afs_xinterface);
3272 /* copy out the client interface information from the
3273 ** kernel data structure "interface" to the output buffer
3275 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3276 && ( j< maxNumber) ; i++, j++, srvout++)
3277 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3279 spout->num_servers = j;
3280 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3282 if ( i >= afs_cb_interface.numberOfInterfaces )
3283 spout->next_offset = 0; /* start from beginning again */
3285 spout->next_offset = spin->offset + j;
3287 ReleaseReadLock(&afs_xinterface);
3291 DECL_PIOCTL(PSetCPrefs)
3293 struct setspref *sin;
3296 AFS_STATCNT(PSetCPrefs);
3297 if ( !afs_resourceinit_flag ) /* afs daemons haven't started yet */
3298 return EIO; /* Inappropriate ioctl for device */
3300 sin = (struct setspref *)ain;
3302 if ( ainSize < sizeof(struct setspref) )
3304 #if 0 /* num_servers is unsigned */
3305 if ( sin->num_servers < 0 )
3308 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3311 ObtainWriteLock(&afs_xinterface, 412);
3312 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3313 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3314 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3316 ReleaseWriteLock(&afs_xinterface);
3320 DECL_PIOCTL(PFlushMount)
3322 register afs_int32 code;
3323 register struct vcache *tvc;
3324 register struct dcache *tdc;
3325 struct VenusFid tfid;
3327 struct sysname_info sysState;
3328 afs_size_t offset, len;
3330 AFS_STATCNT(PFlushMount);
3331 if (!avc) return EINVAL;
3332 code = afs_VerifyVCache(avc, areq);
3333 if (code) return code;
3334 if (vType(avc) != VDIR) {
3337 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3338 if (!tdc) return ENOENT;
3339 Check_AtSys(avc, ain, &sysState, areq);
3340 ObtainReadLock(&tdc->lock);
3342 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3343 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3344 ReleaseReadLock(&tdc->lock);
3345 afs_PutDCache(tdc); /* we're done with the data */
3346 bufp = sysState.name;
3350 tfid.Cell = avc->fid.Cell;
3351 tfid.Fid.Volume = avc->fid.Fid.Volume;
3352 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3353 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3355 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3361 if (tvc->mvstat != 1) {
3366 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3367 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3369 ObtainWriteLock(&tvc->lock,649);
3370 ObtainWriteLock(&afs_xcbhash, 650);
3371 afs_DequeueCallback(tvc);
3372 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3373 ReleaseWriteLock(&afs_xcbhash);
3374 /* now find the disk cache entries */
3375 afs_TryToSmush(tvc, *acred, 1);
3376 osi_dnlc_purgedp(tvc);
3377 afs_symhint_inval(tvc);
3378 if (tvc->linkData && !(tvc->states & CCore)) {
3379 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3380 tvc->linkData = NULL;
3382 ReleaseWriteLock(&tvc->lock);
3383 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3384 afs_BozonUnlock(&tvc->pvnLock, tvc);
3388 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3392 DECL_PIOCTL(PRxStatProc)
3397 if (!afs_osi_suser(*acred)) {
3401 if (ainSize != sizeof(afs_int32)) {
3405 memcpy((char *)&flags, ain, sizeof(afs_int32));
3406 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3410 if (flags & AFSCALL_RXSTATS_ENABLE) {
3411 rx_enableProcessRPCStats();
3413 if (flags & AFSCALL_RXSTATS_DISABLE) {
3414 rx_disableProcessRPCStats();
3416 if (flags & AFSCALL_RXSTATS_CLEAR) {
3417 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3425 DECL_PIOCTL(PRxStatPeer)
3430 if (!afs_osi_suser(*acred)) {
3434 if (ainSize != sizeof(afs_int32)) {
3438 memcpy((char *)&flags, ain, sizeof(afs_int32));
3439 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3443 if (flags & AFSCALL_RXSTATS_ENABLE) {
3444 rx_enablePeerRPCStats();
3446 if (flags & AFSCALL_RXSTATS_DISABLE) {
3447 rx_disablePeerRPCStats();
3449 if (flags & AFSCALL_RXSTATS_CLEAR) {
3450 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3457 DECL_PIOCTL(PPrefetchFromTape)
3459 register afs_int32 code, code1;
3462 struct rx_call *tcall;
3463 struct AFSVolSync tsync;
3464 struct AFSFetchStatus OutStatus;
3465 struct AFSCallBack CallBack;
3466 struct VenusFid tfid;
3470 AFS_STATCNT(PSetAcl);
3474 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3475 Fid = (struct AFSFid *) ain;
3477 Fid = &avc->fid.Fid;
3478 tfid.Cell = avc->fid.Cell;
3479 tfid.Fid.Volume = Fid->Volume;
3480 tfid.Fid.Vnode = Fid->Vnode;
3481 tfid.Fid.Unique = Fid->Unique;
3483 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3485 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3486 ICL_TYPE_POINTER, tvc,
3487 ICL_TYPE_FID, &tfid,
3488 ICL_TYPE_FID, &avc->fid);
3491 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3492 ICL_TYPE_POINTER, tvc,
3493 ICL_TYPE_FID, &tfid,
3494 ICL_TYPE_FID, &tvc->fid);
3497 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3501 tcall = rx_NewCall(tc->id);
3502 code = StartRXAFS_FetchData(tcall,
3503 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3505 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3506 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3508 code1 = rx_EndCall(tcall, code);
3513 (afs_Analyze(tc, code, &tvc->fid, areq,
3514 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3516 /* This call is done only to have the callback things handled correctly */
3517 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3521 *aoutSize = sizeof(afs_int32);
3526 DECL_PIOCTL(PResidencyCmd)
3528 register afs_int32 code;
3531 struct ResidencyCmdInputs *Inputs;
3532 struct ResidencyCmdOutputs *Outputs;
3533 struct VenusFid tfid;
3536 Inputs = (struct ResidencyCmdInputs *) ain;
3537 Outputs = (struct ResidencyCmdOutputs *) aout;
3538 if (!avc) return EINVAL;
3539 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3543 Fid = &avc->fid.Fid;
3545 tfid.Cell = avc->fid.Cell;
3546 tfid.Fid.Volume = Fid->Volume;
3547 tfid.Fid.Vnode = Fid->Vnode;
3548 tfid.Fid.Unique = Fid->Unique;
3550 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3551 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3552 ICL_TYPE_POINTER, tvc,
3553 ICL_TYPE_INT32, Inputs->command,
3554 ICL_TYPE_FID, &tfid);
3558 if (Inputs->command) {
3560 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3563 code = RXAFS_ResidencyCmd(tc->id, Fid,
3565 (struct ResidencyCmdOutputs *) aout);
3570 (afs_Analyze(tc, code, &tvc->fid, areq,
3571 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3573 /* This call is done to have the callback things handled correctly */
3574 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3575 } else { /* just a status request, return also link data */
3577 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3578 Outputs->chars[0] = 0;
3579 if (vType(tvc) == VLNK) {
3580 ObtainWriteLock(&tvc->lock,555);
3581 if (afs_HandleLink(tvc, areq) == 0)
3582 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3583 ReleaseWriteLock(&tvc->lock);
3590 *aoutSize = sizeof(struct ResidencyCmdOutputs);