Пример #1
0
int
afs_UFSHandleLink(register struct vcache *avc, struct vrequest *areq)
{
    register struct dcache *tdc;
    register char *tp, *rbuf;
    void *tfile;
    afs_size_t offset, len;
    afs_int32 tlen, alen;
    register afs_int32 code;

    /* two different formats, one for links protected 644, have a "." at the
     * end of the file name, which we turn into a null.  Others, protected
     * 755, we add a null to the end of */
    AFS_STATCNT(afs_UFSHandleLink);
    if (!avc->linkData) {
        tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 0);
        afs_Trace3(afs_iclSetp, CM_TRACE_UFSLINK, ICL_TYPE_POINTER, avc,
                   ICL_TYPE_POINTER, tdc, ICL_TYPE_OFFSET,
                   ICL_HANDLE_OFFSET(avc->f.m.Length));
        if (!tdc) {
            if (AFS_IS_DISCONNECTED)
                return ENETDOWN;
            else
                return EIO;
        }
        /* otherwise we have the data loaded, go for it */
        if (len > 1024) {
            afs_PutDCache(tdc);
            return EFAULT;
        }
        if (avc->f.m.Mode & 0111)
            alen = len + 1;	/* regular link */
        else
            alen = len;		/* mt point */
        rbuf = (char *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
        tlen = len;
        ObtainReadLock(&tdc->lock);
#if defined(LINUX_USE_FH)
        tfile = osi_UFSOpen_fh(&tdc->f.fh, tdc->f.fh_type);
#else
        tfile = osi_UFSOpen(tdc->f.inode);
#endif
        code = afs_osi_Read(tfile, -1, rbuf, tlen);
        osi_UFSClose(tfile);
        ReleaseReadLock(&tdc->lock);
        afs_PutDCache(tdc);
        rbuf[alen - 1] = '\0';
        alen = strlen(rbuf) + 1;
        tp = afs_osi_Alloc(alen);	/* make room for terminating null */
        memcpy(tp, rbuf, alen);
        osi_FreeLargeSpace(rbuf);
        if (code != tlen) {
            afs_osi_Free(tp, alen);
            return EIO;
        }
        avc->linkData = tp;
    }
    return 0;
}
Пример #2
0
/**
 *
 * @param volid Volume ID. If it's 0, get it from the name.
 * @param aname Volume name.
 * @param ve Volume entry.
 * @param tcell The cell containing this volume.
 * @param agood
 * @param type Type of volume.
 * @param areq Request.
 * @return Volume or NULL if failure.
 */
