Example #1
0
int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
			    struct autofs_sb_info *sbi, int when)
{
	struct dentry *dentry;
	int ret = -EAGAIN;

	if (autofs_type_trigger(sbi->type))
		dentry = autofs4_expire_direct(sb, mnt, sbi, when);
	else
		dentry = autofs4_expire_indirect(sb, mnt, sbi, when);

	if (dentry) {
		struct autofs_info *ino = autofs4_dentry_ino(dentry);

		/* This is synchronous because it makes the daemon a
		 * little easier
		 */
		ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);

		spin_lock(&sbi->fs_lock);
		/* avoid rapid-fire expire attempts if expiry fails */
		ino->last_used = now;
		ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
		complete_all(&ino->expire_complete);
		spin_unlock(&sbi->fs_lock);
		dput(dentry);
	}

	return ret;
}
int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
			    struct autofs_sb_info *sbi, int when)
{
	struct dentry *dentry;
	int ret = -EAGAIN;

	if (autofs_type_trigger(sbi->type))
		dentry = autofs4_expire_direct(sb, mnt, sbi, when);
	else
		dentry = autofs4_expire_indirect(sb, mnt, sbi, when);

	if (dentry) {
		struct autofs_info *ino = autofs4_dentry_ino(dentry);

		ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);

		spin_lock(&sbi->fs_lock);
		ino->flags &= ~AUTOFS_INF_EXPIRING;
		spin_lock(&dentry->d_lock);
		if (!ret) {
			if ((IS_ROOT(dentry) ||
			    (autofs_type_indirect(sbi->type) &&
			     IS_ROOT(dentry->d_parent))) &&
			    !(dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
				__managed_dentry_set_automount(dentry);
		}
		spin_unlock(&dentry->d_lock);
		complete_all(&ino->expire_complete);
		spin_unlock(&sbi->fs_lock);
		dput(dentry);
	}

	return ret;
}
Example #3
0
/* Call repeatedly until it returns -EAGAIN, meaning there's nothing
   more to be done */
int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
			struct autofs_sb_info *sbi, int __user *arg)
{
	struct dentry *dentry;
	int ret = -EAGAIN;
	int do_now = 0;

	if (arg && get_user(do_now, arg))
		return -EFAULT;

	if (sbi->type & AUTOFS_TYPE_DIRECT)
		dentry = autofs4_expire_direct(sb, mnt, sbi, do_now);
	else
		dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now);

	if (dentry) {
		struct autofs_info *ino = autofs4_dentry_ino(dentry);

		/* This is synchronous because it makes the daemon a
                   little easier */
		ino->flags |= AUTOFS_INF_EXPIRING;
		ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
		ino->flags &= ~AUTOFS_INF_EXPIRING;
		dput(dentry);
	}

	return ret;
}
int autofs4_expire_wait(struct dentry *dentry)
{
	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
	struct autofs_info *ino = autofs4_dentry_ino(dentry);
	int status;

	
	spin_lock(&sbi->fs_lock);
	if (ino->flags & AUTOFS_INF_EXPIRING) {
		spin_unlock(&sbi->fs_lock);

		DPRINTK("waiting for expire %p name=%.*s",
			 dentry, dentry->d_name.len, dentry->d_name.name);

		status = autofs4_wait(sbi, dentry, NFY_NONE);
		wait_for_completion(&ino->expire_complete);

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

		if (d_unhashed(dentry))
			return -EAGAIN;

		return status;
	}
	spin_unlock(&sbi->fs_lock);

	return 0;
}
/* Call repeatedly until it returns -EAGAIN, meaning there's nothing
   more to be done */
int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
			struct autofs_sb_info *sbi, int __user *arg)
{
	struct dentry *dentry;
	int ret = -EAGAIN;
	int do_now = 0;

	if (arg && get_user(do_now, arg))
		return -EFAULT;

