Commit 561c5cf9 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Greg Kroah-Hartman

staging: Remove autofs3

autofs3 was moved to staging in 2.6.37, so we can
remove it in the 2.6.39 merge window. If we have
a reason to bring it back after that, this patch
can get reverted.
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
About-fscking-timed-by: default avatarH. Peter Anvin <hpa@zytor.com>
Cc: Ian Kent <raven@themaw.net>
Cc: autofs@linux.kernel.org
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 8aea5882
......@@ -3559,12 +3559,6 @@ W: http://lse.sourceforge.net/kdump/
S: Maintained
F: Documentation/kdump/
KERNEL AUTOMOUNTER (AUTOFS)
M: "H. Peter Anvin" <hpa@zytor.com>
L: autofs@linux.kernel.org
S: Obsolete
F: drivers/staging/autofs/
KERNEL AUTOMOUNTER v4 (AUTOFS4)
M: Ian Kent <raven@themaw.net>
L: autofs@linux.kernel.org
......
......@@ -93,8 +93,6 @@ source "drivers/staging/frontier/Kconfig"
source "drivers/staging/pohmelfs/Kconfig"
source "drivers/staging/autofs/Kconfig"
source "drivers/staging/phison/Kconfig"
source "drivers/staging/line6/Kconfig"
......
......@@ -31,7 +31,6 @@ obj-$(CONFIG_RTS_PSTOR) += rts_pstor/
obj-$(CONFIG_SPECTRA) += spectra/
obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_POHMELFS) += pohmelfs/
obj-$(CONFIG_AUTOFS_FS) += autofs/
obj-$(CONFIG_IDE_PHISON) += phison/
obj-$(CONFIG_LINE6_USB) += line6/
obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
......
config AUTOFS_FS
tristate "Kernel automounter support"
depends on BKL # unfixable, just use autofs4
help
The automounter is a tool to automatically mount remote file systems
on demand. This implementation is partially kernel-based to reduce
overhead in the already-mounted case; this is unlike the BSD
automounter (amd), which is a pure user space daemon.
To use the automounter you need the user-space tools from the autofs
package; you can find the location in <file:Documentation/Changes>.
You also want to answer Y to "NFS file system support", below.
If you want to use the newer version of the automounter with more
features, say N here and say Y to "Kernel automounter v4 support",
below.
To compile this support as a module, choose M here: the module will be
called autofs.
If you are not a part of a fairly large, distributed network, you
probably do not need an automounter, and can say N here.
#
# Makefile for the linux autofs-filesystem routines.
#
obj-$(CONFIG_AUTOFS_FS) += autofs.o
autofs-y := dirhash.o init.o inode.o root.o symlink.o waitq.o
autofs version 3 is on its way out of the kernel,
It has been replaced by autofs4 several years ago.
The autofs3 code uses the big kernel lock which
is getting deprecated.
Users that find autofs3 to work but not autofs4
should talk to Ian Kent <raven@themaw.net>.
/* -*- linux-c -*- ------------------------------------------------------- *
*
* drivers/staging/autofs/autofs_i.h
*
* Copyright 1997-1998 Transmeta Corporation - All Rights Reserved
*
* 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.
*
* ----------------------------------------------------------------------- */
/* Internal header file for autofs */
#include <linux/auto_fs.h>
/* This is the range of ioctl() numbers we claim as ours */
#define AUTOFS_IOC_FIRST AUTOFS_IOC_READY
#define AUTOFS_IOC_COUNT 32
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/sched.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#ifdef DEBUG
#define DPRINTK(D) (printk D)
#else
#define DPRINTK(D) ((void)0)
#endif
/*
* If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the
* kernel will keep the negative response cached for up to the time given
* here, although the time can be shorter if the kernel throws the dcache
* entry away. This probably should be settable from user space.
*/
#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ) /* 1 minute */
/* Structures associated with the root directory hash table */
#define AUTOFS_HASH_SIZE 67
struct autofs_dir_ent {
int hash;
char *name;
int len;
ino_t ino;
struct dentry *dentry;
/* Linked list of entries */
struct autofs_dir_ent *next;
struct autofs_dir_ent **back;
/* The following entries are for the expiry system */
unsigned long last_usage;
struct list_head exp;
};
struct autofs_dirhash {
struct autofs_dir_ent *h[AUTOFS_HASH_SIZE];
struct list_head expiry_head;
};
struct autofs_wait_queue {
wait_queue_head_t queue;
struct autofs_wait_queue *next;
autofs_wqt_t wait_queue_token;
/* We use the following to see what we are waiting for */
int hash;
int len;
char *name;
/* This is for status reporting upon return */
int status;
int wait_ctr;
};
struct autofs_symlink {
char *data;
int len;
time_t mtime;
};
#define AUTOFS_MAX_SYMLINKS 256
#define AUTOFS_ROOT_INO 1
#define AUTOFS_FIRST_SYMLINK 2
#define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS)
#define AUTOFS_SYMLINK_BITMAP_LEN \
((AUTOFS_MAX_SYMLINKS+((sizeof(long)*1)-1))/(sizeof(long)*8))
#define AUTOFS_SBI_MAGIC 0x6d4a556d
struct autofs_sb_info {
u32 magic;
struct file *pipe;
struct pid *oz_pgrp;
int catatonic;
struct super_block *sb;
unsigned long exp_timeout;
ino_t next_dir_ino;
struct autofs_wait_queue *queues; /* Wait queue pointer */
struct autofs_dirhash dirhash; /* Root directory hash */
struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS];
unsigned long symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN];
};
static inline struct autofs_sb_info *autofs_sbi(struct super_block *sb)
{
return (struct autofs_sb_info *)(sb->s_fs_info);
}
/* autofs_oz_mode(): do we see the man behind the curtain? (The
processes which do manipulations for us in user space sees the raw
filesystem without "magic".) */
static inline int autofs_oz_mode(struct autofs_sb_info *sbi) {
return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp;
}
/* Hash operations */
void autofs_initialize_hash(struct autofs_dirhash *);
struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,struct qstr *);
void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *);
void autofs_hash_delete(struct autofs_dir_ent *);
struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *,struct autofs_dir_ent *);
void autofs_hash_dputall(struct autofs_dirhash *);
void autofs_hash_nuke(struct autofs_sb_info *);
/* Expiration-handling functions */
void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *);
struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info *, struct vfsmount *mnt);
/* Operations structures */
extern const struct inode_operations autofs_root_inode_operations;
extern const struct inode_operations autofs_symlink_inode_operations;
extern const struct file_operations autofs_root_operations;
/* Initializing function */
int autofs_fill_super(struct super_block *, void *, int);
void autofs_kill_sb(struct super_block *sb);
struct inode *autofs_iget(struct super_block *, unsigned long);
/* Queue management functions */
int autofs_wait(struct autofs_sb_info *,struct qstr *);
int autofs_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
void autofs_catatonic_mode(struct autofs_sb_info *);
#ifdef DEBUG
void autofs_say(const char *name, int len);
#else
#define autofs_say(n,l) ((void)0)
#endif
/* -*- linux-c -*- --------------------------------------------------------- *
*
* drivers/staging/autofs/dirhash.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
*
* 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 "autofs_i.h"
/* Functions for maintenance of expiry queue */
static void autofs_init_usage(struct autofs_dirhash *dh,
struct autofs_dir_ent *ent)
{
list_add_tail(&ent->exp, &dh->expiry_head);
ent->last_usage = jiffies;
}
static void autofs_delete_usage(struct autofs_dir_ent *ent)
{
list_del(&ent->exp);
}
void autofs_update_usage(struct autofs_dirhash *dh,
struct autofs_dir_ent *ent)
{
autofs_delete_usage(ent); /* Unlink from current position */
autofs_init_usage(dh, ent); /* Relink at queue tail */
}
struct autofs_dir_ent *autofs_expire(struct super_block *sb,
struct autofs_sb_info *sbi,
struct vfsmount *mnt)
{
struct autofs_dirhash *dh = &sbi->dirhash;
struct autofs_dir_ent *ent;
unsigned long timeout = sbi->exp_timeout;
while (1) {
struct path path;
int umount_ok;
if (list_empty(&dh->expiry_head) || sbi->catatonic)
return NULL; /* No entries */
/* We keep the list sorted by last_usage and want old stuff */
ent = list_entry(dh->expiry_head.next,
struct autofs_dir_ent, exp);
if (jiffies - ent->last_usage < timeout)
break;
/* Move to end of list in case expiry isn't desirable */
autofs_update_usage(dh, ent);
/* Check to see that entry is expirable */
if (ent->ino < AUTOFS_FIRST_DIR_INO)
return ent; /* Symlinks are always expirable */
/* Get the dentry for the autofs subdirectory */
path.dentry = ent->dentry;
if (!path.dentry) {
/* Should only happen in catatonic mode */
printk(KERN_DEBUG "autofs: dentry == NULL but inode \
range is directory, entry %s\n", ent->name);
autofs_delete_usage(ent);
continue;
}
if (!path.dentry->d_inode) {
dput(path.dentry);
printk(KERN_DEBUG "autofs: negative dentry on expiry queue: %s\n",
ent->name);
autofs_delete_usage(ent);
continue;
}
/* Make sure entry is mounted and unused; note that dentry will
point to the mounted-on-top root. */
if (!S_ISDIR(path.dentry->d_inode->i_mode) ||
!d_mountpoint(path.dentry)) {
DPRINTK(("autofs: not expirable \
(not a mounted directory): %s\n", ent->name));
continue;
}
path.mnt = mnt;
path_get(&path);
if (!follow_down_one(&path)) {
path_put(&path);
DPRINTK(("autofs: not expirable\
(not a mounted directory): %s\n", ent->name));
continue;
}
follow_down(&path, false); // TODO: need to check error
umount_ok = may_umount(path.mnt);
path_put(&path);
if (umount_ok) {
DPRINTK(("autofs: signaling expire on %s\n",
ent->name));
return ent; /* Expirable! */
}
DPRINTK(("autofs: didn't expire due to may_umount: %s\n",
ent->name));
}
return NULL; /* No expirable entries */
}
void autofs_initialize_hash(struct autofs_dirhash *dh)
{
memset(&dh->h, 0, AUTOFS_HASH_SIZE*sizeof(struct autofs_dir_ent *));
INIT_LIST_HEAD(&dh->expiry_head);
}
struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh,
struct qstr *name)
{
struct autofs_dir_ent *dhn;
DPRINTK(("autofs_hash_lookup: hash = 0x%08x, name = ", name->hash));
autofs_say(name->name, name->len);
for (dhn = dh->h[(unsigned) name->hash % AUTOFS_HASH_SIZE];
dhn;
dhn = dhn->next) {
if (name->hash == dhn->hash &&
name->len == dhn->len &&
!memcmp(name->name, dhn->name, name->len))
break;
}
return dhn;
}
void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent)
{
struct autofs_dir_ent **dhnp;
DPRINTK(("autofs_hash_insert: hash = 0x%08x, name = ", ent->hash));
autofs_say(ent->name, ent->len);
autofs_init_usage(dh, ent);
if (ent->dentry)
dget(ent->dentry);
dhnp = &dh->h[(unsigned) ent->hash % AUTOFS_HASH_SIZE];
ent->next = *dhnp;
ent->back = dhnp;
*dhnp = ent;
if (ent->next)
ent->next->back = &(ent->next);
}
void autofs_hash_delete(struct autofs_dir_ent *ent)
{
*(ent->back) = ent->next;
if (ent->next)
ent->next->back = ent->back;
autofs_delete_usage(ent);
if (ent->dentry)
dput(ent->dentry);
kfree(ent->name);
kfree(ent);
}
/*
* Used by readdir(). We must validate "ptr", so we can't simply make it
* a pointer. Values below 0xffff are reserved; calling with any value
* <= 0x10000 will return the first entry found.
*
* "last" can be NULL or the value returned by the last search *if* we
* want the next sequential entry.
*/
struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *dh,
off_t *ptr, struct autofs_dir_ent *last)
{
int bucket, ecount, i;
struct autofs_dir_ent *ent;
bucket = (*ptr >> 16) - 1;
ecount = *ptr & 0xffff;
if (bucket < 0)
bucket = ecount = 0;
DPRINTK(("autofs_hash_enum: bucket %d, entry %d\n", bucket, ecount));
ent = last ? last->next : NULL;
if (ent) {
ecount++;
} else {
while (bucket < AUTOFS_HASH_SIZE) {
ent = dh->h[bucket];
for (i = ecount ; ent && i ; i--)
ent = ent->next;
if (ent) {
ecount++; /* Point to *next* entry */
break;
}
bucket++; ecount = 0;
}
}
#ifdef DEBUG
if (!ent)
printk(KERN_DEBUG "autofs_hash_enum: nothing found\n");
else {
printk(KERN_DEBUG "autofs_hash_enum: found hash %08x, name",
ent->hash);
autofs_say(ent->name, ent->len);
}
#endif
*ptr = ((bucket+1) << 16) + ecount;
return ent;
}
/* Iterate over all the ents, and remove all dentry pointers. Used on
entering catatonic mode, in order to make the filesystem unmountable. */
void autofs_hash_dputall(struct autofs_dirhash *dh)
{
int i;
struct autofs_dir_ent *ent;
for (i = 0 ; i < AUTOFS_HASH_SIZE ; i++) {
for (ent = dh->h[i] ; ent ; ent = ent->next) {
if (ent->dentry) {
dput(ent->dentry);
ent->dentry = NULL;
}
}
}
}
/* Delete everything. This is used on filesystem destruction, so we
make no attempt to keep the pointers valid */
void autofs_hash_nuke(struct autofs_sb_info *sbi)
{
int i;
struct autofs_dir_ent *ent, *nent;
for (i = 0 ; i < AUTOFS_HASH_SIZE ; i++) {
for (ent = sbi->dirhash.h[i] ; ent ; ent = nent) {
nent = ent->next;
if (ent->dentry)
dput(ent->dentry);
kfree(ent->name);
kfree(ent);
}
}
}
/* -*- linux-c -*- --------------------------------------------------------- *
*
* drivers/staging/autofs/init.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
*
* 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/module.h>
#include <linux/init.h>
#include "autofs_i.h"
static struct dentry *autofs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return mount_nodev(fs_type, flags, data, autofs_fill_super);
}
static struct file_system_type autofs_fs_type = {
.owner = THIS_MODULE,
.name = "autofs",
.mount = autofs_mount,
.kill_sb = autofs_kill_sb,
};
static int __init init_autofs_fs(void)
{
return register_filesystem(&autofs_fs_type);
}
static void __exit exit_autofs_fs(void)
{
unregister_filesystem(&autofs_fs_type);
}
module_init(init_autofs_fs);
module_exit(exit_autofs_fs);
#ifdef DEBUG
void autofs_say(const char *name, int len)
{
printk("(%d: ", len);
while ( len-- )
printk("%c", *name++);
printk(")\n");
}
#endif
MODULE_LICENSE("GPL");
/* -*- linux-c -*- --------------------------------------------------------- *
*
* drivers/staging/autofs/inode.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
*
* 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/kernel.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/parser.h>
#include <linux/bitops.h>
#include <linux/magic.h>
#include "autofs_i.h"
#include <linux/module.h>
void autofs_kill_sb(struct super_block *sb)
{
struct autofs_sb_info *sbi = autofs_sbi(sb);
unsigned int n;
/*
* 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;
if (!sbi->catatonic)
autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
put_pid(sbi->oz_pgrp);
autofs_hash_nuke(sbi);
for (n = 0; n < AUTOFS_MAX_SYMLINKS; n++) {
if (test_bit(n, sbi->symlink_bitmap))
kfree(sbi->symlink[n].data);
}
kfree(sb->s_fs_info);
out_kill_sb:
DPRINTK(("autofs: shutting down\n"));
kill_anon_super(sb);
}
static const struct super_operations autofs_sops = {
.statfs = simple_statfs,
.show_options = generic_show_options,
};
enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto};
static const match_table_t autofs_tokens = {
{Opt_fd, "fd=%u"},
{Opt_uid, "uid=%u"},
{Opt_gid, "gid=%u"},
{Opt_pgrp, "pgrp=%u"},
{Opt_minproto, "minproto=%u"},
{Opt_maxproto, "maxproto=%u"},
{Opt_err, NULL}
};
static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
pid_t *pgrp, int *minproto, int *maxproto)
{
char *p;
substring_t args[MAX_OPT_ARGS];
int option;
*uid = current_uid();
*gid = current_gid();
*pgrp = task_pgrp_nr(current);
*minproto = *maxproto = AUTOFS_PROTO_VERSION;
*pipefd = -1;
if (!options)
return 1;
while ((p = strsep(&options, ",")) != NULL) {
int token;
if (!*p)
continue;
token = match_token(p, autofs_tokens, args);
switch (token) {
case Opt_fd:
if (match_int(&args[0], &option))
return 1;
*pipefd = option;
break;
case Opt_uid:
if (match_int(&args[0], &option))
return 1;
*uid = option;
break;
case Opt_gid:
if (match_int(&args[0], &option))
return 1;
*gid = option;
break;
case Opt_pgrp:
if (match_int(&args[0], &option))
return 1;
*pgrp = option;
break;
case Opt_minproto:
if (match_int(&args[0], &option))
return 1;
*minproto = option;
break;
case Opt_maxproto:
if (match_int(&args[0], &option))
return 1;
*maxproto = option;
break;
default:
return 1;
}
}
return (*pipefd < 0);
}
int autofs_fill_super(struct super_block *s, void *data, int silent)
{
struct inode * root_inode;
struct dentry * root;
struct file * pipe;
int pipefd;
struct autofs_sb_info *sbi;
int minproto, maxproto;
pid_t pgid;
save_mount_options(s, data);
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
goto fail_unlock;
DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
s->s_fs_info = sbi;
sbi->magic = AUTOFS_SBI_MAGIC;
sbi->pipe = NULL;
sbi->catatonic = 1;
sbi->exp_timeout = 0;
autofs_initialize_hash(&sbi->dirhash);
sbi->queues = NULL;
memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN);
sbi->next_dir_ino = AUTOFS_FIRST_DIR_INO;
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->s_magic = AUTOFS_SUPER_MAGIC;
s->s_op = &autofs_sops;
s->s_time_gran = 1;
sbi->sb = s;
root_inode = autofs_iget(s, AUTOFS_ROOT_INO);
if (IS_ERR(root_inode))
goto fail_free;
root = d_alloc_root(root_inode);
pipe = NULL;
if (!root)
goto fail_iput;
/* Can this call block? - WTF cares? s is locked. */
if (parse_options(data, &pipefd, &root_inode->i_uid,
&root_inode->i_gid, &pgid, &minproto,
&maxproto)) {
printk("autofs: called with bogus options\n");
goto fail_dput;
}
/* Couldn't this be tested earlier? */
if (minproto > AUTOFS_PROTO_VERSION ||
maxproto < AUTOFS_PROTO_VERSION) {
printk("autofs: kernel does not match daemon version\n");
goto fail_dput;
}
DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, pgid));
sbi->oz_pgrp = find_get_pid(pgid);
if (!sbi->oz_pgrp) {
printk("autofs: could not find process group %d\n", pgid);
goto fail_dput;
}
pipe = fget(pipefd);
if (!pipe) {
printk("autofs: could not open pipe file descriptor\n");
goto fail_put_pid;
}
if (!pipe->f_op || !pipe->f_op->write)
goto fail_fput;
sbi->pipe = pipe;
sbi->catatonic = 0;
/*
* Success! Install the root dentry now to indicate completion.
*/
s->s_root = root;
return 0;
fail_fput:
printk("autofs: pipe file descriptor does not contain proper ops\n");
fput(pipe);
fail_put_pid:
put_pid(sbi->oz_pgrp);
fail_dput:
dput(root);
goto fail_free;
fail_iput:
printk("autofs: get root dentry failed\n");
iput(root_inode);
fail_free:
kfree(sbi);
s->s_fs_info = NULL;
fail_unlock:
return -EINVAL;
}
struct inode *autofs_iget(struct super_block *sb, unsigned long ino)
{
unsigned int n;
struct autofs_sb_info *sbi = autofs_sbi(sb);
struct inode *inode;
inode = iget_locked(sb, ino);
if (!inode)
return ERR_PTR(-ENOMEM);
if (!(inode->i_state & I_NEW))
return inode;
/* Initialize to the default case (stub directory) */
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
inode->i_nlink = 2;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
if (ino == AUTOFS_ROOT_INO) {
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &autofs_root_inode_operations;
inode->i_fop = &autofs_root_operations;
goto done;
}
inode->i_uid = inode->i_sb->s_root->d_inode->i_uid;
inode->i_gid = inode->i_sb->s_root->d_inode->i_gid;
if (ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO) {
/* Symlink inode - should be in symlink list */
struct autofs_symlink *sl;
n = ino - AUTOFS_FIRST_SYMLINK;
if (n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) {
printk("autofs: Looking for bad symlink inode %u\n", (unsigned int) ino);
goto done;
}
inode->i_op = &autofs_symlink_inode_operations;
sl = &sbi->symlink[n];
inode->i_private = sl;
inode->i_mode = S_IFLNK | S_IRWXUGO;
inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = sl->mtime;
inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
inode->i_size = sl->len;
inode->i_nlink = 1;
}
done:
unlock_new_inode(inode);
return inode;
}
This diff is collapsed.
/* -*- linux-c -*- --------------------------------------------------------- *
*
* drivers/staging/autofs/symlink.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
*
* 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 "autofs_i.h"
/* Nothing to release.. */
static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
char *s=((struct autofs_symlink *)dentry->d_inode->i_private)->data;
nd_set_link(nd, s);
return NULL;
}
const struct inode_operations autofs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = autofs_follow_link
};
/* -*- linux-c -*- --------------------------------------------------------- *
*
* drivers/staging/autofs/waitq.c
*
* Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
*
* 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/slab.h>
#include <linux/time.h>
#include <linux/signal.h>
#include <linux/file.h>
#include "autofs_i.h"
/* We make this a static variable rather than a part of the superblock; it
is better if we don't reassign numbers easily even across filesystems */
static autofs_wqt_t autofs_next_wait_queue = 1;
/* These are the signals we allow interrupting a pending mount */
#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT))
void autofs_catatonic_mode(struct autofs_sb_info *sbi)
{
struct autofs_wait_queue *wq, *nwq;
DPRINTK(("autofs: entering catatonic mode\n"));
sbi->catatonic = 1;
wq = sbi->queues;
sbi->queues = NULL; /* Erase all wait queues */
while ( wq ) {
nwq = wq->next;
wq->status = -ENOENT; /* Magic is gone - report failure */
kfree(wq->name);
wq->name = NULL;
wake_up(&wq->queue);
wq = nwq;
}
fput(sbi->pipe); /* Close the pipe */
sbi->pipe = NULL;
autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */
}
static int autofs_write(struct file *file, const void *addr, int bytes)
{
unsigned long sigpipe, flags;
mm_segment_t fs;
const char *data = (const char *)addr;
ssize_t wr = 0;
/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/
sigpipe = sigismember(&current->pending.signal, SIGPIPE);
/* Save pointer to user space and point back to kernel space */
fs = get_fs();
set_fs(KERNEL_DS);
while (bytes &&
(wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) {
data += wr;
bytes -= wr;
}
set_fs(fs);
/* Keep the currently executing process from receiving a
SIGPIPE unless it was already supposed to get one */
if (wr == -EPIPE && !sigpipe) {
spin_lock_irqsave(&current->sighand->siglock, flags);
sigdelset(&current->pending.signal, SIGPIPE);
recalc_sigpending();
spin_unlock_irqrestore(&current->sighand->siglock, flags);
}
return (bytes > 0);
}
static void autofs_notify_daemon(struct autofs_sb_info *sbi, struct autofs_wait_queue *wq)
{
struct autofs_packet_missing pkt;
DPRINTK(("autofs_wait: wait id = 0x%08lx, name = ", wq->wait_queue_token));
autofs_say(wq->name,wq->len);
memset(&pkt,0,sizeof pkt); /* For security reasons */
pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
pkt.hdr.type = autofs_ptype_missing;
pkt.wait_queue_token = wq->wait_queue_token;
pkt.len = wq->len;
memcpy(pkt.name, wq->name, pkt.len);
pkt.name[pkt.len] = '\0';
if ( autofs_write(sbi->pipe,&pkt,sizeof(struct autofs_packet_missing)) )
autofs_catatonic_mode(sbi);
}
int autofs_wait(struct autofs_sb_info *sbi, struct qstr *name)
{
struct autofs_wait_queue *wq;
int status;
/* In catatonic mode, we don't wait for nobody */
if ( sbi->catatonic )
return -ENOENT;
/* We shouldn't be able to get here, but just in case */
if ( name->len > NAME_MAX )
return -ENOENT;
for ( wq = sbi->queues ; wq ; wq = wq->next ) {
if ( wq->hash == name->hash &&
wq->len == name->len &&
wq->name && !memcmp(wq->name,name->name,name->len) )
break;
}
if ( !wq ) {
/* Create a new wait queue */
wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
if ( !wq )
return -ENOMEM;
wq->name = kmalloc(name->len,GFP_KERNEL);
if ( !wq->name ) {
kfree(wq);
return -ENOMEM;
}
wq->wait_queue_token = autofs_next_wait_queue++;
init_waitqueue_head(&wq->queue);
wq->hash = name->hash;
wq->len = name->len;
wq->status = -EINTR; /* Status return if interrupted */
memcpy(wq->name, name->name, name->len);
wq->next = sbi->queues;
sbi->queues = wq;
/* autofs_notify_daemon() may block */
wq->wait_ctr = 2;
autofs_notify_daemon(sbi,wq);
} else
wq->wait_ctr++;
/* wq->name is NULL if and only if the lock is already released */
if ( sbi->catatonic ) {
/* We might have slept, so check again for catatonic mode */
wq->status = -ENOENT;
kfree(wq->name);
wq->name = NULL;
}
if ( wq->name ) {
/* Block all but "shutdown" signals while waiting */
sigset_t sigmask;
siginitsetinv(&sigmask, SHUTDOWN_SIGS);
sigprocmask(SIG_BLOCK, &sigmask, &sigmask);
interruptible_sleep_on(&wq->queue);
sigprocmask(SIG_SETMASK, &sigmask, NULL);
} else {
DPRINTK(("autofs_wait: skipped sleeping\n"));
}
status = wq->status;
if ( ! --wq->wait_ctr ) /* Are we the last process to need status? */
kfree(wq);
return status;
}
int autofs_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_token, int status)
{
struct autofs_wait_queue *wq, **wql;
for (wql = &sbi->queues; (wq = *wql) != NULL; wql = &wq->next) {
if ( wq->wait_queue_token == wait_queue_token )
break;
}
if ( !wq )
return -EINVAL;
*wql = wq->next; /* Unlink from chain */
kfree(wq->name);
wq->name = NULL; /* Do not wait on this queue */
wq->status = status;
if ( ! --wq->wait_ctr ) /* Is anyone still waiting for this guy? */
kfree(wq);
else
wake_up(&wq->queue);
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment