/* Check a mount point for busyness */
static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
{
	struct dentry *top = dentry;
	struct path path = {.mnt = mnt, .dentry = dentry};
	int status = 1;

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

	path_get(&path);

	if (!follow_down_one(&path))
		goto done;

	if (is_autofs4_dentry(path.dentry)) {
		struct autofs_sb_info *sbi = autofs4_sbi(path.dentry->d_sb);

		/* This is an autofs submount, we can't expire it */
		if (autofs_type_indirect(sbi->type))
			goto done;
	}

	/* Update the expiry counter if fs is busy */
	if (!may_umount_tree(path.mnt)) {
		struct autofs_info *ino = autofs4_dentry_ino(top);
		ino->last_used = jiffies;
		goto done;
	}

	status = 0;
done:
	DPRINTK("returning = %d", status);
	path_put(&path);
	return status;
}
Exemplo n.º 2
0
/*
 * NOTE!
 *
 * Normal filesystems would do a "d_delete()" to tell the VFS dcache
 * that the file no longer exists. However, doing that means that the
 * VFS layer can turn the dentry into a negative dentry.  We don't want
 * this, because since the unlink is probably the result of an expire.
 * We simply d_drop it, which allows the dentry lookup to remount it
 * if necessary.
 *
 * If a process is blocked on the dentry waiting for the expire to finish,
 * it will invalidate the dentry and try to mount with a new one.
 *
 * Also see autofs_dir_rmdir().. 
 */
static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
{
	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
	struct autofs_info *ino = autofs4_dentry_ino(dentry);
	
	/* This allows root to remove symlinks */
	lock_kernel();
	if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) {
		unlock_kernel();
		return -EACCES;
	}

	dput(ino->dentry);

	dentry->d_inode->i_size = 0;
	dentry->d_inode->i_nlink = 0;

	dir->i_mtime = CURRENT_TIME;

	d_drop(dentry);

	unlock_kernel();
	
	return 0;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
{
	struct autofs_sb_info *sbi = autofs4_sbi(mnt->mnt_sb);
	struct inode *root_inode = mnt->mnt_sb->s_root->d_inode;

	if (!sbi)
		return 0;

	seq_printf(m, ",fd=%d", sbi->pipefd);
	if (root_inode->i_uid != 0)
		seq_printf(m, ",uid=%u", root_inode->i_uid);
	if (root_inode->i_gid != 0)
		seq_printf(m, ",gid=%u", root_inode->i_gid);
	seq_printf(m, ",pgrp=%d", sbi->oz_pgrp);
	seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ);
	seq_printf(m, ",minproto=%d", sbi->min_proto);
	seq_printf(m, ",maxproto=%d", sbi->max_proto);

	if (autofs_type_offset(sbi->type))
		seq_printf(m, ",offset");
	else if (autofs_type_direct(sbi->type))
		seq_printf(m, ",direct");
	else
		seq_printf(m, ",indirect");

	return 0;
}
Exemplo n.º 5
0
static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
{
    struct dentry *dentry = file->f_dentry;
    struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
    int status;

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

    if (autofs4_oz_mode(sbi))
        goto out;

    if (autofs4_ispending(dentry)) {
        DPRINTK("dentry busy");
        return -EBUSY;
    }

    if (d_mountpoint(dentry)) {
        struct file *fp = file->private_data;

        if (!fp)
            return -ENOENT;

        if (!fp->f_op || !fp->f_op->readdir)
            goto out;

        status = vfs_readdir(fp, filldir, dirent);
        file->f_pos = fp->f_pos;
        if (status)
            autofs4_copy_atime(file, fp);
        return status;
    }
out:
    return autofs4_dcache_readdir(file, dirent, filldir);
}
Exemplo n.º 6
0
static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
    struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
    struct autofs_info *ino = autofs4_dentry_ino(dentry);
    struct inode *inode;

    if ( !autofs4_oz_mode(sbi) )
        return -EACCES;

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

    ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555);
    if (ino == NULL)
        return -ENOSPC;

    inode = autofs4_get_inode(dir->i_sb, ino);
    d_instantiate(dentry, inode);

    if (dir == dir->i_sb->s_root->d_inode)
        dentry->d_op = &autofs4_root_dentry_operations;
    else
        dentry->d_op = &autofs4_dentry_operations;

    dentry->d_fsdata = ino;
    ino->dentry = dget(dentry);
    ino->inode = inode;
    dir->i_nlink++;
    dir->i_mtime = CURRENT_TIME;

    return 0;
}
Exemplo n.º 7
0
static int autofs4_dir_close(struct inode *inode, struct file *file)
{
    struct dentry *dentry = file->f_dentry;
    struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);

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

    if (autofs4_oz_mode(sbi))
        goto out;

    if (autofs4_ispending(dentry)) {
        DPRINTK("dentry busy");
        return -EBUSY;
    }

    if (d_mountpoint(dentry)) {
        struct file *fp = file->private_data;

        if (!fp)
            return -ENOENT;

        filp_close(fp, current->files);
        file->private_data = NULL;
    }
out:
    return 0;
}
/* Lookups in the root directory */
static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dentry)
{
	struct autofs_sb_info *sbi;
	int oz_mode;

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

	if (dentry->d_name.len > NAME_MAX)
		return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */

	sbi = autofs4_sbi(dir->i_sb);

	oz_mode = autofs4_oz_mode(sbi);
	DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n",
		 current->pid, current->pgrp, sbi->catatonic, oz_mode));

	/*
	 * Mark the dentry incomplete, but add it. This is needed so
	 * that the VFS layer knows about the dentry, and we can count
	 * on catching any lookups through the revalidate.
	 *
	 * Let all the hard work be done by the revalidate function that
	 * needs to be able to do this anyway..
	 *
	 * We need to do this before we release the directory semaphore.
	 */
	dentry->d_op = &autofs4_root_dentry_operations;

	if (!oz_mode)
		dentry->d_flags |= DCACHE_AUTOFS_PENDING;
	dentry->d_fsdata = NULL;
	d_add(dentry, NULL);

	if (dentry->d_op && dentry->d_op->d_revalidate) {
		up(&dir->i_sem);
		(dentry->d_op->d_revalidate)(dentry, 0);
		down(&dir->i_sem);
	}

	/*
	 * If we are still pending, check if we had to handle
	 * a signal. If so we can force a restart..
	 */
	if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
		if (signal_pending(current))
			return ERR_PTR(-ERESTARTNOINTR);
	}

	/*
	 * If this dentry is unhashed, then we shouldn't honour this
	 * lookup even if the dentry is positive.  Returning ENOENT here
	 * doesn't do the right thing for all system calls, but it should
	 * be OK for the operations we permit from an autofs.
	 */
	if ( dentry->d_inode && d_unhashed(dentry) )
		return ERR_PTR(-ENOENT);

	return NULL;
}
Exemplo n.º 9
0
void autofs4_kill_sb(struct super_block *sb)
{
	struct autofs_sb_info *sbi = autofs4_sbi(sb);

	/*
	 * In the event of a failure in get_sb_nodev the superblock
	 * info is not present so nothing else has been setup, so
	 * just call kill_anon_super when we are called from
	 * deactivate_super.
	 */
	if (!sbi)
		goto out_kill_sb;

	/* Free wait queues, close pipe */
	autofs4_catatonic_mode(sbi);

	/* Clean up and release dangling references */
	autofs4_force_release(sbi);

	sb->s_fs_info = NULL;
	kfree(sbi);

out_kill_sb:
	DPRINTK("shutting down");
	kill_anon_super(sb);
}
Exemplo n.º 10
0
static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
{
	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
	struct autofs_info *ino = autofs4_dentry_ino(dentry);
	
	lock_kernel();
	if (!autofs4_oz_mode(sbi)) {
		unlock_kernel();
		return -EACCES;
	}

	spin_lock(&dcache_lock);
	if (!list_empty(&dentry->d_subdirs)) {
		spin_unlock(&dcache_lock);
		unlock_kernel();
		return -ENOTEMPTY;
	}
	__d_drop(dentry);
	spin_unlock(&dcache_lock);

	dput(ino->dentry);

	dentry->d_inode->i_size = 0;
	dentry->d_inode->i_nlink = 0;

	if (dir->i_nlink)
		dir->i_nlink--;

	unlock_kernel();
	return 0;
}
Exemplo n.º 11
0
/*
 * Calculate and dget next entry in top down tree traversal.
 */
static struct dentry *get_next_positive_dentry(struct dentry *prev,
					       struct dentry *root)
{
	struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
	struct list_head *next;
	struct dentry *p, *ret;

	if (prev == NULL)
		return dget(root);

	spin_lock(&sbi->lookup_lock);
relock:
	p = prev;
	spin_lock(&p->d_lock);
again:
	next = p->d_subdirs.next;
	if (next == &p->d_subdirs) {
		while (1) {
			struct dentry *parent;

			if (p == root) {
				spin_unlock(&p->d_lock);
				spin_unlock(&sbi->lookup_lock);
				dput(prev);
				return NULL;
			}

			parent = p->d_parent;
			if (!spin_trylock(&parent->d_lock)) {
				spin_unlock(&p->d_lock);
				cpu_relax();
				goto relock;
			}
			spin_unlock(&p->d_lock);
			next = p->d_child.next;
			p = parent;
			if (next != &parent->d_subdirs)
				break;
		}
	}
	ret = list_entry(next, struct dentry, d_child);

	spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
	/* Negative dentry - try next */
	if (!simple_positive(ret)) {
		spin_unlock(&p->d_lock);
		lock_set_subclass(&ret->d_lock.dep_map, 0, _RET_IP_);
		p = ret;
		goto again;
	}
	dget_dlock(ret);
	spin_unlock(&ret->d_lock);
	spin_unlock(&p->d_lock);
	spin_unlock(&sbi->lookup_lock);

	dput(prev);

	return ret;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
static int autofs4_dir_open(struct inode *inode, struct file *file)
{
    struct dentry *dentry = file->f_dentry;
    struct vfsmount *mnt = file->f_vfsmnt;
    struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
    int status;

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

    if (autofs4_oz_mode(sbi))
        goto out;

    if (autofs4_ispending(dentry)) {
        DPRINTK("dentry busy");
        return -EBUSY;
    }

    if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) {
        struct nameidata nd;
        int empty;

        /* In case there are stale directory dentrys from a failed mount */
        spin_lock(&dcache_lock);
        empty = list_empty(&dentry->d_subdirs);
        spin_unlock(&dcache_lock);

        if (!empty)
            d_invalidate(dentry);

        nd.flags = LOOKUP_DIRECTORY;
        status = (dentry->d_op->d_revalidate)(dentry, &nd);

        if (!status)
            return -ENOENT;
    }

    if (d_mountpoint(dentry)) {
        struct file *fp = NULL;
        struct vfsmount *fp_mnt = mntget(mnt);
        struct dentry *fp_dentry = dget(dentry);

        while (follow_down(&fp_mnt, &fp_dentry) && d_mountpoint(fp_dentry));

        fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
        status = PTR_ERR(fp);
        if (IS_ERR(fp)) {
            file->private_data = NULL;
            return status;
        }
        file->private_data = fp;
    }
out:
    return 0;
}
Exemplo n.º 14
0
/*
 * Get the autofs super block info struct from the file opened on
 * the autofs mount point.
 */
static struct autofs_sb_info *autofs_dev_ioctl_sbi(struct file *f)
{
	struct autofs_sb_info *sbi = NULL;
	struct inode *inode;

	if (f) {
		inode = f->f_path.dentry->d_inode;
		sbi = autofs4_sbi(inode->i_sb);
	}
	return sbi;
}
Exemplo n.º 15
0
/*
 * Get the autofs super block info struct from the file opened on
 * the autofs mount point.
 */
static struct autofs_sb_info *autofs_dev_ioctl_sbi(struct file *f)
{
	struct autofs_sb_info *sbi = NULL;
	struct inode *inode;