	if (autofs_type_trigger(sbi->type))
		dentry = autofs4_expire_direct(sb, mnt, sbi, do_now);
	else
		dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now);

	if (dentry) {
		struct autofs_info *ino = autofs4_dentry_ino(dentry);

		/* This is synchronous because it makes the daemon a
                   little easier */
		ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);

		spin_lock(&sbi->fs_lock);
		if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
			sb->s_root->d_mounted++;
			ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
		}
		ino->flags &= ~AUTOFS_INF_EXPIRING;
		complete_all(&ino->expire_complete);
		spin_unlock(&sbi->fs_lock);
		dput(dentry);
	}

	return ret;
}
Example #6
0
int autofs4_expire_wait(struct dentry *dentry, int rcu_walk)
{
	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
	struct autofs_info *ino = autofs4_dentry_ino(dentry);
	int status;
	int state;

	/* Block on any pending expire */
	if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
		return 0;
	if (rcu_walk)
		return -ECHILD;

retry:
	spin_lock(&sbi->fs_lock);
	state = ino->flags & (AUTOFS_INF_WANT_EXPIRE | AUTOFS_INF_EXPIRING);
	if (state == AUTOFS_INF_WANT_EXPIRE) {
		spin_unlock(&sbi->fs_lock);
		/*
		 * Possibly being selected for expire, wait until
		 * it's selected or not.
		 */
		schedule_timeout_uninterruptible(HZ/10);
		goto retry;
	}
	if (state & AUTOFS_INF_EXPIRING) {
		spin_unlock(&sbi->fs_lock);

		pr_debug("waiting for expire %p name=%pd\n", dentry, dentry);

		status = autofs4_wait(sbi, dentry, NFY_NONE);
		wait_for_completion(&ino->expire_complete);

		pr_debug("expire done status=%d\n", status);

		if (d_unhashed(dentry))
			return -EAGAIN;

		return status;
	}
	spin_unlock(&sbi->fs_lock);

	return 0;
}
Example #7
0
/*
 * Call repeatedly until it returns -EAGAIN, meaning there's nothing
 * more that can be done.
 */
static int autofs_dev_ioctl_expire(struct file *fp,
				   struct autofs_sb_info *sbi,
				   struct autofs_dev_ioctl *param)
{
	struct dentry *dentry;
	struct vfsmount *mnt;
	int err = -EAGAIN;
	int how;

	how = param->arg1;
	mnt = fp->f_path.mnt;

	if (sbi->type & AUTOFS_TYPE_TRIGGER)
		dentry = autofs4_expire_direct(sbi->sb, mnt, sbi, how);
	else
		dentry = autofs4_expire_indirect(sbi->sb, mnt, sbi, how);

	if (dentry) {
		struct autofs_info *ino = autofs4_dentry_ino(dentry);

		/*
		 * This is synchronous because it makes the daemon a
		 * little easier
		*/
		err = autofs4_wait(sbi, dentry, NFY_EXPIRE);

		spin_lock(&sbi->fs_lock);
		if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
			ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
			sbi->sb->s_root->d_mounted++;
		}
		ino->flags &= ~AUTOFS_INF_EXPIRING;
		complete_all(&ino->expire_complete);
		spin_unlock(&sbi->fs_lock);
		dput(dentry);
	}

	return err;
}
Example #8
0
/* Call repeatedly until it returns -EAGAIN, meaning there's nothing
   more to be done */
int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
			struct autofs_sb_info *sbi, int *arg)
{
	struct dentry *dentry;
	int ret = -EAGAIN;
	int do_now = 0;

	if (arg && get_user(do_now, arg))
		return -EFAULT;

	if ((dentry = autofs4_expire(sb, mnt, sbi, do_now)) != NULL) {
		struct autofs_info *de_info = autofs4_dentry_ino(dentry);

		/* This is synchronous because it makes the daemon a
                   little easier */
		de_info->flags |= AUTOFS_INF_EXPIRING;
		ret = autofs4_wait(sbi, &dentry->d_name, NFY_EXPIRE);
		de_info->flags &= ~AUTOFS_INF_EXPIRING;
		dput(dentry);
	}
		
	return ret;
}
Example #9
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 #10
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;
}