Example #1
0
static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
{
	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);

	if (!autofs4_oz_mode(sbi))
		autofs4_update_usage(dentry);

	return 1;
}
/*
 * Revalidate is called on every cache lookup.  Some of those
 * cache lookups may actually happen while the dentry is not
 * yet completely filled in, and revalidate has to delay such
 * lookups..
 */
static int autofs4_root_revalidate(struct dentry * dentry, int flags)
{
	struct inode * dir = dentry->d_parent->d_inode;
	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
	struct autofs_info *ino;
	int oz_mode = autofs4_oz_mode(sbi);

	/* Pending dentry */
	if (autofs4_ispending(dentry)) {
		if (autofs4_oz_mode(sbi))
			return 1;
		else
			return try_to_fill_dentry(dentry, dir->i_sb, sbi);
	}

	/* Negative dentry.. invalidate if "old" */
	if (dentry->d_inode == NULL)
		return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT);

	ino = autofs4_dentry_ino(dentry);

	/* Check for a non-mountpoint directory with no contents */
	spin_lock(&dcache_lock);
	if (S_ISDIR(dentry->d_inode->i_mode) &&
	    !d_mountpoint(dentry) && 
	    list_empty(&dentry->d_subdirs)) {
		DPRINTK(("autofs_root_revalidate: dentry=%p %.*s, emptydir\n",
			 dentry, dentry->d_name.len, dentry->d_name.name));
		spin_unlock(&dcache_lock);
		if (oz_mode)
			return 1;
		else
			return try_to_fill_dentry(dentry, dir->i_sb, sbi);
	}
	spin_unlock(&dcache_lock);

	/* Update the usage list */
	if (!oz_mode)
		autofs4_update_usage(dentry);

	return 1;
}
Example #3
0
static int try_to_fill_dentry(struct dentry *dentry, 
			      struct super_block *sb,
			      struct autofs_sb_info *sbi)
{
	struct autofs_info *de_info = autofs4_dentry_ino(dentry);
	int status = 0;

	/* Block on any pending expiry here; invalidate the dentry
           when expiration is done to trigger mount request with a new
           dentry */
	if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) {
		DPRINTK(("try_to_fill_entry: waiting for expire %p name=%.*s, flags&PENDING=%s de_info=%p de_info->flags=%x\n",
			 dentry, dentry->d_name.len, dentry->d_name.name, 
			 dentry->d_flags & DCACHE_AUTOFS_PENDING?"t":"f",
			 de_info, de_info?de_info->flags:0));
		status = autofs4_wait(sbi, &dentry->d_name, NFY_NONE);
		
		DPRINTK(("try_to_fill_entry: expire done status=%d\n", status));
		
		return 0;
	}

	DPRINTK(("try_to_fill_entry: dentry=%p %.*s ino=%p\n", 
		 dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode));

	/* Wait for a pending mount, triggering one if there isn't one already */
	while(dentry->d_inode == NULL) {
		DPRINTK(("try_to_fill_entry: waiting for mount name=%.*s, de_info=%p de_info->flags=%x\n",
			 dentry->d_name.len, dentry->d_name.name, 
			 de_info, de_info?de_info->flags:0));
		status = autofs4_wait(sbi, &dentry->d_name, NFY_MOUNT);
		 
		DPRINTK(("try_to_fill_entry: mount done status=%d\n", status));

		if (status && dentry->d_inode)
			return 0; /* Try to get the kernel to invalidate this dentry */
		
		/* Turn this into a real negative dentry? */
		if (status == -ENOENT) {
			dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT;
			dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
			return 1;
		} else if (status) {
			/* Return a negative dentry, but leave it "pending" */
			return 1;
		}
	}

	/* If this is an unused directory that isn't a mount point,
	   bitch at the daemon and fix it in user space */
	spin_lock(&dcache_lock);
	if (S_ISDIR(dentry->d_inode->i_mode) &&
	    !d_mountpoint(dentry) && 
	    list_empty(&dentry->d_subdirs)) {
		DPRINTK(("try_to_fill_entry: mounting existing dir\n"));
		spin_unlock(&dcache_lock);
		return autofs4_wait(sbi, &dentry->d_name, NFY_MOUNT) == 0;
	}
	spin_unlock(&dcache_lock);

	/* We don't update the usages for the autofs daemon itself, this
	   is necessary for recursive autofs mounts */
	if (!autofs4_oz_mode(sbi))
		autofs4_update_usage(dentry);

	dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
	return 1;
}
Example #4
0
static int try_to_fill_dentry(struct dentry *dentry,
                              struct super_block *sb,
                              struct autofs_sb_info *sbi, int flags)
{
    struct autofs_info *de_info = autofs4_dentry_ino(dentry);
    int status = 0;

    /* Block on any pending expiry here; invalidate the dentry
           when expiration is done to trigger mount request with a new
           dentry */
    if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) {
        DPRINTK("waiting for expire %p name=%.*s",
                dentry, dentry->d_name.len, dentry->d_name.name);

        status = autofs4_wait(sbi, dentry, NFY_NONE);

        DPRINTK("expire done status=%d", status);

        return 0;
    }

    DPRINTK("dentry=%p %.*s ino=%p",
            dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);

    /* Wait for a pending mount, triggering one if there isn't one already */
    if (dentry->d_inode == NULL) {
        DPRINTK("waiting for mount name=%.*s",
                dentry->d_name.len, dentry->d_name.name);

        status = autofs4_wait(sbi, dentry, NFY_MOUNT);

        DPRINTK("mount done status=%d", status);

        if (status && dentry->d_inode)
            return 0; /* Try to get the kernel to invalidate this dentry */

        /* Turn this into a real negative dentry? */
        if (status == -ENOENT) {
            dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT;
            spin_lock(&dentry->d_lock);
            dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
            spin_unlock(&dentry->d_lock);
            return 1;
        } else if (status) {
            /* Return a negative dentry, but leave it "pending" */
            return 1;
        }
        /* Trigger mount for path component or follow link */
    } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) ||
               current->link_count) {
        DPRINTK("waiting for mount name=%.*s",
                dentry->d_name.len, dentry->d_name.name);

        spin_lock(&dentry->d_lock);
        dentry->d_flags |= DCACHE_AUTOFS_PENDING;
        spin_unlock(&dentry->d_lock);
        status = autofs4_wait(sbi, dentry, NFY_MOUNT);

        DPRINTK("mount done status=%d", status);

        if (status) {
            spin_lock(&dentry->d_lock);
            dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
            spin_unlock(&dentry->d_lock);
            return 0;
        }
    }

    /* We don't update the usages for the autofs daemon itself, this
       is necessary for recursive autofs mounts */
    if (!autofs4_oz_mode(sbi))
        autofs4_update_usage(dentry);

    spin_lock(&dentry->d_lock);
    dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
    spin_unlock(&dentry->d_lock);
    return 1;
}