	if (f) {
		inode = file_inode(f);
		sbi = autofs4_sbi(inode->i_sb);
	}
	return sbi;
}
Exemplo n.º 16
0
static int autofs4_dir_symlink(struct inode *dir, 
			       struct dentry *dentry,
			       const char *symname)
{
	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
	struct autofs_info *ino = autofs4_dentry_ino(dentry);
	struct inode *inode;
	char *cp;

	DPRINTK(("autofs_dir_symlink: %s <- %.*s\n", symname, 
		 dentry->d_name.len, dentry->d_name.name));

	lock_kernel();
	if (!autofs4_oz_mode(sbi)) {
		unlock_kernel();
		return -EACCES;
	}

	ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555);
	if (ino == NULL) {
		unlock_kernel();
		return -ENOSPC;
	}

	ino->size = strlen(symname);
	ino->u.symlink = cp = kmalloc(ino->size + 1, GFP_KERNEL);

	if (cp == NULL) {
		kfree(ino);
		unlock_kernel();
		return -ENOSPC;
	}

	strcpy(cp, symname);

	inode = autofs4_get_inode(dir->i_sb, ino);
	d_instantiate(dentry, inode);

	if (dir == dir->i_sb->s_root->d_inode)
		dentry->d_op = &autofs4_root_dentry_operations;
	else
		dentry->d_op = &autofs4_dentry_operations;

	dentry->d_fsdata = ino;
	ino->dentry = dget(dentry);
	ino->inode = inode;

	dir->i_mtime = CURRENT_TIME;

	unlock_kernel();
	return 0;
}
Exemplo n.º 17
0
static void autofs4_put_super(struct super_block *sb)
{
    struct autofs_sb_info *sbi = autofs4_sbi(sb);

    sb->u.generic_sbp = NULL;

    if ( !sbi->catatonic )
        autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */

    kfree(sbi);

    DPRINTK(("autofs: shutting down\n"));
}
Exemplo n.º 18
0
/*
 * ioctl()'s on the root directory is the chief method for the daemon to
 * generate kernel reactions
 */
static int autofs4_root_ioctl(struct inode *inode, struct file *filp,
                              unsigned int cmd, unsigned long arg)
{
    struct autofs_sb_info *sbi = autofs4_sbi(inode->i_sb);
    void __user *p = (void __user *)arg;

    DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u",
            cmd,arg,sbi,process_group(current));

    if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
            _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT )
        return -ENOTTY;

    if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
        return -EPERM;

    switch(cmd) {
    case AUTOFS_IOC_READY:	/* Wait queue: go ahead and retry */
        return autofs4_wait_release(sbi,(autofs_wqt_t)arg,0);
    case AUTOFS_IOC_FAIL:	/* Wait queue: fail with ENOENT */
        return autofs4_wait_release(sbi,(autofs_wqt_t)arg,-ENOENT);
    case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */
        autofs4_catatonic_mode(sbi);
        return 0;
    case AUTOFS_IOC_PROTOVER: /* Get protocol version */
        return autofs4_get_protover(sbi, p);
    case AUTOFS_IOC_PROTOSUBVER: /* Get protocol sub version */
        return autofs4_get_protosubver(sbi, p);
    case AUTOFS_IOC_SETTIMEOUT:
        return autofs4_get_set_timeout(sbi, p);

    case AUTOFS_IOC_TOGGLEREGHOST:
        return autofs4_toggle_reghost(sbi, p);
    case AUTOFS_IOC_ASKREGHOST:
        return autofs4_ask_reghost(sbi, p);

    case AUTOFS_IOC_ASKUMOUNT:
        return autofs4_ask_umount(filp->f_vfsmnt, p);

    /* return a single thing to expire */
    case AUTOFS_IOC_EXPIRE:
        return autofs4_expire_run(inode->i_sb,filp->f_vfsmnt,sbi, p);
    /* same as above, but can send multiple expires through pipe */
    case AUTOFS_IOC_EXPIRE_MULTI:
        return autofs4_expire_multi(inode->i_sb,filp->f_vfsmnt,sbi, p);

    default:
        return -ENOSYS;
    }
}
Exemplo n.º 19
0
static const char *autofs4_get_link(struct dentry *dentry,
				    struct inode *inode,
				    struct delayed_call *done)
{
	struct autofs_sb_info *sbi;
	struct autofs_info *ino;

	if (!dentry)
		return ERR_PTR(-ECHILD);
	sbi = autofs4_sbi(dentry->d_sb);
	ino = autofs4_dentry_ino(dentry);
	if (ino && !autofs4_oz_mode(sbi))
		ino->last_used = jiffies;
	return d_inode(dentry)->i_private;
}
Exemplo n.º 20
0
static struct dentry *get_next_positive_subdir(struct dentry *prev,
						struct dentry *root)
{
	struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
	struct list_head *next;
	struct dentry *p, *q;

	spin_lock(&sbi->lookup_lock);

	if (prev == NULL) {
		spin_lock(&root->d_lock);
		prev = dget_dlock(root);
		next = prev->d_subdirs.next;
		p = prev;
		goto start;
	}

	p = prev;
	spin_lock(&p->d_lock);
again:
	next = p->d_u.d_child.next;
start:
	if (next == &root->d_subdirs) {
		spin_unlock(&p->d_lock);
		spin_unlock(&sbi->lookup_lock);
		dput(prev);
		return NULL;
	}