static struct volume *
afs_SetupVolume(afs_int32 volid, char *aname, void *ve, struct cell *tcell,
		afs_int32 agood, afs_int32 type, struct vrequest *areq)
{
    struct volume *tv;
    struct vldbentry *ove = (struct vldbentry *)ve;
    struct nvldbentry *nve = (struct nvldbentry *)ve;
    struct uvldbentry *uve = (struct uvldbentry *)ve;

    int whichType;		/* which type of volume to look for */
    int i, j, err = 0;

    if (!volid) {
	int len;
	/* special hint from file server to use vlserver */
	len = strlen(aname);
	if (len >= 8 && strcmp(aname + len - 7, ".backup") == 0)
	    whichType = BACKVOL;
	else if (len >= 10 && strcmp(aname + len - 9, ".readonly") == 0)
	    whichType = ROVOL;
	else
	    whichType = RWVOL;

	/* figure out which one we're really interested in (a set is returned) */
	volid = afs_vtoi(aname);
	if (volid == 0) {
	    if (type == 2) {
		volid = uve->volumeId[whichType];
	    } else if (type == 1) {
		volid = nve->volumeId[whichType];
	    } else {
		volid = ove->volumeId[whichType];
	    }
	} /* end of if (volid == 0) */
    } /* end of if (!volid) */


    ObtainWriteLock(&afs_xvolume, 108);
    i = VHash(volid);
    for (tv = afs_volumes[i]; tv; tv = tv->next) {
	if (tv->volume == volid && tv->cell == tcell->cellNum) {
	    break;
	}
    }
    if (!tv) {
	struct fvolume *tf = 0;

	tv = afs_GetVolSlot();
	if (!tv) {
	    ReleaseWriteLock(&afs_xvolume);
	    return NULL;
	}
	memset(tv, 0, sizeof(struct volume));

	for (j = fvTable[FVHash(tcell->cellNum, volid)]; j != 0; j = tf->next) {
	    if (afs_FVIndex != j) {
		struct osi_file *tfile;
	        tfile = osi_UFSOpen(&volumeInode);
		err =
		    afs_osi_Read(tfile, sizeof(struct fvolume) * j,
				 &staticFVolume, sizeof(struct fvolume));
		osi_UFSClose(tfile);
                if (err != sizeof(struct fvolume)) {
                    afs_warn("afs_SetupVolume: error %d reading volumeinfo\n",
                             (int)err);
                    /* put tv back on the free list; the data in it is not valid */
                    tv->next = afs_freeVolList;
                    afs_freeVolList = tv;
                    /* staticFVolume contents are not valid */
                    afs_FVIndex = -1;
                    ReleaseWriteLock(&afs_xvolume);
                    return NULL;
                }
		afs_FVIndex = j;
	    }
	    tf = &staticFVolume;
	    if (tf->cell == tcell->cellNum && tf->volume == volid)
		break;
	}

        tv->cell = tcell->cellNum;
        AFS_RWLOCK_INIT(&tv->lock, "volume lock");
        tv->next = afs_volumes[i];      /* thread into list */
        afs_volumes[i] = tv;
        tv->volume = volid;

	if (tf && (j != 0)) {
	    tv->vtix = afs_FVIndex;
	    tv->mtpoint = tf->mtpoint;
	    tv->dotdot = tf->dotdot;
	    tv->rootVnode = tf->rootVnode;
	    tv->rootUnique = tf->rootUnique;
	} else {
	    tv->vtix = -1;
	    tv->rootVnode = tv->rootUnique = 0;
            afs_GetDynrootMountFid(&tv->dotdot);
            afs_GetDynrootMountFid(&tv->mtpoint);
            tv->mtpoint.Fid.Vnode =
              VNUM_FROM_TYPEID(VN_TYPE_MOUNT, tcell->cellIndex << 2);
            tv->mtpoint.Fid.Unique = volid;
	}
    }
    tv->refCount++;
    tv->states &= ~VRecheck;	/* just checked it */
    tv->accessTime = osi_Time();
    ReleaseWriteLock(&afs_xvolume);
    if (type == 2) {
	LockAndInstallUVolumeEntry(tv, uve, tcell->cellNum, tcell, areq);
    } else if (type == 1)
	LockAndInstallNVolumeEntry(tv, nve, tcell->cellNum);
    else
	LockAndInstallVolumeEntry(tv, ove, tcell->cellNum);
    if (agood) {
	if (!tv->name) {
	    tv->name = afs_osi_Alloc(strlen(aname) + 1);
	    osi_Assert(tv->name != NULL);
	    strcpy(tv->name, aname);
	}
    }
    for (i = 0; i < NMAXNSERVERS; i++) {
	tv->status[i] = not_busy;
    }
    ReleaseWriteLock(&tv->lock);
    return tv;
}
Пример #3
0
/**
 * UFS specific version of afs_GetVolSlot
 * @return
 */
