/* -*- c -*- --------------------------------------------------------------- *
*
* linux/fs/autofs/root.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
* Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
* Copyright 2001-2006 Ian Kent <raven@themaw.net>
*
* This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your
* option, any later version, incorporated herein by reference.
*
* ------------------------------------------------------------------------- */
#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/param.h>
#include <linux/time.h>
#include "autofs_i.h"
static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
static int autofs4_dir_unlink(struct inode *,struct dentry *);
static int autofs4_dir_rmdir(struct inode *,struct dentry *);
static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
static int autofs4_dir_open(struct inode *inode, struct file *file);
static int autofs4_dir_close(struct inode *inode, struct file *file);
static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
static void *autofs4_follow_link(struct dentry *, struct nameidata *);
const struct file_operations autofs4_root_operations = {
.open = dcache_dir_open,
.release = dcache_dir_close,
.read = generic_read_dir,
.readdir = autofs4_root_readdir,
.ioctl = autofs4_root_ioctl,
};
const struct file_operations autofs4_dir_operations = {
.open = autofs4_dir_open,
.release = autofs4_dir_close,
.read = generic_read_dir,
.readdir = autofs4_dir_readdir,
};
const struct inode_operations autofs4_indirect_root_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
.symlink = autofs4_dir_symlink,
.mkdir = autofs4_dir_mkdir,
.rmdir = autofs4_dir_rmdir,
};
const struct inode_operations autofs4_direct_root_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
.mkdir = autofs4_dir_mkdir,
.rmdir = autofs4_dir_rmdir,
.follow_link = autofs4_follow_link,
};
const struct inode_operations autofs4_dir_inode_operations = {
.lookup = autofs4_lookup,
.unlink = autofs4_dir_unlink,
.symlink = autofs4_dir_symlink,
.mkdir = autofs4_dir_mkdir,
.rmdir = autofs4_dir_rmdir,
};
static int autofs4_root_readdir(struct file *file, void *dirent,
filldir_t filldir)
{
struct autofs_sb_info *sbi = autofs4_sbi(file->f_path.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 dcache_readdir(file, dirent, filldir);
}
static int autofs4_dir_open(struct inode *inode, struct file *file)
{
struct dentry *dentry = file->f_path.dentry;
struct vfsmount *mnt = file->f_path.mnt;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *cursor;
int status;
status = dcache_dir_open(inode, file);
if (status)
goto out;
cursor = file->private_data;
cursor->d_fsdata = NULL;
DPRINTK("file=%p dentry=%p %.*s",
file, dentry, dentry->d_name.len, dentry->d_name.name);<