	q = list_entry(next, struct dentry, d_u.d_child);

	spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
	
	if (!simple_positive(q)) {
		spin_unlock(&p->d_lock);
		lock_set_subclass(&q->d_lock.dep_map, 0, _RET_IP_);
		p = q;
		goto again;
	}
	dget_dlock(q);
	spin_unlock(&q->d_lock);
	spin_unlock(&p->d_lock);
	spin_unlock(&sbi->lookup_lock);

	dput(prev);

	return q;
}
Exemplo n.º 21
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;
}
Exemplo n.º 22
0
/*
 * Calculate and dget next entry in the subdirs list under root.
 */
static struct dentry *get_next_positive_subdir(struct dentry *prev,
					       struct dentry *root)
{
	struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
	struct list_head *next;
	struct dentry *q;

	spin_lock(&sbi->lookup_lock);
	spin_lock(&root->d_lock);

	if (prev)
		next = prev->d_child.next;
	else {
		prev = dget_dlock(root);
		next = prev->d_subdirs.next;
	}

cont:
	if (next == &root->d_subdirs) {
		spin_unlock(&root->d_lock);
		spin_unlock(&sbi->lookup_lock);
		dput(prev);
		return NULL;
	}

	q = list_entry(next, struct dentry, d_child);

	spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
	/* Already gone or negative dentry (under construction) - try next */
	if (!d_count(q) || !simple_positive(q)) {
		spin_unlock(&q->d_lock);
		next = q->d_child.next;
		goto cont;
	}
	dget_dlock(q);
	spin_unlock(&q->d_lock);
	spin_unlock(&root->d_lock);
	spin_unlock(&sbi->lookup_lock);

	dput(prev);

	return q;
}
Exemplo n.º 23
0
/* Check a mount point for busyness */
static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
{
	struct dentry *top = dentry;
	int status = 1;

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

	mntget(mnt);
	dget(dentry);

	if (!follow_down(&mnt, &dentry))
		goto done;

	if (is_autofs4_dentry(dentry)) {
		struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);

		/* This is an autofs submount, we can't expire it */
		if (autofs_type_indirect(sbi->type))
			goto done;

		/*
		 * Otherwise it's an offset mount and we need to check
		 * if we can umount its mount, if there is one.
		 */
		if (!d_mountpoint(dentry))
			goto done;
	}

	/* Update the expiry counter if fs is busy */
	if (!may_umount_tree(mnt)) {
		struct autofs_info *ino = autofs4_dentry_ino(top);
		ino->last_used = jiffies;
		goto done;
	}

	status = 0;
done:
	DPRINTK("returning = %d", status);
	dput(dentry);
	mntput(mnt);
	return status;
}
/*
 * 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;
}
Exemplo n.º 25
0
static int autofs4_root_readdir(struct file *file, void *dirent,
                                filldir_t filldir)
{
    struct autofs_sb_info *sbi = autofs4_sbi(file->f_dentry->d_sb);
    int oz_mode = autofs4_oz_mode(sbi);

    DPRINTK("called, filp->f_pos = %lld", file->f_pos);

    /*
     * Don't set reghost flag if:
     * 1) f_pos is larger than zero -- we've already been here.
     * 2) we haven't even enabled reghosting in the 1st place.
     * 3) this is the daemon doing a readdir
     */
    if (oz_mode && file->f_pos == 0 && sbi->reghost_enabled)
        sbi->needs_reghost = 1;

    DPRINTK("needs_reghost = %d", sbi->needs_reghost);

    return autofs4_dcache_readdir(file, dirent, filldir);
}
Exemplo n.º 26
0
static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
{
	struct autofs_sb_info *sbi = autofs4_sbi(mnt->mnt_sb);

	if (!sbi)
		return 0;

	seq_printf(m, ",fd=%d", sbi->pipefd);
	seq_printf(m, ",pgrp=%d", sbi->oz_pgrp);
	seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ);
	seq_printf(m, ",minproto=%d", sbi->min_proto);
	seq_printf(m, ",maxproto=%d", sbi->max_proto);

	if (sbi->type & AUTOFS_TYPE_OFFSET)
		seq_printf(m, ",offset");
	else if (sbi->type & AUTOFS_TYPE_DIRECT)
		seq_printf(m, ",direct");
	else
		seq_printf(m, ",indirect");

	return 0;
}