struct volume *
afs_UFSGetVolSlot(void)
{
    struct volume *tv = NULL, **lv;
    struct osi_file *tfile;
    afs_int32 i = -1, code;
    afs_int32 bestTime;
    struct volume *bestVp, *oldLp = NULL, **bestLp = NULL;
    char *oldname = NULL;
    afs_int32 oldvtix = -2; /* Initialize to a value that doesn't occur */

    AFS_STATCNT(afs_UFSGetVolSlot);
    if (!afs_freeVolList) {
	/* get free slot */
	bestTime = 0x7fffffff;
	bestVp = 0;
	bestLp = 0;
	for (i = 0; i < NVOLS; i++) {
	    lv = &afs_volumes[i];
	    for (tv = *lv; tv; lv = &tv->next, tv = *lv) {
		if (tv->refCount == 0) {	/* is this one available? */
		    if (tv->accessTime < bestTime) {	/* best one available? */
			bestTime = tv->accessTime;
			bestLp = lv;
			bestVp = tv;
		    }
		}
	    }
	}
	if (!bestVp) {
	    afs_warn("afs_UFSGetVolSlot: no vol slots available\n");
	    goto error;
	}
	tv = bestVp;

	oldLp = *bestLp;
	*bestLp = tv->next;

	oldname = tv->name;
	tv->name = NULL;

	oldvtix = tv->vtix;
	/* now write out volume structure to file */
	if (tv->vtix < 0) {
	    tv->vtix = afs_volCounter++;
	    /* now put on hash chain */
	    i = FVHash(tv->cell, tv->volume);
	    staticFVolume.next = fvTable[i];
	    fvTable[i] = tv->vtix;
	} else {
	    /*
	     * Haul the guy in from disk so we don't overwrite hash table
	     * next chain
	     */
	    if (afs_FVIndex != tv->vtix) {
		tfile = osi_UFSOpen(&volumeInode);
		code =
		    afs_osi_Read(tfile, sizeof(struct fvolume) * tv->vtix,
				 &staticFVolume, sizeof(struct fvolume));
		osi_UFSClose(tfile);
		if (code != sizeof(struct fvolume)) {
		    afs_warn("afs_UFSGetVolSlot: error %d reading volumeinfo\n",
		             (int)code);
		    goto error;
		}
		afs_FVIndex = tv->vtix;
	    }
	}
	afs_FVIndex = tv->vtix;
	staticFVolume.volume = tv->volume;
	staticFVolume.cell = tv->cell;
	staticFVolume.mtpoint = tv->mtpoint;
	staticFVolume.dotdot = tv->dotdot;
	staticFVolume.rootVnode = tv->rootVnode;
	staticFVolume.rootUnique = tv->rootUnique;
	tfile = osi_UFSOpen(&volumeInode);
	code =
	    afs_osi_Write(tfile, sizeof(struct fvolume) * afs_FVIndex,
			  &staticFVolume, sizeof(struct fvolume));
	osi_UFSClose(tfile);
	if (code != sizeof(struct fvolume)) {
	    afs_warn("afs_UFSGetVolSlot: error %d writing volumeinfo\n",
	             (int)code);
	    goto error;
	}
	if (oldname) {
	    afs_osi_Free(oldname, strlen(oldname) + 1);
	    oldname = NULL;
	}
    } else {
	tv = afs_freeVolList;
	afs_freeVolList = tv->next;
    }
    return tv;

 error:
    if (tv) {
	if (oldvtix == -2) {
	    afs_warn("afs_UFSGetVolSlot: oldvtix is uninitialized\n");
	    return NULL;
	}
	if (oldname) {
	    tv->name = oldname;
	    oldname = NULL;
	}
	if (oldvtix < 0) {
	    afs_volCounter--;
	    fvTable[i] = staticFVolume.next;
	}
	if (bestLp) {
	    *bestLp = oldLp;
	}
	tv->vtix = oldvtix;
	/* we messed with staticFVolume, so make sure someone else
	 * doesn't think it's fine to use */
	afs_FVIndex = -1;
    }
    return NULL;
}				/*afs_UFSGetVolSlot */
Пример #4
0
/*!
 * \brief Load the list of cells from given inode.
 * \param inode Source inode.
 * \param lookupcode
 * \return 0 for success. < 0 for error.
 */
int
afs_cellname_init(afs_dcache_id_t *inode, int lookupcode)
{
    struct osi_file *tfile;
    int cc, off = 0;

    ObtainWriteLock(&afs_xcell, 692);

    afs_cellnum_next = 1;
    afs_cellname_dirty = 0;

    if (cacheDiskType == AFS_FCACHE_TYPE_MEM) {
	ReleaseWriteLock(&afs_xcell);
	return 0;
    }
    if (lookupcode) {
	ReleaseWriteLock(&afs_xcell);
	return lookupcode;
    }

    tfile = osi_UFSOpen(inode);
    if (!tfile) {
	ReleaseWriteLock(&afs_xcell);
	return EIO;
    }

    afs_copy_inode(&afs_cellname_inode, inode);
    afs_cellname_inode_set = 1;

    while (1) {
	afs_int32 cellnum, clen, magic;
	struct cell_name *cn;
	char *cellname;

	cc = afs_osi_Read(tfile, off, &magic, sizeof(magic));
	if (cc != sizeof(magic))
	    break;
	if (magic != AFS_CELLINFO_MAGIC)
	    break;
	off += cc;

	cc = afs_osi_Read(tfile, off, &cellnum, sizeof(cellnum));
	if (cc != sizeof(cellnum))
	    break;
	off += cc;

	cc = afs_osi_Read(tfile, off, &clen, sizeof(clen));
	if (cc != sizeof(clen))
	    break;
	off += cc;

	cellname = afs_osi_Alloc(clen + 1);
	if (!cellname)
	    break;

	cc = afs_osi_Read(tfile, off, cellname, clen);
	if (cc != clen) {
	    afs_osi_Free(cellname, clen + 1);
	    break;
	}
	off += cc;
	cellname[clen] = '\0';

	if (afs_cellname_lookup_name(cellname)
	    || afs_cellname_lookup_id(cellnum)) {
	    afs_osi_Free(cellname, clen + 1);
	    break;
	}

	cn = afs_cellname_new(cellname, cellnum);
	afs_osi_Free(cellname, clen + 1);
    }

    osi_UFSClose(tfile);
    ReleaseWriteLock(&afs_xcell);
    return 0;
}
Пример #5
0
/** 
 * UFS specific version of afs_GetVolSlot 
 * @return
 */
