Beispiel #1
0
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;
}
Beispiel #2
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);
}
Beispiel #3
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;
}