Update of /cvsroot/ssic-linux/openssi/kernel/fs/devpts
In directory sc8-pr-cvs1:/tmp/cvs-serv32246/openssi/kernel/fs/devpts
Added Files:
Tag: OPENSSI-RH
root.c inode.c
Log Message:
Globalized devpts. pty numbers are now globally unique which should allow
utmp to function properly in the cluster.
M ci/kernel/include/cluster/nsc.h
Made USHRT_MAX arch-independent.
M ci/kernel/include/cluster/gen/ics_proto_gen.h.list
Added types.
M openssi/kernel/cluster/ssi/util/Makefile
Added new files to makefile.
M openssi/kernel/cluster/ssi/util/fifonm.c
M openssi/kernel/cluster/ssi/util/rmtsock.c
Moved extern of ics_ssidev_chan to header.
M openssi/kernel/cluster/ssi/util/ssidev.c
Changed the clms_ssidev_server_ready() to ssidev_server_ready() to
be more consistent.
M openssi/kernel/cluster/ssi/vproc/reopen.c
Played games in reop_import_path() to import /dev/pts pathnames
correctly.
M openssi/kernel/drivers/char/tty_io.c
Added hook to call pty nameserver.
M openssi/kernel/fs/super.c
Added devpts to list of filesystems that get cluster unique
unnamed device-numbers.
M openssi/kernel/include/cluster/ssi/ssidev.h
Added prototypes, externs, etc,
M openssi/kernel.configs/config.i586
M openssi/kernel.configs/kernel-2.4.20-i586-ssi.config
Added DEVPTS to build configuration.
A openssi/kernel/drivers/char/pty.c
Added hook to call the nameserver to free a pty number.
A openssi/kernel/cluster/ssi/util/ssipty.c
A openssi/kernel/cluster/ssi/util/ssipty.svc
Pty nameserver and support routines.
A openssi/kernel/fs/devpts/root.c
A openssi/kernel/fs/devpts/inode.c
Added hooks.
--- NEW FILE: root.c ---
/* -*- linux-c -*- --------------------------------------------------------- *
*
* linux/fs/devpts/root.c
*
* Copyright 1998 H. Peter Anvin -- 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/errno.h>
#include <linux/stat.h>
#include <linux/param.h>
#include <linux/string.h>
#include <cluster/ssi/ssidev.h>
#include "devpts_i.h"
static int devpts_root_readdir(struct file *,void *,filldir_t);
static struct dentry *devpts_root_lookup(struct inode *,struct dentry *);
static int devpts_revalidate(struct dentry *, int);
#ifdef CONFIG_SSI
struct ssipty_readdir_cookie {
int oldpos;
int start_index;
int entries_len;
struct ssipty_entry *entries;
};
static int
devpts_root_release(struct inode *inode, struct file *file)
{
struct ssipty_readdir_cookie *cp = file->private_data;
if (cp != NULL) {
kfree(cp->entries);
kfree(cp);
}
return 0;
}
#endif
struct file_operations devpts_root_operations = {
read: generic_read_dir,
readdir: devpts_root_readdir,
#ifdef CONFIG_SSI
release: devpts_root_release,
#endif
};
struct inode_operations devpts_root_inode_operations = {
lookup: devpts_root_lookup,
};
static struct dentry_operations devpts_dentry_operations = {
d_revalidate: devpts_revalidate,
};
/*
* The normal naming convention is simply /dev/pts/<number>; this conforms
* to the System V naming convention
*/
#define genptsname(buf,num) sprintf(buf, "%d", num)
static int devpts_root_readdir(struct file *filp, void *dirent, filldir_t
filldir)
{
struct inode * inode = filp->f_dentry->d_inode;
struct devpts_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
off_t nr;
char numbuf[16];
#ifdef CONFIG_SSI
struct ssipty_readdir_cookie *cp;
int ret;
int ptynr;
int curpty;
int idx;
#endif
nr = filp->f_pos;
switch(nr)
{
case 0:
if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
return 0;
filp->f_pos = ++nr;
/* fall through */
case 1:
if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
return 0;
filp->f_pos = ++nr;
/* fall through */
default:
#ifdef CONFIG_SSI
cp = filp->private_data;
if (cp == NULL) {
cp = kmalloc(sizeof(struct ssipty_readdir_cookie),
GFP_KERNEL);
filp->private_data = cp;
if (cp == NULL)
return -ENOMEM;
cp->oldpos = 0;
cp->entries_len = 0;
cp->entries = kmalloc(sbi->max_ptys *
sizeof(struct ssipty_entry),
GFP_KERNEL);
if (cp->entries == NULL)
return -ENOMEM;
}
if (nr != cp->oldpos) {
cp->start_index = 0;
cp->entries_len = sbi->max_ptys;
ret = ssipty_readdir(nr - 2, cp->entries,
&cp->entries_len);
if (ret < 0) {
cp->oldpos = 0;
return ret;
}
}
ptynr = nr - 2;
for (idx = cp->start_index; idx < cp->entries_len; idx++) {
curpty = cp->entries[idx].sp_ptynum;
if (curpty < ptynr)
continue;
genptsname(numbuf, curpty);
if ( filldir(dirent, numbuf, strlen(numbuf),
curpty + 2, curpty + 2, DT_CHR) < 0 )
return 0;
filp->f_pos = curpty + 3;
}
cp->oldpos = filp->f_pos;
cp->start_index = idx;
#else
while ( nr - 2 < sbi->max_ptys ) {
int ptynr = nr - 2;
if ( sbi->inodes[ptynr] ) {
genptsname(numbuf, ptynr);
if ( filldir(dirent, numbuf, strlen(numbuf),
nr, nr, DT_CHR) < 0 )
return 0;
}
filp->f_pos = ++nr;
}
#endif
break;
}
return 0;
}
/*
* Revalidate is called on every cache lookup. We use it to check that
* the pty really does still exist. Never revalidate negative dentries;
* for simplicity (fix later?)
*/
static int devpts_revalidate(struct dentry * dentry, int flags)
{
struct devpts_sb_info *sbi;
#ifdef CONFIG_SSI
struct inode *ip;
int ret;
#endif
if ( !dentry->d_inode )
return 0;
sbi = SBI(dentry->d_inode->i_sb);
#ifdef CONFIG_SSI
ip = sbi->inodes[dentry->d_inode->i_ino - 2];
if (ip != NULL)
return (ip == dentry->d_inode);
ret = ssipty_update_inode(&dentry->d_inode, dentry->d_inode->i_ino - 2);
return (ret >= 0);
#else
return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode );
#endif
}
static struct dentry *devpts_root_lookup(struct inode * dir, struct dentry *
dentry)
{
struct devpts_sb_info *sbi = SBI(dir->i_sb);
unsigned int entry;
int i;
const char *p;
#ifdef CONFIG_SSI
struct inode *ip;
int ret;
#endif
dentry->d_op = &devpts_dentry_operations;
if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) {
entry = 0;
} else if ( dentry->d_name.len < 1 ) {
return NULL;
} else {
p = dentry->d_name.name;
if ( *p < '1' || *p > '9' )
return NULL;
entry = *p++ - '0';
for ( i = dentry->d_name.len-1 ; i ; i-- ) {
unsigned int nentry = *p++ - '0';
if ( nentry > 9 )
return NULL;
if ( entry >= ~0U/10 )
return NULL;
entry = nentry + entry * 10;
}
}
if ( entry >= sbi->max_ptys )
return NULL;
#ifdef CONFIG_SSI
ret = 0;
ip = sbi->inodes[entry];
if (ip != NULL)
atomic_inc(&ip->i_count);
else
ret = ssipty_update_inode(&ip, entry);
d_add(dentry, ip);
return ERR_PTR(ret);
#else
if ( sbi->inodes[entry] )
atomic_inc(&sbi->inodes[entry]->i_count);
d_add(dentry, sbi->inodes[entry]);
#endif
return NULL;
}
--- NEW FILE: inode.c ---
/* -*- linux-c -*- --------------------------------------------------------- *
*
* linux/fs/devpts/inode.c
*
* Copyright 1998 H. Peter Anvin -- 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/string.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/kernel.h>
#include <linux/locks.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/tty.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#ifdef CONFIG_SSI
#include <cluster/ssi/ssidev.h>
#endif
#include "devpts_i.h"
static struct vfsmount *devpts_mnt;
static void devpts_put_super(struct super_block *sb)
{
struct devpts_sb_info *sbi = SBI(sb);
struct inode *inode;
int i;
for ( i = 0 ; i < sbi->max_ptys ; i++ ) {
if ( (inode = sbi->inodes[i]) ) {
if ( atomic_read(&inode->i_count) != 1 )
printk("devpts_put_super: badness: entry %d
count %d\n",
i, atomic_read(&inode->i_count));
inode->i_nlink--;
iput(inode);
}
}
kfree(sbi->inodes);
kfree(sbi);
}
static int devpts_statfs(struct super_block *sb, struct statfs *buf);
#ifndef CONFIG_SSI
static int devpts_remount (struct super_block * sb, int * flags, char * data);
#endif
static struct super_operations devpts_sops = {
put_super: devpts_put_super,
statfs: devpts_statfs,
remount_fs: devpts_remount,
};
static int devpts_parse_options(char *options, struct devpts_sb_info *sbi)
{
int setuid = 0;
int setgid = 0;
uid_t uid = 0;
gid_t gid = 0;
umode_t mode = 0600;
char *this_char, *value;
this_char = NULL;
if ( options )
this_char = strtok(options,",");
for ( ; this_char; this_char = strtok(NULL,",")) {
if ((value = strchr(this_char,'=')) != NULL)
*value++ = 0;
if (!strcmp(this_char,"uid")) {
if (!value || !*value)
return 1;
uid = simple_strtoul(value,&value,0);
if (*value)
return 1;
setuid = 1;
}
else if (!strcmp(this_char,"gid")) {
if (!value || !*value)
return 1;
gid = simple_strtoul(value,&value,0);
if (*value)
return 1;
setgid = 1;
}
else if (!strcmp(this_char,"mode")) {
if (!value || !*value)
return 1;
mode = simple_strtoul(value,&value,8);
if (*value)
return 1;
}
else
return 1;
}
sbi->setuid = setuid;
sbi->setgid = setgid;
sbi->uid = uid;
sbi->gid = gid;
sbi->mode = mode & ~S_IFMT;
return 0;
}
#ifdef CONFIG_SSI
int _devpts_remount(struct super_block * sb, int * flags, char * data)
#else
static int devpts_remount(struct super_block * sb, int * flags, char * data)
#endif
{
struct devpts_sb_info *sbi = sb->u.generic_sbp;
int res = devpts_parse_options(data,sbi);
if (res) {
printk("devpts: called with bogus options\n");
return -EINVAL;
}
return 0;
}
#ifdef CONFIG_SSI
struct super_block *_devpts_read_super(struct super_block *s, void *data,
int silent)
#else
struct super_block *devpts_read_super(struct super_block *s, void *data,
int silent)
#endif
{
struct inode * inode;
struct devpts_sb_info *sbi;
sbi = (struct devpts_sb_info *) kmalloc(sizeof(struct devpts_sb_info),
GFP_KERNEL);
if ( !sbi )
goto fail;
sbi->magic = DEVPTS_SBI_MAGIC;
sbi->max_ptys = unix98_max_ptys;
sbi->inodes = kmalloc(sizeof(struct inode *) * sbi->max_ptys,
GFP_KERNEL);
if ( !sbi->inodes )
goto fail_free;
memset(sbi->inodes, 0, sizeof(struct inode *) * sbi->max_ptys);
if ( devpts_parse_options(data,sbi) && !silent) {
printk("devpts: called with bogus options\n");
goto fail_free;
}
inode = new_inode(s);
if (!inode)
goto fail_free;
inode->i_ino = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = 0;
inode->i_blksize = 1024;
inode->i_uid = inode->i_gid = 0;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &devpts_root_inode_operations;
inode->i_fop = &devpts_root_operations;
inode->i_nlink = 2;
s->u.generic_sbp = (void *) sbi;
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->s_magic = DEVPTS_SUPER_MAGIC;
s->s_op = &devpts_sops;
#ifdef CONFIG_SSI
s->s_mnt_op = &devpts_mnt_ops;
#endif /* CONFIG_SSI */
s->s_root = d_alloc_root(inode);
if (s->s_root)
return s;
printk("devpts: get root dentry failed\n");
iput(inode);
fail_free:
kfree(sbi);
fail:
return NULL;
}
static int devpts_statfs(struct super_block *sb, struct statfs *buf)
{
buf->f_type = DEVPTS_SUPER_MAGIC;
buf->f_bsize = 1024;
buf->f_namelen = NAME_MAX;
return 0;
}
static DECLARE_FSTYPE(devpts_fs_type, "devpts", devpts_read_super, FS_SINGLE);
void devpts_pty_new(int number, kdev_t device)
{
struct super_block *sb = devpts_mnt->mnt_sb;
struct devpts_sb_info *sbi = SBI(sb);
struct inode *inode;
if ( sbi->inodes[number] )
return; /* Already registered, this does happen */
inode = new_inode(sb);
if (!inode)
return;
inode->i_ino = number+2;
inode->i_blocks = 0;
inode->i_blksize = 1024;
inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
#ifdef CONFIG_SSI
inode->u.generic_ip = (void *)this_node;
#endif
init_special_inode(inode, S_IFCHR|sbi->mode, kdev_t_to_nr(device));
if ( sbi->inodes[number] ) {
iput(inode);
return;
}
sbi->inodes[number] = inode;
}
#ifdef CONFIG_SSI
static int
ssipty_remote_open(struct inode *inode, struct file *file)
{
return rmtfb_ropen(file, (clusternode_t)inode->u.generic_ip);
}
static struct file_operations
ssipty_remote_fops = {
open: ssipty_remote_open,
};
struct inode *
ssipty_init_inode(struct inode *inode, int number, clusternode_t svr)
{
struct super_block *sb = devpts_mnt->mnt_sb;
struct devpts_sb_info *sbi = SBI(sb);
kdev_t device;
if (inode == NULL) {
inode = new_inode(sb);
if (inode == NULL)
return NULL;
}
device = MKDEV(pts_driver[number / NR_PTYS].major,
pts_driver[number / NR_PTYS].minor_start +
number % NR_PTYS);
inode->i_ino = number + 2;
inode->i_blocks = 0;
inode->i_blksize = 1024;
init_special_inode(inode, S_IFCHR | sbi->mode, kdev_t_to_nr(device));
inode->i_fop = &ssipty_remote_fops;
inode->u.generic_ip = (void *)svr;
return inode;
}
int
ssipty_get_iattr(int ptynum, struct iattr *iattr)
{
struct super_block *sb = devpts_mnt->mnt_sb;
struct devpts_sb_info *sbi = SBI(sb);
struct inode *inode;
inode = sbi->inodes[ptynum];
if (inode == NULL)
return -ENOENT;
iattr->ia_uid = inode->i_uid;
iattr->ia_gid = inode->i_gid;
iattr->ia_atime = inode->i_atime;
iattr->ia_mtime = inode->i_mtime;
iattr->ia_ctime = inode->i_ctime;
iattr->ia_mode = inode->i_mode;
return 0;
}
void
ssipty_get_mntopts(int *setuid, uid_t *uid, int *setgid, gid_t *gid,
umode_t *mode)
{
struct super_block *sb = devpts_mnt->mnt_sb;
struct devpts_sb_info *sbi = SBI(sb);
*setuid = sbi->setuid;
*uid = sbi->uid;
*setgid = sbi->setgid;
*gid = sbi->gid;
*mode = sbi->mode;
}
#endif
void devpts_pty_kill(int number)
{
struct super_block *sb = devpts_mnt->mnt_sb;
struct devpts_sb_info *sbi = SBI(sb);
struct inode *inode = sbi->inodes[number];
if ( inode ) {
sbi->inodes[number] = NULL;
inode->i_nlink--;
iput(inode);
}
}
static int __init init_devpts_fs(void)
{
int err = register_filesystem(&devpts_fs_type);
if (!err) {
devpts_mnt = kern_mount(&devpts_fs_type);
err = PTR_ERR(devpts_mnt);
if (!IS_ERR(devpts_mnt))
err = 0;
#ifdef MODULE
if ( !err ) {
devpts_upcall_new = devpts_pty_new;
devpts_upcall_kill = devpts_pty_kill;
}
#endif
}
return err;
}
static void __exit exit_devpts_fs(void)
{
#ifdef MODULE
devpts_upcall_new = NULL;
devpts_upcall_kill = NULL;
#endif
unregister_filesystem(&devpts_fs_type);
kern_umount(devpts_mnt);
}
module_init(init_devpts_fs)
module_exit(exit_devpts_fs)
MODULE_LICENSE("GPL");
-------------------------------------------------------
This SF.net email is sponsored by: IBM Linux Tutorials.
Become an expert in LINUX or just sharpen your skills. Sign up for IBM's
Free Linux Tutorials. Learn everything from the bash shell to sys admin.
Click now! http://ads.osdn.com/?ad_id=1278&alloc_id=3371&op=click
|