struct volume *
afs_UFSGetVolSlot(void)
{
    register struct volume *tv, **lv;
    struct osi_file *tfile;
    register afs_int32 i, code;
    afs_int32 bestTime;
    struct volume *bestVp, **bestLp;

    AFS_STATCNT(afs_UFSGetVolSlot);
    if (!afs_freeVolList) {
	/* get free slot */
	bestTime = 0x7fffffff;
	bestVp = 0;
	bestLp = 0;
	for (i = 0; i < NVOLS; i++) {
	    lv = &afs_volumes[i];
	    for (tv = *lv; tv; lv = &tv->next, tv = *lv) {
		if (tv->refCount == 0) {	/* is this one available? */
		    if (tv->accessTime < bestTime) {	/* best one available? */
			bestTime = tv->accessTime;
			bestLp = lv;
			bestVp = tv;
		    }
		}
	    }
	}
	if (!bestVp)
	    osi_Panic("getvolslot none");
	tv = bestVp;
	*bestLp = tv->next;
	if (tv->name)
	    afs_osi_Free(tv->name, strlen(tv->name) + 1);
	tv->name = NULL;
	/* now write out volume structure to file */
	if (tv->vtix < 0) {
	    tv->vtix = afs_volCounter++;
	    /* now put on hash chain */
	    i = FVHash(tv->cell, tv->volume);
	    staticFVolume.next = fvTable[i];
	    fvTable[i] = tv->vtix;
	} else {
	    /*
	     * Haul the guy in from disk so we don't overwrite hash table
	     * next chain
	     */
	    if (afs_FVIndex != tv->vtix) {
#if defined(LINUX_USE_FH)
		tfile = osi_UFSOpen_fh(&volumeinfo_fh, volumeinfo_fh_type);
#else
		tfile = osi_UFSOpen(volumeInode);
#endif
		code =
		    afs_osi_Read(tfile, sizeof(struct fvolume) * tv->vtix,
				 &staticFVolume, sizeof(struct fvolume));
		if (code != sizeof(struct fvolume))
		    osi_Panic("read volumeinfo");
		osi_UFSClose(tfile);
		afs_FVIndex = tv->vtix;
	    }
	}
	afs_FVIndex = tv->vtix;
	staticFVolume.volume = tv->volume;
	staticFVolume.cell = tv->cell;
	staticFVolume.mtpoint = tv->mtpoint;
	staticFVolume.dotdot = tv->dotdot;
	staticFVolume.rootVnode = tv->rootVnode;
	staticFVolume.rootUnique = tv->rootUnique;
#if defined(LINUX_USE_FH)
	tfile = osi_UFSOpen_fh(&volumeinfo_fh, volumeinfo_fh_type);
#else
	tfile = osi_UFSOpen(volumeInode);
#endif
	code =
	    afs_osi_Write(tfile, sizeof(struct fvolume) * afs_FVIndex,
			  &staticFVolume, sizeof(struct fvolume));
	if (code != sizeof(struct fvolume))
	    osi_Panic("write volumeinfo");
	osi_UFSClose(tfile);
    } else {
	tv = afs_freeVolList;
	afs_freeVolList = tv->next;
    }
    return tv;

}				/*afs_UFSGetVolSlot */