int afscp_RemoveFile(const struct afscp_venusfid *dir, char *name) { int code, i, j; struct AFSFid df = dir->fid; struct afscp_volume *vol; struct AFSFetchStatus dfst; struct AFSVolSync vs; struct afscp_server *server; struct rx_connection *c; vol = afscp_VolumeById(dir->cell, dir->fid.Volume); if (vol == NULL) { afscp_errno = ENOENT; return -1; } code = ENOENT; for (i = 0; i < vol->nservers; i++) { server = afscp_ServerByIndex(vol->servers[i]); if (server && server->naddrs > 0) { for (j = 0; j < server->naddrs; j++) { c = afscp_ServerConnection(server, j); if (c == NULL) break; code = RXAFS_RemoveFile(c, &df, name, &dfst, &vs); if (code >= 0) break; } } if (code >= 0) break; } if (code != 0) { _StatInvalidate(dir); afscp_errno = code; return -1; } _StatStuff(dir, &dfst); return 0; }
int afsremove(register struct vcache *adp, register struct dcache *tdc, register struct vcache *tvc, char *aname, afs_ucred_t *acred, struct vrequest *treqp) { register afs_int32 code = 0; register struct afs_conn *tc; struct AFSFetchStatus OutDirStatus; struct AFSVolSync tsync; XSTATS_DECLS; if (!AFS_IS_DISCONNECTED) { do { tc = afs_Conn(&adp->f.fid, treqp, SHARED_LOCK); if (tc) { XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE); RX_AFS_GUNLOCK(); code = RXAFS_RemoveFile(tc->id, (struct AFSFid *)&adp->f.fid.Fid, aname, &OutDirStatus, &tsync); RX_AFS_GLOCK(); XSTATS_END_TIME; } else code = -1; } while (afs_Analyze (tc, code, &adp->f.fid, treqp, AFS_STATS_FS_RPCIDX_REMOVEFILE, SHARED_LOCK, NULL)); } osi_dnlc_remove(adp, aname, tvc); if (code) { if (tdc) { ReleaseSharedLock(&tdc->lock); afs_PutDCache(tdc); } if (tvc) afs_PutVCache(tvc); if (code < 0) { ObtainWriteLock(&afs_xcbhash, 497); afs_DequeueCallback(adp); adp->f.states &= ~CStatd; ReleaseWriteLock(&afs_xcbhash); osi_dnlc_purgedp(adp); } ReleaseWriteLock(&adp->lock); code = afs_CheckCode(code, treqp, 21); return code; } if (tdc) UpgradeSToWLock(&tdc->lock, 637); if (AFS_IS_DISCON_RW || afs_LocalHero(adp, tdc, &OutDirStatus, 1)) { /* we can do it locally */ code = afs_dir_Delete(tdc, aname); if (code) { ZapDCE(tdc); /* surprise error -- invalid value */ DZap(tdc); } } if (tdc) { ReleaseWriteLock(&tdc->lock); afs_PutDCache(tdc); /* drop ref count */ } ReleaseWriteLock(&adp->lock); /* now, get vnode for unlinked dude, and see if we should force it * from cache. adp is now the deleted files vnode. Note that we * call FindVCache instead of GetVCache since if the file's really * gone, we won't be able to fetch the status info anyway. */ if (tvc) { afs_MarinerLog("store$Removing", tvc); #ifdef AFS_BOZONLOCK_ENV afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */ #endif ObtainWriteLock(&tvc->lock, 141); /* note that callback will be broken on the deleted file if there are * still >0 links left to it, so we'll get the stat right */ tvc->f.m.LinkCount--; tvc->f.states &= ~CUnique; /* For the dfs xlator */ if (tvc->f.m.LinkCount == 0 && !osi_Active(tvc)) { if (!AFS_NFSXLATORREQ(acred)) afs_TryToSmush(tvc, acred, 0); } ReleaseWriteLock(&tvc->lock); #ifdef AFS_BOZONLOCK_ENV afs_BozonUnlock(&tvc->pvnLock, tvc); #endif afs_PutVCache(tvc); } return (0); }
/*! * Remove a vnode on the server, be it file or directory. * Not much to do here only get the parent dir's fid and call the * removal rpc. * * \param avc The deleted vcache * \param areq * * \note The vcache refcount should be dropped because it points to * a deleted vnode and has served it's purpouse, but we drop refcount * on shadow dir deletio (we still need it for that). * * \note avc must be write locked. */ int afs_ProcessOpRemove(struct vcache *avc, struct vrequest *areq) { char *tname = NULL; struct AFSFetchStatus OutDirStatus; struct VenusFid pdir_fid; struct AFSVolSync tsync; struct afs_conn *tc; struct rx_connection *rxconn; struct vcache *tdp = NULL; int code = 0; XSTATS_DECLS; tname = afs_osi_Alloc(AFSNAMEMAX); if (!tname) { /* printf("afs_ProcessOpRemove: Couldn't alloc space for file name\n"); */ return ENOMEM; } code = afs_GetParentVCache(avc, 1, &pdir_fid, tname, &tdp); if (code) goto end; if ((vType(avc) == VDIR) && (afs_CheckDeletedChildren(avc))) { /* Deleted children of this dir remain unsynchronized. * Defer this vcache. */ code = EAGAIN; goto end; } if (vType(avc) == VREG || vType(avc) == VLNK) { /* Remove file on server. */ do { tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK, &rxconn); if (tc) { XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE); RX_AFS_GUNLOCK(); code = RXAFS_RemoveFile(rxconn, &pdir_fid.Fid, tname, &OutDirStatus, &tsync); RX_AFS_GLOCK(); XSTATS_END_TIME; } else code = -1; } while (afs_Analyze(tc, rxconn, code, &pdir_fid, areq, AFS_STATS_FS_RPCIDX_REMOVEFILE, SHARED_LOCK, NULL)); } else if (vType(avc) == VDIR) { /* Remove dir on server. */ do { tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK, &rxconn); if (tc) { XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR); RX_AFS_GUNLOCK(); code = RXAFS_RemoveDir(rxconn, &pdir_fid.Fid, tname, &OutDirStatus, &tsync); RX_AFS_GLOCK(); XSTATS_END_TIME; } else code = -1; } while (afs_Analyze(tc, rxconn, code, &pdir_fid, areq, AFS_STATS_FS_RPCIDX_REMOVEDIR, SHARED_LOCK, NULL)); } /* if (vType(avc) == VREG) */ /* if (code) printf("afs_ProcessOpRemove: server returned code=%u\n", code); */ end: afs_osi_Free(tname, AFSNAMEMAX); return code; }