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 */
16 #include "../afs/afsincludes.h" /* Afs-based standard headers */
17 #include "../afs/afs_stats.h" /* afs statistics */
18 #include "../afs/vice.h"
19 #include "../rx/rx_globals.h"
21 struct VenusFid afs_rootFid;
22 afs_int32 afs_waitForever=0;
23 short afs_waitForeverCount = 0;
24 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
26 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
27 char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
28 struct AFS_UCRED **acred)
30 /* Prototypes for pioctl routines */
33 DECL_PIOCTL(PStoreBehind);
38 DECL_PIOCTL(PGetFileCell);
39 DECL_PIOCTL(PGetWSCell);
40 DECL_PIOCTL(PGetUserCell);
41 DECL_PIOCTL(PSetTokens);
42 DECL_PIOCTL(PGetVolumeStatus);
43 DECL_PIOCTL(PSetVolumeStatus);
45 DECL_PIOCTL(PNewStatMount);
46 DECL_PIOCTL(PGetTokens);
48 DECL_PIOCTL(PMariner);
49 DECL_PIOCTL(PCheckServers);
50 DECL_PIOCTL(PCheckVolNames);
51 DECL_PIOCTL(PCheckAuth);
52 DECL_PIOCTL(PFindVolume);
53 DECL_PIOCTL(PViceAccess);
54 DECL_PIOCTL(PSetCacheSize);
55 DECL_PIOCTL(PGetCacheSize);
56 DECL_PIOCTL(PRemoveCallBack);
57 DECL_PIOCTL(PNewCell);
58 DECL_PIOCTL(PNewAlias);
59 DECL_PIOCTL(PListCells);
60 DECL_PIOCTL(PListAliases);
61 DECL_PIOCTL(PRemoveMount);
62 DECL_PIOCTL(PVenusLogging);
63 DECL_PIOCTL(PGetCellStatus);
64 DECL_PIOCTL(PSetCellStatus);
65 DECL_PIOCTL(PFlushVolumeData);
66 DECL_PIOCTL(PGetVnodeXStatus);
67 DECL_PIOCTL(PSetSysName);
68 DECL_PIOCTL(PSetSPrefs);
69 DECL_PIOCTL(PSetSPrefs33);
70 DECL_PIOCTL(PGetSPrefs);
71 DECL_PIOCTL(PExportAfs);
73 DECL_PIOCTL(PTwiddleRx);
74 DECL_PIOCTL(PGetInitParams);
75 DECL_PIOCTL(PGetRxkcrypt);
76 DECL_PIOCTL(PSetRxkcrypt);
77 DECL_PIOCTL(PGetCPrefs);
78 DECL_PIOCTL(PSetCPrefs);
79 DECL_PIOCTL(PFlushMount);
80 DECL_PIOCTL(PRxStatProc);
81 DECL_PIOCTL(PRxStatPeer);
82 DECL_PIOCTL(PPrefetchFromTape);
83 DECL_PIOCTL(PResidencyCmd);
85 /* Prototypes for private routines */
86 static int HandleClientContext(struct afs_ioctl *ablob, int *com,
87 struct AFS_UCRED **acred, struct AFS_UCRED *credp);
88 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata);
89 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
90 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred);
91 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred);
94 static int (*(VpioctlSw[]))() = {
99 PGetVolumeStatus, /* 4 */
100 PSetVolumeStatus, /* 5 */
105 PCheckServers, /* 10 */
106 PCheckVolNames, /* 11 */
108 PBogus, /* 13 -- used to be quick check time */
110 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
111 PBogus, /* 16 -- used to be testing code */
112 PNoop, /* 17 -- used to be enable group */
113 PNoop, /* 18 -- used to be disable group */
114 PBogus, /* 19 -- used to be list group */
115 PViceAccess, /* 20 */
116 PUnlog, /* 21 -- unlog *is* unpag in this system */
117 PGetFID, /* 22 -- get file ID */
118 PBogus, /* 23 -- used to be waitforever */
119 PSetCacheSize, /* 24 */
120 PRemoveCallBack, /* 25 -- flush only the callback */
123 PRemoveMount, /* 28 -- delete mount point */
124 PNewStatMount, /* 29 -- new style mount point stat */
125 PGetFileCell, /* 30 -- get cell name for input file */
126 PGetWSCell, /* 31 -- get cell name for workstation */
127 PMariner, /* 32 - set/get mariner host */
128 PGetUserCell, /* 33 -- get cell name for user */
129 PVenusLogging, /* 34 -- Enable/Disable logging */
130 PGetCellStatus, /* 35 */
131 PSetCellStatus, /* 36 */
132 PFlushVolumeData, /* 37 -- flush all data from a volume */
133 PSetSysName, /* 38 - Set system name */
134 PExportAfs, /* 39 - Export Afs to remote nfs clients */
135 PGetCacheSize, /* 40 - get cache size and usage */
136 PGetVnodeXStatus, /* 41 - get vcache's special status */
137 PSetSPrefs33, /* 42 - Set CM Server preferences... */
138 PGetSPrefs, /* 43 - Get CM Server preferences... */
139 PGag, /* 44 - turn off/on all CM messages */
140 PTwiddleRx, /* 45 - adjust some RX params */
141 PSetSPrefs, /* 46 - Set CM Server preferences... */
142 PStoreBehind, /* 47 - set degree of store behind to be done */
143 PGCPAGs, /* 48 - disable automatic pag gc-ing */
144 PGetInitParams, /* 49 - get initial cm params */
145 PGetCPrefs, /* 50 - get client interface addresses */
146 PSetCPrefs, /* 51 - set client interface addresses */
147 PFlushMount, /* 52 - flush mount symlink data */
148 PRxStatProc, /* 53 - control process RX statistics */
149 PRxStatPeer, /* 54 - control peer RX statistics */
150 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
151 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
152 PBogus, /* 57 -- arla: set file prio */
153 PBogus, /* 58 -- arla: fallback getfh */
154 PBogus, /* 59 -- arla: fallback fhopen */
155 PBogus, /* 60 -- arla: controls xfsdebug */
156 PBogus, /* 61 -- arla: controls arla debug */
157 PBogus, /* 62 -- arla: debug interface */
158 PBogus, /* 63 -- arla: print xfs status */
159 PBogus, /* 64 -- arla: force cache check */
160 PBogus, /* 65 -- arla: break callback */
161 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
162 PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
163 PBogus, /* 68 -- arla: fetch stats */
166 static int (*(CpioctlSw[]))() = {
168 PNewAlias, /* 1 -- create new cell alias */
169 PListAliases, /* 2 -- list cell aliases */
172 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
173 int afs_nobody = NFS_NOBODY;
176 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
178 dst->in = (char *)(unsigned long)src->in;
179 dst->out = (char *)(unsigned long)src->out;
180 dst->in_size = src->in_size;
181 dst->out_size = src->out_size;
185 * If you need to change copyin_afs_ioctl(), you may also need to change
190 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
194 #if defined(AFS_HPUX_64BIT_ENV)
195 struct afs_ioctl32 dst32;
197 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
199 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
201 afs_ioctl32_to_afs_ioctl(&dst32, dst);
204 #endif /* defined(AFS_HPUX_64BIT_ENV) */
206 #if defined(AFS_SUN57_64BIT_ENV)
207 struct afs_ioctl32 dst32;
209 if (get_udatamodel() == DATAMODEL_ILP32) {
210 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
212 afs_ioctl32_to_afs_ioctl(&dst32, dst);
215 #endif /* defined(AFS_SUN57_64BIT_ENV) */
217 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
218 struct afs_ioctl32 dst32;
220 if (!ABI_IS_64BIT(get_current_abi()))
222 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
224 afs_ioctl32_to_afs_ioctl(&dst32, dst);
227 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
229 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
230 struct afs_ioctl32 dst32;
232 #ifdef AFS_SPARC64_LINUX24_ENV
233 if (current->thread.flags & SPARC_FLAG_32BIT)
234 #elif AFS_SPARC64_LINUX20_ENV
235 if (current->tss.flags & SPARC_FLAG_32BIT)
237 #error Not done for this linux type
238 #endif /* AFS_SPARC64_LINUX20_ENV */
240 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
242 afs_ioctl32_to_afs_ioctl(&dst32, dst);
245 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
247 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
251 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata)
253 register afs_int32 code;
256 AFS_STATCNT(HandleIoctl);
258 switch(acom & 0xff) {
260 avc->states |= CSafeStore;
264 /* case 2 used to be abort store, but this is no longer provided,
265 since it is impossible to implement under normal Unix.
269 /* return the name of the cell this file is open on */
270 register struct cell *tcell;
271 register afs_int32 i;
273 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
275 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
277 if (i > adata->out_size) {
278 /* 0 means we're not interested in the output */
279 if (adata->out_size != 0) code = EFAULT;
283 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
285 afs_PutCell(tcell, READ_LOCK);
291 case 49: /* VIOC_GETINITPARAMS */
292 if (adata->out_size < sizeof(struct cm_initparams)) {
296 AFS_COPYOUT(&cm_initParams, adata->out,
297 sizeof(struct cm_initparams), code);
309 return code; /* so far, none implemented */
314 /* For aix we don't temporarily bypass ioctl(2) but rather do our
315 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
316 * is now called from afs_gn_ioctl.
318 int afs_ioctl(struct vcache *tvc, int cmd, int arg)
320 struct afs_ioctl data;
323 AFS_STATCNT(afs_ioctl);
324 if (((cmd >> 8) & 0xff) == 'V') {
325 /* This is a VICEIOCTL call */
326 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
329 error = HandleIoctl(tvc, cmd, &data);
332 /* No-op call; just return. */
336 #endif /* AFS_AIX_ENV */
338 #if defined(AFS_SGI_ENV)
339 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
345 struct afs_ioctl data;
351 AFS_STATCNT(afs_ioctl);
352 if (((cmd >> 8) & 0xff) == 'V') {
353 /* This is a VICEIOCTL call */
354 error = copyin_afs_ioctl(arg, &data);
357 locked = ISAFS_GLOCK();
360 error = HandleIoctl(tvc, cmd, &data);
365 /* No-op call; just return. */
369 #endif /* AFS_SGI_ENV */
372 /* unlike most calls here, this one uses u.u_error to return error conditions,
373 since this is really an intercepted chapter 2 call, rather than a vnode
376 /* AFS_HPUX102 and up uses VNODE ioctl instead */
377 #ifndef AFS_HPUX102_ENV
378 #if !defined(AFS_SGI_ENV)
381 kioctl(fdes, com, arg, ext, arg2, arg3)
384 kioctl(fdes, com, arg, ext)
395 } u_uap, *uap = &u_uap;
399 struct afs_ioctl_sys {
405 afs_xioctl (uap, rvp)
406 struct afs_ioctl_sys *uap;
411 afs_xioctl (p, args, retval)
420 } *uap = (struct a *)args;
421 #else /* AFS_OSF_ENV */
422 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
428 afs_xioctl(p, uap, retval)
430 register struct ioctl_args *uap;
434 #ifdef AFS_LINUX22_ENV
435 struct afs_ioctl_sys {
439 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
440 unsigned int com, unsigned long arg)
442 struct afs_ioctl_sys ua, *uap = &ua;
444 int afs_xioctl (void)
450 } *uap = (struct a *)u.u_ap;
451 #endif /* AFS_LINUX22_ENV */
452 #endif /* AFS_DARWIN_ENV || AFS_FBSD_ENV */
453 #endif /* AFS_OSF_ENV */
454 #endif /* AFS_SUN5_ENV */
456 #ifndef AFS_LINUX22_ENV
457 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
460 register struct file *fd;
463 #if defined(AFS_FBSD_ENV)
464 register struct filedesc *fdp;
466 register struct vcache *tvc;
467 register int ioctlDone = 0, code = 0;
469 AFS_STATCNT(afs_xioctl);
470 #if defined(AFS_FBSD_ENV)
472 if ((u_int)uap->fd >= fdp->fd_nfiles ||
473 (fd = fdp->fd_ofiles[uap->fd]) == NULL)
475 if ((fd->f_flag & (FREAD | FWRITE)) == 0)
478 #if defined(AFS_DARWIN_ENV)
479 if ((code=fdgetf(p, uap->fd, &fd)))
482 #ifdef AFS_LINUX22_ENV
496 if (setuerror(getf(uap->fd, &fd))) {
502 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
504 #else /* AFS_OSF_ENV */
506 #if defined(AFS_SUN57_ENV)
508 if (!fd) return(EBADF);
509 #elif defined(AFS_SUN54_ENV)
511 if (!fd) return(EBADF);
513 if (code = getf(uap->fd, &fd)) {
526 /* first determine whether this is any sort of vnode */
527 #ifdef AFS_LINUX22_ENV
532 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
534 if (fd->f_type == DTYPE_VNODE) {
536 /* good, this is a vnode; next see if it is an AFS vnode */
537 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
538 tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
540 tvc = VTOAFS((struct vnode*)fd->f_data); /* valid, given a vnode */
542 #endif /* AFS_LINUX22_ENV */
543 if (tvc && IsAfsVnode(AFSTOV(tvc))) {
545 tvc = VTOAFS(afs_gntovn((struct gnode *) tvc));
546 if (!tvc) { /* shouldn't happen with held gnodes */
551 /* This is an AFS vnode */
552 if (((uap->com >> 8) & 0xff) == 'V') {
553 register struct afs_ioctl *datap;
555 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
556 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
558 osi_FreeSmallSpace(datap);
560 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
563 #if defined(AFS_SUN5_ENV)
578 #else /* AFS_OSF_ENV */
582 #ifdef AFS_LINUX22_ENV
592 code = HandleIoctl(tvc, uap->com, datap);
593 osi_FreeSmallSpace(datap);
607 #if defined(AFS_LINUX22_ENV)
618 code = okioctl(fdes, com, arg, ext, arg2, arg3);
620 code = okioctl(fdes, com, arg, ext);
625 okioctl(fdes, com, arg, ext);
627 #if defined(AFS_SUN5_ENV)
628 #if defined(AFS_SUN57_ENV)
630 #elif defined(AFS_SUN54_ENV)
635 code = ioctl(uap, rvp);
637 #if defined(AFS_FBSD_ENV)
638 return ioctl(p, uap);
640 #if defined(AFS_DARWIN_ENV)
641 return ioctl(p, uap, retval);
644 code = ioctl(p, args, retval);
651 #else /* AFS_OSF_ENV */
652 #ifndef 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_FBSD_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);
716 #endif /* AFS_SGI_ENV */
719 afs_pioctl(p, args, retval)
729 } *uap = (struct a *) args;
731 AFS_STATCNT(afs_pioctl);
732 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
735 #else /* AFS_OSF_ENV */
736 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
737 afs_pioctl(p, args, retval)
747 } *uap = (struct a *) args;
749 AFS_STATCNT(afs_pioctl);
750 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
753 #else /* AFS_OSF_ENV */
757 /* macro to avoid adding any more #ifdef's to pioctl code. */
758 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
759 #define PIOCTL_FREE_CRED() crfree(credp)
761 #define PIOCTL_FREE_CRED()
765 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
767 struct AFS_UCRED *credp;
769 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
770 afs_syscall_pioctl(path, com, cmarg, follow, credp)
771 struct AFS_UCRED *credp;
773 afs_syscall_pioctl(path, com, cmarg, follow)
781 struct afs_ioctl data;
782 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
783 register afs_int32 code = 0;
789 struct ucred *credp = crref(); /* don't free until done! */
791 #ifdef AFS_LINUX22_ENV
792 cred_t *credp = crref(); /* don't free until done! */
796 AFS_STATCNT(afs_syscall_pioctl);
797 if (follow) follow = 1; /* compat. with old venus */
798 code = copyin_afs_ioctl(cmarg, &data);
801 #if defined(KERNEL_HAVE_UERROR)
806 if ((com & 0xff) == PSetClientContext) {
807 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
808 return EINVAL; /* Not handling these yet. */
809 #elif defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
810 code = HandleClientContext(&data, &com, &foreigncreds, credp);
812 code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
816 crfree(foreigncreds);
819 #if defined(KERNEL_HAVE_UERROR)
820 return (setuerror(code), code);
826 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
829 * We could have done without temporary setting the u.u_cred below
830 * (foreigncreds could be passed as param the pioctl modules)
831 * but calls such as afs_osi_suser() doesn't allow that since it
832 * references u.u_cred directly. We could, of course, do something
833 * like afs_osi_suser(cred) which, I think, is better since it
834 * generalizes and supports multi cred environments...
838 credp = foreigncreds;
841 tmpcred = crref(); /* XXX */
844 #if defined(AFS_HPUX101_ENV)
845 tmpcred = p_cred(u.u_procp);
846 set_p_cred(u.u_procp, foreigncreds);
849 tmpcred = OSI_GET_CURRENT_CRED();
850 OSI_SET_CURRENT_CRED(foreigncreds);
853 tmpcred = osi_curcred();
854 osi_curcred() = foreigncreds;
857 u.u_cred = foreigncreds;
858 #endif /* AFS_SGI64_ENV */
859 #endif /* AFS_HPUX101_ENV */
865 if ((com & 0xff) == 15) {
866 /* special case prefetch so entire pathname eval occurs in helper process.
867 otherwise, the pioctl call is essentially useless */
868 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
869 code = Prefetch(path, &data, follow,
870 foreigncreds ? foreigncreds : credp);
872 code = Prefetch(path, &data, follow, osi_curcred());
874 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
877 crset(tmpcred); /* restore original credentials */
879 #if defined(AFS_HPUX101_ENV)
880 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
884 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
886 u.u_cred = tmpcred; /* restore original credentials */
889 #endif /* AFS_HPUX101_ENV */
890 crfree(foreigncreds);
893 #endif /* AFS_LINUX22_ENV */
895 #if defined(KERNEL_HAVE_UERROR)
896 return (setuerror(code), code);
904 code = lookupname(path, USR, follow, NULL, &vp,
905 foreigncreds ? foreigncreds : credp);
907 #ifdef AFS_LINUX22_ENV
908 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &dp);
910 vp = (struct vnode *)dp->d_inode;
912 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &vp);
913 #endif /* AFS_LINUX22_ENV */
914 #endif /* AFS_AIX41_ENV */
917 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
920 crset(tmpcred); /* restore original credentials */
922 #if defined(AFS_HPUX101_ENV)
923 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
925 #if !defined(AFS_SUN5_ENV)
927 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
929 u.u_cred = tmpcred; /* restore original credentials */
930 #endif /* AFS_SGI64_ENV */
932 #endif /* AFS_HPUX101_ENV */
933 crfree(foreigncreds);
936 #endif /* AFS_LINUX22_ENV */
938 #if defined(KERNEL_HAVE_UERROR)
939 return(setuerror(code), code);
947 /* now make the call if we were passed no file, or were passed an AFS file */
948 if (!vp || IsAfsVnode(vp)) {
950 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
951 * So, we must test in this part of the code. Also, must arrange to
952 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
953 * we hold gnodes, whose references hold our vcache entries.
956 gp = vp; /* remember for "put" */
957 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
962 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
966 struct ucred *cred1, *cred2;
969 cred1 = cred2 = foreigncreds;
971 cred1 = cred2 = credp;
973 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
974 if (cred1 != cred2) {
975 /* something changed the creds */
980 #if defined(AFS_HPUX101_ENV)
982 struct ucred *cred = p_cred(u.u_procp);
983 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
989 credp = OSI_GET_CURRENT_CRED();
990 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
993 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
994 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
996 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
998 #endif /* AFS_SGI_ENV */
999 #endif /* AFS_HPUX101_ENV */
1000 #endif /* AFS_AIX41_ENV */
1001 #endif /* AFS_SUN5_ENV */
1003 #if defined(KERNEL_HAVE_UERROR)
1006 code = EINVAL; /* not in /afs */
1016 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
1018 #ifdef AFS_AIX41_ENV
1021 #if defined(AFS_HPUX101_ENV)
1022 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
1024 #ifndef AFS_SUN5_ENV
1026 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
1028 u.u_cred = tmpcred; /* restore original credentials */
1029 #endif /* ASF_SGI64_ENV */
1031 #endif /* AFS_HPUX101_ENV */
1032 crfree(foreigncreds);
1035 #endif /* AFS_LINUX22_ENV */
1037 #ifdef AFS_LINUX22_ENV
1040 AFS_RELE(vp); /* put vnode back */
1044 #if defined(KERNEL_HAVE_UERROR)
1047 return (getuerror());
1054 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
1055 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1057 struct vrequest treq;
1058 register afs_int32 code;
1059 register afs_int32 function, device;
1060 afs_int32 inSize, outSize;
1061 char *inData, *outData;
1062 int (*(*pioctlSw))();
1064 struct afs_fakestat_state fakestate;
1066 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1067 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1068 AFS_STATCNT(HandlePioctl);
1069 if ((code = afs_InitReq(&treq, *acred))) return code;
1070 afs_InitFakeStat(&fakestate);
1072 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1074 afs_PutFakeStat(&fakestate);
1078 device = (acom & 0xff00) >> 8;
1080 case 'V': /* Original pioctl's */
1081 pioctlSw = VpioctlSw;
1082 pioctlSwSize = sizeof(VpioctlSw);
1084 case 'C': /* Coordinated/common pioctl's */
1085 pioctlSw = CpioctlSw;
1086 pioctlSwSize = sizeof(CpioctlSw);
1089 afs_PutFakeStat(&fakestate);
1092 function = acom & 0xff;
1093 if (function >= (pioctlSwSize / sizeof(char *))) {
1094 afs_PutFakeStat(&fakestate);
1095 return EINVAL; /* out of range */
1097 inSize = ablob->in_size;
1098 if (inSize >= PIGGYSIZE) return E2BIG;
1099 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1101 AFS_COPYIN(ablob->in, inData, inSize, code);
1102 inData[inSize]='\0';
1106 osi_FreeLargeSpace(inData);
1107 afs_PutFakeStat(&fakestate);
1110 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1112 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1113 osi_FreeLargeSpace(inData);
1114 if (code == 0 && ablob->out_size > 0) {
1115 if (outSize > ablob->out_size) outSize = ablob->out_size;
1116 if (outSize >= PIGGYSIZE) code = E2BIG;
1118 outData[outSize]='\0';
1119 AFS_COPYOUT(outData, ablob->out, outSize, code);
1122 osi_FreeLargeSpace(outData);
1123 afs_PutFakeStat(&fakestate);
1124 return afs_CheckCode(code, &treq, 41);
1127 DECL_PIOCTL(PGetFID)
1129 register afs_int32 code;
1131 AFS_STATCNT(PGetFID);
1132 if (!avc) return EINVAL;
1133 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1134 *aoutSize = sizeof(struct VenusFid);
1138 DECL_PIOCTL(PSetAcl)
1140 register afs_int32 code;
1142 struct AFSOpaque acl;
1143 struct AFSVolSync tsync;
1144 struct AFSFetchStatus OutStatus;
1147 AFS_STATCNT(PSetAcl);
1150 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1153 acl.AFSOpaque_val = ain;
1155 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1157 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1159 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1160 &acl, &OutStatus, &tsync);
1166 (afs_Analyze(tconn, code, &avc->fid, areq,
1167 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1169 /* now we've forgotten all of the access info */
1170 ObtainWriteLock(&afs_xcbhash, 455);
1172 afs_DequeueCallback(avc);
1173 avc->states &= ~(CStatd | CUnique);
1174 ReleaseWriteLock(&afs_xcbhash);
1175 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1176 osi_dnlc_purgedp(avc);
1180 int afs_defaultAsynchrony = 0;
1182 DECL_PIOCTL(PStoreBehind)
1185 struct sbstruct *sbr;
1187 sbr = (struct sbstruct *)ain;
1188 if (sbr->sb_default != -1) {
1189 if (afs_osi_suser(*acred))
1190 afs_defaultAsynchrony = sbr->sb_default;
1194 if (avc && (sbr->sb_thisfile != -1)) {
1195 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1196 areq, DONT_CHECK_MODE_BITS))
1197 avc->asynchrony = sbr->sb_thisfile;
1201 *aoutSize = sizeof(struct sbstruct);
1202 sbr = (struct sbstruct *)aout;
1203 sbr->sb_default = afs_defaultAsynchrony;
1205 sbr->sb_thisfile = avc->asynchrony;
1211 DECL_PIOCTL(PGCPAGs)
1213 if (!afs_osi_suser(*acred)) {
1216 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1220 DECL_PIOCTL(PGetAcl)
1222 struct AFSOpaque acl;
1223 struct AFSVolSync tsync;
1224 struct AFSFetchStatus OutStatus;
1230 AFS_STATCNT(PGetAcl);
1231 if (!avc) return EINVAL;
1232 Fid.Volume = avc->fid.Fid.Volume;
1233 Fid.Vnode = avc->fid.Fid.Vnode;
1234 Fid.Unique = avc->fid.Fid.Unique;
1235 if (avc->states & CForeign) {
1237 * For a dfs xlator acl we have a special hack so that the
1238 * xlator will distinguish which type of acl will return. So
1239 * we currently use the top 2-bytes (vals 0-4) to tell which
1240 * type of acl to bring back. Horrible hack but this will
1241 * cause the least number of changes to code size and interfaces.
1243 if (Fid.Vnode & 0xc0000000)
1245 Fid.Vnode |= (ainSize << 30);
1247 acl.AFSOpaque_val = aout;
1249 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1252 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1254 code = RXAFS_FetchACL(tconn->id, &Fid,
1255 &acl, &OutStatus, &tsync);
1261 (afs_Analyze(tconn, code, &avc->fid, areq,
1262 AFS_STATS_FS_RPCIDX_FETCHACL,
1263 SHARED_LOCK, NULL));
1266 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1279 AFS_STATCNT(PBogus);
1283 DECL_PIOCTL(PGetFileCell)
1285 register struct cell *tcell;
1287 AFS_STATCNT(PGetFileCell);
1288 if (!avc) return EINVAL;
1289 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1290 if (!tcell) return ESRCH;
1291 strcpy(aout, tcell->cellName);
1292 afs_PutCell(tcell, READ_LOCK);
1293 *aoutSize = strlen(aout) + 1;
1297 DECL_PIOCTL(PGetWSCell)
1299 struct cell *tcell = NULL;
1301 AFS_STATCNT(PGetWSCell);
1302 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1303 return EIO; /* Inappropriate ioctl for device */
1305 tcell = afs_GetPrimaryCell(READ_LOCK);
1306 if (!tcell) /* no primary cell? */
1308 strcpy(aout, tcell->cellName);
1309 *aoutSize = strlen(aout) + 1;
1310 afs_PutCell(tcell, READ_LOCK);
1314 DECL_PIOCTL(PGetUserCell)
1316 register afs_int32 i;
1317 register struct unixuser *tu;
1318 register struct cell *tcell;
1320 AFS_STATCNT(PGetUserCell);
1321 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1322 return EIO; /* Inappropriate ioctl for device */
1324 /* return the cell name of the primary cell for this user */
1325 i = UHash(areq->uid);
1326 ObtainWriteLock(&afs_xuser,224);
1327 for(tu = afs_users[i]; tu; tu = tu->next) {
1328 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1330 ReleaseWriteLock(&afs_xuser);
1335 tcell = afs_GetCell(tu->cell, READ_LOCK);
1336 afs_PutUser(tu, WRITE_LOCK);
1337 if (!tcell) return ESRCH;
1339 strcpy(aout, tcell->cellName);
1340 afs_PutCell(tcell, READ_LOCK);
1341 *aoutSize = strlen(aout)+1; /* 1 for the null */
1345 ReleaseWriteLock(&afs_xuser);
1352 DECL_PIOCTL(PSetTokens)
1355 register struct unixuser *tu;
1356 struct ClearToken clear;
1357 register struct cell *tcell;
1360 struct vrequest treq;
1361 afs_int32 flag, set_parent_pag = 0;
1363 AFS_STATCNT(PSetTokens);
1364 if (!afs_resourceinit_flag) {
1367 memcpy((char *)&i, ain, sizeof(afs_int32));
1368 ain += sizeof(afs_int32);
1369 stp = ain; /* remember where the ticket is */
1370 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1371 if (i > MAXKTCTICKETLEN) return EINVAL;
1373 ain += i; /* skip over ticket */
1374 memcpy((char *)&i, ain, sizeof(afs_int32));
1375 ain += sizeof(afs_int32);
1376 if (i != sizeof(struct ClearToken)) {
1379 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1380 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1381 ain += sizeof(struct ClearToken);
1382 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1383 /* still stuff left? we've got primary flag and cell name. Set these */
1384 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1385 ain += sizeof(afs_int32); /* skip id field */
1386 /* rest is cell name, look it up */
1387 /* some versions of gcc appear to need != 0 in order to get this right */
1388 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1392 tcell = afs_GetCellByName(ain, READ_LOCK);
1393 if (!tcell) goto nocell;
1396 /* default to primary cell, primary id */
1397 flag = 1; /* primary id */
1398 tcell = afs_GetPrimaryCell(READ_LOCK);
1399 if (!tcell) goto nocell;
1402 afs_PutCell(tcell, READ_LOCK);
1403 if (set_parent_pag) {
1405 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1406 #if defined(AFS_DARWIN_ENV)
1407 struct proc *p=current_proc(); /* XXX */
1409 struct proc *p=curproc; /* XXX */
1411 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1412 p->p_pid, p->p_comm);
1413 if (!setpag(p, acred, -1, &pag, 1)) {
1416 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1418 if (!setpag(acred, -1, &pag, 1)) {
1421 afs_InitReq(&treq, *acred);
1425 /* now we just set the tokens */
1426 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1427 tu->vid = clear.ViceId;
1428 if (tu->stp != NULL) {
1429 afs_osi_Free(tu->stp, tu->stLen);
1431 tu->stp = (char *) afs_osi_Alloc(stLen);
1433 memcpy(tu->stp, stp, stLen);
1436 afs_stats_cmfullperf.authent.TicketUpdates++;
1437 afs_ComputePAGStats();
1438 #endif /* AFS_NOSTATS */
1439 tu->states |= UHasTokens;
1440 tu->states &= ~UTokensBad;
1441 afs_SetPrimary(tu, flag);
1442 tu->tokenTime =osi_Time();
1443 afs_ResetUserConns(tu);
1444 afs_PutUser(tu, WRITE_LOCK);
1459 DECL_PIOCTL(PGetVolumeStatus)
1462 char offLineMsg[256];
1464 register struct conn *tc;
1465 register afs_int32 code;
1466 struct VolumeStatus volstat;
1468 char *Name, *OfflineMsg, *MOTD;
1471 AFS_STATCNT(PGetVolumeStatus);
1472 if (!avc) return EINVAL;
1474 OfflineMsg = offLineMsg;
1477 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1479 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1481 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1482 &Name, &OfflineMsg, &MOTD);
1488 (afs_Analyze(tc, code, &avc->fid, areq,
1489 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1490 SHARED_LOCK, NULL));
1492 if (code) return code;
1493 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1495 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1496 cp += sizeof(VolumeStatus);
1497 strcpy(cp, volName);
1498 cp += strlen(volName)+1;
1499 strcpy(cp, offLineMsg);
1500 cp += strlen(offLineMsg)+1;
1502 cp += strlen(motd)+1;
1503 *aoutSize = (cp - aout);
1507 DECL_PIOCTL(PSetVolumeStatus)
1510 char offLineMsg[256];
1512 register struct conn *tc;
1513 register afs_int32 code;
1514 struct AFSFetchVolumeStatus volstat;
1515 struct AFSStoreVolumeStatus storeStat;
1516 register struct volume *tvp;
1520 AFS_STATCNT(PSetVolumeStatus);
1521 if (!avc) return EINVAL;
1523 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1525 if (tvp->states & (VRO | VBackup)) {
1526 afs_PutVolume(tvp, READ_LOCK);
1529 afs_PutVolume(tvp, READ_LOCK);
1532 /* Copy the junk out, using cp as a roving pointer. */
1534 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1535 cp += sizeof(AFSFetchVolumeStatus);
1536 if (strlen(cp) >= sizeof(volName))
1538 strcpy(volName, cp);
1539 cp += strlen(volName)+1;
1540 if (strlen(cp) >= sizeof(offLineMsg))
1542 strcpy(offLineMsg, cp);
1543 cp += strlen(offLineMsg)+1;
1544 if (strlen(cp) >= sizeof(motd))
1548 if (volstat.MinQuota != -1) {
1549 storeStat.MinQuota = volstat.MinQuota;
1550 storeStat.Mask |= AFS_SETMINQUOTA;
1552 if (volstat.MaxQuota != -1) {
1553 storeStat.MaxQuota = volstat.MaxQuota;
1554 storeStat.Mask |= AFS_SETMAXQUOTA;
1557 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1559 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1561 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1562 &storeStat, volName, offLineMsg, motd);
1568 (afs_Analyze(tc, code, &avc->fid, areq,
1569 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1570 SHARED_LOCK, NULL));
1572 if (code) return code;
1573 /* we are sending parms back to make compat. with prev system. should
1574 change interface later to not ask for current status, just set new status */
1576 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1577 cp += sizeof(VolumeStatus);
1578 strcpy(cp, volName);
1579 cp += strlen(volName)+1;
1580 strcpy(cp, offLineMsg);
1581 cp += strlen(offLineMsg)+1;
1583 cp += strlen(motd)+1;
1584 *aoutSize = cp - aout;
1590 AFS_STATCNT(PFlush);
1591 if (!avc) return EINVAL;
1592 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1593 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1595 ObtainWriteLock(&avc->lock,225);
1596 ObtainWriteLock(&afs_xcbhash, 456);
1597 afs_DequeueCallback(avc);
1598 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1599 ReleaseWriteLock(&afs_xcbhash);
1600 /* now find the disk cache entries */
1601 afs_TryToSmush(avc, *acred, 1);
1602 osi_dnlc_purgedp(avc);
1603 afs_symhint_inval(avc);
1604 if (avc->linkData && !(avc->states & CCore)) {
1605 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1606 avc->linkData = NULL;
1608 ReleaseWriteLock(&avc->lock);
1609 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1610 afs_BozonUnlock(&avc->pvnLock, avc);
1615 DECL_PIOCTL(PNewStatMount)
1617 register afs_int32 code;
1618 register struct vcache *tvc;
1619 register struct dcache *tdc;
1620 struct VenusFid tfid;
1622 struct sysname_info sysState;
1623 afs_size_t offset, len;
1625 AFS_STATCNT(PNewStatMount);
1626 if (!avc) return EINVAL;
1627 code = afs_VerifyVCache(avc, areq);
1628 if (code) return code;
1629 if (vType(avc) != VDIR) {
1632 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1633 if (!tdc) return ENOENT;
1634 Check_AtSys(avc, ain, &sysState, areq);
1635 ObtainReadLock(&tdc->lock);
1637 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1638 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1639 ReleaseReadLock(&tdc->lock);
1640 afs_PutDCache(tdc); /* we're done with the data */
1641 bufp = sysState.name;
1645 tfid.Cell = avc->fid.Cell;
1646 tfid.Fid.Volume = avc->fid.Fid.Volume;
1647 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1648 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1650 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1656 if (tvc->mvstat != 1) {
1661 ObtainWriteLock(&tvc->lock,226);
1662 code = afs_HandleLink(tvc, areq);
1664 if (tvc->linkData) {
1665 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1668 /* we have the data */
1669 strcpy(aout, tvc->linkData);
1670 *aoutSize = strlen(tvc->linkData)+1;
1675 ReleaseWriteLock(&tvc->lock);
1678 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1682 DECL_PIOCTL(PGetTokens)
1684 register struct cell *tcell;
1685 register afs_int32 i;
1686 register struct unixuser *tu;
1691 AFS_STATCNT(PGetTokens);
1692 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1693 return EIO; /* Inappropriate ioctl for device */
1695 /* weird interface. If input parameter is present, it is an integer and
1696 we're supposed to return the parm'th tokens for this unix uid.
1697 If not present, we just return tokens for cell 1.
1698 If counter out of bounds, return EDOM.
1699 If no tokens for the particular cell, return ENOTCONN.
1700 Also, if this mysterious parm is present, we return, along with the
1701 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1702 at the end, in that order.
1704 if ((newStyle = (ainSize > 0))) {
1705 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1707 i = UHash(areq->uid);
1708 ObtainReadLock(&afs_xuser);
1709 for(tu = afs_users[i]; tu; tu=tu->next) {
1711 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1712 if (iterator-- == 0) break; /* are we done yet? */
1716 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1721 * No need to hold a read lock on each user entry
1725 ReleaseReadLock(&afs_xuser);
1730 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1731 tu->states |= (UTokensBad | UNeedsReset);
1732 afs_PutUser(tu, READ_LOCK);
1735 /* use iterator for temp */
1737 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1738 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1739 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1740 cp += sizeof(afs_int32);
1741 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1743 iterator = sizeof(struct ClearToken);
1744 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1745 cp += sizeof(afs_int32);
1746 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1747 cp += sizeof(struct ClearToken);
1749 /* put out primary id and cell name, too */
1750 iterator = (tu->states & UPrimary ? 1 : 0);
1751 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1752 cp += sizeof(afs_int32);
1753 tcell = afs_GetCell(tu->cell, READ_LOCK);
1755 strcpy(cp, tcell->cellName);
1756 cp += strlen(tcell->cellName)+1;
1757 afs_PutCell(tcell, READ_LOCK);
1761 *aoutSize = cp - aout;
1762 afs_PutUser(tu, READ_LOCK);
1768 register afs_int32 i;
1769 register struct unixuser *tu;
1771 AFS_STATCNT(PUnlog);
1772 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1773 return EIO; /* Inappropriate ioctl for device */
1775 i = UHash(areq->uid);
1776 ObtainWriteLock(&afs_xuser,227);
1777 for(tu=afs_users[i]; tu; tu=tu->next) {
1778 if (tu->uid == areq->uid) {
1780 tu->states &= ~UHasTokens;
1781 /* security is not having to say you're sorry */
1782 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1784 ReleaseWriteLock(&afs_xuser);
1785 /* We have to drop the lock over the call to afs_ResetUserConns, since
1786 * it obtains the afs_xvcache lock. We could also keep the lock, and
1787 * modify ResetUserConns to take parm saying we obtained the lock
1788 * already, but that is overkill. By keeping the "tu" pointer
1789 * held over the released lock, we guarantee that we won't lose our
1790 * place, and that we'll pass over every user conn that existed when
1791 * we began this call.
1793 afs_ResetUserConns(tu);
1795 ObtainWriteLock(&afs_xuser,228);
1797 /* set the expire times to 0, causes
1798 * afs_GCUserData to remove this entry
1800 tu->ct.EndTimestamp = 0;
1802 #endif /* UKERNEL */
1805 ReleaseWriteLock(&afs_xuser);
1809 DECL_PIOCTL(PMariner)
1811 afs_int32 newHostAddr;
1812 afs_int32 oldHostAddr;
1814 AFS_STATCNT(PMariner);
1816 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1818 oldHostAddr = 0xffffffff; /* disabled */
1820 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1821 if (newHostAddr == 0xffffffff) {
1822 /* disable mariner operations */
1825 else if (newHostAddr) {
1827 afs_marinerHost = newHostAddr;
1829 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1830 *aoutSize = sizeof(afs_int32);
1834 DECL_PIOCTL(PCheckServers)
1836 register char *cp = 0;
1838 register struct server *ts;
1839 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1841 struct chservinfo *pcheck;
1843 AFS_STATCNT(PCheckServers);
1845 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1846 return EIO; /* Inappropriate ioctl for device */
1848 if (*lp == 0x12345678) { /* For afs3.3 version */
1849 pcheck=(struct chservinfo *)ain;
1850 if (pcheck->tinterval >= 0) {
1852 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1853 *aoutSize = sizeof(afs_int32);
1854 if (pcheck->tinterval > 0) {
1855 if (!afs_osi_suser(*acred))
1857 PROBE_INTERVAL=pcheck->tinterval;
1863 temp=pcheck->tflags;
1864 cp = pcheck->tbuffer;
1865 } else { /* For pre afs3.3 versions */
1866 memcpy((char *)&temp, ain, sizeof(afs_int32));
1867 cp = ain+sizeof(afs_int32);
1868 if (ainSize > sizeof(afs_int32))
1873 * 1: fast check, don't contact servers.
1874 * 2: local cell only.
1877 /* have cell name, too */
1878 cellp = afs_GetCellByName(cp, READ_LOCK);
1879 if (!cellp) return ENOENT;
1882 if (!cellp && (temp & 2)) {
1883 /* use local cell */
1884 cellp = afs_GetPrimaryCell(READ_LOCK);
1886 if (!(temp & 1)) { /* if not fast, call server checker routine */
1887 afs_CheckServers(1, cellp); /* check down servers */
1888 afs_CheckServers(0, cellp); /* check up servers */
1890 /* now return the current down server list */
1892 ObtainReadLock(&afs_xserver);
1893 for(i=0;i<NSERVERS;i++) {
1894 for(ts = afs_servers[i]; ts; ts=ts->next) {
1895 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1896 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1897 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1898 cp += sizeof(afs_int32);
1902 ReleaseReadLock(&afs_xserver);
1903 if (cellp) afs_PutCell(cellp, READ_LOCK);
1904 *aoutSize = cp - aout;
1908 DECL_PIOCTL(PCheckVolNames)
1910 AFS_STATCNT(PCheckVolNames);
1911 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1912 return EIO; /* Inappropriate ioctl for device */
1914 afs_CheckRootVolume();
1915 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1916 AFS_VOLCHECK_EXPIRED |
1918 AFS_VOLCHECK_MTPTS);
1922 DECL_PIOCTL(PCheckAuth)
1927 struct unixuser *tu;
1930 AFS_STATCNT(PCheckAuth);
1931 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1932 return EIO; /* Inappropriate ioctl for device */
1935 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1936 if (!tu) retValue = EACCES;
1938 /* we have a user */
1939 ObtainReadLock(&afs_xsrvAddr);
1940 ObtainReadLock(&afs_xconn);
1942 /* any tokens set? */
1943 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1944 /* all connections in cell 1 working? */
1945 for(i=0;i<NSERVERS;i++) {
1946 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1947 for (tc = sa->conns; tc; tc=tc->next) {
1948 if (tc->user == tu && (tu->states & UTokensBad))
1953 ReleaseReadLock(&afs_xsrvAddr);
1954 ReleaseReadLock(&afs_xconn);
1955 afs_PutUser(tu, READ_LOCK);
1957 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1958 *aoutSize = sizeof(afs_int32);
1962 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1965 register afs_int32 code;
1966 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1972 AFS_STATCNT(Prefetch);
1973 if (!apath) return EINVAL;
1974 tp = osi_AllocLargeSpace(1024);
1975 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1977 osi_FreeLargeSpace(tp);
1980 if (afs_BBusy()) { /* do this as late as possible */
1981 osi_FreeLargeSpace(tp);
1982 return EWOULDBLOCK; /* pretty close */
1984 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1985 (afs_size_t) 0, (afs_size_t) 0, tp);
1989 DECL_PIOCTL(PFindVolume)
1991 register struct volume *tvp;
1992 register struct server *ts;
1993 register afs_int32 i;
1996 AFS_STATCNT(PFindVolume);
1997 if (!avc) return EINVAL;
1998 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2001 for(i=0;i<MAXHOSTS;i++) {
2002 ts = tvp->serverHost[i];
2004 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2005 cp += sizeof(afs_int32);
2008 /* still room for terminating NULL, add it on */
2009 ainSize = 0; /* reuse vbl */
2010 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2011 cp += sizeof(afs_int32);
2013 *aoutSize = cp - aout;
2014 afs_PutVolume(tvp, READ_LOCK);
2020 DECL_PIOCTL(PViceAccess)
2022 register afs_int32 code;
2025 AFS_STATCNT(PViceAccess);
2026 if (!avc) return EINVAL;
2027 code = afs_VerifyVCache(avc, areq);
2028 if (code) return code;
2029 memcpy((char *)&temp, ain, sizeof(afs_int32));
2030 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2035 DECL_PIOCTL(PSetCacheSize)
2040 AFS_STATCNT(PSetCacheSize);
2041 if (!afs_osi_suser(*acred))
2043 /* too many things are setup initially in mem cache version */
2044 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2045 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2046 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2048 if (newValue < afs_min_cache)
2049 afs_cacheBlocks = afs_min_cache;
2051 afs_cacheBlocks = newValue;
2053 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2054 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2055 afs_MaybeWakeupTruncateDaemon();
2056 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2057 afs_osi_Wait(1000, 0, 0);
2058 afs_MaybeWakeupTruncateDaemon();
2063 #define MAXGCSTATS 16
2064 DECL_PIOCTL(PGetCacheSize)
2066 afs_int32 results[MAXGCSTATS];
2068 AFS_STATCNT(PGetCacheSize);
2069 memset((char *)results, 0, sizeof(results));
2070 results[0] = afs_cacheBlocks;
2071 results[1] = afs_blocksUsed;
2072 memcpy(aout, (char *)results, sizeof(results));
2073 *aoutSize = sizeof(results);
2077 DECL_PIOCTL(PRemoveCallBack)
2079 register struct conn *tc;
2080 register afs_int32 code;
2081 struct AFSCallBack CallBacks_Array[1];
2082 struct AFSCBFids theFids;
2083 struct AFSCBs theCBs;
2086 AFS_STATCNT(PRemoveCallBack);
2087 if (!avc) return EINVAL;
2088 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2089 ObtainWriteLock(&avc->lock,229);
2090 theFids.AFSCBFids_len = 1;
2091 theCBs.AFSCBs_len = 1;
2092 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2093 theCBs.AFSCBs_val = CallBacks_Array;
2094 CallBacks_Array[0].CallBackType = CB_DROPPED;
2095 if (avc->callback) {
2097 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2099 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2101 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2105 /* don't set code on failure since we wouldn't use it */
2107 (afs_Analyze(tc, code, &avc->fid, areq,
2108 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2109 SHARED_LOCK, NULL));
2111 ObtainWriteLock(&afs_xcbhash, 457);
2112 afs_DequeueCallback(avc);
2114 avc->states &= ~(CStatd | CUnique);
2115 ReleaseWriteLock(&afs_xcbhash);
2116 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2117 osi_dnlc_purgedp(avc);
2119 ReleaseWriteLock(&avc->lock);
2123 DECL_PIOCTL(PNewCell)
2125 /* create a new cell */
2126 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2127 register struct cell *tcell;
2128 char *newcell=0, *linkedcell=0, *tp= ain;
2129 register afs_int32 code, linkedstate=0, ls;
2130 u_short fsport = 0, vlport = 0;
2133 AFS_STATCNT(PNewCell);
2134 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2135 return EIO; /* Inappropriate ioctl for device */
2137 if (!afs_osi_suser(*acred))
2140 memcpy((char *)&magic, tp, sizeof(afs_int32));
2141 tp += sizeof(afs_int32);
2142 if (magic != 0x12345678)
2145 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2146 * server addresses while the 3.5 fs newcell command passes
2147 * MAXHOSTS. To figure out which is which, check if the cellname
2150 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2151 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2153 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2154 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2155 tp += (scount * sizeof(afs_int32));
2157 lp = (afs_int32 *)tp;
2160 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2161 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2162 tp += (3 * sizeof(afs_int32));
2164 if ((ls = *lp) & 1) {
2165 linkedcell = tp + strlen(newcell)+1;
2166 linkedstate |= CLinkedCell;
2169 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2170 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2175 DECL_PIOCTL(PNewAlias)
2177 /* create a new cell alias */
2179 register afs_int32 code;
2180 char *realName, *aliasName;
2182 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2183 return EIO; /* Inappropriate ioctl for device */
2185 if (!afs_osi_suser(*acred))
2189 tp += strlen(aliasName) + 1;
2192 code = afs_NewCellAlias(aliasName, realName);
2197 DECL_PIOCTL(PListCells)
2199 afs_int32 whichCell;
2200 register struct cell *tcell=0;
2201 register afs_int32 i;
2202 register char *cp, *tp = ain;
2204 AFS_STATCNT(PListCells);
2205 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2206 return EIO; /* Inappropriate ioctl for device */
2208 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2209 tp += sizeof(afs_int32);
2210 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2213 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2214 for(i=0;i<MAXCELLHOSTS;i++) {
2215 if (tcell->cellHosts[i] == 0) break;
2216 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2217 cp += sizeof(afs_int32);
2219 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2220 strcpy(cp, tcell->cellName);
2221 cp += strlen(tcell->cellName)+1;
2222 *aoutSize = cp - aout;
2223 afs_PutCell(tcell, READ_LOCK);
2225 if (tcell) return 0;
2229 DECL_PIOCTL(PListAliases)
2231 afs_int32 whichAlias;
2232 register struct cell_alias *tcalias=0;
2233 register char *cp, *tp = ain;
2235 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2236 return EIO; /* Inappropriate ioctl for device */
2237 if (ainSize < sizeof(afs_int32))
2240 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2241 tp += sizeof(afs_int32);
2243 tcalias = afs_GetCellAlias(whichAlias);
2246 strcpy(cp, tcalias->alias);
2247 cp += strlen(tcalias->alias)+1;
2248 strcpy(cp, tcalias->cell);
2249 cp += strlen(tcalias->cell)+1;
2250 *aoutSize = cp - aout;
2251 afs_PutCellAlias(tcalias);
2253 if (tcalias) return 0;
2257 DECL_PIOCTL(PRemoveMount)
2259 register afs_int32 code;
2261 struct sysname_info sysState;
2262 afs_size_t offset, len;
2263 register struct conn *tc;
2264 register struct dcache *tdc;
2265 register struct vcache *tvc;
2266 struct AFSFetchStatus OutDirStatus;
2267 struct VenusFid tfid;
2268 struct AFSVolSync tsync;
2272 /* "ain" is the name of the file in this dir to remove */
2274 AFS_STATCNT(PRemoveMount);
2275 if (!avc) return EINVAL;
2276 code = afs_VerifyVCache(avc, areq);
2277 if (code) return code;
2278 if (vType(avc) != VDIR) return ENOTDIR;
2280 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2281 if (!tdc) return ENOENT;
2282 Check_AtSys(avc, ain, &sysState, areq);
2283 ObtainReadLock(&tdc->lock);
2285 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2286 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2287 ReleaseReadLock(&tdc->lock);
2288 bufp = sysState.name;
2293 tfid.Cell = avc->fid.Cell;
2294 tfid.Fid.Volume = avc->fid.Fid.Volume;
2295 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2296 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2298 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2305 if (tvc->mvstat != 1) {
2311 ObtainWriteLock(&tvc->lock,230);
2312 code = afs_HandleLink(tvc, areq);
2314 if (tvc->linkData) {
2315 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2320 ReleaseWriteLock(&tvc->lock);
2321 osi_dnlc_purgedp(tvc);
2327 ObtainWriteLock(&avc->lock,231);
2328 osi_dnlc_remove(avc, bufp, tvc);
2330 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2332 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2334 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2335 bufp, &OutDirStatus, &tsync);
2341 (afs_Analyze(tc, code, &avc->fid, areq,
2342 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2343 SHARED_LOCK, NULL));
2346 if (tdc) afs_PutDCache(tdc);
2347 ReleaseWriteLock(&avc->lock);
2351 /* we have the thing in the cache */
2352 ObtainWriteLock(&tdc->lock, 661);
2353 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2354 /* we can do it locally */
2355 code = afs_dir_Delete(&tdc->f.inode, bufp);
2357 ZapDCE(tdc); /* surprise error -- invalid value */
2358 DZap(&tdc->f.inode);
2361 ReleaseWriteLock(&tdc->lock);
2362 afs_PutDCache(tdc); /* drop ref count */
2364 avc->states &= ~CUnique; /* For the dfs xlator */
2365 ReleaseWriteLock(&avc->lock);
2368 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2372 DECL_PIOCTL(PVenusLogging)
2374 return EINVAL; /* OBSOLETE */
2377 DECL_PIOCTL(PGetCellStatus)
2379 register struct cell *tcell;
2382 AFS_STATCNT(PGetCellStatus);
2383 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2384 return EIO; /* Inappropriate ioctl for device */
2386 tcell = afs_GetCellByName(ain, READ_LOCK);
2387 if (!tcell) return ENOENT;
2388 temp = tcell->states;
2389 afs_PutCell(tcell, READ_LOCK);
2390 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2391 *aoutSize = sizeof(afs_int32);
2395 DECL_PIOCTL(PSetCellStatus)
2397 register struct cell *tcell;
2400 if (!afs_osi_suser(*acred))
2402 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2403 return EIO; /* Inappropriate ioctl for device */
2405 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2406 if (!tcell) return ENOENT;
2407 memcpy((char *)&temp, ain, sizeof(afs_int32));
2409 tcell->states |= CNoSUID;
2411 tcell->states &= ~CNoSUID;
2412 afs_PutCell(tcell, WRITE_LOCK);
2416 DECL_PIOCTL(PFlushVolumeData)
2418 register afs_int32 i;
2419 register struct dcache *tdc;
2420 register struct vcache *tvc;
2421 register struct volume *tv;
2422 afs_int32 cell, volume;
2424 AFS_STATCNT(PFlushVolumeData);
2427 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2428 return EIO; /* Inappropriate ioctl for device */
2430 volume = avc->fid.Fid.Volume; /* who to zap */
2431 cell = avc->fid.Cell;
2434 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2435 * the vcaches associated with the volume.
2437 ObtainReadLock(&afs_xvcache);
2438 for(i = 0; i < VCSIZE; i++) {
2439 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2440 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2441 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2442 VN_HOLD(AFSTOV(tvc));
2444 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2450 ReleaseReadLock(&afs_xvcache);
2451 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2452 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2454 ObtainWriteLock(&tvc->lock,232);
2456 ObtainWriteLock(&afs_xcbhash, 458);
2457 afs_DequeueCallback(tvc);
2458 tvc->states &= ~(CStatd | CDirty);
2459 ReleaseWriteLock(&afs_xcbhash);
2460 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2461 osi_dnlc_purgedp(tvc);
2462 afs_TryToSmush(tvc, *acred, 1);
2463 ReleaseWriteLock(&tvc->lock);
2464 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2465 afs_BozonUnlock(&tvc->pvnLock, tvc);
2467 ObtainReadLock(&afs_xvcache);
2468 /* our tvc ptr is still good until now */
2473 ReleaseReadLock(&afs_xvcache);
2476 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2477 for(i=0;i<afs_cacheFiles;i++) {
2478 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2479 tdc = afs_GetDSlot(i, NULL);
2480 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2481 ReleaseReadLock(&tdc->tlock);
2482 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2483 if (! (afs_indexFlags[i] & IFDataMod)) {
2484 /* if the file is modified, but has a ref cnt of only 1, then
2485 someone probably has the file open and is writing into it.
2486 Better to skip flushing such a file, it will be brought back
2487 immediately on the next write anyway.
2489 If we *must* flush, then this code has to be rearranged to call
2490 afs_storeAllSegments() first */
2491 afs_FlushDCache(tdc);
2495 ReleaseReadLock(&tdc->tlock);
2497 afs_PutDCache(tdc); /* bumped by getdslot */
2499 MReleaseWriteLock(&afs_xdcache);
2501 ObtainReadLock(&afs_xvolume);
2502 for (i=0;i<NVOLS;i++) {
2503 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2504 if (tv->volume == volume) {
2505 afs_ResetVolumeInfo(tv);
2510 ReleaseReadLock(&afs_xvolume);
2512 /* probably, a user is doing this, probably, because things are screwed up.
2513 * maybe it's the dnlc's fault? */
2520 DECL_PIOCTL(PGetVnodeXStatus)
2522 register afs_int32 code;
2523 struct vcxstat stat;
2526 /* AFS_STATCNT(PGetVnodeXStatus); */
2527 if (!avc) return EINVAL;
2528 code = afs_VerifyVCache(avc, areq);
2529 if (code) return code;
2530 if (vType(avc) == VDIR)
2531 mode = PRSFS_LOOKUP;
2534 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2536 stat.fid = avc->fid;
2537 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2538 stat.lock = avc->lock;
2539 stat.parentVnode = avc->parentVnode;
2540 stat.parentUnique = avc->parentUnique;
2541 hset(stat.flushDV, avc->flushDV);
2542 hset(stat.mapDV, avc->mapDV);
2543 stat.truncPos = avc->truncPos;
2544 { /* just grab the first two - won't break anything... */
2545 struct axscache *ac;
2547 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2548 stat.randomUid[i] = ac->uid;
2549 stat.randomAccess[i] = ac->axess;
2552 stat.callback = afs_data_pointer_to_int32(avc->callback);
2553 stat.cbExpires = avc->cbExpires;
2554 stat.anyAccess = avc->anyAccess;
2555 stat.opens = avc->opens;
2556 stat.execsOrWriters = avc->execsOrWriters;
2557 stat.flockCount = avc->flockCount;
2558 stat.mvstat = avc->mvstat;
2559 stat.states = avc->states;
2560 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2561 *aoutSize = sizeof(struct vcxstat);
2566 /* We require root for local sysname changes, but not for remote */
2567 /* (since we don't really believe remote uids anyway) */
2568 /* outname[] shouldn't really be needed- this is left as an excercise */
2569 /* for the reader. */
2570 DECL_PIOCTL(PSetSysName)
2572 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2573 int setsysname, foundname=0;
2574 register struct afs_exporter *exporter;
2575 register struct unixuser *au;
2576 register afs_int32 pag, error;
2580 AFS_STATCNT(PSetSysName);
2581 if (!afs_globalVFS) {
2582 /* Afsd is NOT running; disable it */
2583 #if defined(KERNEL_HAVE_UERROR)
2584 return (setuerror(EINVAL), EINVAL);
2589 memset(inname, 0, MAXSYSNAME);
2590 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2591 ain += sizeof(afs_int32);
2595 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2597 for(cp = ain,count = 0;count < setsysname;count++) {
2598 /* won't go past end of ain since maxsysname*num < ain length */
2600 if (t >= MAXSYSNAME || t <= 0)
2602 /* check for names that can shoot us in the foot */
2603 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2609 /* inname gets first entry in case we're being a translater */
2611 memcpy(inname, ain, t+1); /* include terminating null */
2614 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2615 pag = PagInCred(*acred);
2617 return EINVAL; /* Better than panicing */
2619 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2620 return EINVAL; /* Better than panicing */
2622 if (!(exporter = au->exporter)) {
2623 afs_PutUser(au, READ_LOCK);
2624 return EINVAL; /* Better than panicing */
2626 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2628 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2630 afs_PutUser(au, READ_LOCK);
2635 afs_PutUser(au, READ_LOCK);
2638 /* Not xlating, so local case */
2639 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2640 if (!setsysname) { /* user just wants the info */
2641 strcpy(outname, afs_sysname);
2642 foundname = afs_sysnamecount;
2643 } else { /* Local guy; only root can change sysname */
2644 if (!afs_osi_suser(*acred))
2647 /* clear @sys entries from the dnlc, once afs_lookup can
2648 do lookups of @sys entries and thinks it can trust them */
2649 /* privs ok, store the entry, ... */
2650 strcpy(afs_sysname, inname);
2651 if (setsysname > 1) { /* ... or list */
2653 for(count=1; count < setsysname;++count) {
2654 if (!afs_sysnamelist[count])
2655 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2657 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2661 afs_sysnamecount = setsysname;
2665 cp = aout; /* not changing so report back the count and ... */
2666 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2667 cp += sizeof(afs_int32);
2669 strcpy(cp, outname); /* ... the entry, ... */
2670 cp += strlen(outname)+1;
2671 for(count=1; count < foundname; ++count) { /* ... or list. */
2672 /* Note: we don't support @sys lists for exporters */
2673 if (!afs_sysnamelist[count])
2674 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2675 t = strlen(afs_sysnamelist[count]);
2676 if (t >= MAXSYSNAME)
2677 osi_Panic("PSetSysName: sysname entry garbled\n");
2678 strcpy(cp, afs_sysnamelist[count]);
2682 *aoutSize = cp - aout;
2687 /* sequential search through the list of touched cells is not a good
2688 * long-term solution here. For small n, though, it should be just
2689 * fine. Should consider special-casing the local cell for large n.
2690 * Likewise for PSetSPrefs.
2692 * s - number of ids in array l[] -- NOT index of last id
2693 * l - array of cell ids which have volumes that need to be sorted
2694 * vlonly - sort vl servers or file servers?
2696 static void *ReSortCells_cb(struct cell *cell, void *arg)
2698 afs_int32 *p = (afs_int32 *) arg;
2699 afs_int32 *l = p + 1;
2702 for (i=0; i<s; i++) {
2703 if (l[i] == cell->cellNum) {
2704 ObtainWriteLock(&cell->lock, 690);
2705 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2706 ReleaseWriteLock(&cell->lock);
2711 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2719 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2721 memcpy(p+1, l, s * sizeof(afs_int32));
2722 afs_TraverseCells(&ReSortCells_cb, p);
2723 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2727 ObtainReadLock(&afs_xvolume);
2728 for (i= 0; i< NVOLS; i++) {
2729 for (j=afs_volumes[i];j;j=j->next) {
2731 if (j->cell == l[k]) {
2732 ObtainWriteLock(&j->lock,233);
2733 afs_SortServers(j->serverHost, MAXHOSTS);
2734 ReleaseWriteLock(&j->lock);
2739 ReleaseReadLock(&afs_xvolume);
2743 static int debugsetsp = 0;
2744 static int afs_setsprefs(sp, num, vlonly)
2747 unsigned int vlonly;
2750 int i,j,k,matches,touchedSize;
2751 struct server *srvr = NULL;
2752 afs_int32 touched[34];
2756 for (k=0; k < num; sp++, k++) {
2758 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2761 ObtainReadLock(&afs_xserver);
2763 i = SHash(sp->host.s_addr);
2764 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2765 if (sa->sa_ip == sp->host.s_addr) {
2767 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2768 || (sa->sa_portal == AFS_FSPORT);
2769 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2776 if (sa && matches) { /* found one! */
2778 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2780 sa->sa_iprank = sp->rank + afs_randomMod15();
2781 afs_SortOneServer(sa->server);
2784 /* if we don't know yet what cell it's in, this is moot */
2785 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2786 /* is it in our list of touched cells ? */ ;
2787 if (j < 0) { /* no, it's not */
2788 touched[touchedSize++] = srvr->cell->cellNum;
2789 if (touchedSize >= 32) { /* watch for ovrflow */
2790 ReleaseReadLock(&afs_xserver);
2791 ReSortCells(touchedSize, touched, vlonly);
2793 ObtainReadLock(&afs_xserver);
2799 ReleaseReadLock(&afs_xserver);
2800 /* if we didn't find one, start to create one. */
2801 /* Note that it doesn't have a cell yet... */
2803 afs_uint32 temp = sp->host.s_addr;
2804 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2805 WRITE_LOCK, (afsUUID *)0,0);
2806 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2807 afs_PutServer(srvr, WRITE_LOCK);
2809 } /* for all cited preferences */
2811 ReSortCells(touchedSize, touched, vlonly);
2815 /* Note that this may only be performed by the local root user.
2817 DECL_PIOCTL(PSetSPrefs)
2819 struct setspref *ssp;
2820 AFS_STATCNT(PSetSPrefs);
2822 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2823 return EIO; /* Inappropriate ioctl for device */
2825 if (!afs_osi_suser(*acred))
2828 if (ainSize < sizeof(struct setspref))
2831 ssp = (struct setspref *)ain;
2832 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2835 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2836 (ssp->flags & DBservers));
2840 DECL_PIOCTL(PSetSPrefs33)
2843 AFS_STATCNT(PSetSPrefs);
2844 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2845 return EIO; /* Inappropriate ioctl for device */
2848 if (!afs_osi_suser(*acred))
2851 sp = (struct spref *)ain;
2852 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2856 /* some notes on the following code...
2857 * in the hash table of server structs, all servers with the same IP address
2858 * will be on the same overflow chain.
2859 * This could be sped slightly in some circumstances by having it cache the
2860 * immediately previous slot in the hash table and some supporting information
2861 * Only reports file servers now.
2863 DECL_PIOCTL(PGetSPrefs)
2865 struct sprefrequest *spin; /* input */
2866 struct sprefinfo *spout; /* output */
2867 struct spref *srvout; /* one output component */
2868 int i,j; /* counters for hash table traversal */
2869 struct server *srvr; /* one of CM's server structs */
2872 int vlonly; /* just return vlservers ? */
2875 AFS_STATCNT(PGetSPrefs);
2876 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2877 return EIO; /* Inappropriate ioctl for device */
2880 if (ainSize < sizeof (struct sprefrequest_33)) {
2884 spin = ((struct sprefrequest *) ain);
2887 if (ainSize > sizeof (struct sprefrequest_33)) {
2888 vlonly = (spin->flags & DBservers);
2892 /* struct sprefinfo includes 1 server struct... that size gets added
2893 * in during the loop that follows.
2895 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2896 spout = (struct sprefinfo *) aout;
2897 spout->next_offset = spin->offset;
2898 spout->num_servers = 0;
2899 srvout = spout->servers;
2901 ObtainReadLock(&afs_xserver);
2902 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2903 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2904 if (spin->offset > (unsigned short)i) {
2905 continue; /* catch up to where we left off */
2907 spout->next_offset++;
2910 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2911 || (sa->sa_portal == AFS_FSPORT);
2913 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2914 /* only report ranks for vl servers */
2918 srvout->host.s_addr = sa->sa_ip;
2919 srvout->rank = sa->sa_iprank;
2920 *aoutSize += sizeof(struct spref);
2921 spout->num_servers++;
2924 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2925 ReleaseReadLock(&afs_xserver); /* no more room! */
2930 ReleaseReadLock(&afs_xserver);
2932 spout->next_offset = 0; /* start over from the beginning next time */
2936 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2937 int afs_NFSRootOnly = 1;
2938 DECL_PIOCTL(PExportAfs)
2940 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2941 register struct afs_exporter *exporter;
2943 AFS_STATCNT(PExportAfs);
2944 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2945 type = handleValue >> 24;
2950 exporter = exporter_find(type);
2952 export = handleValue & 3;
2953 changestate = handleValue & 0xff;
2954 smounts = (handleValue >> 2) & 3;
2955 pwsync = (handleValue >> 4) & 3;
2956 convmode = (handleValue >> 6) & 3;
2958 changestate = (handleValue >> 16) & 0x1;
2959 convmode = (handleValue >> 16) & 0x2;
2960 pwsync = (handleValue >> 16) & 0x4;
2961 smounts = (handleValue >> 16) & 0x8;
2962 export = handleValue & 0xff;
2965 /* Failed finding desired exporter; */
2969 handleValue = exporter->exp_states;
2970 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2971 *aoutSize = sizeof(afs_int32);
2973 if (!afs_osi_suser(*acred))
2974 return EACCES; /* Only superuser can do this */
2978 exporter->exp_states |= EXP_EXPORTED;
2980 exporter->exp_states &= ~EXP_EXPORTED;
2984 exporter->exp_states |= EXP_UNIXMODE;
2986 exporter->exp_states &= ~EXP_UNIXMODE;
2990 exporter->exp_states |= EXP_PWSYNC;
2992 exporter->exp_states &= ~EXP_PWSYNC;
2996 afs_NFSRootOnly = 0;
2997 exporter->exp_states |= EXP_SUBMOUNTS;
2999 afs_NFSRootOnly = 1;
3000 exporter->exp_states &= ~EXP_SUBMOUNTS;
3003 handleValue = exporter->exp_states;
3004 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
3005 *aoutSize = sizeof(afs_int32);
3008 exporter->exp_states |= EXP_EXPORTED;
3010 exporter->exp_states &= ~EXP_EXPORTED;
3012 exporter->exp_states |= EXP_UNIXMODE;
3014 exporter->exp_states &= ~EXP_UNIXMODE;
3016 exporter->exp_states |= EXP_PWSYNC;
3018 exporter->exp_states &= ~EXP_PWSYNC;
3020 afs_NFSRootOnly = 0;
3021 exporter->exp_states |= EXP_SUBMOUNTS;
3023 afs_NFSRootOnly = 1;
3024 exporter->exp_states &= ~EXP_SUBMOUNTS;
3034 struct gaginfo *gagflags;
3036 if (!afs_osi_suser(*acred))
3039 gagflags = (struct gaginfo *) ain;
3040 afs_showflags = gagflags->showflags;
3046 DECL_PIOCTL(PTwiddleRx)
3048 struct rxparams *rxp;
3050 if (!afs_osi_suser(*acred))
3053 rxp = (struct rxparams *) ain;
3055 if (rxp->rx_initReceiveWindow)
3056 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3057 if (rxp->rx_maxReceiveWindow)
3058 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3059 if (rxp->rx_initSendWindow)
3060 rx_initSendWindow = rxp->rx_initSendWindow;
3061 if (rxp->rx_maxSendWindow)
3062 rx_maxSendWindow = rxp->rx_maxSendWindow;
3063 if (rxp->rxi_nSendFrags)
3064 rxi_nSendFrags = rxp->rxi_nSendFrags;
3065 if (rxp->rxi_nRecvFrags)
3066 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3067 if (rxp->rxi_OrphanFragSize)
3068 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3069 if (rxp->rx_maxReceiveSize)
3071 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3072 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3074 if (rxp->rx_MyMaxSendSize)
3075 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3080 DECL_PIOCTL(PGetInitParams)
3082 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3085 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3086 *aoutSize = sizeof(struct cm_initparams);
3090 #ifdef AFS_SGI65_ENV
3091 /* They took crget() from us, so fake it. */
3092 static cred_t *crget(void)
3095 cr = crdup(get_current_cred());
3096 memset((char*)cr, 0, sizeof(cred_t));
3097 #if CELL || CELL_PREPARE
3104 DECL_PIOCTL(PGetRxkcrypt)
3106 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3107 *aoutSize=sizeof(afs_int32);
3111 DECL_PIOCTL(PSetRxkcrypt)
3115 if (!afs_osi_suser(*acred))
3117 if (ainSize != sizeof(afs_int32) || ain == NULL)
3119 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3120 /* if new mappings added later this will need to be changed */
3121 if (tmpval != 0 && tmpval != 1)
3128 * Create new credentials to correspond to a remote user with given
3129 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3130 * provide pioctl (and other) services to foreign clients (i.e. nfs
3131 * clients) by using this call to `become' the client.
3134 #define PIOCTL_HEADER 6
3135 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3137 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3138 return EINVAL; /* NFS trans not supported for Ultrix */
3141 afs_uint32 hostaddr;
3142 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3143 struct afs_exporter *exporter, *outexporter;
3144 struct AFS_UCRED *newcred;
3145 struct unixuser *au;
3147 #if defined(AFS_SGIMP_ENV)
3148 osi_Assert(ISAFS_GLOCK());
3150 AFS_STATCNT(HandleClientContext);
3151 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3152 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3153 return EINVAL; /* Too small to be good */
3155 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3156 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3158 osi_FreeLargeSpace(inData);
3162 /* Extract information for remote user */
3163 hostaddr = *((afs_uint32 *)ain);
3164 ain += sizeof(hostaddr);
3165 uid = *((afs_uint32 *)ain);
3167 g0 = *((afs_uint32 *)ain);
3169 g1 = *((afs_uint32 *)ain);
3171 *com = *((afs_uint32 *)ain);
3172 ain += sizeof(afs_int32);
3173 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3176 * Of course, one must be root for most of these functions, but
3177 * we'll allow (for knfs) you to set things if the pag is 0 and
3178 * you're setting tokens or unlogging.
3181 if (!afs_osi_suser(credp)) {
3183 #ifndef AFS_SGI64_ENV
3184 /* Since SGI's suser() returns explicit failure after the call.. */
3188 /* check for acceptable opcodes for normal folks, which are, so far,
3189 * set tokens and unlog.
3191 if (i != 9 && i != 3 && i != 38 && i != 8) {
3192 osi_FreeLargeSpace(inData);
3197 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3198 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3199 osi_FreeLargeSpace(inData);
3202 * We map uid 0 to nobody to match the mapping that the nfs
3203 * server does and to ensure that the suser() calls in the afs
3204 * code fails for remote client roots.
3206 uid = afs_nobody; /* NFS_NOBODY == -2 */
3209 #ifdef AFS_AIX41_ENV
3212 newcred->cr_gid = RMTUSER_REQ;
3213 #ifdef AFS_AIX51_ENV
3214 newcred->cr_groupset.gs_union.un_groups[0] = g0;
3215 newcred->cr_groupset.gs_union.un_groups[1] = g1;
3217 newcred->cr_groups[0] = g0;
3218 newcred->cr_groups[1] = g1;
3221 newcred->cr_ngrps = 2;
3223 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3224 newcred->cr_ngroups = 2;
3226 for (i=2; i<NGROUPS; i++)
3227 newcred->cr_groups[i] = NOGROUP;
3230 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3231 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3233 if (!(exporter = exporter_find(exporter_type))) {
3234 /* Exporter wasn't initialized or an invalid exporter type */
3238 if (exporter->exp_states & EXP_PWSYNC) {
3239 if (uid != credp->cr_uid) {
3241 return ENOEXEC; /* XXX Find a better errno XXX */
3244 newcred->cr_uid = uid; /* Only temporary */
3245 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3246 /* The client's pag is the only unique identifier for it */
3247 newcred->cr_uid = pag;
3249 if (!code && *com == PSETPAG) {
3250 /* Special case for 'setpag' */
3251 afs_uint32 pagvalue = genpag();
3253 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3255 * Note that we leave the 'outexporter' struct held so it won't
3258 au->exporter = outexporter;
3259 if (ablob->out_size >= 4) {
3260 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3262 afs_PutUser(au, WRITE_LOCK);
3263 if (code) return code;
3264 return PSETPAG; /* Special return for setpag */
3266 EXP_RELE(outexporter);
3269 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3272 /* get all interface addresses of this client */
3274 DECL_PIOCTL(PGetCPrefs)
3276 struct sprefrequest *spin; /* input */
3277 struct sprefinfo *spout; /* output */
3278 struct spref *srvout; /* one output component */
3282 AFS_STATCNT(PGetCPrefs);
3283 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3284 return EIO; /* Inappropriate ioctl for device */
3286 if ( ainSize < sizeof (struct sprefrequest ))
3289 spin = (struct sprefrequest *) ain;
3290 spout = (struct sprefinfo *) aout;
3292 maxNumber = spin->num_servers; /* max addrs this time */
3293 srvout = spout->servers;
3295 ObtainReadLock(&afs_xinterface);
3297 /* copy out the client interface information from the
3298 ** kernel data structure "interface" to the output buffer
3300 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3301 && ( j< maxNumber) ; i++, j++, srvout++)
3302 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3304 spout->num_servers = j;
3305 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3307 if ( i >= afs_cb_interface.numberOfInterfaces )
3308 spout->next_offset = 0; /* start from beginning again */
3310 spout->next_offset = spin->offset + j;
3312 ReleaseReadLock(&afs_xinterface);
3316 DECL_PIOCTL(PSetCPrefs)
3318 struct setspref *sin;
3321 AFS_STATCNT(PSetCPrefs);
3322 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3323 return EIO; /* Inappropriate ioctl for device */
3325 sin = (struct setspref *)ain;
3327 if ( ainSize < sizeof(struct setspref) )
3329 #if 0 /* num_servers is unsigned */
3330 if ( sin->num_servers < 0 )
3333 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3336 ObtainWriteLock(&afs_xinterface, 412);
3337 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3338 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3339 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3341 ReleaseWriteLock(&afs_xinterface);
3345 DECL_PIOCTL(PFlushMount)
3347 register afs_int32 code;
3348 register struct vcache *tvc;
3349 register struct dcache *tdc;
3350 struct VenusFid tfid;
3352 struct sysname_info sysState;
3353 afs_size_t offset, len;
3355 AFS_STATCNT(PFlushMount);
3356 if (!avc) return EINVAL;
3357 code = afs_VerifyVCache(avc, areq);
3358 if (code) return code;
3359 if (vType(avc) != VDIR) {
3362 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3363 if (!tdc) return ENOENT;
3364 Check_AtSys(avc, ain, &sysState, areq);
3365 ObtainReadLock(&tdc->lock);
3367 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3368 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3369 ReleaseReadLock(&tdc->lock);
3370 afs_PutDCache(tdc); /* we're done with the data */
3371 bufp = sysState.name;
3375 tfid.Cell = avc->fid.Cell;
3376 tfid.Fid.Volume = avc->fid.Fid.Volume;
3377 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3378 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3380 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3386 if (tvc->mvstat != 1) {
3391 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3392 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3394 ObtainWriteLock(&tvc->lock,649);
3395 ObtainWriteLock(&afs_xcbhash, 650);
3396 afs_DequeueCallback(tvc);
3397 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3398 ReleaseWriteLock(&afs_xcbhash);
3399 /* now find the disk cache entries */
3400 afs_TryToSmush(tvc, *acred, 1);
3401 osi_dnlc_purgedp(tvc);
3402 afs_symhint_inval(tvc);
3403 if (tvc->linkData && !(tvc->states & CCore)) {
3404 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3405 tvc->linkData = NULL;
3407 ReleaseWriteLock(&tvc->lock);
3408 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3409 afs_BozonUnlock(&tvc->pvnLock, tvc);
3413 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3417 DECL_PIOCTL(PRxStatProc)
3422 if (!afs_osi_suser(*acred)) {
3426 if (ainSize != sizeof(afs_int32)) {
3430 memcpy((char *)&flags, ain, sizeof(afs_int32));
3431 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3435 if (flags & AFSCALL_RXSTATS_ENABLE) {
3436 rx_enableProcessRPCStats();
3438 if (flags & AFSCALL_RXSTATS_DISABLE) {
3439 rx_disableProcessRPCStats();
3441 if (flags & AFSCALL_RXSTATS_CLEAR) {
3442 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3450 DECL_PIOCTL(PRxStatPeer)
3455 if (!afs_osi_suser(*acred)) {
3459 if (ainSize != sizeof(afs_int32)) {
3463 memcpy((char *)&flags, ain, sizeof(afs_int32));
3464 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3468 if (flags & AFSCALL_RXSTATS_ENABLE) {
3469 rx_enablePeerRPCStats();
3471 if (flags & AFSCALL_RXSTATS_DISABLE) {
3472 rx_disablePeerRPCStats();
3474 if (flags & AFSCALL_RXSTATS_CLEAR) {
3475 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3482 DECL_PIOCTL(PPrefetchFromTape)
3484 register afs_int32 code, code1;
3487 struct rx_call *tcall;
3488 struct AFSVolSync tsync;
3489 struct AFSFetchStatus OutStatus;
3490 struct AFSCallBack CallBack;
3491 struct VenusFid tfid;
3496 AFS_STATCNT(PSetAcl);
3500 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3501 Fid = (struct AFSFid *) ain;
3503 Fid = &avc->fid.Fid;
3504 tfid.Cell = avc->fid.Cell;
3505 tfid.Fid.Volume = Fid->Volume;
3506 tfid.Fid.Vnode = Fid->Vnode;
3507 tfid.Fid.Unique = Fid->Unique;
3509 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3511 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3512 ICL_TYPE_POINTER, tvc,
3513 ICL_TYPE_FID, &tfid,
3514 ICL_TYPE_FID, &avc->fid);
3517 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3518 ICL_TYPE_POINTER, tvc,
3519 ICL_TYPE_FID, &tfid,
3520 ICL_TYPE_FID, &tvc->fid);
3523 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3527 tcall = rx_NewCall(tc->id);
3528 code = StartRXAFS_FetchData(tcall,
3529 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3531 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3532 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3534 code1 = rx_EndCall(tcall, code);
3539 (afs_Analyze(tc, code, &tvc->fid, areq,
3540 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3542 /* This call is done only to have the callback things handled correctly */
3543 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3547 *aoutSize = sizeof(afs_int32);
3552 DECL_PIOCTL(PResidencyCmd)
3554 register afs_int32 code;
3557 struct ResidencyCmdInputs *Inputs;
3558 struct ResidencyCmdOutputs *Outputs;
3559 struct VenusFid tfid;
3562 Inputs = (struct ResidencyCmdInputs *) ain;
3563 Outputs = (struct ResidencyCmdOutputs *) aout;
3564 if (!avc) return EINVAL;
3565 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3569 Fid = &avc->fid.Fid;
3571 tfid.Cell = avc->fid.Cell;
3572 tfid.Fid.Volume = Fid->Volume;
3573 tfid.Fid.Vnode = Fid->Vnode;
3574 tfid.Fid.Unique = Fid->Unique;
3576 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3577 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3578 ICL_TYPE_POINTER, tvc,
3579 ICL_TYPE_INT32, Inputs->command,
3580 ICL_TYPE_FID, &tfid);
3584 if (Inputs->command) {
3586 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3589 code = RXAFS_ResidencyCmd(tc->id, Fid,
3591 (struct ResidencyCmdOutputs *) aout);
3596 (afs_Analyze(tc, code, &tvc->fid, areq,
3597 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3599 /* This call is done to have the callback things handled correctly */
3600 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3601 } else { /* just a status request, return also link data */
3603 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3604 Outputs->chars[0] = 0;
3605 if (vType(tvc) == VLNK) {
3606 ObtainWriteLock(&tvc->lock,555);
3607 if (afs_HandleLink(tvc, areq) == 0)
3608 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3609 ReleaseWriteLock(&tvc->lock);
3616 *aoutSize = sizeof(struct ResidencyCmdOutputs);