/* afs_root - stat the root of the file system. AFS global held on entry. */ static int afs_root(struct super_block *afsp) { afs_int32 code = 0; struct vcache *tvp = 0; AFS_STATCNT(afs_root); if (afs_globalVp && (afs_globalVp->f.states & CStatd)) { tvp = afs_globalVp; } else { struct vrequest *treq = NULL; cred_t *credp = crref(); if (afs_globalVp) { afs_PutVCache(afs_globalVp); afs_globalVp = NULL; } if (!(code = afs_CreateReq(&treq, credp)) && !(code = afs_CheckInit())) { tvp = afs_GetVCache(&afs_rootFid, treq, NULL, NULL); if (tvp) { struct inode *ip = AFSTOV(tvp); struct vattr *vattr = NULL; code = afs_CreateAttr(&vattr); if (!code) { afs_getattr(tvp, vattr, credp); afs_fill_inode(ip, vattr); /* setup super_block and mount point inode. */ afs_globalVp = tvp; #if defined(HAVE_LINUX_D_MAKE_ROOT) afsp->s_root = d_make_root(ip); #else afsp->s_root = d_alloc_root(ip); #endif #if !defined(STRUCT_SUPER_BLOCK_HAS_S_D_OP) afsp->s_root->d_op = &afs_dentry_operations; #endif afs_DestroyAttr(vattr); } } else code = EIO; } crfree(credp); afs_DestroyReq(treq); } afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, afs_globalVp, ICL_TYPE_INT32, code); return code; }
/* afs_root - stat the root of the file system. AFS global held on entry. */ static int afs_root(struct super_block *afsp) { afs_int32 code = 0; struct vrequest treq; struct vcache *tvp = 0; AFS_STATCNT(afs_root); if (afs_globalVp && (afs_globalVp->f.states & CStatd)) { tvp = afs_globalVp; } else { cred_t *credp = crref(); if (afs_globalVp) { afs_PutVCache(afs_globalVp); afs_globalVp = NULL; } if (!(code = afs_InitReq(&treq, credp)) && !(code = afs_CheckInit())) { tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL); if (tvp) { struct inode *ip = AFSTOV(tvp); struct vattr vattr; afs_getattr(tvp, &vattr, credp); afs_fill_inode(ip, &vattr); /* setup super_block and mount point inode. */ afs_globalVp = tvp; #if defined(AFS_LINUX24_ENV) afsp->s_root = d_alloc_root(ip); #else afsp->s_root = d_alloc_root(ip, NULL); #endif afsp->s_root->d_op = &afs_dentry_operations; } else code = ENOENT; } crfree(credp); } afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, afs_globalVp, ICL_TYPE_INT32, code); return code; }
int afs_root(OSI_VFS_DECL(afsp), struct vnode **avpp) { afs_int32 code = 0; struct vrequest treq; struct vcache *tvp = 0; OSI_VFS_CONVERT(afsp); AFS_STATCNT(afs_root); if (afs_globalVp && (afs_globalVp->f.states & CStatd)) { tvp = afs_globalVp; } else { if (afs_globalVp) { afs_PutVCache(afs_globalVp); afs_globalVp = NULL; } if (!(code = afs_InitReq(&treq, get_user_struct()->u_cred)) && !(code = afs_CheckInit())) { tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL); /* we really want this to stay around */ if (tvp) { afs_globalVp = tvp; } else code = ENOENT; } } if (tvp) { VN_HOLD(AFSTOV(tvp)); AFSTOV(tvp)->v_flag |= VROOT; /* No-op on Ultrix 2.2 */ afs_globalVFS = afsp; *avpp = AFSTOV(tvp); } afs_Trace3(afs_iclSetp, CM_TRACE_GOPEN, ICL_TYPE_POINTER, *avpp, ICL_TYPE_INT32, 0, ICL_TYPE_INT32, code); return code; }
afs_root(struct mount *mp, struct vnode **vpp) #endif { int error; struct vrequest treq; register struct vcache *tvp = 0; #ifdef AFS_FBSD50_ENV #ifndef AFS_FBSD53_ENV struct thread *td = curthread; #endif struct ucred *cr = td->td_ucred; #else struct proc *p = curproc; struct ucred *cr = p->p_cred->pc_ucred; #endif AFS_GLOCK(); AFS_STATCNT(afs_root); crhold(cr); if (afs_globalVp && (afs_globalVp->f.states & CStatd)) { tvp = afs_globalVp; error = 0; } else { tryagain: #ifndef AFS_FBSD80_ENV if (afs_globalVp) { afs_PutVCache(afs_globalVp); /* vrele() needed here or not? */ afs_globalVp = NULL; } #endif if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) { tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL); /* we really want this to stay around */ if (tvp) afs_globalVp = tvp; else error = ENOENT; } } if (tvp) { struct vnode *vp = AFSTOV(tvp); #ifdef AFS_FBSD50_ENV ASSERT_VI_UNLOCKED(vp, "afs_root"); #endif AFS_GUNLOCK(); /* * I'm uncomfortable about this. Shouldn't this happen at a * higher level, and shouldn't we busy the top-level directory * to prevent recycling? */ #ifdef AFS_FBSD50_ENV error = vget(vp, LK_EXCLUSIVE | LK_RETRY, td); vp->v_vflag |= VV_ROOT; #else error = vget(vp, LK_EXCLUSIVE | LK_RETRY, p); vp->v_flag |= VROOT; #endif AFS_GLOCK(); if (error != 0) goto tryagain; afs_globalVFS = mp; *vpp = vp; } afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, tvp ? AFSTOV(tvp) : NULL, ICL_TYPE_INT32, error); AFS_GUNLOCK(); crfree(cr); return error; }
afs_root(struct mount *mp, struct vnode **vpp) #endif { int error; struct vrequest treq; struct vcache *tvp = 0; struct vcache *gvp; #if !defined(AFS_FBSD53_ENV) || defined(AFS_FBSD80_ENV) struct thread *td = curthread; #endif struct ucred *cr = osi_curcred(); AFS_GLOCK(); AFS_STATCNT(afs_root); crhold(cr); tryagain: if (afs_globalVp && (afs_globalVp->f.states & CStatd)) { tvp = afs_globalVp; error = 0; } else { if (!(error = afs_InitReq(&treq, cr)) && !(error = afs_CheckInit())) { tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL); /* we really want this to stay around */ if (tvp) { gvp = afs_globalVp; afs_globalVp = tvp; if (gvp) { afs_PutVCache(gvp); if (tvp != afs_globalVp) { /* someone raced us and won */ afs_PutVCache(tvp); goto tryagain; } } } else error = ENOENT; } } if (tvp) { struct vnode *vp = AFSTOV(tvp); ASSERT_VI_UNLOCKED(vp, "afs_root"); AFS_GUNLOCK(); error = vget(vp, LK_EXCLUSIVE | LK_RETRY, td); AFS_GLOCK(); /* we dropped the glock, so re-check everything it had serialized */ if (!afs_globalVp || !(afs_globalVp->f.states & CStatd) || tvp != afs_globalVp) { vput(vp); afs_PutVCache(tvp); goto tryagain; } if (error != 0) goto tryagain; /* * I'm uncomfortable about this. Shouldn't this happen at a * higher level, and shouldn't we busy the top-level directory * to prevent recycling? */ vp->v_vflag |= VV_ROOT; afs_globalVFS = mp; *vpp = vp; } afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, tvp ? AFSTOV(tvp) : NULL, ICL_TYPE_INT32, error); AFS_GUNLOCK(); crfree(cr); return error; }