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)) {
519 if (!fd) return(EBADF);
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 AFS_STATCNT(PGetFID);
1130 if (!avc) return EINVAL;
1131 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1132 *aoutSize = sizeof(struct VenusFid);
1136 DECL_PIOCTL(PSetAcl)
1138 register afs_int32 code;
1140 struct AFSOpaque acl;
1141 struct AFSVolSync tsync;
1142 struct AFSFetchStatus OutStatus;
1145 AFS_STATCNT(PSetAcl);
1148 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1151 acl.AFSOpaque_val = ain;
1153 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1155 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1157 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1158 &acl, &OutStatus, &tsync);
1164 (afs_Analyze(tconn, code, &avc->fid, areq,
1165 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1167 /* now we've forgotten all of the access info */
1168 ObtainWriteLock(&afs_xcbhash, 455);
1170 afs_DequeueCallback(avc);
1171 avc->states &= ~(CStatd | CUnique);
1172 ReleaseWriteLock(&afs_xcbhash);
1173 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1174 osi_dnlc_purgedp(avc);
1178 int afs_defaultAsynchrony = 0;
1180 DECL_PIOCTL(PStoreBehind)
1183 struct sbstruct *sbr;
1185 sbr = (struct sbstruct *)ain;
1186 if (sbr->sb_default != -1) {
1187 if (afs_osi_suser(*acred))
1188 afs_defaultAsynchrony = sbr->sb_default;
1192 if (avc && (sbr->sb_thisfile != -1)) {
1193 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1194 areq, DONT_CHECK_MODE_BITS))
1195 avc->asynchrony = sbr->sb_thisfile;
1199 *aoutSize = sizeof(struct sbstruct);
1200 sbr = (struct sbstruct *)aout;
1201 sbr->sb_default = afs_defaultAsynchrony;
1203 sbr->sb_thisfile = avc->asynchrony;
1209 DECL_PIOCTL(PGCPAGs)
1211 if (!afs_osi_suser(*acred)) {
1214 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1218 DECL_PIOCTL(PGetAcl)
1220 struct AFSOpaque acl;
1221 struct AFSVolSync tsync;
1222 struct AFSFetchStatus OutStatus;
1228 AFS_STATCNT(PGetAcl);
1229 if (!avc) return EINVAL;
1230 Fid.Volume = avc->fid.Fid.Volume;
1231 Fid.Vnode = avc->fid.Fid.Vnode;
1232 Fid.Unique = avc->fid.Fid.Unique;
1233 if (avc->states & CForeign) {
1235 * For a dfs xlator acl we have a special hack so that the
1236 * xlator will distinguish which type of acl will return. So
1237 * we currently use the top 2-bytes (vals 0-4) to tell which
1238 * type of acl to bring back. Horrible hack but this will
1239 * cause the least number of changes to code size and interfaces.
1241 if (Fid.Vnode & 0xc0000000)
1243 Fid.Vnode |= (ainSize << 30);
1245 acl.AFSOpaque_val = aout;
1247 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1250 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1252 code = RXAFS_FetchACL(tconn->id, &Fid,
1253 &acl, &OutStatus, &tsync);
1259 (afs_Analyze(tconn, code, &avc->fid, areq,
1260 AFS_STATS_FS_RPCIDX_FETCHACL,
1261 SHARED_LOCK, NULL));
1264 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1277 AFS_STATCNT(PBogus);
1281 DECL_PIOCTL(PGetFileCell)
1283 register struct cell *tcell;
1285 AFS_STATCNT(PGetFileCell);
1286 if (!avc) return EINVAL;
1287 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1288 if (!tcell) return ESRCH;
1289 strcpy(aout, tcell->cellName);
1290 afs_PutCell(tcell, READ_LOCK);
1291 *aoutSize = strlen(aout) + 1;
1295 DECL_PIOCTL(PGetWSCell)
1297 struct cell *tcell = NULL;
1299 AFS_STATCNT(PGetWSCell);
1300 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1301 return EIO; /* Inappropriate ioctl for device */
1303 tcell = afs_GetPrimaryCell(READ_LOCK);
1304 if (!tcell) /* no primary cell? */
1306 strcpy(aout, tcell->cellName);
1307 *aoutSize = strlen(aout) + 1;
1308 afs_PutCell(tcell, READ_LOCK);
1312 DECL_PIOCTL(PGetUserCell)
1314 register afs_int32 i;
1315 register struct unixuser *tu;
1316 register struct cell *tcell;
1318 AFS_STATCNT(PGetUserCell);
1319 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1320 return EIO; /* Inappropriate ioctl for device */
1322 /* return the cell name of the primary cell for this user */
1323 i = UHash(areq->uid);
1324 ObtainWriteLock(&afs_xuser,224);
1325 for(tu = afs_users[i]; tu; tu = tu->next) {
1326 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1328 ReleaseWriteLock(&afs_xuser);
1333 tcell = afs_GetCell(tu->cell, READ_LOCK);
1334 afs_PutUser(tu, WRITE_LOCK);
1335 if (!tcell) return ESRCH;
1337 strcpy(aout, tcell->cellName);
1338 afs_PutCell(tcell, READ_LOCK);
1339 *aoutSize = strlen(aout)+1; /* 1 for the null */
1343 ReleaseWriteLock(&afs_xuser);
1350 DECL_PIOCTL(PSetTokens)
1353 register struct unixuser *tu;
1354 struct ClearToken clear;
1355 register struct cell *tcell;
1358 struct vrequest treq;
1359 afs_int32 flag, set_parent_pag = 0;
1361 AFS_STATCNT(PSetTokens);
1362 if (!afs_resourceinit_flag) {
1365 memcpy((char *)&i, ain, sizeof(afs_int32));
1366 ain += sizeof(afs_int32);
1367 stp = ain; /* remember where the ticket is */
1368 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1369 if (i > MAXKTCTICKETLEN) return EINVAL;
1371 ain += i; /* skip over ticket */
1372 memcpy((char *)&i, ain, sizeof(afs_int32));
1373 ain += sizeof(afs_int32);
1374 if (i != sizeof(struct ClearToken)) {
1377 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1378 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1379 ain += sizeof(struct ClearToken);
1380 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1381 /* still stuff left? we've got primary flag and cell name. Set these */
1382 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1383 ain += sizeof(afs_int32); /* skip id field */
1384 /* rest is cell name, look it up */
1385 /* some versions of gcc appear to need != 0 in order to get this right */
1386 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1390 tcell = afs_GetCellByName(ain, READ_LOCK);
1391 if (!tcell) goto nocell;
1394 /* default to primary cell, primary id */
1395 flag = 1; /* primary id */
1396 tcell = afs_GetPrimaryCell(READ_LOCK);
1397 if (!tcell) goto nocell;
1400 afs_PutCell(tcell, READ_LOCK);
1401 if (set_parent_pag) {
1403 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1404 #if defined(AFS_DARWIN_ENV)
1405 struct proc *p = current_proc(); /* XXX */
1407 struct proc *p = curproc; /* XXX */
1409 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1410 p->p_pid, p->p_comm);
1411 if (!setpag(p, acred, -1, &pag, 1)) {
1414 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1416 if (!setpag(acred, -1, &pag, 1)) {
1419 afs_InitReq(&treq, *acred);
1423 /* now we just set the tokens */
1424 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1425 tu->vid = clear.ViceId;
1426 if (tu->stp != NULL) {
1427 afs_osi_Free(tu->stp, tu->stLen);
1429 tu->stp = (char *) afs_osi_Alloc(stLen);
1431 memcpy(tu->stp, stp, stLen);
1434 afs_stats_cmfullperf.authent.TicketUpdates++;
1435 afs_ComputePAGStats();
1436 #endif /* AFS_NOSTATS */
1437 tu->states |= UHasTokens;
1438 tu->states &= ~UTokensBad;
1439 afs_SetPrimary(tu, flag);
1440 tu->tokenTime =osi_Time();
1441 afs_ResetUserConns(tu);
1442 afs_PutUser(tu, WRITE_LOCK);
1457 DECL_PIOCTL(PGetVolumeStatus)
1460 char offLineMsg[256];
1462 register struct conn *tc;
1463 register afs_int32 code;
1464 struct VolumeStatus volstat;
1466 char *Name, *OfflineMsg, *MOTD;
1469 AFS_STATCNT(PGetVolumeStatus);
1470 if (!avc) return EINVAL;
1472 OfflineMsg = offLineMsg;
1475 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1477 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1479 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1480 &Name, &OfflineMsg, &MOTD);
1486 (afs_Analyze(tc, code, &avc->fid, areq,
1487 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1488 SHARED_LOCK, NULL));
1490 if (code) return code;
1491 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1493 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1494 cp += sizeof(VolumeStatus);
1495 strcpy(cp, volName);
1496 cp += strlen(volName)+1;
1497 strcpy(cp, offLineMsg);
1498 cp += strlen(offLineMsg)+1;
1500 cp += strlen(motd)+1;
1501 *aoutSize = (cp - aout);
1505 DECL_PIOCTL(PSetVolumeStatus)
1508 char offLineMsg[256];
1510 register struct conn *tc;
1511 register afs_int32 code;
1512 struct AFSFetchVolumeStatus volstat;
1513 struct AFSStoreVolumeStatus storeStat;
1514 register struct volume *tvp;
1518 AFS_STATCNT(PSetVolumeStatus);
1519 if (!avc) return EINVAL;
1521 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1523 if (tvp->states & (VRO | VBackup)) {
1524 afs_PutVolume(tvp, READ_LOCK);
1527 afs_PutVolume(tvp, READ_LOCK);
1530 /* Copy the junk out, using cp as a roving pointer. */
1532 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1533 cp += sizeof(AFSFetchVolumeStatus);
1534 if (strlen(cp) >= sizeof(volName))
1536 strcpy(volName, cp);
1537 cp += strlen(volName)+1;
1538 if (strlen(cp) >= sizeof(offLineMsg))
1540 strcpy(offLineMsg, cp);
1541 cp += strlen(offLineMsg)+1;
1542 if (strlen(cp) >= sizeof(motd))
1546 if (volstat.MinQuota != -1) {
1547 storeStat.MinQuota = volstat.MinQuota;
1548 storeStat.Mask |= AFS_SETMINQUOTA;
1550 if (volstat.MaxQuota != -1) {
1551 storeStat.MaxQuota = volstat.MaxQuota;
1552 storeStat.Mask |= AFS_SETMAXQUOTA;
1555 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1557 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1559 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1560 &storeStat, volName, offLineMsg, motd);
1566 (afs_Analyze(tc, code, &avc->fid, areq,
1567 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1568 SHARED_LOCK, NULL));
1570 if (code) return code;
1571 /* we are sending parms back to make compat. with prev system. should
1572 change interface later to not ask for current status, just set new status */
1574 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1575 cp += sizeof(VolumeStatus);
1576 strcpy(cp, volName);
1577 cp += strlen(volName)+1;
1578 strcpy(cp, offLineMsg);
1579 cp += strlen(offLineMsg)+1;
1581 cp += strlen(motd)+1;
1582 *aoutSize = cp - aout;
1588 AFS_STATCNT(PFlush);
1589 if (!avc) return EINVAL;
1590 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1591 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1593 ObtainWriteLock(&avc->lock,225);
1594 ObtainWriteLock(&afs_xcbhash, 456);
1595 afs_DequeueCallback(avc);
1596 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1597 ReleaseWriteLock(&afs_xcbhash);
1598 /* now find the disk cache entries */
1599 afs_TryToSmush(avc, *acred, 1);
1600 osi_dnlc_purgedp(avc);
1601 afs_symhint_inval(avc);
1602 if (avc->linkData && !(avc->states & CCore)) {
1603 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1604 avc->linkData = NULL;
1606 ReleaseWriteLock(&avc->lock);
1607 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1608 afs_BozonUnlock(&avc->pvnLock, avc);
1613 DECL_PIOCTL(PNewStatMount)
1615 register afs_int32 code;
1616 register struct vcache *tvc;
1617 register struct dcache *tdc;
1618 struct VenusFid tfid;
1620 struct sysname_info sysState;
1621 afs_size_t offset, len;
1623 AFS_STATCNT(PNewStatMount);
1624 if (!avc) return EINVAL;
1625 code = afs_VerifyVCache(avc, areq);
1626 if (code) return code;
1627 if (vType(avc) != VDIR) {
1630 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1631 if (!tdc) return ENOENT;
1632 Check_AtSys(avc, ain, &sysState, areq);
1633 ObtainReadLock(&tdc->lock);
1635 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1636 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1637 ReleaseReadLock(&tdc->lock);
1638 afs_PutDCache(tdc); /* we're done with the data */
1639 bufp = sysState.name;
1643 tfid.Cell = avc->fid.Cell;
1644 tfid.Fid.Volume = avc->fid.Fid.Volume;
1645 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1646 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1648 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1654 if (tvc->mvstat != 1) {
1659 ObtainWriteLock(&tvc->lock,226);
1660 code = afs_HandleLink(tvc, areq);
1662 if (tvc->linkData) {
1663 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1666 /* we have the data */
1667 strcpy(aout, tvc->linkData);
1668 *aoutSize = strlen(tvc->linkData)+1;
1673 ReleaseWriteLock(&tvc->lock);
1676 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1680 DECL_PIOCTL(PGetTokens)
1682 register struct cell *tcell;
1683 register afs_int32 i;
1684 register struct unixuser *tu;
1689 AFS_STATCNT(PGetTokens);
1690 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1691 return EIO; /* Inappropriate ioctl for device */
1693 /* weird interface. If input parameter is present, it is an integer and
1694 we're supposed to return the parm'th tokens for this unix uid.
1695 If not present, we just return tokens for cell 1.
1696 If counter out of bounds, return EDOM.
1697 If no tokens for the particular cell, return ENOTCONN.
1698 Also, if this mysterious parm is present, we return, along with the
1699 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1700 at the end, in that order.
1702 if ((newStyle = (ainSize > 0))) {
1703 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1705 i = UHash(areq->uid);
1706 ObtainReadLock(&afs_xuser);
1707 for(tu = afs_users[i]; tu; tu=tu->next) {
1709 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1710 if (iterator-- == 0) break; /* are we done yet? */
1714 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1719 * No need to hold a read lock on each user entry
1723 ReleaseReadLock(&afs_xuser);
1728 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1729 tu->states |= (UTokensBad | UNeedsReset);
1730 afs_PutUser(tu, READ_LOCK);
1733 /* use iterator for temp */
1735 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1736 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1737 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1738 cp += sizeof(afs_int32);
1739 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1741 iterator = sizeof(struct ClearToken);
1742 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1743 cp += sizeof(afs_int32);
1744 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1745 cp += sizeof(struct ClearToken);
1747 /* put out primary id and cell name, too */
1748 iterator = (tu->states & UPrimary ? 1 : 0);
1749 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1750 cp += sizeof(afs_int32);
1751 tcell = afs_GetCell(tu->cell, READ_LOCK);
1753 strcpy(cp, tcell->cellName);
1754 cp += strlen(tcell->cellName)+1;
1755 afs_PutCell(tcell, READ_LOCK);
1759 *aoutSize = cp - aout;
1760 afs_PutUser(tu, READ_LOCK);
1766 register afs_int32 i;
1767 register struct unixuser *tu;
1769 AFS_STATCNT(PUnlog);
1770 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1771 return EIO; /* Inappropriate ioctl for device */
1773 i = UHash(areq->uid);
1774 ObtainWriteLock(&afs_xuser,227);
1775 for(tu=afs_users[i]; tu; tu=tu->next) {
1776 if (tu->uid == areq->uid) {
1778 tu->states &= ~UHasTokens;
1779 /* security is not having to say you're sorry */
1780 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1782 ReleaseWriteLock(&afs_xuser);
1783 /* We have to drop the lock over the call to afs_ResetUserConns, since
1784 * it obtains the afs_xvcache lock. We could also keep the lock, and
1785 * modify ResetUserConns to take parm saying we obtained the lock
1786 * already, but that is overkill. By keeping the "tu" pointer
1787 * held over the released lock, we guarantee that we won't lose our
1788 * place, and that we'll pass over every user conn that existed when
1789 * we began this call.
1791 afs_ResetUserConns(tu);
1793 ObtainWriteLock(&afs_xuser,228);
1795 /* set the expire times to 0, causes
1796 * afs_GCUserData to remove this entry
1798 tu->ct.EndTimestamp = 0;
1800 #endif /* UKERNEL */
1803 ReleaseWriteLock(&afs_xuser);
1807 DECL_PIOCTL(PMariner)
1809 afs_int32 newHostAddr;
1810 afs_int32 oldHostAddr;
1812 AFS_STATCNT(PMariner);
1814 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1816 oldHostAddr = 0xffffffff; /* disabled */
1818 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1819 if (newHostAddr == 0xffffffff) {
1820 /* disable mariner operations */
1823 else if (newHostAddr) {
1825 afs_marinerHost = newHostAddr;
1827 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1828 *aoutSize = sizeof(afs_int32);
1832 DECL_PIOCTL(PCheckServers)
1834 register char *cp = 0;
1836 register struct server *ts;
1837 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1839 struct chservinfo *pcheck;
1841 AFS_STATCNT(PCheckServers);
1843 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1844 return EIO; /* Inappropriate ioctl for device */
1846 if (*lp == 0x12345678) { /* For afs3.3 version */
1847 pcheck=(struct chservinfo *)ain;
1848 if (pcheck->tinterval >= 0) {
1850 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1851 *aoutSize = sizeof(afs_int32);
1852 if (pcheck->tinterval > 0) {
1853 if (!afs_osi_suser(*acred))
1855 PROBE_INTERVAL=pcheck->tinterval;
1861 temp=pcheck->tflags;
1862 cp = pcheck->tbuffer;
1863 } else { /* For pre afs3.3 versions */
1864 memcpy((char *)&temp, ain, sizeof(afs_int32));
1865 cp = ain+sizeof(afs_int32);
1866 if (ainSize > sizeof(afs_int32))
1871 * 1: fast check, don't contact servers.
1872 * 2: local cell only.
1875 /* have cell name, too */
1876 cellp = afs_GetCellByName(cp, READ_LOCK);
1877 if (!cellp) return ENOENT;
1880 if (!cellp && (temp & 2)) {
1881 /* use local cell */
1882 cellp = afs_GetPrimaryCell(READ_LOCK);
1884 if (!(temp & 1)) { /* if not fast, call server checker routine */
1885 afs_CheckServers(1, cellp); /* check down servers */
1886 afs_CheckServers(0, cellp); /* check up servers */
1888 /* now return the current down server list */
1890 ObtainReadLock(&afs_xserver);
1891 for(i=0;i<NSERVERS;i++) {
1892 for(ts = afs_servers[i]; ts; ts=ts->next) {
1893 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1894 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1895 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1896 cp += sizeof(afs_int32);
1900 ReleaseReadLock(&afs_xserver);
1901 if (cellp) afs_PutCell(cellp, READ_LOCK);
1902 *aoutSize = cp - aout;
1906 DECL_PIOCTL(PCheckVolNames)
1908 AFS_STATCNT(PCheckVolNames);
1909 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1910 return EIO; /* Inappropriate ioctl for device */
1912 afs_CheckRootVolume();
1913 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1914 AFS_VOLCHECK_EXPIRED |
1916 AFS_VOLCHECK_MTPTS);
1920 DECL_PIOCTL(PCheckAuth)
1925 struct unixuser *tu;
1928 AFS_STATCNT(PCheckAuth);
1929 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1930 return EIO; /* Inappropriate ioctl for device */
1933 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1934 if (!tu) retValue = EACCES;
1936 /* we have a user */
1937 ObtainReadLock(&afs_xsrvAddr);
1938 ObtainReadLock(&afs_xconn);
1940 /* any tokens set? */
1941 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1942 /* all connections in cell 1 working? */
1943 for(i=0;i<NSERVERS;i++) {
1944 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1945 for (tc = sa->conns; tc; tc=tc->next) {
1946 if (tc->user == tu && (tu->states & UTokensBad))
1951 ReleaseReadLock(&afs_xsrvAddr);
1952 ReleaseReadLock(&afs_xconn);
1953 afs_PutUser(tu, READ_LOCK);
1955 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1956 *aoutSize = sizeof(afs_int32);
1960 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1963 register afs_int32 code;
1964 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1970 AFS_STATCNT(Prefetch);
1971 if (!apath) return EINVAL;
1972 tp = osi_AllocLargeSpace(1024);
1973 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1975 osi_FreeLargeSpace(tp);
1978 if (afs_BBusy()) { /* do this as late as possible */
1979 osi_FreeLargeSpace(tp);
1980 return EWOULDBLOCK; /* pretty close */
1982 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1983 (afs_size_t) 0, (afs_size_t) 0, tp);
1987 DECL_PIOCTL(PFindVolume)
1989 register struct volume *tvp;
1990 register struct server *ts;
1991 register afs_int32 i;
1994 AFS_STATCNT(PFindVolume);
1995 if (!avc) return EINVAL;
1996 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1999 for(i=0;i<MAXHOSTS;i++) {
2000 ts = tvp->serverHost[i];
2002 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2003 cp += sizeof(afs_int32);
2006 /* still room for terminating NULL, add it on */
2007 ainSize = 0; /* reuse vbl */
2008 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2009 cp += sizeof(afs_int32);
2011 *aoutSize = cp - aout;
2012 afs_PutVolume(tvp, READ_LOCK);
2018 DECL_PIOCTL(PViceAccess)
2020 register afs_int32 code;
2023 AFS_STATCNT(PViceAccess);
2024 if (!avc) return EINVAL;
2025 code = afs_VerifyVCache(avc, areq);
2026 if (code) return code;
2027 memcpy((char *)&temp, ain, sizeof(afs_int32));
2028 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2033 DECL_PIOCTL(PSetCacheSize)
2038 AFS_STATCNT(PSetCacheSize);
2039 if (!afs_osi_suser(*acred))
2041 /* too many things are setup initially in mem cache version */
2042 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2043 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2044 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2046 if (newValue < afs_min_cache)
2047 afs_cacheBlocks = afs_min_cache;
2049 afs_cacheBlocks = newValue;
2051 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2052 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2053 afs_MaybeWakeupTruncateDaemon();
2054 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2055 afs_osi_Wait(1000, 0, 0);
2056 afs_MaybeWakeupTruncateDaemon();
2061 #define MAXGCSTATS 16
2062 DECL_PIOCTL(PGetCacheSize)
2064 afs_int32 results[MAXGCSTATS];
2066 AFS_STATCNT(PGetCacheSize);
2067 memset((char *)results, 0, sizeof(results));
2068 results[0] = afs_cacheBlocks;
2069 results[1] = afs_blocksUsed;
2070 memcpy(aout, (char *)results, sizeof(results));
2071 *aoutSize = sizeof(results);
2075 DECL_PIOCTL(PRemoveCallBack)
2077 register struct conn *tc;
2078 register afs_int32 code = 0;
2079 struct AFSCallBack CallBacks_Array[1];
2080 struct AFSCBFids theFids;
2081 struct AFSCBs theCBs;
2084 AFS_STATCNT(PRemoveCallBack);
2085 if (!avc) return EINVAL;
2086 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2087 ObtainWriteLock(&avc->lock,229);
2088 theFids.AFSCBFids_len = 1;
2089 theCBs.AFSCBs_len = 1;
2090 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2091 theCBs.AFSCBs_val = CallBacks_Array;
2092 CallBacks_Array[0].CallBackType = CB_DROPPED;
2093 if (avc->callback) {
2095 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2097 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2099 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2103 /* don't set code on failure since we wouldn't use it */
2105 (afs_Analyze(tc, code, &avc->fid, areq,
2106 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2107 SHARED_LOCK, NULL));
2109 ObtainWriteLock(&afs_xcbhash, 457);
2110 afs_DequeueCallback(avc);
2112 avc->states &= ~(CStatd | CUnique);
2113 ReleaseWriteLock(&afs_xcbhash);
2114 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2115 osi_dnlc_purgedp(avc);
2117 ReleaseWriteLock(&avc->lock);
2121 DECL_PIOCTL(PNewCell)
2123 /* create a new cell */
2124 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2125 char *newcell=0, *linkedcell=0, *tp= ain;
2126 register afs_int32 code, linkedstate=0, ls;
2127 u_short fsport = 0, vlport = 0;
2130 AFS_STATCNT(PNewCell);
2131 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2132 return EIO; /* Inappropriate ioctl for device */
2134 if (!afs_osi_suser(*acred))
2137 memcpy((char *)&magic, tp, sizeof(afs_int32));
2138 tp += sizeof(afs_int32);
2139 if (magic != 0x12345678)
2142 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2143 * server addresses while the 3.5 fs newcell command passes
2144 * MAXHOSTS. To figure out which is which, check if the cellname
2147 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2148 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2150 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2151 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2152 tp += (scount * sizeof(afs_int32));
2154 lp = (afs_int32 *)tp;
2157 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2158 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2159 tp += (3 * sizeof(afs_int32));
2161 if ((ls = *lp) & 1) {
2162 linkedcell = tp + strlen(newcell)+1;
2163 linkedstate |= CLinkedCell;
2166 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2167 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2172 DECL_PIOCTL(PNewAlias)
2174 /* create a new cell alias */
2176 register afs_int32 code;
2177 char *realName, *aliasName;
2179 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2180 return EIO; /* Inappropriate ioctl for device */
2182 if (!afs_osi_suser(*acred))
2186 tp += strlen(aliasName) + 1;
2189 code = afs_NewCellAlias(aliasName, realName);
2194 DECL_PIOCTL(PListCells)
2196 afs_int32 whichCell;
2197 register struct cell *tcell=0;
2198 register afs_int32 i;
2199 register char *cp, *tp = ain;
2201 AFS_STATCNT(PListCells);
2202 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2203 return EIO; /* Inappropriate ioctl for device */
2205 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2206 tp += sizeof(afs_int32);
2207 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2210 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2211 for(i=0;i<MAXCELLHOSTS;i++) {
2212 if (tcell->cellHosts[i] == 0) break;
2213 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2214 cp += sizeof(afs_int32);
2216 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2217 strcpy(cp, tcell->cellName);
2218 cp += strlen(tcell->cellName)+1;
2219 *aoutSize = cp - aout;
2220 afs_PutCell(tcell, READ_LOCK);
2222 if (tcell) return 0;
2226 DECL_PIOCTL(PListAliases)
2228 afs_int32 whichAlias;
2229 register struct cell_alias *tcalias=0;
2230 register char *cp, *tp = ain;
2232 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2233 return EIO; /* Inappropriate ioctl for device */
2234 if (ainSize < sizeof(afs_int32))
2237 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2238 tp += sizeof(afs_int32);
2240 tcalias = afs_GetCellAlias(whichAlias);
2243 strcpy(cp, tcalias->alias);
2244 cp += strlen(tcalias->alias)+1;
2245 strcpy(cp, tcalias->cell);
2246 cp += strlen(tcalias->cell)+1;
2247 *aoutSize = cp - aout;
2248 afs_PutCellAlias(tcalias);
2250 if (tcalias) return 0;
2254 DECL_PIOCTL(PRemoveMount)
2256 register afs_int32 code;
2258 struct sysname_info sysState;
2259 afs_size_t offset, len;
2260 register struct conn *tc;
2261 register struct dcache *tdc;
2262 register struct vcache *tvc;
2263 struct AFSFetchStatus OutDirStatus;
2264 struct VenusFid tfid;
2265 struct AFSVolSync tsync;
2269 /* "ain" is the name of the file in this dir to remove */
2271 AFS_STATCNT(PRemoveMount);
2272 if (!avc) return EINVAL;
2273 code = afs_VerifyVCache(avc, areq);
2274 if (code) return code;
2275 if (vType(avc) != VDIR) return ENOTDIR;
2277 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2278 if (!tdc) return ENOENT;
2279 Check_AtSys(avc, ain, &sysState, areq);
2280 ObtainReadLock(&tdc->lock);
2282 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2283 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2284 ReleaseReadLock(&tdc->lock);
2285 bufp = sysState.name;
2290 tfid.Cell = avc->fid.Cell;
2291 tfid.Fid.Volume = avc->fid.Fid.Volume;
2292 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2293 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2295 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2302 if (tvc->mvstat != 1) {
2308 ObtainWriteLock(&tvc->lock,230);
2309 code = afs_HandleLink(tvc, areq);
2311 if (tvc->linkData) {
2312 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2317 ReleaseWriteLock(&tvc->lock);
2318 osi_dnlc_purgedp(tvc);
2324 ObtainWriteLock(&avc->lock,231);
2325 osi_dnlc_remove(avc, bufp, tvc);
2327 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2329 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2331 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2332 bufp, &OutDirStatus, &tsync);
2338 (afs_Analyze(tc, code, &avc->fid, areq,
2339 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2340 SHARED_LOCK, NULL));
2343 if (tdc) afs_PutDCache(tdc);
2344 ReleaseWriteLock(&avc->lock);
2348 /* we have the thing in the cache */
2349 ObtainWriteLock(&tdc->lock, 661);
2350 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2351 /* we can do it locally */
2352 code = afs_dir_Delete(&tdc->f.inode, bufp);
2354 ZapDCE(tdc); /* surprise error -- invalid value */
2355 DZap(&tdc->f.inode);
2358 ReleaseWriteLock(&tdc->lock);
2359 afs_PutDCache(tdc); /* drop ref count */
2361 avc->states &= ~CUnique; /* For the dfs xlator */
2362 ReleaseWriteLock(&avc->lock);
2365 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2369 DECL_PIOCTL(PVenusLogging)
2371 return EINVAL; /* OBSOLETE */
2374 DECL_PIOCTL(PGetCellStatus)
2376 register struct cell *tcell;
2379 AFS_STATCNT(PGetCellStatus);
2380 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2381 return EIO; /* Inappropriate ioctl for device */
2383 tcell = afs_GetCellByName(ain, READ_LOCK);
2384 if (!tcell) return ENOENT;
2385 temp = tcell->states;
2386 afs_PutCell(tcell, READ_LOCK);
2387 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2388 *aoutSize = sizeof(afs_int32);
2392 DECL_PIOCTL(PSetCellStatus)
2394 register struct cell *tcell;
2397 if (!afs_osi_suser(*acred))
2399 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2400 return EIO; /* Inappropriate ioctl for device */
2402 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2403 if (!tcell) return ENOENT;
2404 memcpy((char *)&temp, ain, sizeof(afs_int32));
2406 tcell->states |= CNoSUID;
2408 tcell->states &= ~CNoSUID;
2409 afs_PutCell(tcell, WRITE_LOCK);
2413 DECL_PIOCTL(PFlushVolumeData)
2415 register afs_int32 i;
2416 register struct dcache *tdc;
2417 register struct vcache *tvc;
2418 register struct volume *tv;
2419 afs_int32 cell, volume;
2421 AFS_STATCNT(PFlushVolumeData);
2424 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2425 return EIO; /* Inappropriate ioctl for device */
2427 volume = avc->fid.Fid.Volume; /* who to zap */
2428 cell = avc->fid.Cell;
2431 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2432 * the vcaches associated with the volume.
2434 ObtainReadLock(&afs_xvcache);
2435 for(i = 0; i < VCSIZE; i++) {
2436 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2437 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2438 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2439 VN_HOLD(AFSTOV(tvc));
2441 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2447 ReleaseReadLock(&afs_xvcache);
2448 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2449 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2451 ObtainWriteLock(&tvc->lock,232);
2453 ObtainWriteLock(&afs_xcbhash, 458);
2454 afs_DequeueCallback(tvc);
2455 tvc->states &= ~(CStatd | CDirty);
2456 ReleaseWriteLock(&afs_xcbhash);
2457 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2458 osi_dnlc_purgedp(tvc);
2459 afs_TryToSmush(tvc, *acred, 1);
2460 ReleaseWriteLock(&tvc->lock);
2461 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2462 afs_BozonUnlock(&tvc->pvnLock, tvc);
2464 ObtainReadLock(&afs_xvcache);
2465 /* our tvc ptr is still good until now */
2470 ReleaseReadLock(&afs_xvcache);
2473 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2474 for(i=0;i<afs_cacheFiles;i++) {
2475 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2476 tdc = afs_GetDSlot(i, NULL);
2477 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2478 ReleaseReadLock(&tdc->tlock);
2479 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2480 if (! (afs_indexFlags[i] & IFDataMod)) {
2481 /* if the file is modified, but has a ref cnt of only 1, then
2482 someone probably has the file open and is writing into it.
2483 Better to skip flushing such a file, it will be brought back
2484 immediately on the next write anyway.
2486 If we *must* flush, then this code has to be rearranged to call
2487 afs_storeAllSegments() first */
2488 afs_FlushDCache(tdc);
2492 ReleaseReadLock(&tdc->tlock);
2494 afs_PutDCache(tdc); /* bumped by getdslot */
2496 MReleaseWriteLock(&afs_xdcache);
2498 ObtainReadLock(&afs_xvolume);
2499 for (i=0;i<NVOLS;i++) {
2500 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2501 if (tv->volume == volume) {
2502 afs_ResetVolumeInfo(tv);
2507 ReleaseReadLock(&afs_xvolume);
2509 /* probably, a user is doing this, probably, because things are screwed up.
2510 * maybe it's the dnlc's fault? */
2517 DECL_PIOCTL(PGetVnodeXStatus)
2519 register afs_int32 code;
2520 struct vcxstat stat;
2523 /* AFS_STATCNT(PGetVnodeXStatus); */
2524 if (!avc) return EINVAL;
2525 code = afs_VerifyVCache(avc, areq);
2526 if (code) return code;
2527 if (vType(avc) == VDIR)
2528 mode = PRSFS_LOOKUP;
2531 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2533 stat.fid = avc->fid;
2534 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2535 stat.lock = avc->lock;
2536 stat.parentVnode = avc->parentVnode;
2537 stat.parentUnique = avc->parentUnique;
2538 hset(stat.flushDV, avc->flushDV);
2539 hset(stat.mapDV, avc->mapDV);
2540 stat.truncPos = avc->truncPos;
2541 { /* just grab the first two - won't break anything... */
2542 struct axscache *ac;
2544 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2545 stat.randomUid[i] = ac->uid;
2546 stat.randomAccess[i] = ac->axess;
2549 stat.callback = afs_data_pointer_to_int32(avc->callback);
2550 stat.cbExpires = avc->cbExpires;
2551 stat.anyAccess = avc->anyAccess;
2552 stat.opens = avc->opens;
2553 stat.execsOrWriters = avc->execsOrWriters;
2554 stat.flockCount = avc->flockCount;
2555 stat.mvstat = avc->mvstat;
2556 stat.states = avc->states;
2557 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2558 *aoutSize = sizeof(struct vcxstat);
2563 /* We require root for local sysname changes, but not for remote */
2564 /* (since we don't really believe remote uids anyway) */
2565 /* outname[] shouldn't really be needed- this is left as an excercise */
2566 /* for the reader. */
2567 DECL_PIOCTL(PSetSysName)
2569 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2570 int setsysname, foundname=0;
2571 register struct afs_exporter *exporter;
2572 register struct unixuser *au;
2573 register afs_int32 pag, error;
2577 AFS_STATCNT(PSetSysName);
2578 if (!afs_globalVFS) {
2579 /* Afsd is NOT running; disable it */
2580 #if defined(KERNEL_HAVE_UERROR)
2581 return (setuerror(EINVAL), EINVAL);
2586 memset(inname, 0, MAXSYSNAME);
2587 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2588 ain += sizeof(afs_int32);
2592 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2594 for(cp = ain,count = 0;count < setsysname;count++) {
2595 /* won't go past end of ain since maxsysname*num < ain length */
2597 if (t >= MAXSYSNAME || t <= 0)
2599 /* check for names that can shoot us in the foot */
2600 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2606 /* inname gets first entry in case we're being a translater */
2608 memcpy(inname, ain, t+1); /* include terminating null */
2611 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2612 pag = PagInCred(*acred);
2614 return EINVAL; /* Better than panicing */
2616 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2617 return EINVAL; /* Better than panicing */
2619 if (!(exporter = au->exporter)) {
2620 afs_PutUser(au, READ_LOCK);
2621 return EINVAL; /* Better than panicing */
2623 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2625 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2627 afs_PutUser(au, READ_LOCK);
2632 afs_PutUser(au, READ_LOCK);
2635 /* Not xlating, so local case */
2636 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2637 if (!setsysname) { /* user just wants the info */
2638 strcpy(outname, afs_sysname);
2639 foundname = afs_sysnamecount;
2640 } else { /* Local guy; only root can change sysname */
2641 if (!afs_osi_suser(*acred))
2644 /* clear @sys entries from the dnlc, once afs_lookup can
2645 do lookups of @sys entries and thinks it can trust them */
2646 /* privs ok, store the entry, ... */
2647 strcpy(afs_sysname, inname);
2648 if (setsysname > 1) { /* ... or list */
2650 for(count=1; count < setsysname;++count) {
2651 if (!afs_sysnamelist[count])
2652 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2654 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2658 afs_sysnamecount = setsysname;
2662 cp = aout; /* not changing so report back the count and ... */
2663 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2664 cp += sizeof(afs_int32);
2666 strcpy(cp, outname); /* ... the entry, ... */
2667 cp += strlen(outname)+1;
2668 for(count=1; count < foundname; ++count) { /* ... or list. */
2669 /* Note: we don't support @sys lists for exporters */
2670 if (!afs_sysnamelist[count])
2671 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2672 t = strlen(afs_sysnamelist[count]);
2673 if (t >= MAXSYSNAME)
2674 osi_Panic("PSetSysName: sysname entry garbled\n");
2675 strcpy(cp, afs_sysnamelist[count]);
2679 *aoutSize = cp - aout;
2684 /* sequential search through the list of touched cells is not a good
2685 * long-term solution here. For small n, though, it should be just
2686 * fine. Should consider special-casing the local cell for large n.
2687 * Likewise for PSetSPrefs.
2689 * s - number of ids in array l[] -- NOT index of last id
2690 * l - array of cell ids which have volumes that need to be sorted
2691 * vlonly - sort vl servers or file servers?
2693 static void ReSortCells_cb(struct cell *cell, void *arg)
2695 afs_int32 *p = (afs_int32 *) arg;
2696 afs_int32 *l = p + 1;
2699 for (i=0; i<s; i++) {
2700 if (l[i] == cell->cellNum) {
2701 ObtainWriteLock(&cell->lock, 690);
2702 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2703 ReleaseWriteLock(&cell->lock);
2708 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2716 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2718 memcpy(p+1, l, s * sizeof(afs_int32));
2719 afs_TraverseCells(&ReSortCells_cb, p);
2720 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2724 ObtainReadLock(&afs_xvolume);
2725 for (i= 0; i< NVOLS; i++) {
2726 for (j=afs_volumes[i];j;j=j->next) {
2728 if (j->cell == l[k]) {
2729 ObtainWriteLock(&j->lock,233);
2730 afs_SortServers(j->serverHost, MAXHOSTS);
2731 ReleaseWriteLock(&j->lock);
2736 ReleaseReadLock(&afs_xvolume);
2740 static int debugsetsp = 0;
2741 static int afs_setsprefs(sp, num, vlonly)
2744 unsigned int vlonly;
2747 int i,j,k,matches,touchedSize;
2748 struct server *srvr = NULL;
2749 afs_int32 touched[34];
2753 for (k=0; k < num; sp++, k++) {
2755 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2758 ObtainReadLock(&afs_xserver);
2760 i = SHash(sp->host.s_addr);
2761 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2762 if (sa->sa_ip == sp->host.s_addr) {
2764 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2765 || (sa->sa_portal == AFS_FSPORT);
2766 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2773 if (sa && matches) { /* found one! */
2775 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2777 sa->sa_iprank = sp->rank + afs_randomMod15();
2778 afs_SortOneServer(sa->server);
2781 /* if we don't know yet what cell it's in, this is moot */
2782 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2783 /* is it in our list of touched cells ? */ ;
2784 if (j < 0) { /* no, it's not */
2785 touched[touchedSize++] = srvr->cell->cellNum;
2786 if (touchedSize >= 32) { /* watch for ovrflow */
2787 ReleaseReadLock(&afs_xserver);
2788 ReSortCells(touchedSize, touched, vlonly);
2790 ObtainReadLock(&afs_xserver);
2796 ReleaseReadLock(&afs_xserver);
2797 /* if we didn't find one, start to create one. */
2798 /* Note that it doesn't have a cell yet... */
2800 afs_uint32 temp = sp->host.s_addr;
2801 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2802 WRITE_LOCK, (afsUUID *)0,0);
2803 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2804 afs_PutServer(srvr, WRITE_LOCK);
2806 } /* for all cited preferences */
2808 ReSortCells(touchedSize, touched, vlonly);
2812 /* Note that this may only be performed by the local root user.
2814 DECL_PIOCTL(PSetSPrefs)
2816 struct setspref *ssp;
2817 AFS_STATCNT(PSetSPrefs);
2819 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2820 return EIO; /* Inappropriate ioctl for device */
2822 if (!afs_osi_suser(*acred))
2825 if (ainSize < sizeof(struct setspref))
2828 ssp = (struct setspref *)ain;
2829 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2832 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2833 (ssp->flags & DBservers));
2837 DECL_PIOCTL(PSetSPrefs33)
2840 AFS_STATCNT(PSetSPrefs);
2841 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2842 return EIO; /* Inappropriate ioctl for device */
2845 if (!afs_osi_suser(*acred))
2848 sp = (struct spref *)ain;
2849 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2853 /* some notes on the following code...
2854 * in the hash table of server structs, all servers with the same IP address
2855 * will be on the same overflow chain.
2856 * This could be sped slightly in some circumstances by having it cache the
2857 * immediately previous slot in the hash table and some supporting information
2858 * Only reports file servers now.
2860 DECL_PIOCTL(PGetSPrefs)
2862 struct sprefrequest *spin; /* input */
2863 struct sprefinfo *spout; /* output */
2864 struct spref *srvout; /* one output component */
2865 int i,j; /* counters for hash table traversal */
2866 struct server *srvr; /* one of CM's server structs */
2868 int vlonly; /* just return vlservers ? */
2871 AFS_STATCNT(PGetSPrefs);
2872 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2873 return EIO; /* Inappropriate ioctl for device */
2876 if (ainSize < sizeof (struct sprefrequest_33)) {
2880 spin = ((struct sprefrequest *) ain);
2883 if (ainSize > sizeof (struct sprefrequest_33)) {
2884 vlonly = (spin->flags & DBservers);
2888 /* struct sprefinfo includes 1 server struct... that size gets added
2889 * in during the loop that follows.
2891 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2892 spout = (struct sprefinfo *) aout;
2893 spout->next_offset = spin->offset;
2894 spout->num_servers = 0;
2895 srvout = spout->servers;
2897 ObtainReadLock(&afs_xserver);
2898 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2899 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2900 if (spin->offset > (unsigned short)i) {
2901 continue; /* catch up to where we left off */
2903 spout->next_offset++;
2906 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2907 || (sa->sa_portal == AFS_FSPORT);
2909 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2910 /* only report ranks for vl servers */
2914 srvout->host.s_addr = sa->sa_ip;
2915 srvout->rank = sa->sa_iprank;
2916 *aoutSize += sizeof(struct spref);
2917 spout->num_servers++;
2920 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2921 ReleaseReadLock(&afs_xserver); /* no more room! */
2926 ReleaseReadLock(&afs_xserver);
2928 spout->next_offset = 0; /* start over from the beginning next time */
2932 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2933 int afs_NFSRootOnly = 1;
2934 DECL_PIOCTL(PExportAfs)
2936 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2937 register struct afs_exporter *exporter;
2939 AFS_STATCNT(PExportAfs);
2940 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2941 type = handleValue >> 24;
2946 exporter = exporter_find(type);
2948 export = handleValue & 3;
2949 changestate = handleValue & 0xff;
2950 smounts = (handleValue >> 2) & 3;
2951 pwsync = (handleValue >> 4) & 3;
2952 convmode = (handleValue >> 6) & 3;
2954 changestate = (handleValue >> 16) & 0x1;
2955 convmode = (handleValue >> 16) & 0x2;
2956 pwsync = (handleValue >> 16) & 0x4;
2957 smounts = (handleValue >> 16) & 0x8;
2958 export = handleValue & 0xff;
2961 /* Failed finding desired exporter; */
2965 handleValue = exporter->exp_states;
2966 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2967 *aoutSize = sizeof(afs_int32);
2969 if (!afs_osi_suser(*acred))
2970 return EACCES; /* Only superuser can do this */
2974 exporter->exp_states |= EXP_EXPORTED;
2976 exporter->exp_states &= ~EXP_EXPORTED;
2980 exporter->exp_states |= EXP_UNIXMODE;
2982 exporter->exp_states &= ~EXP_UNIXMODE;
2986 exporter->exp_states |= EXP_PWSYNC;
2988 exporter->exp_states &= ~EXP_PWSYNC;
2992 afs_NFSRootOnly = 0;
2993 exporter->exp_states |= EXP_SUBMOUNTS;
2995 afs_NFSRootOnly = 1;
2996 exporter->exp_states &= ~EXP_SUBMOUNTS;
2999 handleValue = exporter->exp_states;
3000 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
3001 *aoutSize = sizeof(afs_int32);
3004 exporter->exp_states |= EXP_EXPORTED;
3006 exporter->exp_states &= ~EXP_EXPORTED;
3008 exporter->exp_states |= EXP_UNIXMODE;
3010 exporter->exp_states &= ~EXP_UNIXMODE;
3012 exporter->exp_states |= EXP_PWSYNC;
3014 exporter->exp_states &= ~EXP_PWSYNC;
3016 afs_NFSRootOnly = 0;
3017 exporter->exp_states |= EXP_SUBMOUNTS;
3019 afs_NFSRootOnly = 1;
3020 exporter->exp_states &= ~EXP_SUBMOUNTS;
3030 struct gaginfo *gagflags;
3032 if (!afs_osi_suser(*acred))
3035 gagflags = (struct gaginfo *) ain;
3036 afs_showflags = gagflags->showflags;
3042 DECL_PIOCTL(PTwiddleRx)
3044 struct rxparams *rxp;
3046 if (!afs_osi_suser(*acred))
3049 rxp = (struct rxparams *) ain;
3051 if (rxp->rx_initReceiveWindow)
3052 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3053 if (rxp->rx_maxReceiveWindow)
3054 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3055 if (rxp->rx_initSendWindow)
3056 rx_initSendWindow = rxp->rx_initSendWindow;
3057 if (rxp->rx_maxSendWindow)
3058 rx_maxSendWindow = rxp->rx_maxSendWindow;
3059 if (rxp->rxi_nSendFrags)
3060 rxi_nSendFrags = rxp->rxi_nSendFrags;
3061 if (rxp->rxi_nRecvFrags)
3062 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3063 if (rxp->rxi_OrphanFragSize)
3064 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3065 if (rxp->rx_maxReceiveSize)
3067 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3068 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3070 if (rxp->rx_MyMaxSendSize)
3071 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3076 DECL_PIOCTL(PGetInitParams)
3078 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3081 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3082 *aoutSize = sizeof(struct cm_initparams);
3086 #ifdef AFS_SGI65_ENV
3087 /* They took crget() from us, so fake it. */
3088 static cred_t *crget(void)
3091 cr = crdup(get_current_cred());
3092 memset((char*)cr, 0, sizeof(cred_t));
3093 #if CELL || CELL_PREPARE
3100 DECL_PIOCTL(PGetRxkcrypt)
3102 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3103 *aoutSize=sizeof(afs_int32);
3107 DECL_PIOCTL(PSetRxkcrypt)
3111 if (!afs_osi_suser(*acred))
3113 if (ainSize != sizeof(afs_int32) || ain == NULL)
3115 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3116 /* if new mappings added later this will need to be changed */
3117 if (tmpval != 0 && tmpval != 1)
3124 * Create new credentials to correspond to a remote user with given
3125 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3126 * provide pioctl (and other) services to foreign clients (i.e. nfs
3127 * clients) by using this call to `become' the client.
3130 #define PIOCTL_HEADER 6
3131 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3133 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3134 return EINVAL; /* NFS trans not supported for Ultrix */
3137 afs_uint32 hostaddr;
3138 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3139 struct afs_exporter *exporter, *outexporter;
3140 struct AFS_UCRED *newcred;
3141 struct unixuser *au;
3143 #if defined(AFS_SGIMP_ENV)
3144 osi_Assert(ISAFS_GLOCK());
3146 AFS_STATCNT(HandleClientContext);
3147 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3148 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3149 return EINVAL; /* Too small to be good */
3151 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3152 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3154 osi_FreeLargeSpace(inData);
3158 /* Extract information for remote user */
3159 hostaddr = *((afs_uint32 *)ain);
3160 ain += sizeof(hostaddr);
3161 uid = *((afs_uint32 *)ain);
3163 g0 = *((afs_uint32 *)ain);
3165 g1 = *((afs_uint32 *)ain);
3167 *com = *((afs_uint32 *)ain);
3168 ain += sizeof(afs_int32);
3169 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3172 * Of course, one must be root for most of these functions, but
3173 * we'll allow (for knfs) you to set things if the pag is 0 and
3174 * you're setting tokens or unlogging.
3177 if (!afs_osi_suser(credp)) {
3179 #ifndef AFS_SGI64_ENV
3180 /* Since SGI's suser() returns explicit failure after the call.. */
3184 /* check for acceptable opcodes for normal folks, which are, so far,
3185 * set tokens and unlog.
3187 if (i != 9 && i != 3 && i != 38 && i != 8) {
3188 osi_FreeLargeSpace(inData);
3193 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3194 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3195 osi_FreeLargeSpace(inData);
3198 * We map uid 0 to nobody to match the mapping that the nfs
3199 * server does and to ensure that the suser() calls in the afs
3200 * code fails for remote client roots.
3202 uid = afs_nobody; /* NFS_NOBODY == -2 */
3205 #ifdef AFS_AIX41_ENV
3208 newcred->cr_gid = RMTUSER_REQ;
3209 #ifdef AFS_AIX51_ENV
3210 newcred->cr_groupset.gs_union.un_groups[0] = g0;
3211 newcred->cr_groupset.gs_union.un_groups[1] = g1;
3213 newcred->cr_groups[0] = g0;
3214 newcred->cr_groups[1] = g1;
3217 newcred->cr_ngrps = 2;
3219 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3220 newcred->cr_ngroups = 2;
3222 for (i=2; i<NGROUPS; i++)
3223 newcred->cr_groups[i] = NOGROUP;
3226 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3227 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3229 if (!(exporter = exporter_find(exporter_type))) {
3230 /* Exporter wasn't initialized or an invalid exporter type */
3234 if (exporter->exp_states & EXP_PWSYNC) {
3235 if (uid != credp->cr_uid) {
3237 return ENOEXEC; /* XXX Find a better errno XXX */
3240 newcred->cr_uid = uid; /* Only temporary */
3241 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3242 /* The client's pag is the only unique identifier for it */
3243 newcred->cr_uid = pag;
3245 if (!code && *com == PSETPAG) {
3246 /* Special case for 'setpag' */
3247 afs_uint32 pagvalue = genpag();
3249 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3251 * Note that we leave the 'outexporter' struct held so it won't
3254 au->exporter = outexporter;
3255 if (ablob->out_size >= 4) {
3256 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3258 afs_PutUser(au, WRITE_LOCK);
3259 if (code) return code;
3260 return PSETPAG; /* Special return for setpag */
3262 EXP_RELE(outexporter);
3265 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3268 /* get all interface addresses of this client */
3270 DECL_PIOCTL(PGetCPrefs)
3272 struct sprefrequest *spin; /* input */
3273 struct sprefinfo *spout; /* output */
3274 struct spref *srvout; /* one output component */
3278 AFS_STATCNT(PGetCPrefs);
3279 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3280 return EIO; /* Inappropriate ioctl for device */
3282 if ( ainSize < sizeof (struct sprefrequest ))
3285 spin = (struct sprefrequest *) ain;
3286 spout = (struct sprefinfo *) aout;
3288 maxNumber = spin->num_servers; /* max addrs this time */
3289 srvout = spout->servers;
3291 ObtainReadLock(&afs_xinterface);
3293 /* copy out the client interface information from the
3294 ** kernel data structure "interface" to the output buffer
3296 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3297 && ( j< maxNumber) ; i++, j++, srvout++)
3298 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3300 spout->num_servers = j;
3301 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3303 if ( i >= afs_cb_interface.numberOfInterfaces )
3304 spout->next_offset = 0; /* start from beginning again */
3306 spout->next_offset = spin->offset + j;
3308 ReleaseReadLock(&afs_xinterface);
3312 DECL_PIOCTL(PSetCPrefs)
3314 struct setspref *sin;
3317 AFS_STATCNT(PSetCPrefs);
3318 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3319 return EIO; /* Inappropriate ioctl for device */
3321 sin = (struct setspref *)ain;
3323 if ( ainSize < sizeof(struct setspref) )
3325 #if 0 /* num_servers is unsigned */
3326 if ( sin->num_servers < 0 )
3329 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3332 ObtainWriteLock(&afs_xinterface, 412);
3333 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3334 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3335 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3337 ReleaseWriteLock(&afs_xinterface);
3341 DECL_PIOCTL(PFlushMount)
3343 register afs_int32 code;
3344 register struct vcache *tvc;
3345 register struct dcache *tdc;
3346 struct VenusFid tfid;
3348 struct sysname_info sysState;
3349 afs_size_t offset, len;
3351 AFS_STATCNT(PFlushMount);
3352 if (!avc) return EINVAL;
3353 code = afs_VerifyVCache(avc, areq);
3354 if (code) return code;
3355 if (vType(avc) != VDIR) {
3358 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3359 if (!tdc) return ENOENT;
3360 Check_AtSys(avc, ain, &sysState, areq);
3361 ObtainReadLock(&tdc->lock);
3363 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3364 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3365 ReleaseReadLock(&tdc->lock);
3366 afs_PutDCache(tdc); /* we're done with the data */
3367 bufp = sysState.name;
3371 tfid.Cell = avc->fid.Cell;
3372 tfid.Fid.Volume = avc->fid.Fid.Volume;
3373 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3374 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3376 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3382 if (tvc->mvstat != 1) {
3387 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3388 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3390 ObtainWriteLock(&tvc->lock,649);
3391 ObtainWriteLock(&afs_xcbhash, 650);
3392 afs_DequeueCallback(tvc);
3393 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3394 ReleaseWriteLock(&afs_xcbhash);
3395 /* now find the disk cache entries */
3396 afs_TryToSmush(tvc, *acred, 1);
3397 osi_dnlc_purgedp(tvc);
3398 afs_symhint_inval(tvc);
3399 if (tvc->linkData && !(tvc->states & CCore)) {
3400 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3401 tvc->linkData = NULL;
3403 ReleaseWriteLock(&tvc->lock);
3404 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3405 afs_BozonUnlock(&tvc->pvnLock, tvc);
3409 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3413 DECL_PIOCTL(PRxStatProc)
3418 if (!afs_osi_suser(*acred)) {
3422 if (ainSize != sizeof(afs_int32)) {
3426 memcpy((char *)&flags, ain, sizeof(afs_int32));
3427 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3431 if (flags & AFSCALL_RXSTATS_ENABLE) {
3432 rx_enableProcessRPCStats();
3434 if (flags & AFSCALL_RXSTATS_DISABLE) {
3435 rx_disableProcessRPCStats();
3437 if (flags & AFSCALL_RXSTATS_CLEAR) {
3438 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3446 DECL_PIOCTL(PRxStatPeer)
3451 if (!afs_osi_suser(*acred)) {
3455 if (ainSize != sizeof(afs_int32)) {
3459 memcpy((char *)&flags, ain, sizeof(afs_int32));
3460 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3464 if (flags & AFSCALL_RXSTATS_ENABLE) {
3465 rx_enablePeerRPCStats();
3467 if (flags & AFSCALL_RXSTATS_DISABLE) {
3468 rx_disablePeerRPCStats();
3470 if (flags & AFSCALL_RXSTATS_CLEAR) {
3471 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3478 DECL_PIOCTL(PPrefetchFromTape)
3480 register afs_int32 code, code1;
3483 struct rx_call *tcall;
3484 struct AFSVolSync tsync;
3485 struct AFSFetchStatus OutStatus;
3486 struct AFSCallBack CallBack;
3487 struct VenusFid tfid;
3491 AFS_STATCNT(PSetAcl);
3495 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3496 Fid = (struct AFSFid *) ain;
3498 Fid = &avc->fid.Fid;
3499 tfid.Cell = avc->fid.Cell;
3500 tfid.Fid.Volume = Fid->Volume;
3501 tfid.Fid.Vnode = Fid->Vnode;
3502 tfid.Fid.Unique = Fid->Unique;
3504 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3506 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3507 ICL_TYPE_POINTER, tvc,
3508 ICL_TYPE_FID, &tfid,
3509 ICL_TYPE_FID, &avc->fid);
3512 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3513 ICL_TYPE_POINTER, tvc,
3514 ICL_TYPE_FID, &tfid,
3515 ICL_TYPE_FID, &tvc->fid);
3518 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3522 tcall = rx_NewCall(tc->id);
3523 code = StartRXAFS_FetchData(tcall,
3524 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3526 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3527 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3529 code1 = rx_EndCall(tcall, code);
3534 (afs_Analyze(tc, code, &tvc->fid, areq,
3535 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3537 /* This call is done only to have the callback things handled correctly */
3538 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3542 *aoutSize = sizeof(afs_int32);
3547 DECL_PIOCTL(PResidencyCmd)
3549 register afs_int32 code;
3552 struct ResidencyCmdInputs *Inputs;
3553 struct ResidencyCmdOutputs *Outputs;
3554 struct VenusFid tfid;
3557 Inputs = (struct ResidencyCmdInputs *) ain;
3558 Outputs = (struct ResidencyCmdOutputs *) aout;
3559 if (!avc) return EINVAL;
3560 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3564 Fid = &avc->fid.Fid;
3566 tfid.Cell = avc->fid.Cell;
3567 tfid.Fid.Volume = Fid->Volume;
3568 tfid.Fid.Vnode = Fid->Vnode;
3569 tfid.Fid.Unique = Fid->Unique;
3571 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3572 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3573 ICL_TYPE_POINTER, tvc,
3574 ICL_TYPE_INT32, Inputs->command,
3575 ICL_TYPE_FID, &tfid);
3579 if (Inputs->command) {
3581 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3584 code = RXAFS_ResidencyCmd(tc->id, Fid,
3586 (struct ResidencyCmdOutputs *) aout);
3591 (afs_Analyze(tc, code, &tvc->fid, areq,
3592 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3594 /* This call is done to have the callback things handled correctly */
3595 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3596 } else { /* just a status request, return also link data */
3598 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3599 Outputs->chars[0] = 0;
3600 if (vType(tvc) == VLNK) {
3601 ObtainWriteLock(&tvc->lock,555);
3602 if (afs_HandleLink(tvc, areq) == 0)
3603 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3604 ReleaseWriteLock(&tvc->lock);
3611 *aoutSize = sizeof(struct ResidencyCmdOutputs);