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"
16 #include "afs/sysincludes.h" /* Standard vendor system headers */
18 #include "h/syscallargs.h"
21 #include "h/sysproto.h"
23 #include "afsincludes.h" /* Afs-based standard headers */
24 #include "afs/afs_stats.h" /* afs statistics */
26 #include "afs/afs_bypasscache.h"
27 #include "rx/rx_globals.h"
29 struct VenusFid afs_rootFid;
30 afs_int32 afs_waitForever = 0;
31 short afs_waitForeverCount = 0;
32 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
35 afs_int32 afs_is_disconnected;
36 afs_int32 afs_is_logging;
37 afs_int32 afs_is_discon_rw;
38 /* On reconnection, turn this knob on until it finishes,
41 afs_int32 afs_in_sync = 0;
45 * \defgroup pioctl Path IOCTL functions
47 * DECL_PIOCTL is a macro defined to contain the following parameters for functions:
49 * \param[in] avc the AFS vcache structure in use by pioctl
50 * \param[in] afun not in use
51 * \param[in] areq the AFS vrequest structure
52 * \param[in] ain as defined by the function
53 * \param[in] aout as defined by the function
54 * \param[in] ainSize size of ain
55 * \param[in] aoutSize size of aout
56 * \param[in] acred UNIX credentials structure underlying the operation
59 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
60 char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
61 struct AFS_UCRED **acred)
63 /* Prototypes for pioctl routines */
66 DECL_PIOCTL(PStoreBehind);
71 DECL_PIOCTL(PGetFileCell);
72 DECL_PIOCTL(PGetWSCell);
73 DECL_PIOCTL(PGetUserCell);
74 DECL_PIOCTL(PSetTokens);
75 DECL_PIOCTL(PGetVolumeStatus);
76 DECL_PIOCTL(PSetVolumeStatus);
78 DECL_PIOCTL(PNewStatMount);
79 DECL_PIOCTL(PGetTokens);
81 DECL_PIOCTL(PMariner);
82 DECL_PIOCTL(PCheckServers);
83 DECL_PIOCTL(PCheckVolNames);
84 DECL_PIOCTL(PCheckAuth);
85 DECL_PIOCTL(PFindVolume);
86 DECL_PIOCTL(PViceAccess);
87 DECL_PIOCTL(PSetCacheSize);
88 DECL_PIOCTL(PGetCacheSize);
89 DECL_PIOCTL(PRemoveCallBack);
90 DECL_PIOCTL(PNewCell);
91 DECL_PIOCTL(PNewAlias);
92 DECL_PIOCTL(PListCells);
93 DECL_PIOCTL(PListAliases);
94 DECL_PIOCTL(PRemoveMount);
95 DECL_PIOCTL(PVenusLogging);
96 DECL_PIOCTL(PGetCellStatus);
97 DECL_PIOCTL(PSetCellStatus);
98 DECL_PIOCTL(PFlushVolumeData);
99 DECL_PIOCTL(PGetVnodeXStatus);
100 DECL_PIOCTL(PGetVnodeXStatus2);
101 DECL_PIOCTL(PSetSysName);
102 DECL_PIOCTL(PSetSPrefs);
103 DECL_PIOCTL(PSetSPrefs33);
104 DECL_PIOCTL(PGetSPrefs);
105 DECL_PIOCTL(PExportAfs);
107 DECL_PIOCTL(PTwiddleRx);
108 DECL_PIOCTL(PGetInitParams);
109 DECL_PIOCTL(PGetRxkcrypt);
110 DECL_PIOCTL(PSetRxkcrypt);
111 DECL_PIOCTL(PGetCPrefs);
112 DECL_PIOCTL(PSetCPrefs);
113 DECL_PIOCTL(PFlushMount);
114 DECL_PIOCTL(PRxStatProc);
115 DECL_PIOCTL(PRxStatPeer);
116 DECL_PIOCTL(PPrefetchFromTape);
118 DECL_PIOCTL(PCallBackAddr);
119 DECL_PIOCTL(PDiscon);
120 DECL_PIOCTL(PNFSNukeCreds);
121 DECL_PIOCTL(PNewUuid);
122 DECL_PIOCTL(PPrecache);
123 #if defined(AFS_CACHE_BYPASS)
124 DECL_PIOCTL(PSetCachingThreshold);
125 DECL_PIOCTL(PSetCachingBlkSize);
129 * A macro that says whether we're going to need HandleClientContext().
130 * This is currently used only by the nfs translator.
132 #if !defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV)
133 #define AFS_NEED_CLIENTCONTEXT
136 /* Prototypes for private routines */
137 #ifdef AFS_NEED_CLIENTCONTEXT
138 static int HandleClientContext(struct afs_ioctl *ablob, int *com,
139 struct AFS_UCRED **acred,
140 struct AFS_UCRED *credp);
142 int HandleIoctl(register struct vcache *avc, register afs_int32 acom,
143 struct afs_ioctl *adata);
144 int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
145 register struct afs_ioctl *ablob, int afollow,
146 struct AFS_UCRED **acred);
147 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
148 struct AFS_UCRED *acred);
150 typedef int (*pioctlFunction) (struct vcache *, int, struct vrequest *,
151 char *, char *, afs_int32, afs_int32 *,
152 struct AFS_UCRED **);
154 static pioctlFunction VpioctlSw[] = {
159 PGetVolumeStatus, /* 4 */
160 PSetVolumeStatus, /* 5 */
165 PCheckServers, /* 10 */
166 PCheckVolNames, /* 11 */
168 PBogus, /* 13 -- used to be quick check time */
169 PFindVolume, /* 14 */
170 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
171 PBogus, /* 16 -- used to be testing code */
172 PNoop, /* 17 -- used to be enable group */
173 PNoop, /* 18 -- used to be disable group */
174 PBogus, /* 19 -- used to be list group */
175 PViceAccess, /* 20 */
176 PUnlog, /* 21 -- unlog *is* unpag in this system */
177 PGetFID, /* 22 -- get file ID */
178 PBogus, /* 23 -- used to be waitforever */
179 PSetCacheSize, /* 24 */
180 PRemoveCallBack, /* 25 -- flush only the callback */
183 PRemoveMount, /* 28 -- delete mount point */
184 PNewStatMount, /* 29 -- new style mount point stat */
185 PGetFileCell, /* 30 -- get cell name for input file */
186 PGetWSCell, /* 31 -- get cell name for workstation */
187 PMariner, /* 32 - set/get mariner host */
188 PGetUserCell, /* 33 -- get cell name for user */
189 PVenusLogging, /* 34 -- Enable/Disable logging */
190 PGetCellStatus, /* 35 */
191 PSetCellStatus, /* 36 */
192 PFlushVolumeData, /* 37 -- flush all data from a volume */
193 PSetSysName, /* 38 - Set system name */
194 PExportAfs, /* 39 - Export Afs to remote nfs clients */
195 PGetCacheSize, /* 40 - get cache size and usage */
196 PGetVnodeXStatus, /* 41 - get vcache's special status */
197 PSetSPrefs33, /* 42 - Set CM Server preferences... */
198 PGetSPrefs, /* 43 - Get CM Server preferences... */
199 PGag, /* 44 - turn off/on all CM messages */
200 PTwiddleRx, /* 45 - adjust some RX params */
201 PSetSPrefs, /* 46 - Set CM Server preferences... */
202 PStoreBehind, /* 47 - set degree of store behind to be done */
203 PGCPAGs, /* 48 - disable automatic pag gc-ing */
204 PGetInitParams, /* 49 - get initial cm params */
205 PGetCPrefs, /* 50 - get client interface addresses */
206 PSetCPrefs, /* 51 - set client interface addresses */
207 PFlushMount, /* 52 - flush mount symlink data */
208 PRxStatProc, /* 53 - control process RX statistics */
209 PRxStatPeer, /* 54 - control peer RX statistics */
210 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
211 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
212 PBogus, /* 57 -- arla: set file prio */
213 PBogus, /* 58 -- arla: fallback getfh */
214 PBogus, /* 59 -- arla: fallback fhopen */
215 PBogus, /* 60 -- arla: controls xfsdebug */
216 PBogus, /* 61 -- arla: controls arla debug */
217 PBogus, /* 62 -- arla: debug interface */
218 PBogus, /* 63 -- arla: print xfs status */
219 PBogus, /* 64 -- arla: force cache check */
220 PBogus, /* 65 -- arla: break callback */
221 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
222 PFsCmd, /* 67 -- RXOSD: generic commnd interface */
223 PBogus, /* 68 -- arla: fetch stats */
224 PGetVnodeXStatus2, /* 69 - get caller access and some vcache status */
227 static pioctlFunction CpioctlSw[] = {
229 PNewAlias, /* 1 -- create new cell alias */
230 PListAliases, /* 2 -- list cell aliases */
231 PCallBackAddr, /* 3 -- request addr for callback rxcon */
233 PDiscon, /* 5 -- get/set discon mode */
243 static int (*(OpioctlSw[])) () = {
245 PNFSNukeCreds, /* 1 -- nuke all creds for NFS client */
246 #if defined(AFS_CACHE_BYPASS)
247 PSetCachingThreshold /* 2 -- get/set cache-bypass size threshold */
249 PNoop /* 2 -- get/set cache-bypass size threshold */
253 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
254 int afs_nobody = NFS_NOBODY;
257 HandleIoctl(register struct vcache *avc, register afs_int32 acom,
258 struct afs_ioctl *adata)
260 register afs_int32 code;
263 AFS_STATCNT(HandleIoctl);
265 switch (acom & 0xff) {
267 avc->states |= CSafeStore;
271 /* case 2 used to be abort store, but this is no longer provided,
272 * since it is impossible to implement under normal Unix.
276 /* return the name of the cell this file is open on */
277 register struct cell *tcell;
278 register afs_int32 i;
280 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
282 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
284 if (i > adata->out_size) {
285 /* 0 means we're not interested in the output */
286 if (adata->out_size != 0)
290 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
292 afs_PutCell(tcell, READ_LOCK);
298 case 49: /* VIOC_GETINITPARAMS */
299 if (adata->out_size < sizeof(struct cm_initparams)) {
302 AFS_COPYOUT(&cm_initParams, adata->out,
303 sizeof(struct cm_initparams), code);
315 return code; /* so far, none implemented */
320 /* For aix we don't temporarily bypass ioctl(2) but rather do our
321 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
322 * is now called from afs_gn_ioctl.
325 afs_ioctl(struct vcache *tvc, int cmd, int arg)
327 struct afs_ioctl data;
330 AFS_STATCNT(afs_ioctl);
331 if (((cmd >> 8) & 0xff) == 'V') {
332 /* This is a VICEIOCTL call */
333 AFS_COPYIN(arg, (caddr_t) & data, sizeof(data), error);
336 error = HandleIoctl(tvc, cmd, &data);
339 /* No-op call; just return. */
343 #endif /* AFS_AIX_ENV */
345 #if defined(AFS_SGI_ENV)
346 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void *arg, int flag, cred_t * cr,
349 , struct vopbd * vbds
353 struct afs_ioctl data;
359 AFS_STATCNT(afs_ioctl);
360 if (((cmd >> 8) & 0xff) == 'V') {
361 /* This is a VICEIOCTL call */
362 error = copyin_afs_ioctl(arg, &data);
365 locked = ISAFS_GLOCK();
368 error = HandleIoctl(tvc, cmd, &data);
373 /* No-op call; just return. */
377 #endif /* AFS_SGI_ENV */
379 /* unlike most calls here, this one uses u.u_error to return error conditions,
380 since this is really an intercepted chapter 2 call, rather than a vnode
383 /* AFS_HPUX102 and up uses VNODE ioctl instead */
384 #if !defined(AFS_HPUX102_ENV) && !defined(AFS_DARWIN80_ENV)
385 #if !defined(AFS_SGI_ENV)
390 kioctl(int fdes, int com, caddr_t arg, caddr_t ext, caddr_t arg2,
392 #else /* __64BIT__ */
394 kioctl32(int fdes, int com, caddr_t arg, caddr_t ext, caddr_t arg2,
396 #endif /* __64BIT__ */
399 kioctl(int fdes, int com, caddr_t arg, caddr_t ext)
408 } u_uap, *uap = &u_uap;
410 #if defined(AFS_SUN5_ENV)
412 struct afs_ioctl_sys {
419 afs_xioctl(struct afs_ioctl_sys *uap, rval_t *rvp)
421 #elif defined(AFS_OSF_ENV)
423 afs_xioctl(struct proc *p, void *args, long *retval)
429 } *uap = (struct a *)args;
430 #elif defined(AFS_FBSD50_ENV)
433 afs_xioctl(struct thread *td, register struct ioctl_args *uap,
436 struct proc *p = td->td_proc;
437 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
445 afs_xioctl(struct proc *p, register struct ioctl_args *uap, register_t *retval)
447 #elif defined(AFS_LINUX22_ENV)
448 struct afs_ioctl_sys {
453 afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
456 struct afs_ioctl_sys ua, *uap = &ua;
465 } *uap = (struct a *)u.u_ap;
466 #endif /* AFS_SUN5_ENV */
468 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
470 #elif !defined(AFS_LINUX22_ENV)
471 register struct file *fd;
473 #if defined(AFS_XBSD_ENV)
474 register struct filedesc *fdp;
476 register struct vcache *tvc;
477 register int ioctlDone = 0, code = 0;
479 AFS_STATCNT(afs_xioctl);
480 #if defined(AFS_DARWIN_ENV)
481 if ((code = fdgetf(p, uap->fd, &fd)))
483 #elif defined(AFS_XBSD_ENV)
485 if ((u_int) uap->fd >= fdp->fd_nfiles
486 || (fd = fdp->fd_ofiles[uap->fd]) == NULL)
488 if ((fd->f_flag & (FREAD | FWRITE)) == 0)
490 #elif defined(AFS_LINUX22_ENV)
493 #elif defined(AFS_AIX32_ENV)
501 if (setuerror(getf(uap->fd, &fd))) {
504 #elif defined(AFS_OSF_ENV)
506 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
508 #elif defined(AFS_SUN5_ENV)
509 # if defined(AFS_SUN57_ENV)
513 # elif defined(AFS_SUN54_ENV)
518 if (code = getf(uap->fd, &fd)) {
521 # endif /* AFS_SUN57_ENV */
527 /* first determine whether this is any sort of vnode */
528 #if defined(AFS_LINUX22_ENV)
533 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
535 if (fd->f_type == DTYPE_VNODE) {
537 /* good, this is a vnode; next see if it is an AFS vnode */
538 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
539 tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
540 #elif defined(AFS_OBSD_ENV)
542 IsAfsVnode((struct vnode *)fd->
543 f_data) ? VTOAFS((struct vnode *)fd->f_data) : NULL;
545 tvc = VTOAFS((struct vnode *)fd->f_data); /* valid, given a vnode */
547 #endif /* AFS_LINUX22_ENV */
548 if (tvc && IsAfsVnode(AFSTOV(tvc))) {
549 /* This is an AFS vnode */
550 if (((uap->com >> 8) & 0xff) == 'V') {
551 register struct afs_ioctl *datap;
554 (struct afs_ioctl *)osi_AllocSmallSpace(AFS_SMALLOCSIZ);
555 code=copyin_afs_ioctl((char *)uap->arg, datap);
557 osi_FreeSmallSpace(datap);
559 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
562 #if defined(AFS_SUN5_ENV)
577 #else /* AFS_OSF_ENV */
581 #ifdef AFS_LINUX22_ENV
591 code = HandleIoctl(tvc, uap->com, datap);
592 osi_FreeSmallSpace(datap);
606 #if defined(AFS_LINUX22_ENV)
618 code = okioctl(fdes, com, arg, ext, arg2, arg3);
619 #else /* __64BIT__ */
620 code = okioctl32(fdes, com, arg, ext, arg2, arg3);
621 #endif /* __64BIT__ */
622 #else /* !AFS_AIX51_ENV */
623 code = okioctl(fdes, com, arg, ext);
624 #endif /* AFS_AIX51_ENV */
626 #else /* !AFS_AIX41_ENV */
628 okioctl(fdes, com, arg, ext);
629 #elif defined(AFS_SUN5_ENV)
630 #if defined(AFS_SUN57_ENV)
632 #elif defined(AFS_SUN54_ENV)
637 code = ioctl(uap, rvp);
638 #elif defined(AFS_FBSD50_ENV)
639 return ioctl(td, uap);
640 #elif defined(AFS_FBSD_ENV)
641 return ioctl(p, uap);
642 #elif defined(AFS_OBSD_ENV)
643 code = sys_ioctl(p, uap, retval);
644 #elif defined(AFS_DARWIN_ENV)
645 return ioctl(p, uap, retval);
646 #elif defined(AFS_OSF_ENV)
647 code = ioctl(p, args, retval);
654 #elif !defined(AFS_LINUX22_ENV)
668 #ifdef AFS_LINUX22_ENV
671 #if defined(KERNEL_HAVE_UERROR)
674 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
675 return (getuerror()? -1 : u.u_ioctlrv);
677 return getuerror()? -1 : 0;
680 #endif /* AFS_LINUX22_ENV */
681 #endif /* AFS_SUN5_ENV */
682 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
686 #endif /* AFS_SGI_ENV */
687 #endif /* AFS_HPUX102_ENV */
689 #if defined(AFS_SGI_ENV)
690 /* "pioctl" system call entry point; just pass argument to the parameterized
699 afs_pioctl(struct pioctlargs *uap, rval_t * rvp)
703 AFS_STATCNT(afs_pioctl);
705 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
714 #elif defined(AFS_OSF_ENV)
715 afs_pioctl(struct proc *p, void *args, int *retval)
722 } *uap = (struct a *)args;
724 AFS_STATCNT(afs_pioctl);
725 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
728 #elif defined(AFS_FBSD50_ENV)
730 afs_pioctl(struct thread *td, void *args, int *retval)
737 } *uap = (struct a *)args;
739 AFS_STATCNT(afs_pioctl);
740 return (afs_syscall_pioctl
741 (uap->path, uap->cmd, uap->cmarg, uap->follow, td->td_ucred));
744 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
746 afs_pioctl(struct proc *p, void *args, int *retval)
753 } *uap = (struct a *)args;
755 AFS_STATCNT(afs_pioctl);
756 #ifdef AFS_DARWIN80_ENV
757 return (afs_syscall_pioctl
758 (uap->path, uap->cmd, uap->cmarg, uap->follow,
761 return (afs_syscall_pioctl
762 (uap->path, uap->cmd, uap->cmarg, uap->follow,
763 p->p_cred->pc_ucred));
769 /* macro to avoid adding any more #ifdef's to pioctl code. */
770 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
771 #define PIOCTL_FREE_CRED() crfree(credp)
773 #define PIOCTL_FREE_CRED()
778 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow,
779 rval_t *vvp, struct AFS_UCRED *credp)
781 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
782 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow,
783 struct AFS_UCRED *credp)
785 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
789 struct afs_ioctl data;
790 #ifdef AFS_NEED_CLIENTCONTEXT
791 struct AFS_UCRED *tmpcred = NULL;
793 struct AFS_UCRED *foreigncreds = NULL;
794 register afs_int32 code = 0;
795 struct vnode *vp = NULL;
797 struct ucred *credp = crref(); /* don't free until done! */
799 #ifdef AFS_LINUX22_ENV
800 cred_t *credp = crref(); /* don't free until done! */
804 AFS_STATCNT(afs_syscall_pioctl);
806 follow = 1; /* compat. with old venus */
807 code = copyin_afs_ioctl(cmarg, &data);
810 #if defined(KERNEL_HAVE_UERROR)
815 if ((com & 0xff) == PSetClientContext) {
816 #ifdef AFS_NEED_CLIENTCONTEXT
817 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
818 code = HandleClientContext(&data, &com, &foreigncreds, credp);
820 code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
824 crfree(foreigncreds);
827 #if defined(KERNEL_HAVE_UERROR)
828 return (setuerror(code), code);
833 #else /* AFS_NEED_CLIENTCONTEXT */
835 #endif /* AFS_NEED_CLIENTCONTEXT */
837 #ifdef AFS_NEED_CLIENTCONTEXT
840 * We could have done without temporary setting the u.u_cred below
841 * (foreigncreds could be passed as param the pioctl modules)
842 * but calls such as afs_osi_suser() doesn't allow that since it
843 * references u.u_cred directly. We could, of course, do something
844 * like afs_osi_suser(cred) which, I think, is better since it
845 * generalizes and supports multi cred environments...
847 #if defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
849 credp = foreigncreds;
850 #elif defined(AFS_AIX41_ENV)
851 tmpcred = crref(); /* XXX */
853 #elif defined(AFS_HPUX101_ENV)
854 tmpcred = p_cred(u.u_procp);
855 set_p_cred(u.u_procp, foreigncreds);
856 #elif defined(AFS_SGI_ENV)
857 tmpcred = OSI_GET_CURRENT_CRED();
858 OSI_SET_CURRENT_CRED(foreigncreds);
861 u.u_cred = foreigncreds;
864 #endif /* AFS_NEED_CLIENTCONTEXT */
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_XBSD_ENV)
870 Prefetch(path, &data, follow,
871 foreigncreds ? foreigncreds : credp);
873 code = Prefetch(path, &data, follow, osi_curcred());
876 #if defined(KERNEL_HAVE_UERROR)
885 lookupname(path, USR, follow, NULL, &vp,
886 foreigncreds ? foreigncreds : credp);
888 #ifdef AFS_LINUX22_ENV
889 code = gop_lookupname(path, AFS_UIOUSER, follow, &dp);
891 vp = (struct vnode *)dp->d_inode;
893 code = gop_lookupname(path, AFS_UIOUSER, follow, &vp);
894 #endif /* AFS_LINUX22_ENV */
895 #endif /* AFS_AIX41_ENV */
899 #if defined(KERNEL_HAVE_UERROR)
907 #if defined(AFS_SUN510_ENV)
908 if (vp && !IsAfsVnode(vp)) {
909 struct vnode *realvp;
911 #ifdef AFS_SUN511_ENV
912 (VOP_REALVP(vp, &realvp, NULL) == 0)
914 (VOP_REALVP(vp, &realvp) == 0)
917 struct vnode *oldvp = vp;
925 /* now make the call if we were passed no file, or were passed an AFS file */
926 if (!vp || IsAfsVnode(vp)) {
927 #if defined(AFS_SUN5_ENV)
928 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
929 #elif defined(AFS_AIX41_ENV)
931 struct ucred *cred1, *cred2;
934 cred1 = cred2 = foreigncreds;
936 cred1 = cred2 = credp;
938 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
939 if (cred1 != cred2) {
940 /* something changed the creds */
944 #elif defined(AFS_HPUX101_ENV)
946 struct ucred *cred = p_cred(u.u_procp);
947 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
949 #elif defined(AFS_SGI_ENV)
952 credp = OSI_GET_CURRENT_CRED();
953 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
955 #elif defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
956 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
958 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
961 #if defined(KERNEL_HAVE_UERROR)
964 code = EINVAL; /* not in /afs */
969 #if defined(AFS_NEED_CLIENTCONTEXT)
972 crset(tmpcred); /* restore original credentials */
974 #if defined(AFS_HPUX101_ENV)
975 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
976 #elif defined(AFS_SGI_ENV)
977 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
978 #elif defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
979 credp = tmpcred; /* restore original credentials */
981 osi_curcred() = tmpcred; /* restore original credentials */
982 #endif /* AFS_HPUX101_ENV */
983 crfree(foreigncreds);
986 #endif /* AFS_NEED_CLIENTCONTEXT */
988 #ifdef AFS_LINUX22_ENV
991 AFS_RELE(vp); /* put vnode back */
995 #if defined(KERNEL_HAVE_UERROR)
998 return (getuerror());
1004 #define MAXPIOCTLTOKENLEN \
1005 (3*sizeof(afs_int32)+MAXKTCTICKETLEN+sizeof(struct ClearToken)+MAXKTCREALMLEN)
1008 afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
1009 register struct afs_ioctl *ablob, int afollow,
1010 struct AFS_UCRED **acred)
1013 struct vrequest treq;
1014 register afs_int32 code;
1015 register afs_int32 function, device;
1016 afs_int32 inSize, outSize, outSizeMax;
1017 char *inData, *outData;
1018 pioctlFunction *pioctlSw;
1020 struct afs_fakestat_state fakestate;
1022 avc = avp ? VTOAFS(avp) : NULL;
1023 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1024 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1025 AFS_STATCNT(HandlePioctl);
1026 if ((code = afs_InitReq(&treq, *acred)))
1028 afs_InitFakeStat(&fakestate);
1030 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1032 afs_PutFakeStat(&fakestate);
1036 device = (acom & 0xff00) >> 8;
1038 case 'V': /* Original pioctls */
1039 pioctlSw = VpioctlSw;
1040 pioctlSwSize = sizeof(VpioctlSw);
1042 case 'C': /* Coordinated/common pioctls */
1043 pioctlSw = CpioctlSw;
1044 pioctlSwSize = sizeof(CpioctlSw);
1046 case 'O': /* Coordinated/common pioctls */
1047 pioctlSw = OpioctlSw;
1048 pioctlSwSize = sizeof(OpioctlSw);
1051 afs_PutFakeStat(&fakestate);
1054 function = acom & 0xff;
1055 if (function >= (pioctlSwSize / sizeof(char *))) {
1056 afs_PutFakeStat(&fakestate);
1057 return EINVAL; /* out of range */
1059 inSize = ablob->in_size;
1061 /* Do all range checking before continuing */
1062 if (inSize > MAXPIOCTLTOKENLEN || inSize < 0 || ablob->out_size < 0)
1065 /* Note that we use osi_Alloc for large allocs and osi_AllocLargeSpace for small ones */
1066 if (inSize > AFS_LRALLOCSIZ) {
1067 inData = osi_Alloc(inSize + 1);
1069 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1074 AFS_COPYIN(ablob->in, inData, inSize, code);
1075 inData[inSize] = '\0';
1079 if (inSize > AFS_LRALLOCSIZ) {
1080 osi_Free(inData, inSize + 1);
1082 osi_FreeLargeSpace(inData);
1084 afs_PutFakeStat(&fakestate);
1087 if (function == 8 && device == 'V') { /* PGetTokens */
1088 outSizeMax = MAXPIOCTLTOKENLEN;
1089 outData = osi_Alloc(outSizeMax);
1091 outSizeMax = AFS_LRALLOCSIZ;
1092 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1095 if (inSize > AFS_LRALLOCSIZ) {
1096 osi_Free(inData, inSize + 1);
1098 osi_FreeLargeSpace(inData);
1100 afs_PutFakeStat(&fakestate);
1105 (*pioctlSw[function]) (avc, function, &treq, inData, outData, inSize,
1107 if (inSize > AFS_LRALLOCSIZ) {
1108 osi_Free(inData, inSize + 1);
1110 osi_FreeLargeSpace(inData);
1112 if (code == 0 && ablob->out_size > 0) {
1113 if (outSize > ablob->out_size) {
1114 code = E2BIG; /* data wont fit in user buffer */
1115 } else if (outSize) {
1116 AFS_COPYOUT(outData, ablob->out, outSize, code);
1119 if (outSizeMax > AFS_LRALLOCSIZ) {
1120 osi_Free(outData, outSizeMax);
1122 osi_FreeLargeSpace(outData);
1124 afs_PutFakeStat(&fakestate);
1125 return afs_CheckCode(code, &treq, 41);
1129 * VIOCGETFID (22) - Get file ID quickly
1133 * \param[in] ain not in use
1134 * \param[out] aout fid of requested file
1136 * \retval EINVAL Error if some of the initial arguments aren't set
1138 * \post get the file id of some file
1140 DECL_PIOCTL(PGetFID)
1142 AFS_STATCNT(PGetFID);
1145 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1146 *aoutSize = sizeof(struct VenusFid);
1151 * VIOCSETAL (1) - Set access control list
1155 * \param[in] ain the ACL being set
1156 * \param[out] aout the ACL being set returned
1158 * \retval EINVAL Error if some of the standard args aren't set
1160 * \post Changed ACL, via direct writing to the wire
1162 int dummy_PSetAcl(char *ain, char *aout)
1167 DECL_PIOCTL(PSetAcl)
1169 register afs_int32 code;
1171 struct AFSOpaque acl;
1172 struct AFSVolSync tsync;
1173 struct AFSFetchStatus OutStatus;
1176 AFS_STATCNT(PSetAcl);
1179 if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1024 /* AFSOPAQUEMAX */)
1182 acl.AFSOpaque_val = ain;
1184 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1186 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1189 RXAFS_StoreACL(tconn->id, (struct AFSFid *)&avc->fid.Fid,
1190 &acl, &OutStatus, &tsync);
1195 } while (afs_Analyze
1196 (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STOREACL,
1197 SHARED_LOCK, NULL));
1199 /* now we've forgotten all of the access info */
1200 ObtainWriteLock(&afs_xcbhash, 455);
1202 afs_DequeueCallback(avc);
1203 avc->states &= ~(CStatd | CUnique);
1204 ReleaseWriteLock(&afs_xcbhash);
1205 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1206 osi_dnlc_purgedp(avc);
1210 int afs_defaultAsynchrony = 0;
1213 * VIOC_STOREBEHIND (47) Adjust store asynchrony
1217 * \param[in] ain sbstruct (store behind structure) input
1218 * \param[out] aout resulting sbstruct
1220 * \retval EPERM Error if the user doesn't have super-user credentials
1221 * \retval EACCES Error if there isn't enough access to not check the mode bits
1223 * \post sets asynchrony based on a file, from a struct sbstruct "I THINK"
1225 DECL_PIOCTL(PStoreBehind)
1228 struct sbstruct *sbr;
1230 sbr = (struct sbstruct *)ain;
1231 if (sbr->sb_default != -1) {
1232 if (afs_osi_suser(*acred))
1233 afs_defaultAsynchrony = sbr->sb_default;
1238 if (avc && (sbr->sb_thisfile != -1)) {
1240 (avc, PRSFS_WRITE | PRSFS_ADMINISTER, areq, DONT_CHECK_MODE_BITS))
1241 avc->asynchrony = sbr->sb_thisfile;
1246 *aoutSize = sizeof(struct sbstruct);
1247 sbr = (struct sbstruct *)aout;
1248 sbr->sb_default = afs_defaultAsynchrony;
1250 sbr->sb_thisfile = avc->asynchrony;
1257 * VIOC_GCPAGS (48) - Disable automatic PAG gc'ing
1261 * \param[in] ain not in use
1262 * \param[out] aout not in use
1264 * \retval EACCES Error if the user doesn't have super-user credentials
1266 * \post set the gcpags to GCPAGS_USERDISABLED
1268 DECL_PIOCTL(PGCPAGs)
1270 if (!afs_osi_suser(*acred)) {
1273 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1278 * VIOCGETAL (2) - Get access control list
1282 * \param[in] ain not in use
1283 * \param[out] aout the ACL
1285 * \retval EINVAL Error if some of the standard args aren't set
1286 * \retval ERANGE Error if the vnode of the file id is too large
1287 * \retval -1 Error if getting the ACL failed
1289 * \post Obtain the ACL, based on file ID
1291 * \notes there is a hack to tell which type of ACL is being returned, checks the top 2-bytes to judge what type of ACL it is, only for dfs xlat or ACLs
1293 DECL_PIOCTL(PGetAcl)
1295 struct AFSOpaque acl;
1296 struct AFSVolSync tsync;
1297 struct AFSFetchStatus OutStatus;
1303 AFS_STATCNT(PGetAcl);
1306 Fid.Volume = avc->fid.Fid.Volume;
1307 Fid.Vnode = avc->fid.Fid.Vnode;
1308 Fid.Unique = avc->fid.Fid.Unique;
1309 if (avc->states & CForeign) {
1311 * For a dfs xlator acl we have a special hack so that the
1312 * xlator will distinguish which type of acl will return. So
1313 * we currently use the top 2-bytes (vals 0-4) to tell which
1314 * type of acl to bring back. Horrible hack but this will
1315 * cause the least number of changes to code size and interfaces.
1317 if (Fid.Vnode & 0xc0000000)
1319 Fid.Vnode |= (ainSize << 30);
1321 acl.AFSOpaque_val = aout;
1323 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1326 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1328 code = RXAFS_FetchACL(tconn->id, &Fid, &acl, &OutStatus, &tsync);
1333 } while (afs_Analyze
1334 (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_FETCHACL,
1335 SHARED_LOCK, NULL));
1338 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1344 * PNoop returns success. Used for functions which are not implemented or are no longer in use.
1348 * \notes Functions involved in this: 17 (VIOCENGROUP) -- used to be enable group; 18 (VIOCDISGROUP) -- used to be disable group; 2 (?) -- get/set cache-bypass size threshold
1357 * PBogus returns fail. Used for functions which are not implemented or are no longer in use.
1361 * \retval EINVAL Error if some of the standard args aren't set
1363 * \notes Functions involved in this: 0 (?); 4 (?); 6 (?); 7 (VIOCSTAT); 8 (?); 13 (VIOCGETTIME) -- used to be quick check time; 15 (VIOCPREFETCH) -- prefetch is now special-cased; see pioctl code!; 16 (VIOCNOP) -- used to be testing code; 19 (VIOCLISTGROUPS) -- used to be list group; 23 (VIOCWAITFOREVER) -- used to be waitforever; 57 (VIOC_FPRIOSTATUS) -- arla: set file prio; 58 (VIOC_FHGET) -- arla: fallback getfh; 59 (VIOC_FHOPEN) -- arla: fallback fhopen; 60 (VIOC_XFSDEBUG) -- arla: controls xfsdebug; 61 (VIOC_ARLADEBUG) -- arla: controls arla debug; 62 (VIOC_AVIATOR) -- arla: debug interface; 63 (VIOC_XFSDEBUG_PRINT) -- arla: print xfs status; 64 (VIOC_CALCULATE_CACHE) -- arla: force cache check; 65 (VIOC_BREAKCELLBACK) -- arla: break callback; 68 (?) -- arla: fetch stats;
1367 AFS_STATCNT(PBogus);
1372 * VIOC_FILE_CELL_NAME (30) - Get cell in which file lives
1376 * \param[in] ain not in use (avc used to pass in file id)
1377 * \param[out] aout cell name
1379 * \retval EINVAL Error if some of the standard args aren't set
1380 * \retval ESRCH Error if the file isn't part of a cell
1382 * \post Get a cell based on a passed in file id
1384 DECL_PIOCTL(PGetFileCell)
1386 register struct cell *tcell;
1388 AFS_STATCNT(PGetFileCell);
1391 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1394 strcpy(aout, tcell->cellName);
1395 afs_PutCell(tcell, READ_LOCK);
1396 *aoutSize = strlen(aout) + 1;
1401 * VIOC_GET_WS_CELL (31) - Get cell in which workstation lives
1405 * \param[in] ain not in use
1406 * \param[out] aout cell name
1408 * \retval EIO Error if the afs daemon hasn't started yet
1409 * \retval ESRCH Error if the machine isn't part of a cell, for whatever reason
1411 * \post Get the primary cell that the machine is a part of.
1413 DECL_PIOCTL(PGetWSCell)
1415 struct cell *tcell = NULL;
1417 AFS_STATCNT(PGetWSCell);
1418 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
1419 return EIO; /* Inappropriate ioctl for device */
1421 tcell = afs_GetPrimaryCell(READ_LOCK);
1422 if (!tcell) /* no primary cell? */
1424 strcpy(aout, tcell->cellName);
1425 *aoutSize = strlen(aout) + 1;
1426 afs_PutCell(tcell, READ_LOCK);
1431 * VIOC_GET_PRIMARY_CELL (33) - Get primary cell for caller
1435 * \param[in] ain not in use (user id found via areq)
1436 * \param[out] aout cell name
1438 * \retval ESRCH Error if the user id doesn't have a primary cell specified
1440 * \post Get the primary cell for a certain user, based on the user's uid
1442 DECL_PIOCTL(PGetUserCell)
1444 register afs_int32 i;
1445 register struct unixuser *tu;
1446 register struct cell *tcell;
1448 AFS_STATCNT(PGetUserCell);
1449 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
1450 return EIO; /* Inappropriate ioctl for device */
1452 /* return the cell name of the primary cell for this user */
1453 i = UHash(areq->uid);
1454 ObtainWriteLock(&afs_xuser, 224);
1455 for (tu = afs_users[i]; tu; tu = tu->next) {
1456 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1458 ReleaseWriteLock(&afs_xuser);
1463 tcell = afs_GetCell(tu->cell, READ_LOCK);
1464 afs_PutUser(tu, WRITE_LOCK);
1468 strcpy(aout, tcell->cellName);
1469 afs_PutCell(tcell, READ_LOCK);
1470 *aoutSize = strlen(aout) + 1; /* 1 for the null */
1473 ReleaseWriteLock(&afs_xuser);
1481 * VIOCSETTOK (3) - Set authentication tokens
1485 * \param[in] ain the krb tickets from which to set the afs tokens
1486 * \param[out] aout not in use
1488 * \retval EINVAL Error if the ticket is either too long or too short
1489 * \retval EIO Error if the AFS initState is below 101
1490 * \retval ESRCH Error if the cell for which the Token is being set can't be found
1492 * \post Set the Tokens for a specific cell name, unless there is none set, then default to primary
1495 DECL_PIOCTL(PSetTokens)
1498 register struct unixuser *tu;
1499 struct ClearToken clear;
1500 register struct cell *tcell;
1503 struct vrequest treq;
1504 afs_int32 flag, set_parent_pag = 0;
1506 AFS_STATCNT(PSetTokens);
1507 if (!afs_resourceinit_flag) {
1510 memcpy((char *)&i, ain, sizeof(afs_int32));
1511 ain += sizeof(afs_int32);
1512 stp = ain; /* remember where the ticket is */
1513 if (i < 0 || i > MAXKTCTICKETLEN)
1514 return EINVAL; /* malloc may fail */
1516 ain += i; /* skip over ticket */
1517 memcpy((char *)&i, ain, sizeof(afs_int32));
1518 ain += sizeof(afs_int32);
1519 if (i != sizeof(struct ClearToken)) {
1522 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1523 if (clear.AuthHandle == -1)
1524 clear.AuthHandle = 999; /* more rxvab compat stuff */
1525 ain += sizeof(struct ClearToken);
1526 if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1527 /* still stuff left? we've got primary flag and cell name. Set these */
1528 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1529 ain += sizeof(afs_int32); /* skip id field */
1530 /* rest is cell name, look it up */
1531 /* some versions of gcc appear to need != 0 in order to get this right */
1532 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1536 tcell = afs_GetCellByName(ain, READ_LOCK);
1540 /* default to primary cell, primary id */
1541 flag = 1; /* primary id */
1542 tcell = afs_GetPrimaryCell(READ_LOCK);
1547 afs_PutCell(tcell, READ_LOCK);
1548 if (set_parent_pag) {
1550 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1551 #if defined(AFS_DARWIN_ENV)
1552 struct proc *p = current_proc(); /* XXX */
1554 struct proc *p = curproc; /* XXX */
1556 #ifndef AFS_DARWIN80_ENV
1557 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1558 p->p_pid, p->p_comm);
1560 if (!setpag(p, acred, -1, &pag, 1)) {
1563 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1565 if (!setpag(acred, -1, &pag, 1)) {
1568 afs_InitReq(&treq, *acred);
1572 /* now we just set the tokens */
1573 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1574 tu->vid = clear.ViceId;
1575 if (tu->stp != NULL) {
1576 afs_osi_Free(tu->stp, tu->stLen);
1578 tu->stp = (char *)afs_osi_Alloc(stLen);
1579 if (tu->stp == NULL) {
1583 memcpy(tu->stp, stp, stLen);
1586 afs_stats_cmfullperf.authent.TicketUpdates++;
1587 afs_ComputePAGStats();
1588 #endif /* AFS_NOSTATS */
1589 tu->states |= UHasTokens;
1590 tu->states &= ~UTokensBad;
1591 afs_SetPrimary(tu, flag);
1592 tu->tokenTime = osi_Time();
1593 afs_ResetUserConns(tu);
1594 afs_PutUser(tu, WRITE_LOCK);
1610 * VIOCGETVOLSTAT (4) - Get volume status
1614 * \param[in] ain not in use
1615 * \param[out] aout status of the volume
1617 * \retval EINVAL Error if some of the standard args aren't set
1619 * \post The status of a volume (based on the FID of the volume), or an offline message /motd
1621 DECL_PIOCTL(PGetVolumeStatus)
1624 char *offLineMsg = afs_osi_Alloc(256);
1625 char *motd = afs_osi_Alloc(256);
1626 register struct conn *tc;
1627 register afs_int32 code = 0;
1628 struct AFSFetchVolumeStatus volstat;
1630 char *Name, *OfflineMsg, *MOTD;
1633 AFS_STATCNT(PGetVolumeStatus);
1639 OfflineMsg = offLineMsg;
1642 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1644 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1647 RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1648 &Name, &OfflineMsg, &MOTD);
1653 } while (afs_Analyze
1654 (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1655 SHARED_LOCK, NULL));
1659 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1661 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1662 cp += sizeof(VolumeStatus);
1663 strcpy(cp, volName);
1664 cp += strlen(volName) + 1;
1665 strcpy(cp, offLineMsg);
1666 cp += strlen(offLineMsg) + 1;
1668 cp += strlen(motd) + 1;
1669 *aoutSize = (cp - aout);
1671 afs_osi_Free(offLineMsg, 256);
1672 afs_osi_Free(motd, 256);
1677 * VIOCSETVOLSTAT (5) - Set volume status
1681 * \param[in] ain values to set the status at, offline message, message of the day, volume name, minimum quota, maximum quota
1682 * \param[out] aout status of a volume, offlines messages, minimum quota, maximumm quota
1684 * \retval EINVAL Error if some of the standard args aren't set
1685 * \retval EROFS Error if the volume is read only, or a backup volume
1686 * \retval ENODEV Error if the volume can't be accessed
1687 * \retval E2BIG Error if the volume name, offline message, and motd are too big
1689 * \post Set the status of a volume, including any offline messages, a minimum quota, and a maximum quota
1691 DECL_PIOCTL(PSetVolumeStatus)
1694 char *offLineMsg = afs_osi_Alloc(256);
1695 char *motd = afs_osi_Alloc(256);
1696 register struct conn *tc;
1697 register afs_int32 code = 0;
1698 struct AFSFetchVolumeStatus volstat;
1699 struct AFSStoreVolumeStatus storeStat;
1700 register struct volume *tvp;
1704 AFS_STATCNT(PSetVolumeStatus);
1710 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1712 if (tvp->states & (VRO | VBackup)) {
1713 afs_PutVolume(tvp, READ_LOCK);
1717 afs_PutVolume(tvp, READ_LOCK);
1722 /* Copy the junk out, using cp as a roving pointer. */
1724 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1725 cp += sizeof(AFSFetchVolumeStatus);
1726 if (strlen(cp) >= sizeof(volName)) {
1730 strcpy(volName, cp);
1731 cp += strlen(volName) + 1;
1732 if (strlen(cp) >= sizeof(offLineMsg)) {
1736 strcpy(offLineMsg, cp);
1737 cp += strlen(offLineMsg) + 1;
1738 if (strlen(cp) >= sizeof(motd)) {
1744 if (volstat.MinQuota != -1) {
1745 storeStat.MinQuota = volstat.MinQuota;
1746 storeStat.Mask |= AFS_SETMINQUOTA;
1748 if (volstat.MaxQuota != -1) {
1749 storeStat.MaxQuota = volstat.MaxQuota;
1750 storeStat.Mask |= AFS_SETMAXQUOTA;
1753 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1755 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1758 RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume, &storeStat,
1759 volName, offLineMsg, motd);
1764 } while (afs_Analyze
1765 (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1766 SHARED_LOCK, NULL));
1770 /* we are sending parms back to make compat. with prev system. should
1771 * change interface later to not ask for current status, just set new status */
1773 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1774 cp += sizeof(VolumeStatus);
1775 strcpy(cp, volName);
1776 cp += strlen(volName) + 1;
1777 strcpy(cp, offLineMsg);
1778 cp += strlen(offLineMsg) + 1;
1780 cp += strlen(motd) + 1;
1781 *aoutSize = cp - aout;
1783 afs_osi_Free(offLineMsg, 256);
1784 afs_osi_Free(motd, 256);
1789 * VIOCFLUSH (6) - Invalidate cache entry
1793 * \param[in] ain not in use
1794 * \param[out] aout not in use
1796 * \retval EINVAL Error if some of the standard args aren't set
1798 * \post Flush any information the cache manager has on an entry
1802 AFS_STATCNT(PFlush);
1805 #ifdef AFS_BOZONLOCK_ENV
1806 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1808 ObtainWriteLock(&avc->lock, 225);
1809 afs_ResetVCache(avc, *acred);
1810 ReleaseWriteLock(&avc->lock);
1811 #ifdef AFS_BOZONLOCK_ENV
1812 afs_BozonUnlock(&avc->pvnLock, avc);
1818 * VIOC_AFS_STAT_MT_PT (29) - Stat mount point
1822 * \param[in] ain the last component in a path, related to mountpoint that we're looking for information about
1823 * \param[out] aout volume, cell, link data
1825 * \retval EINVAL Error if some of the standard args aren't set
1826 * \retval ENOTDIR Error if the 'mount point' argument isn't a directory
1827 * \retval EIO Error if the link data can't be accessed
1829 * \post Get the volume, and cell, as well as the link data for a mount point
1831 DECL_PIOCTL(PNewStatMount)
1833 register afs_int32 code;
1834 register struct vcache *tvc;
1835 register struct dcache *tdc;
1836 struct VenusFid tfid;
1838 struct sysname_info sysState;
1839 afs_size_t offset, len;
1841 AFS_STATCNT(PNewStatMount);
1844 code = afs_VerifyVCache(avc, areq);
1847 if (vType(avc) != VDIR) {
1850 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1853 Check_AtSys(avc, ain, &sysState, areq);
1854 ObtainReadLock(&tdc->lock);
1856 code = afs_dir_Lookup(tdc, sysState.name, &tfid.Fid);
1857 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1858 ReleaseReadLock(&tdc->lock);
1859 afs_PutDCache(tdc); /* we're done with the data */
1860 bufp = sysState.name;
1864 tfid.Cell = avc->fid.Cell;
1865 tfid.Fid.Volume = avc->fid.Fid.Volume;
1866 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1867 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1869 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1875 if (tvc->mvstat != 1) {
1880 ObtainWriteLock(&tvc->lock, 226);
1881 code = afs_HandleLink(tvc, areq);
1883 if (tvc->linkData) {
1884 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1887 /* we have the data */
1888 strcpy(aout, tvc->linkData);
1889 *aoutSize = strlen(tvc->linkData) + 1;
1894 ReleaseWriteLock(&tvc->lock);
1897 if (sysState.allocked)
1898 osi_FreeLargeSpace(bufp);
1903 * VIOCGETTOK (8) - Get authentication tokens
1907 * \param[in] ain userid
1908 * \param[out] aout token
1910 * \retval EIO Error if the afs daemon hasn't started yet
1911 * \retval EDOM Error if the input parameter is out of the bounds of the available tokens
1912 * \retval ENOTCONN Error if there aren't tokens for this cell
1914 * \post If the input paramater exists, get the token that corresponds to the parameter value, if there is no token at this value, get the token for the first cell
1916 * \notes "it's a weird interface (from comments in the code)"
1919 DECL_PIOCTL(PGetTokens)
1921 register struct cell *tcell;
1922 register afs_int32 i;
1923 register struct unixuser *tu;
1928 AFS_STATCNT(PGetTokens);
1929 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
1930 return EIO; /* Inappropriate ioctl for device */
1932 /* weird interface. If input parameter is present, it is an integer and
1933 * we're supposed to return the parm'th tokens for this unix uid.
1934 * If not present, we just return tokens for cell 1.
1935 * If counter out of bounds, return EDOM.
1936 * If no tokens for the particular cell, return ENOTCONN.
1937 * Also, if this mysterious parm is present, we return, along with the
1938 * tokens, the primary cell indicator (an afs_int32 0) and the cell name
1939 * at the end, in that order.
1941 if ((newStyle = (ainSize > 0))) {
1942 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1944 i = UHash(areq->uid);
1945 ObtainReadLock(&afs_xuser);
1946 for (tu = afs_users[i]; tu; tu = tu->next) {
1948 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1949 if (iterator-- == 0)
1950 break; /* are we done yet? */
1953 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell))
1959 * No need to hold a read lock on each user entry
1963 ReleaseReadLock(&afs_xuser);
1968 if (((tu->states & UHasTokens) == 0)
1969 || (tu->ct.EndTimestamp < osi_Time())) {
1970 tu->states |= (UTokensBad | UNeedsReset);
1971 afs_PutUser(tu, READ_LOCK);
1974 /* use iterator for temp */
1976 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1978 iterator = 56; /* # of bytes we're returning */
1979 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1980 cp += sizeof(afs_int32);
1981 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1983 iterator = sizeof(struct ClearToken);
1984 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1985 cp += sizeof(afs_int32);
1986 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1987 cp += sizeof(struct ClearToken);
1989 /* put out primary id and cell name, too */
1990 iterator = (tu->states & UPrimary ? 1 : 0);
1991 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1992 cp += sizeof(afs_int32);
1993 tcell = afs_GetCell(tu->cell, READ_LOCK);
1995 strcpy(cp, tcell->cellName);
1996 cp += strlen(tcell->cellName) + 1;
1997 afs_PutCell(tcell, READ_LOCK);
2001 *aoutSize = cp - aout;
2002 afs_PutUser(tu, READ_LOCK);
2007 * VIOCUNLOG (9) - Invalidate tokens
2011 * \param[in] ain not in use
2012 * \param[out] aout not in use
2014 * \retval EIO Error if the afs daemon hasn't been started yet
2016 * \post remove tokens from a user, specified by the user id
2018 * \notes sets the token's time to 0, which then causes it to be removed
2019 * \notes Unlog is the same as un-pag in OpenAFS
2023 register afs_int32 i;
2024 register struct unixuser *tu;
2026 AFS_STATCNT(PUnlog);
2027 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2028 return EIO; /* Inappropriate ioctl for device */
2030 i = UHash(areq->uid);
2031 ObtainWriteLock(&afs_xuser, 227);
2032 for (tu = afs_users[i]; tu; tu = tu->next) {
2033 if (tu->uid == areq->uid) {
2035 tu->states &= ~UHasTokens;
2036 /* security is not having to say you're sorry */
2037 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
2039 ReleaseWriteLock(&afs_xuser);
2040 /* We have to drop the lock over the call to afs_ResetUserConns, since
2041 * it obtains the afs_xvcache lock. We could also keep the lock, and
2042 * modify ResetUserConns to take parm saying we obtained the lock
2043 * already, but that is overkill. By keeping the "tu" pointer
2044 * held over the released lock, we guarantee that we won't lose our
2045 * place, and that we'll pass over every user conn that existed when
2046 * we began this call.
2048 afs_ResetUserConns(tu);
2050 ObtainWriteLock(&afs_xuser, 228);
2052 /* set the expire times to 0, causes
2053 * afs_GCUserData to remove this entry
2055 tu->ct.EndTimestamp = 0;
2057 #endif /* UKERNEL */
2060 ReleaseWriteLock(&afs_xuser);
2065 * VIOC_AFS_MARINER_HOST (32) - Get/set mariner (cache manager monitor) host
2069 * \param[in] ain host address to be set
2070 * \param[out] aout old host address
2072 * \post depending on whether or not a variable is set, either get the host for the cache manager monitor, or set the old address and give it a new address
2074 * \notes Errors turn off mariner
2076 DECL_PIOCTL(PMariner)
2078 afs_int32 newHostAddr;
2079 afs_int32 oldHostAddr;
2081 AFS_STATCNT(PMariner);
2083 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost,
2086 oldHostAddr = 0xffffffff; /* disabled */
2088 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
2089 if (newHostAddr == 0xffffffff) {
2090 /* disable mariner operations */
2092 } else if (newHostAddr) {
2094 afs_marinerHost = newHostAddr;
2096 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
2097 *aoutSize = sizeof(afs_int32);
2102 * VIOCCKSERV (10) - Check that servers are up
2106 * \param[in] ain name of the cell
2107 * \param[out] aout current down server list
2109 * \retval EIO Error if the afs daemon hasn't started yet
2110 * \retval EACCES Error if the user doesn't have super-user credentials
2111 * \retval ENOENT Error if we are unable to obtain the cell
2113 * \post Either a fast check (where it doesn't contact servers) or a local check (checks local cell only)
2115 DECL_PIOCTL(PCheckServers)
2117 register char *cp = 0;
2119 register struct server *ts;
2120 afs_int32 temp, *lp = (afs_int32 *) ain, havecell = 0;
2122 struct chservinfo *pcheck;
2124 AFS_STATCNT(PCheckServers);
2126 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2127 return EIO; /* Inappropriate ioctl for device */
2129 if (*lp == 0x12345678) { /* For afs3.3 version */
2130 pcheck = (struct chservinfo *)ain;
2131 if (pcheck->tinterval >= 0) {
2133 memcpy(cp, (char *)&afs_probe_interval, sizeof(afs_int32));
2134 *aoutSize = sizeof(afs_int32);
2135 if (pcheck->tinterval > 0) {
2136 if (!afs_osi_suser(*acred))
2138 afs_probe_interval = pcheck->tinterval;
2144 temp = pcheck->tflags;
2145 cp = pcheck->tbuffer;
2146 } else { /* For pre afs3.3 versions */
2147 memcpy((char *)&temp, ain, sizeof(afs_int32));
2148 cp = ain + sizeof(afs_int32);
2149 if (ainSize > sizeof(afs_int32))
2154 * 1: fast check, don't contact servers.
2155 * 2: local cell only.
2158 /* have cell name, too */
2159 cellp = afs_GetCellByName(cp, READ_LOCK);
2164 if (!cellp && (temp & 2)) {
2165 /* use local cell */
2166 cellp = afs_GetPrimaryCell(READ_LOCK);
2168 if (!(temp & 1)) { /* if not fast, call server checker routine */
2169 afs_CheckServers(1, cellp); /* check down servers */
2170 afs_CheckServers(0, cellp); /* check up servers */
2172 /* now return the current down server list */
2174 ObtainReadLock(&afs_xserver);
2175 for (i = 0; i < NSERVERS; i++) {
2176 for (ts = afs_servers[i]; ts; ts = ts->next) {
2177 if (cellp && ts->cell != cellp)
2178 continue; /* cell spec'd and wrong */
2179 if ((ts->flags & SRVR_ISDOWN)
2180 && ts->addr->sa_portal != ts->cell->vlport) {
2181 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2182 cp += sizeof(afs_int32);
2186 ReleaseReadLock(&afs_xserver);
2188 afs_PutCell(cellp, READ_LOCK);
2189 *aoutSize = cp - aout;
2194 * VIOCCKBACK (11) - Check backup volume mappings
2198 * \param[in] ain not in use
2199 * \param[out] aout not in use
2201 * \retval EIO Error if the afs daemon hasn't started yet
2203 * \post Check the root volume, and then check the names if the volume check variable is set to force, has expired, is busy, or if the mount points variable is set
2205 DECL_PIOCTL(PCheckVolNames)
2207 AFS_STATCNT(PCheckVolNames);
2208 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2209 return EIO; /* Inappropriate ioctl for device */
2211 afs_CheckRootVolume();
2212 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE | AFS_VOLCHECK_EXPIRED |
2213 AFS_VOLCHECK_BUSY | AFS_VOLCHECK_MTPTS);
2218 * VIOCCKCONN (12) - Check connections for a user
2222 * \param[in] ain not in use
2223 * \param[out] aout not in use
2225 * \retval EACCESS Error if no user is specififed, the user has no tokens set, or if the user's tokens are bad
2227 * \post check to see if a user has the correct authentication. If so, allow access.
2229 * \notes Check the connections to all the servers specified
2231 DECL_PIOCTL(PCheckAuth)
2236 struct unixuser *tu;
2239 AFS_STATCNT(PCheckAuth);
2240 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2241 return EIO; /* Inappropriate ioctl for device */
2244 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
2248 /* we have a user */
2249 ObtainReadLock(&afs_xsrvAddr);
2250 ObtainReadLock(&afs_xconn);
2252 /* any tokens set? */
2253 if ((tu->states & UHasTokens) == 0)
2255 /* all connections in cell 1 working? */
2256 for (i = 0; i < NSERVERS; i++) {
2257 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2258 for (tc = sa->conns; tc; tc = tc->next) {
2259 if (tc->user == tu && (tu->states & UTokensBad))
2264 ReleaseReadLock(&afs_xsrvAddr);
2265 ReleaseReadLock(&afs_xconn);
2266 afs_PutUser(tu, READ_LOCK);
2268 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
2269 *aoutSize = sizeof(afs_int32);
2274 Prefetch(char *apath, struct afs_ioctl *adata, int afollow,
2275 struct AFS_UCRED *acred)
2278 register afs_int32 code;
2279 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
2285 AFS_STATCNT(Prefetch);
2288 tp = osi_AllocLargeSpace(1024);
2289 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
2291 osi_FreeLargeSpace(tp);
2294 if (afs_BBusy()) { /* do this as late as possible */
2295 osi_FreeLargeSpace(tp);
2296 return EWOULDBLOCK; /* pretty close */
2298 afs_BQueue(BOP_PATH, (struct vcache *)0, 0, 0, acred, (afs_size_t) 0,
2299 (afs_size_t) 0, tp);
2304 * VIOCWHEREIS (14) - Find out where a volume is located
2308 * \param[in] ain not in use
2309 * \param[out] aout volume location
2311 * \retval EINVAL Error if some of the default arguments don't exist
2312 * \retval ENODEV Error if there is no such volume
2314 * \post fine a volume, based on a volume file id
2316 * \notes check each of the servers specified
2318 DECL_PIOCTL(PFindVolume)
2320 register struct volume *tvp;
2321 register struct server *ts;
2322 register afs_int32 i;
2325 AFS_STATCNT(PFindVolume);
2328 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2331 for (i = 0; i < MAXHOSTS; i++) {
2332 ts = tvp->serverHost[i];
2335 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2336 cp += sizeof(afs_int32);
2339 /* still room for terminating NULL, add it on */
2340 ainSize = 0; /* reuse vbl */
2341 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2342 cp += sizeof(afs_int32);
2344 *aoutSize = cp - aout;
2345 afs_PutVolume(tvp, READ_LOCK);
2352 * VIOCACCESS (20) - Access using PRS_FS bits
2356 * \param[in] ain PRS_FS bits
2357 * \param[out] aout not in use
2359 * \retval EINVAL Error if some of the initial arguments aren't set
2360 * \retval EACCES Error if access is denied
2362 * \post check to make sure access is allowed
2364 DECL_PIOCTL(PViceAccess)
2366 register afs_int32 code;
2369 AFS_STATCNT(PViceAccess);
2372 code = afs_VerifyVCache(avc, areq);
2375 memcpy((char *)&temp, ain, sizeof(afs_int32));
2376 code = afs_AccessOK(avc, temp, areq, CHECK_MODE_BITS);
2383 DECL_PIOCTL(PPrecache)
2387 /*AFS_STATCNT(PPrecache);*/
2388 if (!afs_osi_suser(*acred))
2390 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2391 afs_preCache = newValue*1024;
2396 * VIOCSETCACHESIZE (24) - Set venus cache size in 1000 units
2400 * \param[in] ain the size the venus cache should be set to
2401 * \param[out] aout not in use
2403 * \retval EACCES Error if the user doesn't have super-user credentials
2404 * \retval EROFS Error if the cache is set to be in memory
2406 * \post Set the cache size based on user input. If no size is given, set it to the default OpenAFS cache size.
2408 * \notes recompute the general cache parameters for every single block allocated
2410 DECL_PIOCTL(PSetCacheSize)
2415 AFS_STATCNT(PSetCacheSize);
2416 if (!afs_osi_suser(*acred))
2418 /* too many things are setup initially in mem cache version */
2419 if (cacheDiskType == AFS_FCACHE_TYPE_MEM)
2421 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2423 afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2425 if (newValue < afs_min_cache)
2426 afs_cacheBlocks = afs_min_cache;
2428 afs_cacheBlocks = newValue;
2430 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2431 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2432 afs_MaybeWakeupTruncateDaemon();
2433 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2434 afs_osi_Wait(1000, 0, 0);
2435 afs_MaybeWakeupTruncateDaemon();
2440 #define MAXGCSTATS 16
2442 * VIOCGETCACHEPARMS (40) - Get cache stats
2446 * \param[in] ain afs index flags
2447 * \param[out] aout cache blocks, blocks used, blocks files (in an array)
2449 * \post Get the cache blocks, and how many of the cache blocks there are
2451 DECL_PIOCTL(PGetCacheSize)
2453 afs_int32 results[MAXGCSTATS];
2455 register struct dcache * tdc;
2458 AFS_STATCNT(PGetCacheSize);
2460 if (sizeof(afs_int32) == ainSize){
2461 memcpy((char *)&flags, ain, sizeof(afs_int32));
2462 } else if (0 == ainSize){
2468 memset((char *)results, 0, sizeof(results));
2469 results[0] = afs_cacheBlocks;
2470 results[1] = afs_blocksUsed;
2471 results[2] = afs_cacheFiles;
2474 for (i = 0; i < afs_cacheFiles; i++) {
2475 if (afs_indexFlags[i] & IFFree) results[3]++;
2477 } else if (2 == flags){
2478 for (i = 0; i < afs_cacheFiles; i++) {
2479 if (afs_indexFlags[i] & IFFree) results[3]++;
2480 if (afs_indexFlags[i] & IFEverUsed) results[4]++;
2481 if (afs_indexFlags[i] & IFDataMod) results[5]++;
2482 if (afs_indexFlags[i] & IFDirtyPages) results[6]++;
2483 if (afs_indexFlags[i] & IFAnyPages) results[7]++;
2484 if (afs_indexFlags[i] & IFDiscarded) results[8]++;
2486 tdc = afs_indexTable[i];
2489 size = tdc->validPos;
2490 if ( 0 < size && size < (1<<12) ) results[10]++;
2491 else if (size < (1<<14) ) results[11]++;
2492 else if (size < (1<<16) ) results[12]++;
2493 else if (size < (1<<18) ) results[13]++;
2494 else if (size < (1<<20) ) results[14]++;
2495 else if (size >= (1<<20) ) results[15]++;
2499 memcpy(aout, (char *)results, sizeof(results));
2500 *aoutSize = sizeof(results);
2505 * VIOCFLUSHCB (25) - Flush callback only
2509 * \param[in] ain not in use
2510 * \param[out] aout not in use
2512 * \retval EINVAL Error if some of the standard args aren't set
2513 * \retval 0 0 returned if the volume is set to read-only
2515 * \post Flushes callbacks, by setting the length of callbacks to one, setting the next callback to be sent to the CB_DROPPED value, and then dequeues everything else.
2517 DECL_PIOCTL(PRemoveCallBack)
2519 register struct conn *tc;
2520 register afs_int32 code = 0;
2521 struct AFSCallBack CallBacks_Array[1];
2522 struct AFSCBFids theFids;
2523 struct AFSCBs theCBs;
2526 AFS_STATCNT(PRemoveCallBack);
2529 if (avc->states & CRO)
2530 return 0; /* read-only-ness can't change */
2531 ObtainWriteLock(&avc->lock, 229);
2532 theFids.AFSCBFids_len = 1;
2533 theCBs.AFSCBs_len = 1;
2534 theFids.AFSCBFids_val = (struct AFSFid *)&avc->fid.Fid;
2535 theCBs.AFSCBs_val = CallBacks_Array;
2536 CallBacks_Array[0].CallBackType = CB_DROPPED;
2537 if (avc->callback) {
2539 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2541 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2543 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2547 /* don't set code on failure since we wouldn't use it */
2548 } while (afs_Analyze
2549 (tc, code, &avc->fid, areq,
2550 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS, SHARED_LOCK, NULL));
2552 ObtainWriteLock(&afs_xcbhash, 457);
2553 afs_DequeueCallback(avc);
2555 avc->states &= ~(CStatd | CUnique);
2556 ReleaseWriteLock(&afs_xcbhash);
2557 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2558 osi_dnlc_purgedp(avc);
2560 ReleaseWriteLock(&avc->lock);
2565 * VIOCNEWCELL (26) - Configure new cell
2569 * \param[in] ain the name of the cell, the hosts that will be a part of the cell, whether or not it's linked with another cell, the other cell it's linked with, the file server port, and the volume server port
2570 * \param[out] aout not in use
2572 * \retval EIO Error if the afs daemon hasn't started yet
2573 * \retval EACCES Error if the user doesn't have super-user cedentials
2574 * \retval EINVAL Error if some 'magic' var doesn't have a certain bit set
2576 * \post creates a new cell
2578 DECL_PIOCTL(PNewCell)
2580 /* create a new cell */
2581 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic = 0;
2582 char *newcell = 0, *linkedcell = 0, *tp = ain;
2583 register afs_int32 code, linkedstate = 0, ls;
2584 u_short fsport = 0, vlport = 0;
2587 AFS_STATCNT(PNewCell);
2588 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2589 return EIO; /* Inappropriate ioctl for device */
2591 if (!afs_osi_suser(*acred))
2594 memcpy((char *)&magic, tp, sizeof(afs_int32));
2595 tp += sizeof(afs_int32);
2596 if (magic != 0x12345678)
2599 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2600 * server addresses while the 3.5 fs newcell command passes
2601 * MAXHOSTS. To figure out which is which, check if the cellname
2604 newcell = tp + (MAXCELLHOSTS + 3) * sizeof(afs_int32);
2605 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2607 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2608 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2609 tp += (scount * sizeof(afs_int32));
2611 lp = (afs_int32 *) tp;
2615 fsport = 0; /* Privileged ports not allowed */
2617 vlport = 0; /* Privileged ports not allowed */
2618 tp += (3 * sizeof(afs_int32));
2620 if ((ls = *lp) & 1) {
2621 linkedcell = tp + strlen(newcell) + 1;
2622 linkedstate |= CLinkedCell;
2625 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2627 afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2632 DECL_PIOCTL(PNewAlias)
2634 /* create a new cell alias */
2636 register afs_int32 code;
2637 char *realName, *aliasName;
2639 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2640 return EIO; /* Inappropriate ioctl for device */
2642 if (!afs_osi_suser(*acred))
2646 tp += strlen(aliasName) + 1;
2649 code = afs_NewCellAlias(aliasName, realName);
2655 * VIOCGETCELL (27) - Get cell info
2659 * \param[in] ain The cell index of a specific cell
2660 * \param[out] aout list of servers in the cell
2662 * \retval EIO Error if the afs daemon hasn't started yet
2663 * \retval EDOM Error if there is no cell asked about
2665 * \post Lists the cell's server names and and addresses
2667 DECL_PIOCTL(PListCells)
2669 afs_int32 whichCell;
2670 register struct cell *tcell = 0;
2671 register afs_int32 i;
2672 register char *cp, *tp = ain;
2674 AFS_STATCNT(PListCells);
2675 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2676 return EIO; /* Inappropriate ioctl for device */
2678 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2679 tp += sizeof(afs_int32);
2680 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2683 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2684 for (i = 0; i < MAXCELLHOSTS; i++) {
2685 if (tcell->cellHosts[i] == 0)
2687 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip,
2689 cp += sizeof(afs_int32);
2691 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2692 strcpy(cp, tcell->cellName);
2693 cp += strlen(tcell->cellName) + 1;
2694 *aoutSize = cp - aout;
2695 afs_PutCell(tcell, READ_LOCK);
2703 DECL_PIOCTL(PListAliases)
2705 afs_int32 whichAlias;
2706 register struct cell_alias *tcalias = 0;
2707 register char *cp, *tp = ain;
2709 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2710 return EIO; /* Inappropriate ioctl for device */
2711 if (ainSize < sizeof(afs_int32))
2714 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2715 tp += sizeof(afs_int32);
2717 tcalias = afs_GetCellAlias(whichAlias);
2720 strcpy(cp, tcalias->alias);
2721 cp += strlen(tcalias->alias) + 1;
2722 strcpy(cp, tcalias->cell);
2723 cp += strlen(tcalias->cell) + 1;
2724 *aoutSize = cp - aout;
2725 afs_PutCellAlias(tcalias);
2734 * VIOC_AFS_DELETE_MT_PT (28) - Delete mount point
2738 * \param[in] ain the name of the file in this dir to remove
2739 * \param[out] aout not in use
2741 * \retval EINVAL Error if some of the standard args aren't set
2742 * \retval ENOTDIR Error if the argument to remove is not a directory
2743 * \retval ENOENT Error if there is no cache to remove the mount point from or if a vcache doesn't exist
2745 * \post Ensure that everything is OK before deleting the mountpoint. If not, don't delete. Delete a mount point based on a file id.
2747 DECL_PIOCTL(PRemoveMount)
2749 register afs_int32 code;
2751 struct sysname_info sysState;
2752 afs_size_t offset, len;
2753 register struct conn *tc;
2754 register struct dcache *tdc;
2755 register struct vcache *tvc;
2756 struct AFSFetchStatus OutDirStatus;
2757 struct VenusFid tfid;
2758 struct AFSVolSync tsync;
2762 /* "ain" is the name of the file in this dir to remove */
2764 AFS_STATCNT(PRemoveMount);
2767 code = afs_VerifyVCache(avc, areq);
2770 if (vType(avc) != VDIR)
2773 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2776 Check_AtSys(avc, ain, &sysState, areq);
2777 ObtainReadLock(&tdc->lock);
2779 code = afs_dir_Lookup(tdc, sysState.name, &tfid.Fid);
2780 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2781 ReleaseReadLock(&tdc->lock);
2782 bufp = sysState.name;
2787 tfid.Cell = avc->fid.Cell;
2788 tfid.Fid.Volume = avc->fid.Fid.Volume;
2789 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2790 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2792 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2799 if (tvc->mvstat != 1) {
2805 ObtainWriteLock(&tvc->lock, 230);
2806 code = afs_HandleLink(tvc, areq);
2808 if (tvc->linkData) {
2809 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2814 ReleaseWriteLock(&tvc->lock);
2815 osi_dnlc_purgedp(tvc);
2821 ObtainWriteLock(&avc->lock, 231);
2822 osi_dnlc_remove(avc, bufp, tvc);
2824 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2826 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2829 RXAFS_RemoveFile(tc->id, (struct AFSFid *)&avc->fid.Fid, bufp,
2830 &OutDirStatus, &tsync);
2835 } while (afs_Analyze
2836 (tc, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_REMOVEFILE,
2837 SHARED_LOCK, NULL));
2842 ReleaseWriteLock(&avc->lock);
2846 /* we have the thing in the cache */
2847 ObtainWriteLock(&tdc->lock, 661);
2848 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2849 /* we can do it locally */
2850 code = afs_dir_Delete(tdc, bufp);
2852 ZapDCE(tdc); /* surprise error -- invalid value */
2856 ReleaseWriteLock(&tdc->lock);
2857 afs_PutDCache(tdc); /* drop ref count */
2859 avc->states &= ~CUnique; /* For the dfs xlator */
2860 ReleaseWriteLock(&avc->lock);
2863 if (sysState.allocked)
2864 osi_FreeLargeSpace(bufp);
2869 * VIOC_VENUSLOG (34) - Enable/Disable venus logging
2873 * \retval EINVAL Error if some of the standard args aren't set
2875 * \notes Obsoleted, perhaps should be PBogus
2877 DECL_PIOCTL(PVenusLogging)
2879 return EINVAL; /* OBSOLETE */
2883 * VIOC_GETCELLSTATUS (35) - Get cell status info
2887 * \param[in] ain The cell you want status information on
2888 * \param[out] aout cell state (as a struct)
2890 * \retval EIO Error if the afs daemon hasn't started yet
2891 * \retval ENOENT Error if the cell doesn't exist
2893 * \post Returns the state of the cell as defined in a struct cell
2895 DECL_PIOCTL(PGetCellStatus)
2897 register struct cell *tcell;
2900 AFS_STATCNT(PGetCellStatus);
2901 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2902 return EIO; /* Inappropriate ioctl for device */
2904 tcell = afs_GetCellByName(ain, READ_LOCK);
2907 temp = tcell->states;
2908 afs_PutCell(tcell, READ_LOCK);
2909 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2910 *aoutSize = sizeof(afs_int32);
2915 * VIOC_SETCELLSTATUS (36) - Set corresponding info
2919 * \param[in] ain The cell you want to set information about, and the values you want to set
2920 * \param[out] aout not in use
2922 * \retval EIO Error if the afs daemon hasn't started yet
2923 * \retval EACCES Error if the user doesn't have super-user credentials
2925 * \post Set the state of the cell in a defined struct cell, based on whether or not SetUID is allowed
2927 DECL_PIOCTL(PSetCellStatus)
2929 register struct cell *tcell;
2932 if (!afs_osi_suser(*acred))
2934 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2935 return EIO; /* Inappropriate ioctl for device */
2937 tcell = afs_GetCellByName(ain + 2 * sizeof(afs_int32), WRITE_LOCK);
2940 memcpy((char *)&temp, ain, sizeof(afs_int32));
2942 tcell->states |= CNoSUID;
2944 tcell->states &= ~CNoSUID;
2945 afs_PutCell(tcell, WRITE_LOCK);
2950 * VIOC_FLUSHVOLUME (37) - Flush whole volume's data
2954 * \param[in] ain not in use (args in avc)
2955 * \param[out] aout not in use
2957 * \retval EINVAL Error if some of the standard args aren't set
2958 * \retval EIO Error if the afs daemon hasn't started yet
2960 * \post Wipe everything on the volume. This is done dependent on which platform this is for.
2962 * \notes Does not flush a file that a user has open and is using, because it will be re-created on next write. Also purges the dnlc, because things are screwed up.
2964 DECL_PIOCTL(PFlushVolumeData)
2966 register afs_int32 i;
2967 register struct dcache *tdc;
2968 register struct vcache *tvc;
2969 register struct volume *tv;
2970 afs_int32 cell, volume;
2971 struct afs_q *tq, *uq;
2972 #ifdef AFS_DARWIN80_ENV
2976 AFS_STATCNT(PFlushVolumeData);
2979 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
2980 return EIO; /* Inappropriate ioctl for device */
2982 volume = avc->fid.Fid.Volume; /* who to zap */
2983 cell = avc->fid.Cell;
2986 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2987 * the vcaches associated with the volume.
2990 ObtainReadLock(&afs_xvcache);
2991 i = VCHashV(&avc->fid);
2992 for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
2995 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2996 if (tvc->states & CVInit) {
2997 ReleaseReadLock(&afs_xvcache);
2998 afs_osi_Sleep(&tvc->states);
3001 #ifdef AFS_DARWIN80_ENV
3002 if (tvc->states & CDeadVnode) {
3003 ReleaseReadLock(&afs_xvcache);
3004 afs_osi_Sleep(&tvc->states);
3008 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
3009 VN_HOLD(AFSTOV(tvc));
3011 #ifdef AFS_DARWIN80_ENV
3015 if (vnode_ref(vp)) {
3022 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
3025 VREFCOUNT_INC(tvc); /* AIX, apparently */
3029 ReleaseReadLock(&afs_xvcache);
3030 #ifdef AFS_BOZONLOCK_ENV
3031 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3033 ObtainWriteLock(&tvc->lock, 232);
3035 ObtainWriteLock(&afs_xcbhash, 458);
3036 afs_DequeueCallback(tvc);
3037 tvc->states &= ~(CStatd | CDirty);
3038 ReleaseWriteLock(&afs_xcbhash);
3039 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
3040 osi_dnlc_purgedp(tvc);
3041 afs_TryToSmush(tvc, *acred, 1);
3042 ReleaseWriteLock(&tvc->lock);
3043 #ifdef AFS_BOZONLOCK_ENV
3044 afs_BozonUnlock(&tvc->pvnLock, tvc);
3046 #ifdef AFS_DARWIN80_ENV
3047 vnode_put(AFSTOV(tvc));
3049 ObtainReadLock(&afs_xvcache);
3051 /* our tvc ptr is still good until now */
3055 ReleaseReadLock(&afs_xvcache);
3058 MObtainWriteLock(&afs_xdcache, 328); /* needed if you're going to flush any stuff */
3059 for (i = 0; i < afs_cacheFiles; i++) {
3060 if (!(afs_indexFlags[i] & IFEverUsed))
3061 continue; /* never had any data */
3062 tdc = afs_GetDSlot(i, NULL);
3063 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
3064 ReleaseReadLock(&tdc->tlock);
3065 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
3066 if (!(afs_indexFlags[i] & IFDataMod)) {
3067 /* if the file is modified, but has a ref cnt of only 1, then
3068 * someone probably has the file open and is writing into it.
3069 * Better to skip flushing such a file, it will be brought back
3070 * immediately on the next write anyway.
3072 * If we *must* flush, then this code has to be rearranged to call
3073 * afs_storeAllSegments() first */
3074 afs_FlushDCache(tdc);
3078 ReleaseReadLock(&tdc->tlock);
3080 afs_PutDCache(tdc); /* bumped by getdslot */
3082 MReleaseWriteLock(&afs_xdcache);
3084 ObtainReadLock(&afs_xvolume);
3085 for (i = 0; i < NVOLS; i++) {
3086 for (tv = afs_volumes[i]; tv; tv = tv->next) {
3087 if (tv->volume == volume) {
3088 afs_ResetVolumeInfo(tv);
3093 ReleaseReadLock(&afs_xvolume);
3095 /* probably, a user is doing this, probably, because things are screwed up.
3096 * maybe it's the dnlc's fault? */
3103 * VIOCGETVCXSTATUS (41) - gets vnode x status
3107 * \param[in] ain not in use (avc used)
3108 * \param[out] aout vcxstat: the file id, the data version, any lock, the parent vnode, the parent unique id, the trunc position, the callback, cbExpires, what access is being made, what files are open, any users executing/writing, the flock ount, the states, the move stat
3110 * \retval EINVAL Error if some of the initial default arguments aren't set
3111 * \retval EACCES Error if access to check the mode bits is denied
3113 * \post gets stats for the vnode, a struct listed in vcxstat
3115 DECL_PIOCTL(PGetVnodeXStatus)
3117 register afs_int32 code;
3118 struct vcxstat stat;
3121 /* AFS_STATCNT(PGetVnodeXStatus); */
3124 code = afs_VerifyVCache(avc, areq);
3127 if (vType(avc) == VDIR)
3128 mode = PRSFS_LOOKUP;
3131 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
3134 memset(&stat, 0, sizeof(struct vcxstat));
3135 stat.fid = avc->fid;
3136 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
3137 stat.lock = avc->lock;
3138 stat.parentVnode = avc->parentVnode;
3139 stat.parentUnique = avc->parentUnique;
3140 hset(stat.flushDV, avc->flushDV);
3141 hset(stat.mapDV, avc->mapDV);
3142 stat.truncPos = avc->truncPos;
3143 { /* just grab the first two - won't break anything... */
3144 struct axscache *ac;
3146 for (i = 0, ac = avc->Access; ac && i < CPSIZE; i++, ac = ac->next) {
3147 stat.randomUid[i] = ac->uid;
3148 stat.randomAccess[i] = ac->axess;
3151 stat.callback = afs_data_pointer_to_int32(avc->callback);
3152 stat.cbExpires = avc->cbExpires;
3153 stat.anyAccess = avc->anyAccess;
3154 stat.opens = avc->opens;
3155 stat.execsOrWriters = avc->execsOrWriters;
3156 stat.flockCount = avc->flockCount;
3157 stat.mvstat = avc->mvstat;
3158 stat.states = avc->states;
3159 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
3160 *aoutSize = sizeof(struct vcxstat);
3165 DECL_PIOCTL(PGetVnodeXStatus2)
3167 register afs_int32 code;
3168 struct vcxstat2 stat;
3173 code = afs_VerifyVCache(avc, areq);
3176 if (vType(avc) == VDIR)
3177 mode = PRSFS_LOOKUP;
3180 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
3183 memset(&stat, 0, sizeof(struct vcxstat2));
3185 stat.cbExpires = avc->cbExpires;
3186 stat.anyAccess = avc->anyAccess;
3187 stat.mvstat = avc->mvstat;
3188 stat.callerAccess = afs_GetAccessBits(avc, ~0, areq);
3190 memcpy(aout, (char *)&stat, sizeof(struct vcxstat2));
3191 *aoutSize = sizeof(struct vcxstat2);
3197 * VIOC_AFS_SYSNAME (38) - Change @sys value
3201 * \param[in] ain new value for @sys
3202 * \param[out] aout count, entry, list (debug values?)
3204 * \retval EINVAL Error if afsd isn't running, the new sysname is too large, the new sysname causes issues (starts with a .0 or ..0), there is no PAG set in the credentials, the user of a PAG can't be found, (!(exporter = au->exporter)) "NOT SURE ON THIS"
3205 * \retval ENODEV Error if there isn't already a system named that ("I THINK")
3206 * \retval EACCES Error if the user doesn't have super-user credentials
3208 * \post Set the value of @sys if these things work: if the input isn't too long or if input doesn't start with .0 or ..0
3210 * \notes We require root for local sysname changes, but not for remote (since we don't really believe remote uids anyway) outname[] shouldn't really be needed- this is left as an exercise for the reader.
3212 DECL_PIOCTL(PSetSysName)
3214 char *cp, *cp2 = NULL, inname[MAXSYSNAME], outname[MAXSYSNAME];
3215 afs_int32 setsysname;
3217 register struct afs_exporter *exporter;
3218 register struct unixuser *au;
3219 register afs_int32 pag, error;
3220 int t, count, num = 0, allpags = 0;
3223 AFS_STATCNT(PSetSysName);
3224 if (!afs_globalVFS) {
3225 /* Afsd is NOT running; disable it */
3226 #if defined(KERNEL_HAVE_UERROR)
3227 return (setuerror(EINVAL), EINVAL);
3232 memset(inname, 0, MAXSYSNAME);
3233 memcpy(&setsysname, ain, sizeof(afs_int32));
3234 ain += sizeof(afs_int32);
3235 if (setsysname & 0x8000) {
3237 setsysname &= ~0x8000;
3242 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
3245 for (cp = ain, count = 0; count < setsysname; count++) {
3246 /* won't go past end of ain since maxsysname*num < ain length */
3248 if (t >= MAXSYSNAME || t <= 0)
3250 /* check for names that can shoot us in the foot */
3251 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
3257 /* inname gets first entry in case we're being a translator */
3259 memcpy(inname, ain, t + 1); /* include terminating null */
3263 if ((*acred)->cr_gid == RMTUSER_REQ ||
3264 (*acred)->cr_gid == RMTUSER_REQ_PRIV) { /* Handles all exporters */
3265 if (allpags && (*acred)->cr_gid != RMTUSER_REQ_PRIV) {
3268 pag = PagInCred(*acred);
3270 return EINVAL; /* Better than panicing */
3272 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
3273 return EINVAL; /* Better than panicing */
3275 if (!(exporter = au->exporter)) {
3276 afs_PutUser(au, READ_LOCK);
3277 return EINVAL; /* Better than panicing */
3279 error = EXP_SYSNAME(exporter, (setsysname ? cp2 : NULL), &sysnamelist,
3282 if (error == ENODEV)
3283 foundname = 0; /* sysname not set yet! */
3285 afs_PutUser(au, READ_LOCK);
3290 strcpy(outname, sysnamelist[0]);
3292 afs_PutUser(au, READ_LOCK);
3296 /* Not xlating, so local case */
3298 osi_Panic("PSetSysName: !afs_sysname\n");
3299 if (!setsysname) { /* user just wants the info */
3300 strcpy(outname, afs_sysname);
3301 foundname = afs_sysnamecount;
3302 sysnamelist = afs_sysnamelist;
3303 } else { /* Local guy; only root can change sysname */
3304 if (!afs_osi_suser(*acred))
3307 /* allpags makes no sense for local use */
3311 /* clear @sys entries from the dnlc, once afs_lookup can
3312 * do lookups of @sys entries and thinks it can trust them */
3313 /* privs ok, store the entry, ... */
3314 strcpy(afs_sysname, inname);
3315 if (setsysname > 1) { /* ... or list */
3317 for (count = 1; count < setsysname; ++count) {
3318 if (!afs_sysnamelist[count])
3320 ("PSetSysName: no afs_sysnamelist entry to write\n");
3322 memcpy(afs_sysnamelist[count], cp, t + 1); /* include null */
3326 afs_sysnamecount = setsysname;
3331 cp = aout; /* not changing so report back the count and ... */
3332 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
3333 cp += sizeof(afs_int32);
3335 strcpy(cp, outname); /* ... the entry, ... */
3336 cp += strlen(outname) + 1;
3337 for (count = 1; count < foundname; ++count) { /* ... or list. */
3338 if (!sysnamelist[count])
3340 ("PSetSysName: no afs_sysnamelist entry to read\n");
3341 t = strlen(sysnamelist[count]);
3342 if (t >= MAXSYSNAME)
3343 osi_Panic("PSetSysName: sysname entry garbled\n");
3344 strcpy(cp, sysnamelist[count]);
3348 *aoutSize = cp - aout;
3353 /* sequential search through the list of touched cells is not a good
3354 * long-term solution here. For small n, though, it should be just
3355 * fine. Should consider special-casing the local cell for large n.
3356 * Likewise for PSetSPrefs.
3358 * s - number of ids in array l[] -- NOT index of last id
3359 * l - array of cell ids which have volumes that need to be sorted
3360 * vlonly - sort vl servers or file servers?
3363 ReSortCells_cb(struct cell *cell, void *arg)
3365 afs_int32 *p = (afs_int32 *) arg;
3366 afs_int32 *l = p + 1;
3369 for (i = 0; i < s; i++) {
3370 if (l[i] == cell->cellNum) {
3371 ObtainWriteLock(&cell->lock, 690);
3372 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
3373 ReleaseWriteLock(&cell->lock);
3381 ReSortCells(int s, afs_int32 * l, int vlonly)
3389 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s + 1));
3391 memcpy(p + 1, l, s * sizeof(afs_int32));
3392 afs_TraverseCells(&ReSortCells_cb, p);
3393 afs_osi_Free(p, sizeof(afs_int32) * (s + 1));
3397 ObtainReadLock(&afs_xvolume);
3398 for (i = 0; i < NVOLS; i++) {
3399 for (j = afs_volumes[i]; j; j = j->next) {
3400 for (k = 0; k < s; k++)
3401 if (j->cell == l[k]) {
3402 ObtainWriteLock(&j->lock, 233);
3403 afs_SortServers(j->serverHost, MAXHOSTS);
3404 ReleaseWriteLock(&j->lock);
3409 ReleaseReadLock(&afs_xvolume);
3413 static int debugsetsp = 0;
3415 afs_setsprefs(struct spref *sp, unsigned int num, unsigned int vlonly)
3418 int i, j, k, matches, touchedSize;
3419 struct server *srvr = NULL;
3420 afs_int32 touched[34];
3424 for (k = 0; k < num; sp++, k++) {
3426 printf("sp host=%x, rank=%d\n", sp->host.s_addr, sp->rank);
3429 ObtainReadLock(&afs_xserver);
3431 i = SHash(sp->host.s_addr);
3432 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
3433 if (sa->sa_ip == sp->host.s_addr) {
3435 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
3436 || (sa->sa_portal == AFS_FSPORT);
3437 if ((!vlonly && isfs) || (vlonly && !isfs)) {
3444 if (sa && matches) { /* found one! */
3446 printf("sa ip=%x, ip_rank=%d\n", sa->sa_ip, sa->sa_iprank);
3448 sa->sa_iprank = sp->rank + afs_randomMod15();
3449 afs_SortOneServer(sa->server);
3452 /* if we don't know yet what cell it's in, this is moot */
3453 for (j = touchedSize - 1;
3454 j >= 0 && touched[j] != srvr->cell->cellNum; j--)
3455 /* is it in our list of touched cells ? */ ;
3456 if (j < 0) { /* no, it's not */
3457 touched[touchedSize++] = srvr->cell->cellNum;
3458 if (touchedSize >= 32) { /* watch for ovrflow */
3459 ReleaseReadLock(&afs_xserver);
3460 ReSortCells(touchedSize, touched, vlonly);
3462 ObtainReadLock(&afs_xserver);
3468 ReleaseReadLock(&afs_xserver);
3469 /* if we didn't find one, start to create one. */
3470 /* Note that it doesn't have a cell yet... */
3472 afs_uint32 temp = sp->host.s_addr;
3474 afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
3475 WRITE_LOCK, (afsUUID *) 0, 0);
3476 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
3477 afs_PutServer(srvr, WRITE_LOCK);
3479 } /* for all cited preferences */
3481 ReSortCells(touchedSize, touched, vlonly);
3486 * VIOC_SETPREFS (46) - Set server ranks
3488 * \param[in] ain the sprefs value you want the sprefs to be set to
3489 * \param[out] aout not in use
3491 * \retval EIO Error if the afs daemon hasn't started yet
3492 * \retval EACCES Error if the user doesn't have super-user credentials
3493 * \retval EINVAL Error if the struct setsprefs is too large or if it multiplied by the number of servers is too large
3495 * \post set the sprefs using the afs_setsprefs() function
3497 DECL_PIOCTL(PSetSPrefs)
3499 struct setspref *ssp;
3500 AFS_STATCNT(PSetSPrefs);
3502 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
3503 return EIO; /* Inappropriate ioctl for device */
3505 if (!afs_osi_suser(*acred))
3508 if (ainSize < sizeof(struct setspref))
3511 ssp = (struct setspref *)ain;
3512 if (ainSize < sizeof(struct spref) * ssp->num_servers)
3515 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
3516 (ssp->flags & DBservers));
3521 * VIOC_SETPREFS33 (42) - Set server ranks (deprecated)
3523 * \param[in] ain the server preferences to be set
3524 * \param[out] aout not in use
3526 * \retval EIO Error if the afs daemon hasn't started yet
3527 * \retval EACCES Error if the user doesn't have super-user credentials
3529 * \post set the server preferences, calling a function
3531 * \notes this may only be performed by the local root user.
3533 DECL_PIOCTL(PSetSPrefs33)
3536 AFS_STATCNT(PSetSPrefs);
3537 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
3538 return EIO; /* Inappropriate ioctl for device */
3541 if (!afs_osi_suser(*acred))
3544 sp = (struct spref *)ain;
3545 afs_setsprefs(sp, ainSize / (sizeof(struct spref)), 0 /*!vlonly */ );
3550 * VIOC_GETSPREFS (43) - Get server ranks
3554 * \param[in] ain the server preferences to get
3555 * \param[out] aout the server preferences information
3557 * \retval EIO Error if the afs daemon hasn't started yet
3558 * \retval ENOENT Error if the sprefrequest is too large
3560 * \post Get the sprefs
3562 * \notes in the hash table of server structs, all servers with the same IP address; will be on the same overflow chain; This could be sped slightly in some circumstances by having it cache the immediately previous slot in the hash table and some supporting information; Only reports file servers now.
3564 DECL_PIOCTL(PGetSPrefs)
3566 struct sprefrequest *spin; /* input */
3567 struct sprefinfo *spout; /* output */
3568 struct spref *srvout; /* one output component */
3569 int i, j; /* counters for hash table traversal */
3570 struct server *srvr; /* one of CM's server structs */
3572 int vlonly; /* just return vlservers ? */
3575 AFS_STATCNT(PGetSPrefs);
3576 if (!afs_resourceinit_flag) /* afs daemons haven't started yet */
3577 return EIO; /* Inappropriate ioctl for device */
3580 if (ainSize < sizeof(struct sprefrequest_33)) {
3583 spin = ((struct sprefrequest *)ain);
3586 if (ainSize > sizeof(struct sprefrequest_33)) {
3587 vlonly = (spin->flags & DBservers);
3591 /* struct sprefinfo includes 1 server struct... that size gets added
3592 * in during the loop that follows.
3594 *aoutSize = sizeof(struct sprefinfo) - sizeof(struct spref);
3595 spout = (struct sprefinfo *)aout;
3596 spout->next_offset = spin->offset;
3597 spout->num_servers = 0;
3598 srvout = spout->servers;
3600 ObtainReadLock(&afs_xserver);
3601 for (i = 0, j = 0; j < NSERVERS; j++) { /* sift through hash table */
3602 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
3603 if (spin->offset > (unsigned short)i) {
3604 continue; /* catch up to where we left off */
3606 spout->next_offset++;
3609 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
3610 || (sa->sa_portal == AFS_FSPORT);
3612 if ((vlonly && isfs) || (!vlonly && !isfs)) {
3613 /* only report ranks for vl servers */
3617 srvout->host.s_addr = sa->sa_ip;
3618 srvout->rank = sa->sa_iprank;
3619 *aoutSize += sizeof(struct spref);
3620 spout->num_servers++;
3623 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
3624 ReleaseReadLock(&afs_xserver); /* no more room! */
3629 ReleaseReadLock(&afs_xserver);
3631 spout->next_offset = 0; /* start over from the beginning next time */
3635 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
3636 int afs_NFSRootOnly = 1;
3638 * VIOC_EXPORTAFS (39) - Export afs to nfs clients
3642 * \param[in] ain a struct Vic * EIOctl containing export values needed to change between nfs and afs
3643 * \param[out] aout a struct of the exporter states (exporter->exp_states)
3645 * \retval ENODEV Error if the exporter doesn't exist
3646 * \retval EACCES Error if the user doesn't have super-user credentials
3648 * \post Changes the state of various values to reflect the change of the export values between nfs and afs.
3650 * \notes Legacy code obtained from IBM.
3652 DECL_PIOCTL(PExportAfs)
3654 afs_int32 export, newint =
3655 0, type, changestate, handleValue, convmode, pwsync, smounts;
3656 afs_int32 rempags = 0, pagcb = 0;
3657 register struct afs_exporter *exporter;
3659 AFS_STATCNT(PExportAfs);
3660 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
3661 type = handleValue >> 24;
3666 exporter = exporter_find(type);
3668 export = handleValue & 3;
3669 changestate = handleValue & 0xfff;
3670 smounts = (handleValue >> 2) & 3;
3671 pwsync = (handleValue >> 4) & 3;
3672 convmode = (handleValue >> 6) & 3;
3673 rempags = (handleValue >> 8) & 3;
3674 pagcb = (handleValue >> 10) & 3;
3676 changestate = (handleValue >> 16) & 0x1;
3677 convmode = (handleValue >> 16) & 0x2;
3678 pwsync = (handleValue >> 16) & 0x4;
3679 smounts = (handleValue >> 16) & 0x8;
3680 export = handleValue & 0xff;
3683 /* Failed finding desired exporter; */
3687 handleValue = exporter->exp_states;
3688 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
3689 *aoutSize = sizeof(afs_int32);
3691 if (!afs_osi_suser(*acred))
3692 return EACCES; /* Only superuser can do this */
3696 exporter->exp_states |= EXP_EXPORTED;
3698 exporter->exp_states &= ~EXP_EXPORTED;
3702 exporter->exp_states |= EXP_UNIXMODE;
3704 exporter->exp_states &= ~EXP_UNIXMODE;
3708 exporter->exp_states |= EXP_PWSYNC;
3710 exporter->exp_states &= ~EXP_PWSYNC;
3714 afs_NFSRootOnly = 0;
3715 exporter->exp_states |= EXP_SUBMOUNTS;