예제 #1
0
/*
 * Invalidate the /afs vnode for dynroot; called when the underlying
 * directory has changed and needs to be re-read.
 */
void
afs_DynrootInvalidate(void)
{
    afs_int32 retry;
    struct vcache *tvc;
    struct VenusFid tfid;

    if (!afs_dynrootEnable)
	return;

    ObtainWriteLock(&afs_dynrootDirLock, 687);
    afs_dynrootVersion++;
    afs_dynrootVersionHigh = osi_Time();
    ReleaseWriteLock(&afs_dynrootDirLock);

    afs_GetDynrootFid(&tfid);
    do {
	retry = 0;
	ObtainReadLock(&afs_xvcache);
	tvc = afs_FindVCache(&tfid, &retry, 0);
	ReleaseReadLock(&afs_xvcache);
    } while (retry);
    if (tvc) {
	tvc->f.states &= ~(CStatd | CUnique);
	osi_dnlc_purgedp(tvc);
	afs_PutVCache(tvc);
    }
}
예제 #2
0
static struct dentry *afs_decode_fh(struct super_block *sb, __u32 *fh,
				    int fh_len, int fh_type,
				    int (*acceptable)(void *, struct dentry *),
				    void *context)
#endif
{
    struct VenusFid fid;
    struct cell *tc;
    struct dentry *result;
#if defined(NEW_EXPORT_OPS)
    __u32 *fh = (__u32 *)fh_fid->raw;
#endif


    switch (fh_type) {
	case AFSFH_VENUSFID:
	    if (fh_len != 4)
		return NULL;
	    fid.Cell       = fh[0];
	    fid.Fid.Volume = fh[1];
	    fid.Fid.Vnode  = fh[2];
	    fid.Fid.Unique = fh[3];
	    break;

	case AFSFH_CELLFID:
	    if (fh_len != 7)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    fid.Cell       = tc->cellNum;
	    fid.Fid.Volume = fh[4];
	    fid.Fid.Vnode  = fh[5];
	    fid.Fid.Unique = fh[6];
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_NET_VENUSFID:
	    fid.Cell       = ntohl(fh[0]);
	    fid.Fid.Volume = ntohl(fh[1]);
	    fid.Fid.Vnode  = ntohl(fh[2]);
	    fid.Fid.Unique = ntohl(fh[3]);
	    break;

	case AFSFH_NET_CELLFID:
	    if (fh_len != 7)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    fid.Cell       = tc->cellNum;
	    fid.Fid.Volume = ntohl(fh[4]);
	    fid.Fid.Vnode  = ntohl(fh[5]);
	    fid.Fid.Unique = ntohl(fh[6]);
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_DYN_RO_CELL:
	case AFSFH_DYN_RW_CELL:
	    if (fh_len != 4)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    afs_GetDynrootFid(&fid);
	    fid.Fid.Vnode  = VNUM_FROM_CIDX_RW(tc->cellIndex, fh_type & 1);
	    fid.Fid.Unique = 1;
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_DYN_RO_LINK:
	case AFSFH_DYN_RW_LINK:
	    if (fh_len != 4)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    afs_GetDynrootFid(&fid);
	    fid.Fid.Vnode  = VNUM_FROM_CAIDX_RW(tc->cellIndex, fh_type & 1);
	    fid.Fid.Unique = 1;
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_DYN_MOUNT:
	    if (fh_len != 5)
		return NULL;
	    AFS_GLOCK();
	    tc = afs_GetCellByHandle((void *)fh, READ_LOCK);
	    if (!tc) {
		AFS_GUNLOCK();
		return NULL;
	    }
	    afs_GetDynrootFid(&fid);
	    fid.Fid.Vnode  = VNUM_FROM_TYPEID(VN_TYPE_MOUNT,
					      tc->cellIndex << 2);
	    fid.Fid.Unique = ntohl(fh[4]);
	    afs_PutCell(tc, READ_LOCK);
	    AFS_GUNLOCK();
	    break;

	case AFSFH_DYN_SYMLINK:
	    /* XXX parse dynroot symlink filehandle */
	    /* break; */

	default:
	    return NULL;
    }

#if defined(NEW_EXPORT_OPS)
    result = afs_export_get_dentry(sb, &fid);
#else
    result = sb->s_export_op->find_exported_dentry(sb, &fid, 0,
						   acceptable, context);

#endif

#ifdef OSI_EXPORT_DEBUG
    if (!result) {
	printk("afs: decode_fh(0x%08x/%d/%d.%d): no dentry\n",
	       fid.Cell,      fid.Fid.Volume,
	       fid.Fid.Vnode, fid.Fid.Unique);
    } else if (IS_ERR(result)) {
	printk("afs: decode_fh(0x%08x/%d/%d.%d): error %ld\n",
	       fid.Cell,      fid.Fid.Volume,
	       fid.Fid.Vnode, fid.Fid.Unique, PTR_ERR(result));
    }
#endif
    return result;
}
예제 #3
0
int
afs_CheckRootVolume(void)
{
    char rootVolName[32];
    struct volume *tvp = NULL;
    int usingDynroot = afs_GetDynrootEnable();
    int localcell;

    AFS_STATCNT(afs_CheckRootVolume);
    if (*afs_rootVolumeName == 0) {
	strcpy(rootVolName, "root.afs");
    } else {
	strcpy(rootVolName, afs_rootVolumeName);
    }

    if (usingDynroot) {
	afs_GetDynrootFid(&afs_rootFid);
	tvp = afs_GetVolume(&afs_rootFid, NULL, READ_LOCK);
    } else {
	struct cell *lc = afs_GetPrimaryCell(READ_LOCK);

	if (!lc)
	    return ENOENT;
	localcell = lc->cellNum;
	afs_PutCell(lc, READ_LOCK);
	tvp = afs_GetVolumeByName(rootVolName, localcell, 1, NULL, READ_LOCK);
	if (!tvp) {
	    char buf[128];
	    int len = strlen(rootVolName);

	    if ((len < 9) || strcmp(&rootVolName[len - 9], ".readonly")) {
		strcpy(buf, rootVolName);
		afs_strcat(buf, ".readonly");
		tvp = afs_GetVolumeByName(buf, localcell, 1, NULL, READ_LOCK);
	    }
	}
	if (tvp) {
	    int volid = (tvp->roVol ? tvp->roVol : tvp->volume);
	    afs_rootFid.Cell = localcell;
	    if (afs_rootFid.Fid.Volume && afs_rootFid.Fid.Volume != volid
		&& afs_globalVp) {
		/* If we had a root fid before and it changed location we reset
		 * the afs_globalVp so that it will be reevaluated.
		 * Just decrement the reference count. This only occurs during
		 * initial cell setup and can panic the machine if we set the
		 * count to zero and fs checkv is executed when the current
		 * directory is /afs.
		 */
#ifdef AFS_LINUX20_ENV
		{
		    struct vrequest *treq = NULL;
		    struct vattr vattr;
		    cred_t *credp;
		    struct dentry *dp;
		    struct vcache *vcp;

		    afs_rootFid.Fid.Volume = volid;
		    afs_rootFid.Fid.Vnode = 1;
		    afs_rootFid.Fid.Unique = 1;

		    credp = crref();
		    if (afs_CreateReq(&treq, credp))
			goto out;
		    vcp = afs_GetVCache(&afs_rootFid, treq, NULL, NULL);
		    if (!vcp)
			goto out;
		    afs_getattr(vcp, &vattr, credp);
		    afs_fill_inode(AFSTOV(vcp), &vattr);

		    dp = d_find_alias(AFSTOV(afs_globalVp));

#if defined(AFS_LINUX24_ENV)
#if defined(HAVE_DCACHE_LOCK)
		    spin_lock(&dcache_lock);
#else
		    spin_lock(&AFSTOV(vcp)->i_lock);
#endif
#if defined(AFS_LINUX26_ENV)
		    spin_lock(&dp->d_lock);
#endif
#endif
#if defined(D_ALIAS_IS_HLIST)
		    hlist_del_init(&dp->d_alias);
		    hlist_add_head(&dp->d_alias, &(AFSTOV(vcp)->i_dentry));
#else
		    list_del_init(&dp->d_alias);
		    list_add(&dp->d_alias, &(AFSTOV(vcp)->i_dentry));
#endif
		    dp->d_inode = AFSTOV(vcp);
#if defined(AFS_LINUX24_ENV)
#if defined(AFS_LINUX26_ENV)
		    spin_unlock(&dp->d_lock);
#endif
#if defined(HAVE_DCACHE_LOCK)
		    spin_unlock(&dcache_lock);
#else
		    spin_unlock(&AFSTOV(vcp)->i_lock);
#endif
#endif
		    dput(dp);

		    AFS_FAST_RELE(afs_globalVp);
		    afs_globalVp = vcp;
		out:
		    crfree(credp);
		    afs_DestroyReq(treq);
		}
#else
#ifdef AFS_DARWIN80_ENV
		afs_PutVCache(afs_globalVp);
#else
		AFS_FAST_RELE(afs_globalVp);
#endif
		afs_globalVp = 0;
#endif
	    }
	    afs_rootFid.Fid.Volume = volid;
	    afs_rootFid.Fid.Vnode = 1;
	    afs_rootFid.Fid.Unique = 1;
	}
    }
    if (tvp) {
	afs_initState = 300;	/* won */
	afs_osi_Wakeup(&afs_initState);
	afs_PutVolume(tvp, READ_LOCK);
    }
    if (afs_rootFid.Fid.Volume)
	return 0;
    else
	return ENOENT;
}