예제 #1
0
/* Close all cached file descriptors for this inode. */
int
ih_reallyclose(IHandle_t * ihP)
{
    if (!ihP)
	return 0;

    IH_LOCK;
    ihP->ih_refcnt++;   /* must not disappear over unlock */
    if (ihP->ih_synced) {
	FdHandle_t *fdP;
        ihP->ih_synced = 0;
	IH_UNLOCK;

	fdP = IH_OPEN(ihP);
	if (fdP) {
	    OS_SYNC(fdP->fd_fd);
	    FDH_CLOSE(fdP);
	}

	IH_LOCK;
    }

    osi_Assert(ihP->ih_refcnt > 0);

    ih_fdclose(ihP);

    if (ihP->ih_refcnt > 1)
	ihP->ih_refcnt--;
    else
	_ih_release_r(ihP);

    IH_UNLOCK;
    return 0;
}
예제 #2
0
void
ih_sync_all(void) {

    int ihash;

    IH_LOCK;
    for (ihash = 0; ihash < I_HANDLE_HASH_SIZE; ihash++) {
	IHandle_t *ihP, *ihPnext;

	ihP = ihashTable[ihash].ihash_head;
	if (ihP)
	    ihP->ih_refcnt++;	/* must not disappear over unlock */
	for (; ihP; ihP = ihPnext) {
	    
	    if (ihP->ih_synced) {
		FdHandle_t *fdP;

		ihP->ih_synced = 0;
		IH_UNLOCK;

		fdP = IH_OPEN(ihP);
		if (fdP) { 
		    OS_SYNC(fdP->fd_fd);
		    FDH_CLOSE(fdP);
		}

	  	IH_LOCK;
	    }

	    /* when decrementing the refcount, the ihandle might disappear
	       and we might not even be able to proceed to the next one.
	       Hence the gymnastics putting a hold on the next one already */
	    ihPnext = ihP->ih_next;
	    if (ihPnext) ihPnext->ih_refcnt++;

	    if (ihP->ih_refcnt > 1) {
		ihP->ih_refcnt--;
	    } else {
		IH_UNLOCK;
		ih_release(ihP);
		IH_LOCK;
	    }

	}
    }
    IH_UNLOCK;
}
예제 #3
0
/* delete a portion of an index, adjusting offset appropriately.  Returns 0 if
   things work and we should be called again, 1 if success full and done, and -1
   if an error occurred.  It adjusts offset appropriately on 0 or 1 return codes,
   and otherwise doesn't touch it */
static int
ObliterateRegion(Volume * avp, VnodeClass aclass, StreamHandle_t * afile,
		 afs_int32 * aoffset)
{
    register struct VnodeClassInfo *vcp;
    Inode inodes[MAXOBLITATONCE];
    register afs_int32 iindex, nscanned;
    afs_int32 offset;
    char buf[SIZEOF_LARGEDISKVNODE];
    int hitEOF;
    register int i;
    register afs_int32 code;
    register struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;

    hitEOF = 0;
    vcp = &VnodeClassInfo[aclass];
    offset = *aoffset;		/* original offset */
    iindex = 0;
    nscanned = 0;
    /* advance over up to MAXOBLITATONCE inodes.  nscanned tells us how many we examined.
     * We remember the inodes in an array, and idec them after zeroing them in the index.
     * The reason for these contortions is to make volume deletion idempotent, even
     * if we crash in the middle of a delete operation. */
    STREAM_SEEK(afile, offset, 0);
    while (1) {
	if (iindex >= MAXOBLITATONCE) {
	    break;
	}
	code = STREAM_READ(vnode, vcp->diskSize, 1, afile);
	nscanned++;
	offset += vcp->diskSize;
	if (code != 1) {
	    hitEOF = 1;
	    break;
	}
	if (vnode->type != vNull) {
	    if (vnode->vnodeMagic != vcp->magic)
		goto fail;	/* something really wrong; let salvager take care of it */
	    if (VNDISK_GET_INO(vnode))
		inodes[iindex++] = VNDISK_GET_INO(vnode);
	}
    }

    /* next, obliterate the index and fflush (and fsync) it */
    STREAM_SEEK(afile, *aoffset, 0);	/* seek back to start of vnode index region */
    memset(buf, 0, sizeof(buf));	/* zero out our proto-vnode */
    for (i = 0; i < nscanned; i++) {
	if (STREAM_WRITE(buf, vcp->diskSize, 1, afile) != 1)
	    goto fail;
    }
    STREAM_FLUSH(afile);	/* ensure 0s are on the disk */
    OS_SYNC(afile->str_fd);

    /* finally, do the idec's */
    for (i = 0; i < iindex; i++) {
	IH_DEC(V_linkHandle(avp), inodes[i], V_parentId(avp));
	DOPOLL;
    }

    /* return the new offset */
    *aoffset = offset;
    return hitEOF;		/* return 1 if hit EOF (don't call again), otherwise 0 */

  fail:
    return -1;
}