int afs_vrdwr(struct usr_vnode *avc, struct usr_uio *uio, int rw, int io, struct usr_ucred *cred) { int rc; if (rw == UIO_WRITE) { rc = afs_write(VTOAFS(avc), uio, io, cred, 0); } else { rc = afs_read(VTOAFS(avc), uio, cred, 0, 0, 0); } return rc; }
/* ptr_parm 0 is the pathname, size_parm 0 to the fetch is the chunk number */ static void BPath(struct brequest *ab) { struct dcache *tdc = NULL; struct vcache *tvc = NULL; struct vnode *tvn = NULL; #ifdef AFS_LINUX22_ENV struct dentry *dp = NULL; #endif afs_size_t offset, len; struct vrequest *treq = NULL; afs_int32 code; AFS_STATCNT(BPath); if ((code = afs_CreateReq(&treq, ab->cred))) { return; } AFS_GUNLOCK(); #ifdef AFS_LINUX22_ENV code = gop_lookupname((char *)ab->ptr_parm[0], AFS_UIOSYS, 1, &dp); if (dp) tvn = (struct vnode *)dp->d_inode; #else code = gop_lookupname((char *)ab->ptr_parm[0], AFS_UIOSYS, 1, &tvn); #endif AFS_GLOCK(); osi_FreeLargeSpace((char *)ab->ptr_parm[0]); /* free path name buffer here */ if (code) { afs_DestroyReq(treq); return; } /* now path may not have been in afs, so check that before calling our cache manager */ if (!tvn || !IsAfsVnode(tvn)) { /* release it and give up */ if (tvn) { #ifdef AFS_LINUX22_ENV dput(dp); #else AFS_RELE(tvn); #endif } afs_DestroyReq(treq); return; } tvc = VTOAFS(tvn); /* here we know its an afs vnode, so we can get the data for the chunk */ tdc = afs_GetDCache(tvc, ab->size_parm[0], treq, &offset, &len, 1); if (tdc) { afs_PutDCache(tdc); } #ifdef AFS_LINUX22_ENV dput(dp); #else AFS_RELE(tvn); #endif afs_DestroyReq(treq); }
/* afs_notify_change * Linux version of setattr call. What to change is in the iattr struct. * We need to set bits in both the Linux inode as well as the vcache. */ int afs_notify_change(struct dentry *dp, struct iattr *iattrp) { struct vattr vattr; cred_t *credp = crref(); struct inode *ip = dp->d_inode; int code; VATTR_NULL(&vattr); iattr2vattr(&vattr, iattrp); /* Convert for AFS vnodeops call. */ AFS_GLOCK(); code = afs_setattr(VTOAFS(ip), &vattr, credp); if (!code) { afs_getattr(VTOAFS(ip), &vattr, credp); vattr2inode(ip, &vattr); } AFS_GUNLOCK(); crfree(credp); return -code; }
static void afs_clear_inode(struct inode *ip) { struct vcache *vcp = VTOAFS(ip); if (vcp->vlruq.prev || vcp->vlruq.next) osi_Panic("inode freed while on LRU"); if (vcp->hnext) osi_Panic("inode freed while still hashed"); #if !defined(STRUCT_SUPER_OPERATIONS_HAS_ALLOC_INODE) afs_osi_Free(ip->u.generic_ip, sizeof(struct vcache)); #endif }
static void afs_evict_inode(struct inode *ip) { struct vcache *vcp = VTOAFS(ip); if (vcp->vlruq.prev || vcp->vlruq.next) osi_Panic("inode freed while on LRU"); if (vcp->hnext) osi_Panic("inode freed while still hashed"); truncate_inode_pages(&ip->i_data, 0); end_writeback(ip); #if !defined(STRUCT_SUPER_OPERATIONS_HAS_ALLOC_INODE) afs_osi_Free(ip->u.generic_ip, sizeof(struct vcache)); #endif }
afs_open(struct vcache **avcp, afs_int32 aflags, afs_ucred_t *acred) #endif { afs_int32 code; struct vrequest treq; struct vcache *tvc; int writing; struct afs_fakestat_state fakestate; AFS_STATCNT(afs_open); if ((code = afs_InitReq(&treq, acred))) return code; #ifdef AFS_SGI64_ENV /* avcpp can be, but is not necesarily, bhp's vnode. */ tvc = VTOAFS(BHV_TO_VNODE(bhv)); #else tvc = *avcp; #endif afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, aflags); afs_InitFakeStat(&fakestate); AFS_DISCON_LOCK(); code = afs_EvalFakeStat(&tvc, &fakestate, &treq); if (code) goto done; code = afs_VerifyVCache(tvc, &treq); if (code) goto done; ObtainReadLock(&tvc->lock); if (AFS_IS_DISCONNECTED && (afs_DCacheMissingChunks(tvc) != 0)) { ReleaseReadLock(&tvc->lock); /* printf("Network is down in afs_open: missing chunks\n"); */ code = ENETDOWN; goto done; } ReleaseReadLock(&tvc->lock); if (aflags & (FWRITE | FTRUNC)) writing = 1; else writing = 0; if (vType(tvc) == VDIR) { /* directory */ if (writing) { code = EISDIR; goto done; } else { if (!afs_AccessOK (tvc, ((tvc->f.states & CForeign) ? PRSFS_READ : PRSFS_LOOKUP), &treq, CHECK_MODE_BITS)) { code = EACCES; /* printf("afs_Open: no access for dir\n"); */ goto done; } } } else { #ifdef AFS_SUN5_ENV if (AFS_NFSXLATORREQ(acred) && (aflags & FREAD)) { if (!afs_AccessOK (tvc, PRSFS_READ, &treq, CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) { code = EACCES; goto done; } } #endif #ifdef AFS_AIX41_ENV if (aflags & FRSHARE) { /* * Hack for AIX 4.1: * Apparently it is possible for a file to get mapped without * either VNOP_MAP or VNOP_RDWR being called, if (1) it is a * sharable library, and (2) it has already been loaded. We must * ensure that the credp is up to date. We detect the situation * by checking for O_RSHARE at open time. */ /* * We keep the caller's credentials since an async daemon will * handle the request at some point. We assume that the same * credentials will be used. */ ObtainWriteLock(&tvc->lock, 140); if (!tvc->credp || (tvc->credp != acred)) { crhold(acred); if (tvc->credp) { struct ucred *crp = tvc->credp; tvc->credp = NULL; crfree(crp); } tvc->credp = acred; } ReleaseWriteLock(&tvc->lock); } #endif /* normal file or symlink */ osi_FlushText(tvc); /* only needed to flush text if text locked last time */ #ifdef AFS_BOZONLOCK_ENV afs_BozonLock(&tvc->pvnLock, tvc); #endif osi_FlushPages(tvc, acred); #ifdef AFS_BOZONLOCK_ENV afs_BozonUnlock(&tvc->pvnLock, tvc); #endif } /* set date on file if open in O_TRUNC mode */ if (aflags & FTRUNC) { /* this fixes touch */ ObtainWriteLock(&tvc->lock, 123); tvc->f.m.Date = osi_Time(); tvc->f.states |= CDirty; ReleaseWriteLock(&tvc->lock); } ObtainReadLock(&tvc->lock); if (writing) tvc->execsOrWriters++; tvc->opens++; #if defined(AFS_SGI_ENV) || defined (AFS_LINUX26_ENV) if (writing && tvc->cred == NULL) { crhold(acred); tvc->cred = acred; } #endif ReleaseReadLock(&tvc->lock); if ((afs_preCache != 0) && (writing == 0) && (vType(tvc) != VDIR) && (!afs_BBusy())) { struct dcache *tdc; afs_size_t offset, len; tdc = afs_GetDCache(tvc, 0, &treq, &offset, &len, 1); ObtainSharedLock(&tdc->mflock, 865); if (!(tdc->mflags & DFFetchReq)) { struct brequest *bp; /* start the daemon (may already be running, however) */ UpgradeSToWLock(&tdc->mflock, 666); tdc->mflags |= DFFetchReq; /* guaranteed to be cleared by BKG or GetDCache */ /* last parm (1) tells bkg daemon to do an afs_PutDCache when it is done, since we don't want to wait for it to finish before doing so ourselves. */ bp = afs_BQueue(BOP_FETCH, tvc, B_DONTWAIT, 0, acred, (afs_size_t) 0, (afs_size_t) 1, tdc, (void *)0, (void *)0); if (!bp) { tdc->mflags &= ~DFFetchReq; } ReleaseWriteLock(&tdc->mflock); } else { ReleaseSharedLock(&tdc->mflock); } } done: afs_PutFakeStat(&fakestate); AFS_DISCON_UNLOCK(); code = afs_CheckCode(code, &treq, 4); /* avoid AIX -O bug */ afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, 999999); return code; }
static struct dentry *afs_export_get_parent(struct dentry *child) { struct VenusFid tfid; struct vrequest treq; struct cell *tcell; struct vcache *vcp; struct dentry *dp = NULL; cred_t *credp; afs_uint32 cellidx; int code; if (!child->d_inode) { /* can't find the parent of a negative dentry */ #ifdef OSI_EXPORT_DEBUG printk("afs: get_parent(%s): no inode\n", child->d_name.name ? (char *)child->d_name.name : "?"); #endif return ERR_PTR(-EIO); } credp = crref(); AFS_GLOCK(); vcp = VTOAFS(child->d_inode); if (afs_IsDynrootMount(vcp)) { /* the dynmount directory; parent is always the AFS root */ tfid = afs_globalVp->f.fid; } else if (afs_IsDynrootAny(vcp) && VNUM_TO_VNTYPE(vcp->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) { /* a mount point in the dynmount directory */ afs_GetDynrootMountFid(&tfid); } else if (vcp->mvstat == 2) { /* volume root */ ObtainReadLock(&vcp->lock); if (vcp->mvid && vcp->mvid->Fid.Volume) { tfid = *vcp->mvid; ReleaseReadLock(&vcp->lock); } else { ReleaseReadLock(&vcp->lock); tcell = afs_GetCell(vcp->f.fid.Cell, READ_LOCK); if (!tcell) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_parent(0x%08x/%d/%d.%d): no cell\n", vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique); #endif dp = ERR_PTR(-ENOENT); goto done; } cellidx = tcell->cellIndex; afs_PutCell(tcell, READ_LOCK); afs_GetDynrootMountFid(&tfid); tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2); tfid.Fid.Unique = vcp->f.fid.Fid.Volume; } } else { /* any other vnode */ if (vType(vcp) == VDIR && !vcp->f.parent.vnode && vcp->mvstat != 1) { code = afs_InitReq(&treq, credp); if (code) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_parent(0x%08x/%d/%d.%d): InitReq: %d\n", vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code); #endif dp = ERR_PTR(-ENOENT); goto done; } else { code = update_dir_parent(&treq, vcp); if (code) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_parent(0x%08x/%d/%d.%d): update_dir_parent: %d\n", vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code); #endif dp = ERR_PTR(-ENOENT); goto done; } } } tfid.Cell = vcp->f.fid.Cell; tfid.Fid.Volume = vcp->f.fid.Fid.Volume; tfid.Fid.Vnode = vcp->f.parent.vnode; tfid.Fid.Unique = vcp->f.parent.unique; } #ifdef OSI_EXPORT_DEBUG printk("afs: get_parent(0x%08x/%d/%d.%d): => 0x%08x/%d/%d.%d\n", vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, tfid.Cell, tfid.Fid.Volume, tfid.Fid.Vnode, tfid.Fid.Unique); #endif dp = get_dentry_from_fid(credp, &tfid); if (!dp) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_parent(0x%08x/%d/%d.%d): no dentry\n", vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique); #endif dp = ERR_PTR(-ENOENT); } done: AFS_GUNLOCK(); crfree(credp); return dp; }
static int afs_encode_fh(struct dentry *de, __u32 *fh, int *max_len, int connectable) { struct vcache *tvc; struct cell *tc; int vntype; if (!de->d_inode) /* encode a negative dentry?! */ return 255; if (*max_len < 4) /* not enough space */ return 255; tvc = VTOAFS(de->d_inode); #ifdef OSI_EXPORT_DEBUG printk("afs: encode_fh(0x%08x/%d/%d.%d)\n", tvc->f.fid.Cell, tvc->f.fid.Fid.Volume, tvc->f.fid.Fid.Vnode, tvc->f.fid.Fid.Unique); #endif if (afs_IsDynrootAnyFid(&tvc->f.fid)) { vntype = VNUM_TO_VNTYPE(tvc->f.fid.Fid.Vnode); switch (vntype) { case 0: /* encode as a normal filehandle */ break; case VN_TYPE_MOUNT: if (*max_len < 5) { return 255; } /* fall through */ case VN_TYPE_CELL: case VN_TYPE_ALIAS: AFS_GLOCK(); tc = afs_GetCellByIndex(VNUM_TO_CIDX(tvc->f.fid.Fid.Vnode), READ_LOCK); if (!tc) { AFS_GUNLOCK(); return 255; } memcpy((void *)fh, tc->cellHandle, 16); afs_PutCell(tc, READ_LOCK); AFS_GUNLOCK(); if (vntype == VN_TYPE_MOUNT) { fh[4] = htonl(tvc->f.fid.Fid.Unique); *max_len = 5; return AFSFH_DYN_MOUNT; } *max_len = 4; if (vntype == VN_TYPE_CELL) { return AFSFH_DYN_RO_CELL | VNUM_TO_RW(tvc->f.fid.Fid.Vnode); } else { return AFSFH_DYN_RO_LINK | VNUM_TO_RW(tvc->f.fid.Fid.Vnode); } case VN_TYPE_SYMLINK: /* XXX fill in filehandle for dynroot symlink */ /* XXX return AFSFH_DYN_SYMLINK; */ default: return 255; } } if (*max_len < 7) { /* not big enough for a migratable filehandle */ /* always encode in network order */ fh[0] = htonl(tvc->f.fid.Cell); fh[1] = htonl(tvc->f.fid.Fid.Volume); fh[2] = htonl(tvc->f.fid.Fid.Vnode); fh[3] = htonl(tvc->f.fid.Fid.Unique); *max_len = 4; return AFSFH_NET_VENUSFID; } AFS_GLOCK(); tc = afs_GetCell(tvc->f.fid.Cell, READ_LOCK); if (!tc) { AFS_GUNLOCK(); return 255; } memcpy((void *)fh, tc->cellHandle, 16); afs_PutCell(tc, READ_LOCK); AFS_GUNLOCK(); /* always encode in network order */ fh[4] = htonl(tvc->f.fid.Fid.Volume); fh[5] = htonl(tvc->f.fid.Fid.Vnode); fh[6] = htonl(tvc->f.fid.Fid.Unique); *max_len = 7; return AFSFH_NET_CELLFID; }
static int afs_export_get_name(struct dentry *parent, char *name, struct dentry *child) { struct afs_fakestat_state fakestate; struct get_name_data data; struct vrequest treq; struct volume *tvp; struct vcache *vcp; struct dcache *tdc; cred_t *credp; afs_size_t dirOffset, dirLen; afs_int32 code = 0; if (!parent->d_inode) { #ifdef OSI_EXPORT_DEBUG /* can't lookup name in a negative dentry */ printk("afs: get_name(%s, %s): no parent inode\n", parent->d_name.name ? (char *)parent->d_name.name : "?", child->d_name.name ? (char *)child->d_name.name : "?"); #endif return -EIO; } if (!child->d_inode) { #ifdef OSI_EXPORT_DEBUG /* can't find the FID of negative dentry */ printk("afs: get_name(%s, %s): no child inode\n", parent->d_name.name ? (char *)parent->d_name.name : "?", child->d_name.name ? (char *)child->d_name.name : "?"); #endif return -ENOENT; } afs_InitFakeStat(&fakestate); credp = crref(); AFS_GLOCK(); vcp = VTOAFS(child->d_inode); /* special case dynamic mount directory */ if (afs_IsDynrootMount(vcp)) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): this is the dynmount dir\n", parent->d_name.name ? (char *)parent->d_name.name : "?", vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique); #endif data.fid = vcp->f.fid; if (VTOAFS(parent->d_inode) == afs_globalVp) strcpy(name, AFS_DYNROOT_MOUNTNAME); else code = -ENOENT; goto done; } /* Figure out what FID to look for */ if (vcp->mvstat == 2) { /* volume root */ tvp = afs_GetVolume(&vcp->f.fid, 0, READ_LOCK); if (!tvp) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no volume for root\n", parent->d_name.name ? (char *)parent->d_name.name : "?", vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique); #endif code = ENOENT; goto done; } data.fid = tvp->mtpoint; afs_PutVolume(tvp, READ_LOCK); } else { data.fid = vcp->f.fid; } vcp = VTOAFS(parent->d_inode); #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): parent is 0x%08x/%d/%d.%d\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique, vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique); #endif code = afs_InitReq(&treq, credp); if (code) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): afs_InitReq: %d\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique, code); #endif goto done; } /* a dynamic mount point in the dynamic mount directory */ if (afs_IsDynrootMount(vcp) && afs_IsDynrootAnyFid(&data.fid) && VNUM_TO_VNTYPE(data.fid.Fid.Vnode) == VN_TYPE_MOUNT) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dynamic mount point\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique); #endif vcp = afs_GetVCache(&data.fid, &treq, NULL, NULL); if (vcp) { ObtainReadLock(&vcp->lock); if (strlen(vcp->linkData + 1) <= NAME_MAX) strcpy(name, vcp->linkData + 1); else code = ENOENT; ReleaseReadLock(&vcp->lock); afs_PutVCache(vcp); } else { #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): no vcache\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique); #endif code = ENOENT; } goto done; } code = afs_EvalFakeStat(&vcp, &fakestate, &treq); if (code) goto done; if (vcp->f.fid.Cell != data.fid.Cell || vcp->f.fid.Fid.Volume != data.fid.Fid.Volume) { /* parent is not the expected cell and volume; thus it * cannot possibly contain the fid we are looking for */ #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): wrong parent 0x%08x/%d\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique, vcp->f.fid.Cell, vcp->f.fid.Fid.Volume); #endif code = ENOENT; goto done; } redo: if (!(vcp->f.states & CStatd)) { if ((code = afs_VerifyVCache2(vcp, &treq))) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): VerifyVCache2(0x%08x/%d/%d.%d): %d\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique, vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code); #endif goto done; } } tdc = afs_GetDCache(vcp, (afs_size_t) 0, &treq, &dirOffset, &dirLen, 1); if (!tdc) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): GetDCache(0x%08x/%d/%d.%d): %d\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique, vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code); #endif code = EIO; goto done; } ObtainReadLock(&vcp->lock); ObtainReadLock(&tdc->lock); /* * Make sure that the data in the cache is current. There are two * cases we need to worry about: * 1. The cache data is being fetched by another process. * 2. The cache data is no longer valid */ while ((vcp->f.states & CStatd) && (tdc->dflags & DFFetching) && hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) { ReleaseReadLock(&tdc->lock); ReleaseReadLock(&vcp->lock); afs_osi_Sleep(&tdc->validPos); ObtainReadLock(&vcp->lock); ObtainReadLock(&tdc->lock); } if (!(vcp->f.states & CStatd) || !hsame(vcp->f.m.DataVersion, tdc->f.versionNo)) { ReleaseReadLock(&tdc->lock); ReleaseReadLock(&vcp->lock); afs_PutDCache(tdc); #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): dir (0x%08x/%d/%d.%d) changed; retrying\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique, vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique); #endif goto redo; } data.name = name; data.found = 0; code = afs_dir_EnumerateDir(tdc, get_name_hook, &data); if (!code && !data.found) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): not found\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique); #endif code = ENOENT; } else if (code) { #ifdef OSI_EXPORT_DEBUG printk("afs: get_name(%s, 0x%08x/%d/%d.%d): Enumeratedir(0x%08x/%d/%d.%d): %d\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique, vcp->f.fid.Cell, vcp->f.fid.Fid.Volume, vcp->f.fid.Fid.Vnode, vcp->f.fid.Fid.Unique, code); #endif } ReleaseReadLock(&tdc->lock); ReleaseReadLock(&vcp->lock); afs_PutDCache(tdc); done: if (!code) { printk("afs: get_name(%s, 0x%08x/%d/%d.%d) => %s\n", parent->d_name.name ? (char *)parent->d_name.name : "?", data.fid.Cell, data.fid.Fid.Volume, data.fid.Fid.Vnode, data.fid.Fid.Unique, name); } afs_PutFakeStat(&fakestate); AFS_GUNLOCK(); crfree(credp); code = afs_CheckCode(code, &treq, 102); return -code; }
int afs_BioDaemon(afs_int32 nbiods) { afs_int32 code, s, pflg = 0; label_t jmpbuf; struct buf *bp, *bp1, *tbp1, *tbp2; /* temp pointers only */ caddr_t tmpaddr; struct vnode *vp; struct vcache *vcp; char tmperr; if (!afs_initbiod) { /* XXX ###1 XXX */ afs_initbiod = 1; /* pin lock, since we'll be using it in an interrupt. */ lock_alloc(&afs_asyncbuf_lock, LOCK_ALLOC_PIN, 2, 1); simple_lock_init(&afs_asyncbuf_lock); pin(&afs_asyncbuf, sizeof(struct buf *)); pin(&afs_asyncbuf_cv, sizeof(afs_int32)); } /* Ignore HUP signals... */ { sigset_t sigbits, osigbits; /* * add SIGHUP to the set of already masked signals */ SIGFILLSET(sigbits); /* allow all signals */ SIGDELSET(sigbits, SIGHUP); /* except SIGHUP */ limit_sigs(&sigbits, &osigbits); /* and already masked */ } /* Main body starts here -- this is an intentional infinite loop, and * should NEVER exit * * Now, the loop will exit if get_bioreq() returns NULL, indicating * that we've been interrupted. */ while (1) { bp = afs_get_bioreq(); if (!bp) break; /* we were interrupted */ if (code = setjmpx(&jmpbuf)) { /* This should not have happend, maybe a lack of resources */ AFS_GUNLOCK(); s = disable_lock(INTMAX, &afs_asyncbuf_lock); for (bp1 = bp; bp; bp = bp1) { if (bp1) bp1 = (struct buf *)bp1->b_work; bp->b_actf = 0; bp->b_error = code; bp->b_flags |= B_ERROR; iodone(bp); } unlock_enable(s, &afs_asyncbuf_lock); AFS_GLOCK(); continue; } vcp = VTOAFS(bp->b_vp); if (bp->b_flags & B_PFSTORE) { /* XXXX */ ObtainWriteLock(&vcp->lock, 404); if (vcp->v.v_gnode->gn_mwrcnt) { afs_offs_t newlength = (afs_offs_t) dbtob(bp->b_blkno) + bp->b_bcount; if (vcp->f.m.Length < newlength) { afs_Trace4(afs_iclSetp, CM_TRACE_SETLENGTH, ICL_TYPE_STRING, __FILE__, ICL_TYPE_LONG, __LINE__, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(vcp->f.m.Length), ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(newlength)); vcp->f.m.Length = newlength; } } ReleaseWriteLock(&vcp->lock); } /* If the buffer represents a protection violation, rather than * an actual request for I/O, no special action need be taken. */ if (bp->b_flags & B_PFPROT) { iodone(bp); /* Notify all users of the buffer that we're done */ clrjmpx(&jmpbuf); continue; } if (DOvmlock) ObtainWriteLock(&vcp->pvmlock, 211); /* * First map its data area to a region in the current address space * by calling vm_att with the subspace identifier, and a pointer to * the data area. vm_att returns a new data area pointer, but we * also want to hang onto the old one. */ tmpaddr = bp->b_baddr; bp->b_baddr = (caddr_t) vm_att(bp->b_xmemd.subspace_id, tmpaddr); tmperr = afs_ustrategy(bp); /* temp variable saves offset calculation */ if (tmperr) { /* in non-error case */ bp->b_flags |= B_ERROR; /* should other flags remain set ??? */ bp->b_error = tmperr; } /* Unmap the buffer's data area by calling vm_det. Reset data area * to the value that we saved above. */ vm_det(bp->b_baddr); bp->b_baddr = tmpaddr; /* * buffer may be linked with other buffers via the b_work field. * See also afs_gn_strategy. For each buffer in the chain (including * bp) notify all users of the buffer that the daemon is finished * using it by calling iodone. * assumes iodone can modify the b_work field. */ for (tbp1 = bp;;) { tbp2 = (struct buf *)tbp1->b_work; iodone(tbp1); if (!tbp2) break; tbp1 = (struct buf *)tbp2->b_work; iodone(tbp2); if (!tbp1) break; } if (DOvmlock) ReleaseWriteLock(&vcp->pvmlock); /* Unlock the vnode. */ clrjmpx(&jmpbuf); } /* infinite loop (unless we're interrupted) */ } /* end of afs_BioDaemon() */