Commit c83fb0bd authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.45pre8

parent 1b081ced
Kernel Support for miscellaneous (your favourite) Binary Formats v1.1
=====================================================================
Kernel Support for miscellaneous (your favourite) Binary Formats v1.1
=====================================================================
This Kernel feature allows to invoke almost (for restrictions see below) every
program by simply typing it's name in the shell.
program by simply typing its name in the shell.
This includes for example compiled Java(TM), Python or Emacs programs.
To achieve this you must tell binfmt_misc which interpreter has to be invoked with
which binary. Binfmt_misc recognises the binary-type by matching some bytes at the
beginning of the file with a magic byte sequence (masking out specified bits) you
have supplied. Binfmt_misc can also recognise a filename extension (aka .com) and
optionally strip it off.
To achieve this you must tell binfmt_misc which interpreter has to be invoked
with which binary. Binfmt_misc recognises the binary-type by matching some bytes
at the beginning of the file with a magic byte sequence (masking out specified
bits) you have supplied. Binfmt_misc can also recognise a filename extension
(aka .com) and optionally strip it off.
To actually register a new binary type, you have to set up a string looking like
:name:type:offset:magic:mask:interpreter: (where you can choose the ':' upon your
needs) and echo it to /proc/sys/fs/binfmt_misc/register.
:name:type:offset:magic:mask:interpreter: (where you can choose the ':' upon
your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
Here is what the fields mean:
- 'name' is an identifier string. A new /proc file will be created with this
this name below /proc/sys/fs/binfmt_misc
name below /proc/sys/fs/binfmt_misc
- 'type' is the type of recognition. Give 'M' for magic and 'E' for extension.
Give the corresponding lowercase letter to let binfmt_misc strip of the
Give the corresponding lowercase letter to let binfmt_misc strip off the
filename extension.
- 'offset' is the offset of the magic/mask in the file counted in bytes. This
- 'offset' is the offset of the magic/mask in the file, counted in bytes. This
defaults to 0 if you omit it (i.e. you write ':name:type::magic...')
- 'magic' is the byte sequence binfmt_misc is matching for. The magic string
may contain hex-encoded characters like \x0a or \xA4. In a shell environment
......@@ -28,26 +28,23 @@ Here is what the fields mean:
If you chose filename extension matching, this is the extension to be
recognised (the \x0a specials are not allowed). Extension matching is case
sensitive!
- 'mask' is an (optional, defaults to all 0xff) mask. You can mask out some bits
from matching by supplying a string like magic and as long as magic. The
mask is anded with the byte sequence of the file.
- 'mask' is an (optional, defaults to all 0xff) mask. You can mask out some
bits from matching by supplying a string like magic and as long as magic.
The mask is anded with the byte sequence of the file.
- 'interpreter' is the program that should be invoked with the binary as first
argument (specify the full path)
There are some restrictions:
- the whole register string may not exceed 255 characters
- the magic must resist in the first 128 bytes of the file, i.e. offset+size(magic)
has to be less than 128
- the magic must resist in the first 128 bytes of the file, i.e.
offset+size(magic) has to be less than 128
- the interpreter string may not exceed 127 characters
You may want to add the binary formats in one of your /etc/rc scripts during boot-up.
Read the manual of your init program to figure out how to do this right.
You may want to add the binary formats in one of your /etc/rc scripts during
boot-up. Read the manual of your init program to figure out how to do this
right.
A few examples (assumed you are in /proc/sys/fs/binfmt_misc):
- enable Java(TM)-support (like binfmt_java):
echo ":Java:M::\xca\xfe\xba\xbe::/usr/local/bin/java:" > register
echo :Applet:M::\<\!--applet::/usr/local/bin/appletviewer: > register
- enable support for em86 (like binfmt_em86, for Alpha AXP only):
echo ":i386:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:" > register
echo ":i486:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:" > register
......@@ -57,8 +54,9 @@ A few examples (assumed you are in /proc/sys/fs/binfmt_misc):
- enable support for DOS/Windows executables (using mzloader and dosemu/wine):
echo ":DOSWin:M::MZ::/usr/sbin/mzloader:" > register
echo ":DOS:E::com::/usr/sbin/mzloader:" > register
echo ":DOS2:E::exe::/usr/sbin/mzloader:" > register
echo ":DOScom:E::com::/usr/sbin/mzloader:" > register
echo ":DOSexe:E::exe::/usr/sbin/mzloader:" > register
You can enable/disable binfmt_misc or one binary type by echoing 0 (to disable)
or 1 (to enable) to /proc/sys/fs/binfmt_misc/status or /proc/.../the_name.
......@@ -68,6 +66,25 @@ You can remove one entry or all entries by echoing -1 to /proc/.../the_name
or /proc/sys/fs/binfmt_misc/status.
Emulating binfmt_java:
======================
To emulate binfmt_java the following register-strings are necessary
(the first two for byte-compiled Java binaries, the third for applets
contained in a html-file). Register exactly in this order!
":Java:M::\xca\xfe\xba\xbe::/usr/local/java/bin/java:"
":JavaC:e::class::/usr/local/java/bin/java:"
":Applet:E::html::/usr/local/java/bin/appletviewer:"
To add a Java-executable to your path you can either make a symbolic
link to the .class file elsewhere in your path (cut the .class-extension
in the destination name for convenience) or add the directory of your
.class files to your PATH environment. In both cases, ensure that the
.class files are in your CLASSPATH environment!
This is sort of ugly - Javas filename handling is just broken.
HINTS:
======
......
......@@ -37,9 +37,10 @@ static int autofs_dir_readdir(struct inode *inode, struct file *filp,
/*
* No entries except for "." and "..", both of which are handled by the VFS layer
*/
static int autofs_dir_lookup(struct inode *dir, struct qstr *str, struct inode **result)
static int autofs_dir_lookup(struct inode *dir, struct dentry * dentry)
{
return -ENOENT; /* No other entries */
d_add(dentry, NULL);
return 0;
}
static struct file_operations autofs_dir_operations = {
......
......@@ -19,10 +19,16 @@
#define __NO_VERSION__
#include <linux/module.h>
/*
* Dummy functions - do we ever actually want to do
* something here?
*/
static void autofs_put_inode(struct inode *inode)
{
if (inode->i_nlink)
return;
}
static void autofs_delete_inode(struct inode *inode)
{
inode->i_size = 0;
}
......@@ -59,11 +65,12 @@ static void autofs_write_inode(struct inode *inode);
static struct super_operations autofs_sops = {
autofs_read_inode,
NULL,
autofs_write_inode,
autofs_put_inode,
autofs_delete_inode,
NULL, /* notify_change */
autofs_put_super,
NULL,
NULL, /* write_super */
autofs_statfs,
NULL
};
......
......@@ -16,7 +16,7 @@
#include "autofs_i.h"
static int autofs_root_readdir(struct inode *,struct file *,void *,filldir_t);
static int autofs_root_lookup(struct inode *,struct qstr *,struct inode **);
static int autofs_root_lookup(struct inode *,struct dentry *);
static int autofs_root_symlink(struct inode *,struct dentry *,const char *);
static int autofs_root_unlink(struct inode *,struct dentry *);
static int autofs_root_rmdir(struct inode *,struct dentry *);
......@@ -93,64 +93,105 @@ static int autofs_root_readdir(struct inode *inode, struct file *filp,
return 0;
}
static int autofs_root_lookup(struct inode *dir, struct qstr *str, struct inode **result)
static int try_to_fill_dentry(struct dentry * dentry, struct super_block * sb, struct autofs_sb_info *sbi)
{
struct autofs_sb_info *sbi;
struct inode * inode;
struct autofs_dir_ent *ent;
while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name))) {
int status = autofs_wait(sbi, &dentry->d_name);
/* Turn this into a real negative dentry? */
if (status == -ENOENT) {
dentry->d_flags = 0;
return 0;
}
if (status)
return status;
}
if (!dentry->d_inode) {
inode = iget(sb, ent->ino);
if (!inode)
return -EACCES;
dentry->d_inode = inode;
}
if (S_ISDIR(dentry->d_inode->i_mode)) {
while (dentry == dentry->d_mounts)
schedule();
}
dentry->d_flags = 0;
return 0;
}
/*
* 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 struct dentry * autofs_revalidate(struct dentry * dentry)
{
struct autofs_sb_info *sbi;
struct inode * dir = dentry->d_parent->d_inode;
sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
/* Incomplete dentry? */
if (dentry->d_flags) {
if (autofs_oz_mode(sbi))
return dentry;
try_to_fill_dentry(dentry, dir->i_sb, sbi);
return dentry;
}
/* Negative dentry.. Should we time these out? */
if (!dentry->d_inode)
return dentry;
/* We should update the usage stuff here.. */
return dentry;
}
static int autofs_root_lookup(struct inode *dir, struct dentry * dentry)
{
struct autofs_sb_info *sbi;
struct inode *res;
int status, oz_mode;
int oz_mode;
DPRINTK(("autofs_root_lookup: name = "));
autofs_say(str->name,str->len);
autofs_say(dentry->d_name.name,dentry->d_name.len);
*result = NULL;
if (!dir)
return -ENOENT;
if (!S_ISDIR(dir->i_mode))
return -ENOTDIR;
*result = res = NULL;
res = NULL;
sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
oz_mode = autofs_oz_mode(sbi);
DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", current->pid, current->pgrp, sbi->catatonic, oz_mode));
do {
while ( !(ent = autofs_hash_lookup(&sbi->dirhash,str)) ) {
DPRINTK(("lookup failed, pid = %u, pgrp = %u\n", current->pid, current->pgrp));
if ( oz_mode )
return -ENOENT;
up(&dir->i_sem);
status = autofs_wait(sbi,str);
down(&dir->i_sem);
DPRINTK(("autofs_wait returned %d\n", status));
if ( status )
return status;
}
DPRINTK(("lookup successful, inode = %08x\n", (unsigned int)ent->ino));
if (!(res = iget(dir->i_sb,ent->ino))) {
printk("autofs: iget returned null!\n");
return -EACCES;
}
if ( !oz_mode && S_ISDIR(res->i_mode) && i_dentry(res)->d_covers == i_dentry(res)) {
/* Not a mount point yet, call 1-800-DAEMON */
DPRINTK(("autofs: waiting on non-mountpoint dir, inode = %lu, pid = %u, pgrp = %u\n", res->i_ino, current->pid, current->pgrp));
iput(res);
res = NULL;
up(&dir->i_sem);
status = autofs_wait(sbi,str);
down(&dir->i_sem);
if ( status )
return status;
}
} while(!res);
autofs_update_usage(&sbi->dirhash,ent);
*result = res;
/*
* 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_revalidate = autofs_revalidate;
dentry->d_flags = 1;
d_add(dentry, NULL);
up(&dir->i_sem);
autofs_revalidate(dentry);
down(&dir->i_sem);
return 0;
}
......@@ -164,7 +205,7 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c
struct autofs_symlink *sl;
DPRINTK(("autofs_root_symlink: %s <- ", symname));
autofs_say(name,len);
autofs_say(dentry->d_name.name,dentry->d_name.len);
if ( !autofs_oz_mode(sbi) )
return -EPERM;
......
......@@ -50,7 +50,7 @@ struct binfmt_entry {
#define ENTRY_ENABLED 1 /* the old binfmt_entry.enabled */
#define ENTRY_MAGIC 8 /* not filename detection */
#define ENTRY_STRIP_EXT 32 /* strip of last filename extension */
#define ENTRY_STRIP_EXT 32 /* strip off last filename extension */
static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs);
static void entry_proc_cleanup(struct binfmt_entry *e);
......@@ -162,6 +162,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
char *iname_addr = iname, *p;
int retval, fmt_flags = 0;
MOD_INC_USE_COUNT;
if (!enabled) {
retval = -ENOEXEC;
goto _ret;
......@@ -208,6 +209,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
if (retval >= 0)
retval = search_binary_handler(bprm, regs);
_ret:
MOD_DEC_USE_COUNT;
return retval;
}
......@@ -266,13 +268,18 @@ static int proc_write_register(struct file *file, const char *buffer,
struct binfmt_entry *e;
int memsize, cnt = count - 1, err = 0;
MOD_INC_USE_COUNT;
/* some sanity checks */
if ((count < 11) || (count > 256))
return -EINVAL;
if ((count < 11) || (count > 256)) {
err = -EINVAL;
goto _err;
}
memsize = sizeof(struct binfmt_entry) + count;
if (!(e = (struct binfmt_entry *) kmalloc(memsize, GFP_USER)))
return -ENOMEM;
if (!(e = (struct binfmt_entry *) kmalloc(memsize, GFP_USER))) {
err = -ENOMEM;
goto _err;
}
sp = buffer + 1;
del = buffer[0];
......@@ -309,7 +316,8 @@ static int proc_write_register(struct file *file, const char *buffer,
!(e->proc_name) || !(e->interpreter) ||
entry_proc_setup(e)) {
kfree(e);
return -EINVAL;
err = -EINVAL;
goto _err;
}
write_lock(&entries_lock);
......@@ -317,7 +325,10 @@ static int proc_write_register(struct file *file, const char *buffer,
entries = e;
write_unlock(&entries_lock);
return count;
err = count;
_err:
MOD_DEC_USE_COUNT;
return err;
}
/*
......@@ -332,6 +343,7 @@ static int proc_read_status(char *page, char **start, off_t off,
char *dp;
int elen, i;
MOD_INC_USE_COUNT;
#ifndef VERBOSE_STATUS
if (data) {
read_lock(&entries_lock);
......@@ -391,6 +403,7 @@ static int proc_read_status(char *page, char **start, off_t off,
*eof = (elen <= count) ? 1 : 0;
*start = page + off;
MOD_DEC_USE_COUNT;
return elen;
}
......@@ -404,6 +417,7 @@ static int proc_write_status(struct file *file, const char *buffer,
struct binfmt_entry *e;
int res = count;
MOD_INC_USE_COUNT;
if (((buffer[0] == '1') || (buffer[0] == '0')) &&
((count == 1) || ((count == 2) && (buffer[1] == '\n')))) {
if (data) {
......@@ -423,6 +437,7 @@ static int proc_write_status(struct file *file, const char *buffer,
} else {
res = -EINVAL;
}
MOD_DEC_USE_COUNT;
return res;
}
......
......@@ -171,9 +171,8 @@ void ext2_free_inode (struct inode * inode)
printk ("ext2_free_inode: inode has no device\n");
return;
}
if (atomic_read(&inode->i_count) > 1) {
printk ("ext2_free_inode: inode has count=%d\n",
atomic_read(&inode->i_count));
if (inode->i_count > 1) {
printk ("ext2_free_inode: inode has count=%d\n", inode->i_count);
return;
}
if (inode->i_nlink) {
......@@ -403,7 +402,6 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
sb->s_dirt = 1;
inode->i_mode = mode;
inode->i_sb = sb;
atomic_set(&inode->i_count, 1);
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->fsuid;
......
......@@ -31,10 +31,20 @@
static int ext2_update_inode(struct inode * inode, int do_sync);
/*
* Called at each iput()
*/
void ext2_put_inode (struct inode * inode)
{
ext2_discard_prealloc (inode);
if (inode->i_nlink || inode->i_ino == EXT2_ACL_IDX_INO ||
}
/*
* Called at the last iput() if i_nlink is zero.
*/
void ext2_delete_inode (struct inode * inode)
{
if (inode->i_ino == EXT2_ACL_IDX_INO ||
inode->i_ino == EXT2_ACL_DATA_INO)
return;
inode->u.ext2_i.i_dtime = CURRENT_TIME;
......
......@@ -155,31 +155,26 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
return NULL;
}
int ext2_lookup(struct inode * dir, struct qstr *name, struct inode ** result)
int ext2_lookup(struct inode * dir, struct dentry *dentry)
{
unsigned long ino;
struct inode * inode;
struct ext2_dir_entry * de;
struct buffer_head * bh;
*result = NULL;
if (!dir)
return -ENOENT;
if (!S_ISDIR(dir->i_mode))
return -ENOTDIR;
if (name->len > EXT2_NAME_LEN)
if (dentry->d_name.len > EXT2_NAME_LEN)
return -ENAMETOOLONG;
ino = dir->i_version;
if (!(bh = ext2_find_entry (dir, name->name, name->len, &de)))
return -ENOENT;
ino = le32_to_cpu(de->inode);
brelse (bh);
if (!(*result = iget (dir->i_sb, ino)))
return -EACCES;
bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
inode = NULL;
if (bh) {
unsigned long ino = le32_to_cpu(de->inode);
brelse (bh);
inode = iget(dir->i_sb, ino);
if (!inode)
return -EACCES;
}
d_add(dentry, inode);
return 0;
}
......@@ -613,7 +608,7 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
else if (le32_to_cpu(de->inode) != inode->i_ino)
retval = -ENOENT;
else {
if (atomic_read(&inode->i_count) > 1) {
if (inode->i_count > 1) {
/*
* Are we deleting the last instance of a busy directory?
* Better clean up if so.
......@@ -809,32 +804,30 @@ int ext2_link (struct inode * inode, struct inode * dir, struct dentry *dentry)
inode->i_nlink++;
inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
atomic_inc(&inode->i_count);
inode->i_count++;
d_instantiate(dentry, inode);
return 0;
}
static int subdir (struct inode * new_inode, struct inode * old_inode)
/*
* Trivially implemented using the dcache structure
*/
static int subdir (struct dentry * new_dentry, struct dentry * old_dentry)
{
int ino;
int result;
atomic_inc(&new_inode->i_count);
result = 0;
for (;;) {
if (new_inode == old_inode) {
result = 1;
break;
if (new_dentry != old_dentry) {
struct dentry * parent = new_dentry->d_parent;
if (parent == new_dentry)
break;
new_dentry = parent;
continue;
}
if (new_inode->i_dev != old_inode->i_dev)
break;
ino = new_inode->i_ino;
if (ext2_lookup (new_inode, &(struct qstr) { "..", 2, 0 }, &new_inode))
break;
if (new_inode->i_ino == ino)
break;
result = 1;
break;
}
iput (new_inode);
return result;
}
......@@ -842,10 +835,6 @@ static int subdir (struct inode * new_inode, struct inode * old_inode)
((struct ext2_dir_entry *) ((char *) buffer + \
le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->inode
#define PARENT_NAME(buffer) \
((struct ext2_dir_entry *) ((char *) buffer + \
le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->name
/*
* rename uses retrying to avoid race-conditions: at least they should be
* minimal.
......@@ -906,13 +895,13 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
if (!S_ISDIR(old_inode->i_mode))
goto end_rename;
retval = -EINVAL;
if (subdir (new_dir, old_inode))
if (subdir(new_dentry, old_dentry))
goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir (new_inode))
goto end_rename;
retval = -EBUSY;
if (atomic_read(&new_inode->i_count) > 1)
if (new_inode->i_count > 1)
goto end_rename;
}
retval = -EPERM;
......@@ -925,7 +914,7 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
if (new_inode && !S_ISDIR(new_inode->i_mode))
goto end_rename;
retval = -EINVAL;
if (subdir (new_dir, old_inode))
if (subdir(new_dentry, old_dentry))
goto end_rename;
dir_bh = ext2_bread (old_inode, 0, 0, &retval);
if (!dir_bh)
......
......@@ -133,9 +133,10 @@ void ext2_put_super (struct super_block * sb)
static struct super_operations ext2_sops = {
ext2_read_inode,
NULL,
ext2_write_inode,
ext2_put_inode,
ext2_delete_inode,
NULL,
ext2_put_super,
ext2_write_super,
ext2_statfs,
......
......@@ -280,7 +280,7 @@ int fat_free(struct inode *inode,int skip)
12 ? EOF_FAT12 : EOF_FAT16);
else {
MSDOS_I(inode)->i_start = 0;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
lock_fat(inode->i_sb);
while (nr != -1) {
......
......@@ -52,6 +52,7 @@ struct inode_operations fat_file_inode_operations = {
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
generic_readpage, /* readpage */
NULL, /* writepage */
fat_bmap, /* bmap */
......@@ -99,6 +100,7 @@ struct inode_operations fat_file_inode_operations_1024 = {
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
......@@ -355,7 +357,7 @@ long fat_file_write(
filp->f_pos += written;
if (filp->f_pos > inode->i_size) {
inode->i_size = filp->f_pos;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
fat_set_uptodate(sb, bh, 1);
fat_mark_buffer_dirty(sb, bh, 0);
......@@ -365,7 +367,7 @@ long fat_file_write(
return error;
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
inode->i_dirt = 1;
mark_inode_dirty(inode);
return buf-start;
}
......@@ -379,5 +381,5 @@ void fat_truncate(struct inode *inode)
cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
(void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
......@@ -196,6 +196,7 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
int debug,error,fat;
int blksize = 512;
struct fat_mount_options opts;
struct inode *root_inode;
MOD_INC_USE_COUNT;
if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
......@@ -329,7 +330,10 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
MSDOS_SB(sb)->fat_lock = 0;
MSDOS_SB(sb)->prev_free = 0;
memcpy(&(MSDOS_SB(sb)->options), &opts, sizeof(struct fat_mount_options));
if (!(sb->s_mounted = iget(sb,MSDOS_ROOT_INO))) {
root_inode = iget(sb,MSDOS_ROOT_INO);
sb->s_root = d_alloc_root(root_inode, NULL);
if (!sb->s_root) {
sb->s_dev = 0;
printk("get root inode failed\n");
MOD_DEC_USE_COUNT;
......@@ -339,7 +343,7 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
}
void fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
int fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
{
int free,nr;
struct statfs tmp;
......@@ -362,7 +366,7 @@ void fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
tmp.f_files = 0;
tmp.f_ffree = 0;
tmp.f_namelen = 12;
copy_to_user(buf, &tmp, bufsiz);
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
......@@ -514,10 +518,9 @@ void fat_write_inode(struct inode *inode)
linked->i_blocks = inode->i_blocks;
linked->i_atime = inode->i_atime;
MSDOS_I(linked)->i_attrs = MSDOS_I(inode)->i_attrs;
linked->i_dirt = 1;
mark_inode_dirty(linked);
}
inode->i_dirt = 0;
if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return;
if (!(bh = fat_bread(sb, inode->i_ino >> MSDOS_DPB_BITS))) {
printk("dev = %s, ino = %ld\n",
......
......@@ -40,9 +40,7 @@ void fat_fs_panic(struct super_block *s,const char *msg)
not_ro = !(s->s_flags & MS_RDONLY);
if (not_ro) s->s_flags |= MS_RDONLY;
printk("Filesystem panic (dev %s, ", kdevname(s->s_dev));
printk("mounted on %s:%ld)\n %s\n", /* note: kdevname returns & static char[] */
kdevname(s->s_covered->i_dev), s->s_covered->i_ino, msg);
printk("Filesystem panic (dev %s).", kdevname(s->s_dev));
if (not_ro)
printk(" File system has been set read-only\n");
}
......@@ -180,7 +178,7 @@ printk("last = %d\n",last);
if (last) fat_access(sb,last,nr);
else {
MSDOS_I(inode)->i_start = nr;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
#ifdef DEBUG
if (last) printk("next set to %d\n",fat_access(sb,last,-1));
......@@ -217,7 +215,7 @@ if (last) printk("next set to %d\n",fat_access(sb,last,-1));
#ifdef DEBUG
printk("size is %d now (%x)\n",inode->i_size,inode);
#endif
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
return 0;
}
......
......@@ -29,7 +29,7 @@ static unsigned long fat_file_mmap_nopage(
unsigned long address,
int error_code)
{
struct inode * inode = area->vm_inode;
struct inode * inode = area->vm_dentry->d_inode;
unsigned long page;
unsigned int clear;
int pos;
......@@ -101,10 +101,10 @@ int fat_mmap(struct inode * inode, struct file * file, struct vm_area_struct * v
return -EACCES;
if (!IS_RDONLY(inode)) {
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
vma->vm_inode = inode;
vma->vm_dentry = dget(file->f_dentry);
atomic_inc(&inode->i_count);
vma->vm_ops = &fat_file_mmap;
return 0;
......
......@@ -153,7 +153,6 @@ struct inode_operations fifo_inode_operations = {
void init_fifo(struct inode * inode)
{
inode->i_op = &fifo_inode_operations;
inode->i_pipe = 1;
PIPE_LOCK(*inode) = 0;
PIPE_BASE(*inode) = NULL;
PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
......
......@@ -104,6 +104,7 @@ static inline void init_once(struct inode * inode)
memset(inode, 0, sizeof(*inode));
init_waitqueue(&inode->i_wait);
INIT_LIST_HEAD(&inode->i_dentry);
INIT_LIST_HEAD(&inode->i_hash);
sema_init(&inode->i_sem, 1);
}
......@@ -192,18 +193,13 @@ void clear_inode(struct inode *inode)
if (IS_WRITABLE(inode) && inode->i_sb && inode->i_sb->dq_op)
inode->i_sb->dq_op->drop(inode);
spin_lock(&inode_lock);
inode->i_state = 0;
list_del(&inode->i_hash);
list_del(&inode->i_list);
list_add(&inode->i_list, &inode_unused);
spin_unlock(&inode_lock);
}
#define CAN_UNUSE(inode) \
((atomic_read(&(inode)->i_count) == 0) && \
(((inode)->i_count == 0) && \
((inode)->i_nrpages == 0) && \
(!test_bit(I_LOCK, &(inode)->i_state)))
(!(inode)->i_state))
static void invalidate_list(struct list_head *head, kdev_t dev)
{
......@@ -223,6 +219,7 @@ static void invalidate_list(struct list_head *head, kdev_t dev)
if (!CAN_UNUSE(inode))
continue;
list_del(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_hash);
list_del(&inode->i_list);
list_add(&inode->i_list, &inode_unused);
}
......@@ -257,6 +254,7 @@ static void try_to_free_inodes(void)
inode = list_entry(tmp, struct inode, i_list);
if (CAN_UNUSE(inode)) {
list_del(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_hash);
head = &inode_unused;
}
list_add(tmp, head);
......@@ -280,7 +278,7 @@ static struct inode * find_inode(struct super_block * sb, unsigned long ino, str
continue;
if (inode->i_ino != ino)
continue;
atomic_inc(&inode->i_count);
inode->i_count++;
break;
}
return inode;
......@@ -296,10 +294,9 @@ static struct inode * find_inode(struct super_block * sb, unsigned long ino, str
void clean_inode(struct inode *inode)
{
memset(&inode->u, 0, sizeof(inode->u));
inode->i_pipe = 0;
inode->i_sock = 0;
inode->i_op = NULL;
inode->i_nlink = 1;
inode->i_nlink = 0;
inode->i_writecount = 0;
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
sema_init(&inode->i_sem, 1);
......@@ -322,15 +319,15 @@ struct inode * get_empty_inode(void)
struct list_head * tmp;
spin_lock(&inode_lock);
try_to_free_inodes();
tmp = inode_unused.next;
if (tmp != &inode_unused) {
list_del(tmp);
inode = list_entry(tmp, struct inode, i_list);
add_new_inode:
INIT_LIST_HEAD(&inode->i_hash);
inode->i_sb = NULL;
inode->i_ino = ++last_ino;
atomic_set(&inode->i_count, 1);
inode->i_count = 1;
list_add(&inode->i_list, &inode_in_use);
inode->i_state = 0;
spin_unlock(&inode_lock);
......@@ -350,44 +347,6 @@ struct inode * get_empty_inode(void)
return inode;
}
struct inode * get_pipe_inode(void)
{
extern struct inode_operations pipe_inode_operations;
struct inode *inode = get_empty_inode();
if (inode) {
unsigned long page = __get_free_page(GFP_USER);
if (!page) {
iput(inode);
inode = NULL;
} else {
PIPE_BASE(*inode) = (char *) page;
inode->i_op = &pipe_inode_operations;
atomic_set(&inode->i_count, 1);
PIPE_WAIT(*inode) = NULL;
PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
PIPE_LOCK(*inode) = 0;
/*
* Mark the inode dirty from the very beginning,
* that way it will never be moved to the dirty
* list because "make_inode_dirty()" will think
* that it already _is_ on the dirty list.
*/
inode->i_state = 1 << I_DIRTY;
inode->i_pipe = 1;
inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR;
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_blksize = PAGE_SIZE;
}
}
return inode;
}
/*
* This is called with the inode lock held.. Be careful.
*/
......@@ -406,7 +365,7 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s
inode->i_dev = sb->s_dev;
inode->i_ino = ino;
inode->i_flags = sb->s_flags;
atomic_set(&inode->i_count, 1);
inode->i_count = 1;
inode->i_state = 1 << I_LOCK;
spin_unlock(&inode_lock);
clean_inode(inode);
......@@ -466,27 +425,31 @@ void insert_inode_hash(struct inode *inode)
void iput(struct inode *inode)
{
if (inode) {
if (inode->i_pipe)
wake_up_interruptible(&PIPE_WAIT(*inode));
struct super_operations *op = NULL;
/*
* Last user dropping the inode?
*/
if (atomic_read(&inode->i_count) == 1) {
void (*put)(struct inode *);
if (inode->i_sb && inode->i_sb->s_op)
op = inode->i_sb->s_op;
if (op && op->put_inode)
op->put_inode(inode);
if (inode->i_pipe) {
free_page((unsigned long)PIPE_BASE(*inode));
PIPE_BASE(*inode)= NULL;
spin_lock(&inode_lock);
if (!--inode->i_count) {
if (!inode->i_nlink) {
list_del(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_hash);
if (op && op->delete_inode) {
void (*delete)(struct inode *) = op->delete_inode;
spin_unlock(&inode_lock);
delete(inode);
spin_lock(&inode_lock);
}
}
if (inode->i_sb && inode->i_sb->s_op) {
put = inode->i_sb->s_op->put_inode;
if (put)
put(inode);
if (list_empty(&inode->i_hash)) {
list_del(&inode->i_list);
list_add(&inode->i_list, &inode_unused);
}
}
atomic_dec(&inode->i_count);
spin_unlock(&inode_lock);
}
}
......
......@@ -62,20 +62,6 @@ struct inode_operations isofs_dir_inode_operations =
NULL /* permission */
};
static int parent_inode_number(struct inode * inode, struct iso_directory_record * de)
{
int inode_number = inode->i_ino;
if ((inode->i_sb->u.isofs_sb.s_firstdatazone) != inode->i_ino)
inode_number = inode->u.isofs_i.i_backlink;
if (inode_number != -1)
return inode_number;
/* This should never happen, but who knows. Try to be forgiving */
return isofs_lookup_grandparent(inode, find_rock_ridge_relocation(de, inode));
}
static int isofs_name_translate(char * old, int len, char * new)
{
int i, c;
......@@ -197,9 +183,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
/* Handle the case of the '..' directory */
if (de->name_len[0] == 1 && de->name[0] == 1) {
inode_number = parent_inode_number(inode, de);
if (inode_number == -1)
break;
inode_number = filp->f_dentry->d_parent->d_inode->i_ino;
if (filldir(dirent, "..", 2, filp->f_pos, inode_number) < 0)
break;
filp->f_pos += de_len;
......
......@@ -54,9 +54,10 @@ void isofs_put_super(struct super_block *sb)
static struct super_operations isofs_sops = {
isofs_read_inode,
NULL, /* notify_change */
NULL, /* write_inode */
NULL, /* put_inode */
NULL, /* delete_inode */
NULL, /* notify_change */
isofs_put_super,
NULL, /* write_super */
isofs_statfs,
......@@ -663,7 +664,6 @@ void isofs_read_inode(struct inode * inode)
isonum_711 (raw_inode->ext_attr_length))
<< inode -> i_sb -> u.isofs_sb.s_log_zone_size;
inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
switch (inode->i_sb->u.isofs_sb.s_conversion){
case 'a':
inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
......@@ -735,7 +735,6 @@ void isofs_read_inode(struct inode * inode)
/* With a data error we return this information */
inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
inode->u.isofs_i.i_first_extent = 0;
inode->u.isofs_i.i_backlink = 0xffffffff;
inode->i_size = 0;
inode->i_nlink = 1;
inode->i_uid = inode->i_gid = 0;
......
......@@ -59,14 +59,13 @@ static int isofs_match(int len,const char * name, const char * compare, int dlen
* entry - you'll have to do that yourself if you want to.
*/
static struct buffer_head * isofs_find_entry(struct inode * dir,
const char * name, int namelen, unsigned long * ino, unsigned long * ino_back)
const char * name, int namelen, unsigned long * ino)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
unsigned int block, i, f_pos, offset, inode_number;
struct buffer_head * bh;
unsigned int old_offset;
unsigned int backlink;
int dlen, rrflag, match;
char * dpnt;
struct iso_directory_record * de;
......@@ -86,7 +85,6 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
while (f_pos < dir->i_size) {
de = (struct iso_directory_record *) (bh->b_data + offset);
backlink = dir->i_ino;
inode_number = (block << bufbits) + (offset & (bufsize - 1));
/* If byte is zero, this is the end of file, or time to move to
......@@ -120,28 +118,6 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
return 0;
}
/* Handle the '.' case */
if (de->name[0]==0 && de->name_len[0]==1) {
inode_number = dir->i_ino;
backlink = 0;
}
/* Handle the '..' case */
if (de->name[0]==1 && de->name_len[0]==1) {
#if 0
printk("Doing .. (%d %d)",
dir->i_sb->s_firstdatazone,
dir->i_ino);
#endif
if((dir->i_sb->u.isofs_sb.s_firstdatazone) != dir->i_ino)
inode_number = dir->u.isofs_i.i_backlink;
else
inode_number = dir->i_ino;
backlink = 0;
}
dlen = de->name_len[0];
dpnt = de->name;
/* Now convert the filename in the buffer to lower case */
......@@ -183,16 +159,8 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
inode_number =
isofs_lookup_grandparent(dir,
find_rock_ridge_relocation(de,dir));
if(inode_number == -1){
/* Should never happen */
printk("Backlink not properly set %x %lx.\n",
isonum_733(de->extent),
dir->i_ino);
goto out;
}
}
*ino = inode_number;
*ino_back = backlink;
return bh;
}
}
......@@ -201,16 +169,15 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
return NULL;
}
int isofs_lookup(struct inode * dir, struct qstr *name,
struct inode ** result)
int isofs_lookup(struct inode * dir, struct dentry * dentry)
{
unsigned long ino, ino_back;
unsigned long ino;
struct buffer_head * bh;
char *lcname;
struct inode *inode;
#ifdef DEBUG
printk("lookup: %x %d\n",dir->i_ino, name->len);
printk("lookup: %x %d\n",dir->i_ino, dentry->d_name.len);
#endif
if (!dir)
return -ENOENT;
......@@ -222,39 +189,28 @@ int isofs_lookup(struct inode * dir, struct qstr *name,
* then first convert this name to lower case.
*/
if (dir->i_sb->u.isofs_sb.s_name_check == 'r' &&
(lcname = kmalloc(name->len, GFP_KERNEL)) != NULL) {
(lcname = kmalloc(dentry->d_name.len, GFP_KERNEL)) != NULL) {
int i;
char c;
for (i=0; i<name->len; i++) {
c = name->name[i];
for (i=0; i<dentry->d_name.len; i++) {
c = dentry->d_name.name[i];
if (c >= 'A' && c <= 'Z') c |= 0x20;
lcname[i] = c;
}
bh = isofs_find_entry(dir, lcname, name->len,
&ino, &ino_back);
bh = isofs_find_entry(dir, lcname, dentry->d_name.len, &ino);
kfree(lcname);
} else
bh = isofs_find_entry(dir, name->name,
name->len, &ino, &ino_back);
bh = isofs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &ino);
if (!bh)
return -ENOENT;
brelse(bh);
inode = NULL;
if (bh) {
brelse(bh);
inode = iget(dir->i_sb,ino);
if (!inode)
return -EACCES;
/* We need this backlink for the ".." entry unless the name that we
* are looking up traversed a mount point (in which case the inode
* may not even be on an iso9660 filesystem, and writing to
* u.isofs_i would only cause memory corruption).
*/
if (ino_back && !inode->i_pipe && inode->i_sb == dir->i_sb)
inode->u.isofs_i.i_backlink = ino_back;
*result = inode;
inode = iget(dir->i_sb,ino);
if (!inode)
return -EACCES;
}
d_add(dentry, inode);
return 0;
}
......@@ -256,7 +256,7 @@ struct inode * minix_new_inode(const struct inode * dir)
inode->i_dev = sb->s_dev;
inode->i_uid = current->fsuid;
inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
inode->i_dirt = 1;
mark_inode_dirty(inode);
inode->i_ino = j;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = NULL;
......
......@@ -121,6 +121,6 @@ static long minix_file_write(struct inode * inode, struct file * filp,
inode->i_size = pos;
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
filp->f_pos = pos;
inode->i_dirt = 1;
mark_inode_dirty(inode);
return written;
}
......@@ -307,7 +307,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
return s;
}
void minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
struct statfs tmp;
......@@ -319,7 +319,7 @@ void minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
tmp.f_files = sb->u.minix_sb.s_ninodes;
tmp.f_ffree = minix_count_free_inodes(sb);
tmp.f_namelen = sb->u.minix_sb.s_namelen;
copy_to_user(buf, &tmp, bufsiz);
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
/*
......@@ -472,7 +472,7 @@ static struct buffer_head * V1_inode_getblk(struct inode * inode, int nr,
}
*p = tmp;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
mark_inode_dirty(inode);
return result;
}
......@@ -585,7 +585,7 @@ static struct buffer_head * V2_inode_getblk(struct inode * inode, int nr,
}
*p = tmp;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
mark_inode_dirty(inode);
return result;
}
......@@ -833,14 +833,12 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode)
printk("Bad inode number on dev %s"
": %d is out of range\n",
kdevname(inode->i_dev), ino);
inode->i_dirt = 0;
return 0;
}
block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks + inode->i_sb->u.minix_sb.s_zmap_blocks +
(ino-1)/MINIX_INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) {
printk("unable to read i-node block\n");
inode->i_dirt = 0;
return 0;
}
raw_inode = ((struct minix_inode *)bh->b_data) +
......@@ -855,7 +853,6 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode)
raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
else for (block = 0; block < 9; block++)
raw_inode->i_zone[block] = inode->u.minix_i.u.i1_data[block];
inode->i_dirt=0;
mark_buffer_dirty(bh, 1);
return bh;
}
......@@ -874,14 +871,12 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode)
printk("Bad inode number on dev %s"
": %d is out of range\n",
kdevname(inode->i_dev), ino);
inode->i_dirt = 0;
return 0;
}
block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks + inode->i_sb->u.minix_sb.s_zmap_blocks +
(ino-1)/MINIX2_INODES_PER_BLOCK;
if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) {
printk("unable to read i-node block\n");
inode->i_dirt = 0;
return 0;
}
raw_inode = ((struct minix2_inode *)bh->b_data) +
......@@ -898,7 +893,6 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode)
raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
else for (block = 0; block < 10; block++)
raw_inode->i_zone[block] = inode->u.minix_i.u.i2_data[block];
inode->i_dirt=0;
mark_buffer_dirty(bh, 1);
return bh;
}
......
......@@ -173,7 +173,7 @@ static int minix_add_entry(struct inode * dir,
if (block*bh->b_size + offset > dir->i_size) {
de->inode = 0;
dir->i_size = block*bh->b_size + offset;
dir->i_dirt = 1;
mark_inode_dirty(dir);
}
if (de->inode) {
if (namecompare(namelen, info->s_namelen, name, de->name)) {
......@@ -182,7 +182,7 @@ static int minix_add_entry(struct inode * dir,
}
} else {
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
dir->i_dirt = 1;
mark_inode_dirty(dir);
for (i = 0; i < info->s_namelen ; i++)
de->name[i] = (i < namelen) ? name[i] : 0;
dir->i_version = ++event;
......@@ -215,12 +215,12 @@ int minix_create(struct inode * dir, struct dentry *dentry, int mode)
return -ENOSPC;
inode->i_op = &minix_file_inode_operations;
inode->i_mode = mode;
inode->i_dirt = 1;
mark_inode_dirty(inode);
error = minix_add_entry(dir, dentry->d_name.name,
dentry->d_name.len, &bh ,&de);
if (error) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
return error;
}
......@@ -269,11 +269,11 @@ int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
init_fifo(inode);
if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = to_kdev_t(rdev);
inode->i_dirt = 1;
mark_inode_dirty(inode);
error = minix_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
if (error) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
return error;
}
......@@ -311,7 +311,7 @@ int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
dir_block = minix_bread(inode,0,1);
if (!dir_block) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
return -ENOSPC;
}
......@@ -327,7 +327,7 @@ int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
if (dir->i_mode & S_ISGID)
inode->i_mode |= S_ISGID;
inode->i_dirt = 1;
mark_inode_dirty(inode);
error = minix_add_entry(dir, dentry->d_name.name,
dentry->d_name.len, &bh, &de);
if (error) {
......@@ -338,7 +338,7 @@ int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1);
dir->i_nlink++;
dir->i_dirt = 1;
mark_inode_dirty(dir);
brelse(bh);
d_instantiate(dentry, inode);
return 0;
......@@ -449,10 +449,10 @@ int minix_rmdir(struct inode * dir, struct dentry *dentry)
dir->i_version = ++event;
mark_buffer_dirty(bh, 1);
inode->i_nlink=0;
inode->i_dirt=1;
mark_inode_dirty(inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_nlink--;
dir->i_dirt=1;
mark_inode_dirty(dir);
d_delete(dentry);
retval = 0;
end_rmdir:
......@@ -503,10 +503,10 @@ int minix_unlink(struct inode * dir, struct dentry *dentry)
dir->i_version = ++event;
mark_buffer_dirty(bh, 1);
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
mark_inode_dirty(dir);
inode->i_nlink--;
inode->i_ctime = dir->i_ctime;
inode->i_dirt = 1;
mark_inode_dirty(inode);
d_delete(dentry); /* This also frees the inode */
retval = 0;
end_unlink:
......@@ -531,7 +531,7 @@ int minix_symlink(struct inode * dir, struct dentry *dentry,
name_block = minix_bread(inode,0,1);
if (!name_block) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
return -ENOSPC;
}
......@@ -542,12 +542,12 @@ int minix_symlink(struct inode * dir, struct dentry *dentry,
mark_buffer_dirty(name_block, 1);
brelse(name_block);
inode->i_size = i;
inode->i_dirt = 1;
mark_inode_dirty(inode);
bh = minix_find_entry(dir, dentry->d_name.name,
dentry->d_name.len, &de);
if (bh) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
brelse(bh);
return -EEXIST;
......@@ -556,7 +556,7 @@ int minix_symlink(struct inode * dir, struct dentry *dentry,
dentry->d_name.len, &bh, &de);
if (i) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
return i;
}
......@@ -597,7 +597,7 @@ int minix_link(struct inode * inode, struct inode * dir,
brelse(bh);
inode->i_nlink++;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
mark_inode_dirty(inode);
d_instantiate(dentry, inode);
return 0;
}
......@@ -740,15 +740,15 @@ static int do_minix_rename(struct inode * old_dir, struct dentry *old_dentry,
old_de->inode = 0;
new_de->inode = old_inode->i_ino;
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
old_dir->i_dirt = 1;
mark_inode_dirty(old_dir);
old_dir->i_version = ++event;
new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
new_dir->i_dirt = 1;
mark_inode_dirty(new_dir);
new_dir->i_version = ++event;
if (new_inode) {
new_inode->i_nlink--;
new_inode->i_ctime = CURRENT_TIME;
new_inode->i_dirt = 1;
mark_inode_dirty(new_inode);
}
mark_buffer_dirty(old_bh, 1);
mark_buffer_dirty(new_bh, 1);
......@@ -756,13 +756,13 @@ static int do_minix_rename(struct inode * old_dir, struct dentry *old_dentry,
PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
mark_buffer_dirty(dir_bh, 1);
old_dir->i_nlink--;
old_dir->i_dirt = 1;
mark_inode_dirty(old_dir);
if (new_inode) {
new_inode->i_nlink--;
new_inode->i_dirt = 1;
mark_inode_dirty(new_inode);
} else {
new_dir->i_nlink++;
new_dir->i_dirt = 1;
mark_inode_dirty(new_dir);
}
}
/* Update the dcache */
......
......@@ -15,6 +15,7 @@
#include <asm/uaccess.h>
static int minix_readlink(struct inode *, char *, int);
static struct dentry *minix_follow_link(struct inode *, struct dentry *);
/*
* symlinks can't do much...
......@@ -31,6 +32,7 @@ struct inode_operations minix_symlink_inode_operations = {
NULL, /* mknod */
NULL, /* rename */
minix_readlink, /* readlink */
minix_follow_link, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
......@@ -38,6 +40,21 @@ struct inode_operations minix_symlink_inode_operations = {
NULL /* permission */
};
static struct dentry * minix_follow_link(struct inode * inode, struct dentry * base)
{
struct buffer_head * bh;
bh = minix_bread(inode, 0, 0);
if (!bh) {
dput(base);
return ERR_PTR(-EIO);
}
UPDATE_ATIME(inode);
base = lookup_dentry(bh->b_data, base, 1);
brelse(bh);
return base;
}
static int minix_readlink(struct inode * inode, char * buffer, int buflen)
{
struct buffer_head * bh;
......@@ -47,7 +64,6 @@ static int minix_readlink(struct inode * inode, char * buffer, int buflen)
if (buflen > 1023)
buflen = 1023;
bh = minix_bread(inode, 0, 0);
iput(inode);
if (!bh)
return 0;
i = 0;
......
......@@ -58,7 +58,7 @@ static int V1_trunc_direct(struct inode * inode)
continue;
}
*p = 0;
inode->i_dirt = 1;
mark_inode_dirty(inode);
if (bh) {
mark_buffer_clean(bh);
brelse(bh);
......@@ -167,7 +167,7 @@ static int V1_trunc_dindirect(struct inode * inode, int offset, unsigned short *
else {
tmp = *p;
*p = 0;
inode->i_dirt = 1;
mark_inode_dirty(inode);
minix_free_block(inode->i_sb,tmp);
}
brelse(dind_bh);
......@@ -191,7 +191,7 @@ void V1_minix_truncate(struct inode * inode)
schedule();
}
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
/*
......@@ -220,7 +220,7 @@ static int V2_trunc_direct(struct inode * inode)
continue;
}
*p = 0;
inode->i_dirt = 1;
mark_inode_dirty(inode);
if (bh) {
mark_buffer_clean(bh);
brelse(bh);
......@@ -329,7 +329,7 @@ static int V2_trunc_dindirect(struct inode * inode, int offset, unsigned long *p
else {
tmp = *p;
*p = 0;
inode->i_dirt = 1;
mark_inode_dirty(inode);
minix_free_block(inode->i_sb,tmp);
}
brelse(dind_bh);
......@@ -374,7 +374,7 @@ static int V2_trunc_tindirect(struct inode * inode, int offset, unsigned long *
else {
tmp = *p;
*p = 0;
inode->i_dirt = 1;
mark_inode_dirty(inode);
minix_free_block(inode->i_sb,tmp);
}
brelse(tind_bh);
......@@ -402,7 +402,7 @@ static void V2_minix_truncate(struct inode * inode)
schedule();
}
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
/*
......
......@@ -280,7 +280,7 @@ static int msdos_create_entry(struct inode *dir, const char *name,int len,
* XXX all times should be set by caller upon successful completion.
*/
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
mark_inode_dirty(dir);
memcpy(de->name,name,MSDOS_NAME);
memset(de->unused, 0, sizeof(de->unused));
de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
......@@ -295,7 +295,7 @@ static int msdos_create_entry(struct inode *dir, const char *name,int len,
if (!*result) return -EIO;
(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
CURRENT_TIME;
(*result)->i_dirt = 1;
mark_inode_dirty(*result);
return 0;
}
......@@ -415,7 +415,8 @@ int msdos_rmdir(struct inode *dir,const char *name,int len)
inode->i_nlink = 0;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_nlink--;
inode->i_dirt = dir->i_dirt = 1;
mark_inode_dirty(inode);
mark_inode_dirty(dir);
de->name[0] = DELETED_FLAG;
fat_mark_buffer_dirty(sb, bh, 1);
res = 0;
......@@ -465,7 +466,7 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
dot->i_size = inode->i_size; /* doesn't grow in the 2nd create_entry */
MSDOS_I(dot)->i_start = MSDOS_I(inode)->i_start;
dot->i_nlink = inode->i_nlink;
dot->i_dirt = 1;
mark_inode_dirty(dot);
iput(dot);
if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,2,1,0,&dot)) < 0)
goto mkdir_error;
......@@ -473,7 +474,7 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
dot->i_size = dir->i_size;
MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
dot->i_nlink = dir->i_nlink;
dot->i_dirt = 1;
mark_inode_dirty(dot);
MSDOS_I(inode)->i_busy = 0;
iput(dot);
iput(inode);
......@@ -519,7 +520,8 @@ static int msdos_unlinkx(
inode->i_nlink = 0;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
MSDOS_I(inode)->i_busy = 1;
inode->i_dirt = dir->i_dirt = 1;
mark_inode_dirty(inode);
mark_inode_dirty(dir);
de->name[0] = DELETED_FLAG;
fat_mark_buffer_dirty(sb, bh, 1);
unlink_done:
......@@ -580,11 +582,11 @@ static int rename_same_dir(struct inode *old_dir,char *old_name,int old_len,
}
if (S_ISDIR(new_inode->i_mode)) {
new_dir->i_nlink--;
new_dir->i_dirt = 1;
mark_inode_dirty(new_dir);
}
new_inode->i_nlink = 0;
MSDOS_I(new_inode)->i_busy = 1;
new_inode->i_dirt = 1;
mark_inode_dirty(new_inode);
new_de->name[0] = DELETED_FLAG;
fat_mark_buffer_dirty(sb, new_bh, 1);
iput(new_inode);
......@@ -675,7 +677,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,int old_len,
}
new_inode->i_nlink = 0;
MSDOS_I(new_inode)->i_busy = 1;
new_inode->i_dirt = 1;
mark_inode_dirty(new_inode);
new_de->name[0] = DELETED_FLAG;
fat_mark_buffer_dirty(sb, new_bh, 1);
}
......@@ -696,14 +698,14 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,int old_len,
}
if (exists && S_ISDIR(new_inode->i_mode)) {
new_dir->i_nlink--;
new_dir->i_dirt = 1;
mark_inode_dirty(new_dir);
}
msdos_read_inode(free_inode);
MSDOS_I(old_inode)->i_busy = 1;
MSDOS_I(old_inode)->i_linked = free_inode;
MSDOS_I(free_inode)->i_oldlink = old_inode;
fat_cache_inval_inode(old_inode);
old_inode->i_dirt = 1;
mark_inode_dirty(old_inode);
old_de->name[0] = DELETED_FLAG;
fat_mark_buffer_dirty(sb, old_bh, 1);
fat_mark_buffer_dirty(sb, free_bh, 1);
......@@ -726,7 +728,7 @@ static int rename_diff_dir(struct inode *old_dir,char *old_name,int old_len,
}
dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
MSDOS_I(new_dir)->i_start;
dotdot_inode->i_dirt = 1;
mark_inode_dirty(dotdot_inode);
fat_mark_buffer_dirty(sb, dotdot_bh, 1);
old_dir->i_nlink--;
new_dir->i_nlink++;
......@@ -793,6 +795,7 @@ struct inode_operations msdos_dir_inode_operations = {
NULL, /* mknod */
msdos_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
fat_bmap, /* bmap */
......
......@@ -237,38 +237,23 @@ void put_write_access(struct inode * inode)
*/
static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
{
struct dentry * result;
struct inode *dir = parent->d_inode;
struct dentry *result;
struct inode *inode;
int error = -ENOTDIR;
down(&dir->i_sem);
error = -ENOTDIR;
if (dir->i_op && dir->i_op->lookup)
error = dir->i_op->lookup(dir, name, &inode);
result = ERR_PTR(error);
if (!error || error == -ENOENT) {
struct dentry *new;
if (error)
inode = NULL;
new = d_alloc(parent, name);
/*
* Ok, now we can't sleep any more. Double-check that
* nobody else added this in the meantime..
*/
result = ERR_PTR(-ENOTDIR);
if (dir->i_op && dir->i_op->lookup) {
down(&dir->i_sem);
result = d_lookup(parent, name);
if (result) {
d_free(new);
iput(inode);
} else {
d_add(new, inode);
result = new;
if (!result) {
int error;
result = d_alloc(parent, name);
error = dir->i_op->lookup(dir, result);
if (error) {
d_free(result);
result = ERR_PTR(error);
}
}
up(&dir->i_sem);
}
up(&dir->i_sem);
return result;
......@@ -280,8 +265,11 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
struct dentry * dentry = d_lookup(parent, name);
if (dentry) {
if (dentry->d_revalidate)
if (dentry->d_revalidate) {
/* spin_unlock(&dentry_lock); */
dentry = dentry->d_revalidate(dentry);
/* spin_lock(&dentry_lock); */
}
/*
* The parent d_count _should_ be at least 2: one for the
......
......@@ -42,7 +42,7 @@ struct nfs_dirent {
static int nfs_dir_open(struct inode * inode, struct file * file);
static long nfs_dir_read(struct inode *, struct file *, char *, unsigned long);
static int nfs_readdir(struct inode *, struct file *, void *, filldir_t);
static int nfs_lookup(struct inode *, struct qstr *, struct inode **);
static int nfs_lookup(struct inode *, struct dentry *);
static int nfs_create(struct inode *, struct dentry *, int);
static int nfs_mkdir(struct inode *, struct dentry *, int);
static int nfs_rmdir(struct inode *, struct dentry *);
......@@ -328,19 +328,17 @@ nfs_free_dircache(void)
}
static int nfs_lookup(struct inode *dir, struct qstr * __name,
struct inode **result)
static int nfs_lookup(struct inode *dir, struct dentry * dentry)
{
struct inode *inode;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
int len = __name->len;
char name[len > NFS_MAXNAMLEN? 1 : len+1];
int len = dentry->d_name.len;
int error;
dfprintk(VFS, "NFS: lookup(%x/%ld, %.*s)\n",
dir->i_dev, dir->i_ino, len, __name->name);
dir->i_dev, dir->i_ino, len, dentry->d_name.name);
*result = NULL;
if (!dir || !S_ISDIR(dir->i_mode)) {
printk("nfs_lookup: inode is NULL or not a directory\n");
return -ENOENT;
......@@ -349,17 +347,18 @@ static int nfs_lookup(struct inode *dir, struct qstr * __name,
if (len > NFS_MAXNAMLEN)
return -ENAMETOOLONG;
memcpy(name,__name->name,len);
name[len] = '\0';
error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name, &fhandle, &fattr);
error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
name, &fhandle, &fattr);
if (error)
inode = NULL;
if (!error) {
error = -ENOENT;
inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
if (!inode)
return -EACCES;
} else if (error != -ENOENT)
return error;
if (!(*result = nfs_fhget(dir->i_sb, &fhandle, &fattr)))
return -EACCES;
d_add(dentry, inode);
return 0;
}
......@@ -587,7 +586,7 @@ static int nfs_link(struct inode *inode, struct inode *dir, struct dentry *dentr
if (error)
return error;
atomic_inc(&inode->i_count);
inode->i_count++;
d_instantiate(dentry, inode);
return 0;
}
......@@ -647,8 +646,7 @@ void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
int was_empty;
dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d)\n",
inode->i_dev, inode->i_ino,
atomic_read(&inode->i_count));
inode->i_dev, inode->i_ino, inode->i_count);
if (!inode || !fattr) {
printk("nfs_refresh_inode: inode or fattr is NULL\n");
......
......@@ -143,7 +143,7 @@ nfs_file_write(struct inode *inode, struct file *file,
int result;
dfprintk(VFS, "nfs: write(%x/%ld (%d), %lu@%lu)\n",
inode->i_dev, inode->i_ino, atomic_read(&inode->i_count),
inode->i_dev, inode->i_ino, inode->i_count,
count, (unsigned long) file->f_pos);
if (!inode) {
......
......@@ -36,15 +36,17 @@
static int nfs_notify_change(struct inode *, struct iattr *);
static void nfs_put_inode(struct inode *);
static void nfs_delete_inode(struct inode *);
static void nfs_put_super(struct super_block *);
static void nfs_read_inode(struct inode *);
static int nfs_statfs(struct super_block *, struct statfs *, int bufsiz);
static struct super_operations nfs_sops = {
nfs_read_inode, /* read inode */
nfs_notify_change, /* notify change */
NULL, /* write inode */
nfs_put_inode, /* put inode */
nfs_delete_inode, /* delete inode */
nfs_notify_change, /* notify change */
nfs_put_super, /* put superblock */
NULL, /* write superblock */
nfs_statfs, /* stat filesystem */
......@@ -73,9 +75,16 @@ static void
nfs_put_inode(struct inode * inode)
{
dprintk("NFS: put_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
}
if (inode->i_pipe)
clear_inode(inode);
/*
* This should do any silly-rename cleanups once we
* get silly-renaming working again..
*/
static void
nfs_delete_inode(struct inode * inode)
{
dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
}
void
......@@ -316,7 +325,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
}
dprintk("NFS: fhget(%x/%ld ct=%d)\n",
inode->i_dev, inode->i_ino,
atomic_read(&inode->i_count));
inode->i_count);
return inode;
}
......
......@@ -150,7 +150,6 @@ nfs_readpage_result(struct rpc_task *task)
fail++;
dprintk("NFS: %d successful reads, %d failures\n", succ, fail);
}
iput(req->ra_inode);
clear_bit(PG_locked, &page->flags);
wake_up(&page->wait);
......@@ -188,7 +187,6 @@ nfs_readpage_async(struct inode *inode, struct page *page)
nfs_readpage_result, req);
if (result >= 0) {
atomic_inc(&inode->i_count);
atomic_inc(&page->count);
return 0;
}
......
......@@ -338,7 +338,7 @@ create_write_request(struct inode *inode, struct page *page,
wreq->wb_page = page;
wreq->wb_offset = offset;
wreq->wb_bytes = bytes;
atomic_inc(&inode->i_count);
atomic_inc(&page->count);
append_write_request(&NFS_WRITEBACK(inode), wreq);
......@@ -695,7 +695,6 @@ nfs_check_error(struct inode *inode)
status = req->wb_task.tk_status;
remove_write_request(&nfs_failed_requests, req);
iput(req->wb_inode);
kfree(req);
return status;
}
......@@ -788,7 +787,6 @@ nfs_wback_result(struct rpc_task *task)
dprintk("NFS: %4d saving write failure code\n",
task->tk_pid);
append_write_request(&nfs_failed_requests, req);
atomic_inc(&inode->i_count);
}
clear_bit(PG_uptodate, &page->flags);
} else if (!WB_CANCELLED(req)) {
......@@ -818,6 +816,5 @@ nfs_wback_result(struct rpc_task *task)
kfree(req);
free_page(page_address(page));
iput(inode);
nr_write_requests--;
}
......@@ -416,6 +416,7 @@ asmlinkage int sys_chroot(const char * filename)
tmp = current->fs->root;
current->fs->root = dentry;
dentry = tmp;
error = 0;
dput_and_out:
dput(dentry);
......
......@@ -230,18 +230,26 @@ static unsigned int connect_poll(struct file * filp, poll_table * wait)
return POLLOUT | POLLWRNORM;
}
static int pipe_read_release(struct inode * inode, struct file * filp)
static int pipe_release(struct inode * inode)
{
PIPE_READERS(*inode)--;
if (!PIPE_READERS(*inode) && !PIPE_READERS(*inode)) {
free_page((unsigned long) PIPE_BASE(*inode));
PIPE_BASE(*inode) = NULL;
}
wake_up_interruptible(&PIPE_WAIT(*inode));
return 0;
}
static int pipe_read_release(struct inode * inode, struct file * filp)
{
PIPE_READERS(*inode)--;
return pipe_release(inode);
}
static int pipe_write_release(struct inode * inode, struct file * filp)
{
PIPE_WRITERS(*inode)--;
wake_up_interruptible(&PIPE_WAIT(*inode));
return 0;
return pipe_release(inode);
}
static int pipe_rdwr_release(struct inode * inode, struct file * filp)
......@@ -250,8 +258,7 @@ static int pipe_rdwr_release(struct inode * inode, struct file * filp)
PIPE_READERS(*inode)--;
if (filp->f_mode & FMODE_WRITE)
PIPE_WRITERS(*inode)--;
wake_up_interruptible(&PIPE_WAIT(*inode));
return 0;
return pipe_release(inode);
}
static int pipe_read_open(struct inode * inode, struct file * filp)
......@@ -370,6 +377,43 @@ struct file_operations rdwr_pipe_fops = {
NULL
};
static struct inode * get_pipe_inode(void)
{
extern struct inode_operations pipe_inode_operations;
struct inode *inode = get_empty_inode();
if (inode) {
unsigned long page = __get_free_page(GFP_USER);
if (!page) {
iput(inode);
inode = NULL;
} else {
PIPE_BASE(*inode) = (char *) page;
inode->i_op = &pipe_inode_operations;
inode->i_count = 1;
PIPE_WAIT(*inode) = NULL;
PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
PIPE_LOCK(*inode) = 0;
/*
* Mark the inode dirty from the very beginning,
* that way it will never be moved to the dirty
* list because "make_inode_dirty()" will think
* that it already _is_ on the dirty list.
*/
inode->i_state = 1 << I_DIRTY;
inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR;
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_blksize = PAGE_SIZE;
}
}
return inode;
}
struct inode_operations pipe_inode_operations = {
&rdwr_pipe_fops,
NULL, /* create */
......
......@@ -8,7 +8,7 @@
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := proc.o
O_OBJS := inode.o root.o base.o generic.o mem.o link.o arbitrary.o fd.o array.o \
O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \
kmsg.o scsi.o proc_tty.o
ifdef CONFIG_OMIRR
O_OBJS := $(O_OBJS) omirr.o
......
/*
* $Id: arbitrary.c,v 1.2 1997/06/05 01:27:47 davem Exp $
*
* linux/fs/proc/arbitrary.c - lookup() for arbitrary inodes.
* Copyright (C) 1997, Thomas Schoebel-Theuer,
* <schoebel@informatik.uni-stuttgart.de>.
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
/* Format of dev/inode pairs that can be used as file names:
* [<dev_number_in_hex]:<inode_number_in_decimal>
* (the same format that is already in use in /proc/<pid>/exe,
* /proc/<pid>/cwd and /proc/<pid>/root).
*/
/* Note that readdir does not supply such names, so they must be used
* either "blind" or must be queried another way, for example
* as result of a virtual symlink (see linux/proc/link.c).
*/
int proc_arbitrary_lookup(struct inode * dir, const char * name,
int len, struct inode ** result)
{
int dev, ino;
char * ptr = (char*)name;
kdev_t kdev;
int i;
int error = -EINVAL;
if(*ptr++ != '[')
goto done;
dev = simple_strtoul(ptr, &ptr, 16);
if(*ptr++ != ']')
goto done;
if(*ptr++ != ':')
goto done;
ino = simple_strtoul(ptr, &ptr, 0);
if((long)ptr - (long)name != len)
goto done;
error = -ENOENT;
kdev = to_kdev_t(dev);
if(!kdev)
goto done;
for(i = 0; i < NR_SUPER; i++)
if(super_blocks[i].s_dev == kdev)
break;
if(i < NR_SUPER) {
*result = iget(&super_blocks[i], ino);
if(*result)
error = 0;
}
done:
return error;
}
......@@ -14,7 +14,7 @@
#include <linux/stat.h>
static int proc_readfd(struct inode *, struct file *, void *, filldir_t);
static int proc_lookupfd(struct inode *,struct qstr *,struct inode **);
static int proc_lookupfd(struct inode *, struct dentry *);
static struct file_operations proc_fd_operations = {
NULL, /* lseek - default */
......@@ -52,15 +52,24 @@ struct inode_operations proc_fd_inode_operations = {
NULL /* permission */
};
static int proc_lookupfd(struct inode * dir, struct qstr *str, struct inode ** result)
/*
* NOTE! Normally we'd indicate that a file does not
* exist by creating a negative dentry and returning
* a successful return code. However, for this case
* we do not want to create negative dentries, because
* the state of the world can change behind our backs.
*
* Thus just return -ENOENT instead.
*/
static int proc_lookupfd(struct inode * dir, struct dentry * dentry)
{
unsigned int ino, pid, fd, c;
struct task_struct * p;
struct super_block * sb;
struct inode *inode;
const char *name;
int len;
*result = NULL;
ino = dir->i_ino;
pid = ino >> 16;
ino &= 0x0000ffff;
......@@ -71,8 +80,8 @@ static int proc_lookupfd(struct inode * dir, struct qstr *str, struct inode ** r
return -ENOENT;
fd = 0;
len = str->len;
name = str->name;
len = dentry->d_name.len;
name = dentry->d_name.name;
while (len-- > 0) {
c = *name - '0';
name++;
......@@ -105,8 +114,11 @@ static int proc_lookupfd(struct inode * dir, struct qstr *str, struct inode ** r
ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd;
if (!(*result = proc_get_inode(sb, ino, NULL)))
inode = proc_get_inode(sb, ino, NULL);
if (!inode)
return -ENOENT;
d_add(dentry, inode);
return 0;
}
......
......@@ -25,8 +25,14 @@ static void proc_put_inode(struct inode *inode)
&& proc_openprom_use)
(*proc_openprom_use)(inode, 0);
#endif
if (inode->i_nlink)
return;
}
/*
* Does this ever happen?
*/
static void proc_delete_inode(struct inode *inode)
{
printk("proc_delete_inode()?\n");
inode->i_size = 0;
}
......@@ -39,9 +45,10 @@ static void proc_put_super(struct super_block *sb)
static struct super_operations proc_sops = {
proc_read_inode,
NULL,
proc_write_inode,
proc_put_inode,
proc_delete_inode,
NULL,
proc_put_super,
NULL,
proc_statfs,
......
......@@ -24,7 +24,7 @@
#define FIRST_PROCESS_ENTRY 256
static int proc_root_readdir(struct inode *, struct file *, void *, filldir_t);
static int proc_root_lookup(struct inode *,struct qstr *,struct inode **);
static int proc_root_lookup(struct inode *,struct dentry *);
static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
......@@ -227,7 +227,6 @@ proc_openprom_deflookup(struct inode * dir, struct qstr *str, struct inode ** re
proc_openprom_deflookup)
return proc_openprom_inode_operations.lookup
(dir, str, result);
iput(dir);
return -ENOENT;
}
#endif
......@@ -622,45 +621,50 @@ void proc_root_init(void)
proc_tty_init();
}
int proc_lookup(struct inode * dir, struct qstr * str, struct inode ** result)
/*
* Don't create negative dentries here, return -ENOENT by hand
* instead.
*/
int proc_lookup(struct inode * dir, struct dentry *dentry)
{
struct inode *inode;
struct proc_dir_entry * de;
*result = NULL;
if (!dir || !S_ISDIR(dir->i_mode))
return -ENOTDIR;
de = (struct proc_dir_entry *) dir->u.generic_ip;
if (!de)
return -EINVAL;
*result = NULL;
for (de = de->subdir; de ; de = de->next) {
if (!de || !de->low_ino)
continue;
if (de->namelen != str->len)
continue;
if (!memcmp(str->name, de->name, str->len)) {
int ino = de->low_ino | (dir->i_ino & ~(0xffff));
if (!(*result = proc_get_inode(dir->i_sb, ino, de)))
return -EINVAL;
return 0;
inode = NULL;
if (de) {
for (de = de->subdir; de ; de = de->next) {
if (!de || !de->low_ino)
continue;
if (de->namelen != dentry->d_name.len)
continue;
if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
int ino = de->low_ino | (dir->i_ino & ~(0xffff));
inode = proc_get_inode(dir->i_sb, ino, de);
if (!inode)
return -EINVAL;
break;
}
}
}
return -ENOENT;
if (!inode)
return -ENOENT;
d_add(dentry, inode);
return 0;
}
static int proc_root_lookup(struct inode * dir,struct qstr *str, struct inode ** result)
static int proc_root_lookup(struct inode * dir, struct dentry * dentry)
{
unsigned int pid, c;
int ino, retval;
struct task_struct *p;
const char *name;
struct inode *inode;
int len;
atomic_inc(&dir->i_count);
if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */
dir->i_nlink = proc_root.nlink;
......@@ -672,13 +676,12 @@ static int proc_root_lookup(struct inode * dir,struct qstr *str, struct inode **
read_unlock(&tasklist_lock);
}
retval = proc_lookup(dir, str, result);
if (retval != -ENOENT)
return retval;
if (!proc_lookup(dir, dentry))
return 0;
pid = 0;
name = str->name;
len = str->len;
name = dentry->d_name.name;
len = dentry->d_name.len;
while (len-- > 0) {
c = *name - '0';
name++;
......@@ -694,12 +697,14 @@ static int proc_root_lookup(struct inode * dir,struct qstr *str, struct inode **
}
}
p = find_task_by_pid(pid);
if (!pid || !p)
return -ENOENT;
ino = (pid << 16) + PROC_PID_INO;
if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid)))
return -EINVAL;
inode = NULL;
if (pid && p) {
unsigned long ino = (pid << 16) + PROC_PID_INO;
inode = proc_get_inode(dir->i_sb, ino, &proc_pid);
if (!inode)
return -EINVAL;
}
d_add(dentry, inode);
return 0;
}
......
......@@ -48,8 +48,6 @@ static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
tmp.st_gid = inode->i_gid;
tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
tmp.st_size = inode->i_size;
if (inode->i_pipe)
tmp.st_size = PIPE_SIZE(*inode);
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
......@@ -72,8 +70,6 @@ static int cp_new_stat(struct inode * inode, struct stat * statbuf)
tmp.st_gid = inode->i_gid;
tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
tmp.st_size = inode->i_size;
if (inode->i_pipe)
tmp.st_size = PIPE_SIZE(*inode);
tmp.st_atime = inode->i_atime;
tmp.st_mtime = inode->i_mtime;
tmp.st_ctime = inode->i_ctime;
......
......@@ -57,6 +57,7 @@ struct inode_operations sysv_dir_inode_operations = {
sysv_mknod, /* mknod */
sysv_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
......
......@@ -64,6 +64,7 @@ struct inode_operations sysv_file_inode_operations = {
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
generic_readpage, /* readpage */
NULL, /* writepage */
sysv_bmap, /* bmap */
......@@ -194,7 +195,7 @@ long sysv_file_read(struct inode * inode, struct file * filp,
filp->f_reada = 1;
if (!IS_RDONLY(inode)) {
inode->i_atime = CURRENT_TIME;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
return read;
}
......@@ -255,7 +256,7 @@ static long sysv_file_write(struct inode * inode, struct file * filp,
pos += c;
if (pos > inode->i_size) {
inode->i_size = pos;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
written += c;
buf += c;
......@@ -265,6 +266,6 @@ static long sysv_file_write(struct inode * inode, struct file * filp,
}
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
filp->f_pos = pos;
inode->i_dirt = 1;
mark_inode_dirty(inode);
return written;
}
......@@ -155,7 +155,7 @@ struct inode * sysv_new_inode(const struct inode * dir)
inode->i_dev = sb->s_dev;
inode->i_uid = current->fsuid;
inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
inode->i_dirt = 1;
mark_inode_dirty(inode);
inode->i_ino = ino;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_op = NULL;
......@@ -166,7 +166,7 @@ struct inode * sysv_new_inode(const struct inode * dir)
inode->i_size = 0; /* ditto */
sysv_write_inode(inode); /* ensure inode not allocated again */
/* FIXME: caller may call this too. */
inode->i_dirt = 1; /* cleared by sysv_write_inode() */
mark_inode_dirty(inode); /* cleared by sysv_write_inode() */
/* That's it. */
(*sb->sv_sb_total_free_inodes)--;
mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified again */
......
......@@ -344,6 +344,7 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
struct buffer_head *bh;
const char *found;
kdev_t dev = sb->s_dev;
struct inode *root_inode;
if (1024 != sizeof (struct xenix_super_block))
panic("Xenix FS: bad super-block size");
......@@ -483,9 +484,10 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
/* set up enough so that it can read an inode */
sb->s_dev = dev;
sb->s_op = &sysv_sops;
sb->s_mounted = iget(sb,SYSV_ROOT_INO);
root_inode = iget(sb,SYSV_ROOT_INO);
sb->s_root = d_alloc_root(root_inode, NULL);
unlock_super(sb);
if (!sb->s_mounted) {
if (!sb->s_root) {
printk("SysV FS: get root inode failed\n");
sysv_put_super(sb);
return NULL;
......@@ -534,7 +536,7 @@ void sysv_put_super(struct super_block *sb)
MOD_DEC_USE_COUNT;
}
void sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
int sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
struct statfs tmp;
......@@ -547,7 +549,7 @@ void sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
tmp.f_ffree = sysv_count_free_inodes(sb); /* free file nodes in fs */
tmp.f_namelen = SYSV_NAMELEN;
/* Don't know what value to put in tmp.f_fsid */ /* file system id */
copy_to_user(buf, &tmp, bufsiz);
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
......@@ -667,7 +669,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, int nr, int creat
}
*p = tmp;
inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
mark_inode_dirty(inode);
return result;
}
......@@ -900,13 +902,11 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
printk("Bad inode number on dev %s"
": %d is out of range\n",
kdevname(inode->i_dev), ino);
inode->i_dirt = 0;
return 0;
}
block = sb->sv_firstinodezone + ((ino-1) >> sb->sv_inodes_per_block_bits);
if (!(bh = sv_bread(sb,inode->i_dev,block))) {
printk("unable to read i-node block\n");
inode->i_dirt = 0;
return 0;
}
raw_inode = (struct sysv_inode *) bh->b_data + ((ino-1) & sb->sv_inodes_per_block_1);
......@@ -937,7 +937,6 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
else
for (block = 0; block < 10+1+1+1; block++)
write3byte(&raw_inode->i_a.i_addb[3*block],inode->u.sysv_i.i_data[block]);
inode->i_dirt=0;
mark_buffer_dirty(bh, 1);
return bh;
}
......
......@@ -175,7 +175,7 @@ static int sysv_add_entry(struct inode * dir,
if (pos > dir->i_size) {
de->inode = 0;
dir->i_size = pos;
dir->i_dirt = 1;
mark_inode_dirty(dir);
}
if (de->inode) {
if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) {
......@@ -184,7 +184,7 @@ static int sysv_add_entry(struct inode * dir,
}
} else {
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
dir->i_dirt = 1;
mark_inode_dirty(dir);
for (i = 0; i < SYSV_NAMELEN ; i++)
de->name[i] = (i < namelen) ? name[i] : 0;
mark_buffer_dirty(bh, 1);
......@@ -219,11 +219,11 @@ int sysv_create(struct inode * dir,const char * name, int len, int mode,
}
inode->i_op = &sysv_file_inode_operations;
inode->i_mode = mode;
inode->i_dirt = 1;
mark_inode_dirty(inode);
error = sysv_add_entry(dir,name,len, &bh ,&de);
if (error) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
iput(dir);
return error;
......@@ -276,11 +276,11 @@ int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rde
init_fifo(inode);
if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = to_kdev_t(rdev);
inode->i_dirt = 1;
mark_inode_dirty(inode);
error = sysv_add_entry(dir, name, len, &bh, &de);
if (error) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
iput(dir);
return error;
......@@ -325,7 +325,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
if (!dir_block) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
return -ENOSPC;
}
......@@ -341,7 +341,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
if (dir->i_mode & S_ISGID)
inode->i_mode |= S_ISGID;
inode->i_dirt = 1;
mark_inode_dirty(inode);
error = sysv_add_entry(dir, name, len, &bh, &de);
if (error) {
iput(dir);
......@@ -352,7 +352,7 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode)
de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1);
dir->i_nlink++;
dir->i_dirt = 1;
mark_inode_dirty(dir);
iput(dir);
iput(inode);
brelse(bh);
......@@ -463,10 +463,10 @@ int sysv_rmdir(struct inode * dir, const char * name, int len)
de->inode = 0;
mark_buffer_dirty(bh, 1);
inode->i_nlink=0;
inode->i_dirt=1;
mark_inode_dirty(inode);
dir->i_nlink--;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt=1;
mark_inode_dirty(dir);
retval = 0;
end_rmdir:
iput(dir);
......@@ -517,10 +517,10 @@ int sysv_unlink(struct inode * dir, const char * name, int len)
de->inode = 0;
mark_buffer_dirty(bh, 1);
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
mark_inode_dirty(dir);
inode->i_nlink--;
inode->i_ctime = dir->i_ctime;
inode->i_dirt = 1;
mark_inode_dirty(inode);
retval = 0;
end_unlink:
brelse(bh);
......@@ -550,7 +550,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy
if (!name_block) {
iput(dir);
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
return -ENOSPC;
}
......@@ -563,11 +563,11 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy
mark_buffer_dirty(name_block, 1);
brelse(name_block);
inode->i_size = i;
inode->i_dirt = 1;
mark_inode_dirty(inode);
bh = sysv_find_entry(dir,name,len,&de);
if (bh) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
brelse(bh);
iput(dir);
......@@ -576,7 +576,7 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy
i = sysv_add_entry(dir, name, len, &bh, &de);
if (i) {
inode->i_nlink--;
inode->i_dirt = 1;
mark_inode_dirty(inode);
iput(inode);
iput(dir);
return i;
......@@ -624,7 +624,7 @@ int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, in
iput(dir);
oldinode->i_nlink++;
oldinode->i_ctime = CURRENT_TIME;
oldinode->i_dirt = 1;
mark_inode_dirty(oldinode);
iput(oldinode);
return 0;
}
......@@ -667,8 +667,8 @@ static int subdir(struct inode * new_inode, struct inode * old_inode)
* Anybody can rename anything with this: the permission checks are left to the
* higher-level routines.
*/
static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len)
static int do_sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
struct inode * new_dir, struct dentry * new_dentry)
{
struct inode * old_inode, * new_inode;
struct buffer_head * old_bh, * new_bh, * dir_bh;
......@@ -687,21 +687,21 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old
start_up:
old_inode = new_inode = NULL;
old_bh = new_bh = dir_bh = NULL;
old_bh = sysv_find_entry(old_dir,old_name,old_len,&old_de);
old_bh = sysv_find_entry(old_dir,old_dentry->d_name.name,
old_dentry->d_name.len,&old_de);
retval = -ENOENT;
if (!old_bh)
goto end_rename;
old_inode = __iget(old_dir->i_sb, old_de->inode, 0); /* don't cross mnt-points */
if (!old_inode)
goto end_rename;
old_inode = old_dentry->d_inode;/* don't cross mnt-points */
retval = -EPERM;
if ((old_dir->i_mode & S_ISVTX) &&
current->fsuid != old_inode->i_uid &&
current->fsuid != old_dir->i_uid && !fsuser())
goto end_rename;
new_bh = sysv_find_entry(new_dir,new_name,new_len,&new_de);
new_inode = new_dentry->d_inode;
new_bh = sysv_find_entry(new_dir,new_dentry->d_name.name,
new_dentry->d_name.len,&new_de);
if (new_bh) {
new_inode = __iget(new_dir->i_sb, new_de->inode, 0);
if (!new_inode) {
brelse(new_bh);
new_bh = NULL;
......@@ -748,7 +748,8 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old
goto end_rename;
}
if (!new_bh) {
retval = sysv_add_entry(new_dir,new_name,new_len,&new_bh,&new_de);
retval = sysv_add_entry(new_dir,new_dentry->d_name.name,
new_dentry->d_name.len,&new_bh,&new_de);
if (retval)
goto end_rename;
}
......@@ -763,13 +764,13 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old
old_de->inode = 0;
new_de->inode = old_inode->i_ino;
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
old_dir->i_dirt = 1;
mark_inode_dirty(old_dir);
new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
new_dir->i_dirt = 1;
mark_inode_dirty(new_dir);
if (new_inode) {
new_inode->i_nlink--;
new_inode->i_ctime = CURRENT_TIME;
new_inode->i_dirt = 1;
mark_inode_dirty(new_inode);
}
mark_buffer_dirty(old_bh, 1);
mark_buffer_dirty(new_bh, 1);
......@@ -777,13 +778,13 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old
PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
mark_buffer_dirty(dir_bh, 1);
old_dir->i_nlink--;
old_dir->i_dirt = 1;
mark_inode_dirty(old_dir);
if (new_inode) {
new_inode->i_nlink--;
new_inode->i_dirt = 1;
mark_inode_dirty(new_inode);
} else {
new_dir->i_nlink++;
new_dir->i_dirt = 1;
mark_inode_dirty(new_dir);
}
}
retval = 0;
......@@ -807,8 +808,8 @@ static int do_sysv_rename(struct inode * old_dir, const char * old_name, int old
* the same device that races occur: many renames can happen at once, as long
* as they are on different partitions.
*/
int sysv_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len)
int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
struct inode * new_dir, struct dentry * new_dentry)
{
static struct wait_queue * wait = NULL;
static int lock = 0;
......@@ -817,8 +818,8 @@ int sysv_rename(struct inode * old_dir, const char * old_name, int old_len,
while (lock)
sleep_on(&wait);
lock = 1;
result = do_sysv_rename(old_dir, old_name, old_len,
new_dir, new_name, new_len);
result = do_sysv_rename(old_dir, old_dentry,
new_dir, new_dentry);
lock = 0;
wake_up(&wait);
return result;
......
......@@ -21,6 +21,7 @@
#include <asm/uaccess.h>
static int sysv_readlink(struct inode *, char *, int);
static struct dentry *sysv_follow_link(struct inode *, struct dentry *);
/*
* symlinks can't do much...
......@@ -37,6 +38,7 @@ struct inode_operations sysv_symlink_inode_operations = {
NULL, /* mknod */
NULL, /* rename */
sysv_readlink, /* readlink */
sysv_follow_link, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
......@@ -44,6 +46,21 @@ struct inode_operations sysv_symlink_inode_operations = {
NULL /* permission */
};
static struct dentry *sysv_follow_link(struct inode * inode, struct dentry * base)
{
struct buffer_head * bh;
bh = sysv_file_bread(inode, 0, 0);
if (!bh) {
dput(base);
return ERR_PTR(-EIO);
}
UPDATE_ATIME(inode);
base = lookup_dentry(bh->b_data, base, 1);
brelse(bh);
return base;
}
static int sysv_readlink(struct inode * inode, char * buffer, int buflen)
{
struct buffer_head * bh;
......@@ -54,7 +71,6 @@ static int sysv_readlink(struct inode * inode, char * buffer, int buflen)
if (buflen > inode->i_sb->sv_block_size_1)
buflen = inode->i_sb->sv_block_size_1;
bh = sysv_file_bread(inode, 0, 0);
iput(inode);
if (!bh)
return 0;
bh_data = bh->b_data;
......
......@@ -64,7 +64,7 @@ static int trunc_direct(struct inode * inode)
continue;
}
*p = 0;
inode->i_dirt = 1;
mark_inode_dirty(inode);
brelse(bh);
sysv_free_block(sb,block);
}
......@@ -257,12 +257,14 @@ static int trunc_tindirect(struct inode * inode, unsigned long offset, unsigned
static int trunc_all(struct inode * inode)
{
struct super_block * sb;
char * res;
sb = inode->i_sb;
res = (char *)test_bit(I_DIRTY,&inode->i_state);
return trunc_direct(inode)
| trunc_indirect(inode,sb->sv_ind0_size,&inode->u.sysv_i.i_data[10],0,&inode->i_dirt)
| trunc_dindirect(inode,sb->sv_ind1_size,&inode->u.sysv_i.i_data[11],0,&inode->i_dirt)
| trunc_tindirect(inode,sb->sv_ind2_size,&inode->u.sysv_i.i_data[12],0,&inode->i_dirt);
| trunc_indirect(inode,sb->sv_ind0_size,&inode->u.sysv_i.i_data[10],0,res)
| trunc_dindirect(inode,sb->sv_ind1_size,&inode->u.sysv_i.i_data[11],0,res)
| trunc_tindirect(inode,sb->sv_ind2_size,&inode->u.sysv_i.i_data[12],0,res);
}
......@@ -285,5 +287,5 @@ void sysv_truncate(struct inode * inode)
schedule();
}
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
mark_inode_dirty(inode);
}
......@@ -877,7 +877,7 @@ static int vfat_find(struct inode *dir,const char *name,int len,
PRINTK(("vfat_find: create file 4\n"));
dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
dir->i_dirt = 1;
mark_inode_dirty(dir);
PRINTK(("vfat_find: create file 5\n"));
......@@ -1010,7 +1010,7 @@ static int vfat_create_entry(struct inode *dir,const char *name,int len,
return -EIO;
(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
CURRENT_TIME;
(*result)->i_dirt = 1;
mark_inode_dirty(*result);
(*result)->i_version = ++event;
dir->i_version = event;
......@@ -1046,7 +1046,7 @@ static int vfat_create_a_dotdir(struct inode *dir,struct inode *parent,
* XXX all times should be set by caller upon successful completion.
*/
dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_dirt = 1;
mark_inode_dirty(dir);
memcpy(de->name,name,MSDOS_NAME);
memset(de->unused, 0, sizeof(de->unused));
de->lcase = 0;
......@@ -1062,7 +1062,7 @@ static int vfat_create_a_dotdir(struct inode *dir,struct inode *parent,
vfat_read_inode(dot);
if (!dot) return -EIO;
dot->i_mtime = dot->i_atime = CURRENT_TIME;
dot->i_dirt = 1;
mark_inode_dirty(dot);
if (isdot) {
dot->i_size = dir->i_size;
MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
......@@ -1173,7 +1173,8 @@ static int vfat_rmdir_free_ino(struct inode *dir,struct buffer_head *bh,
inode->i_mtime = dir->i_mtime = CURRENT_TIME;
inode->i_atime = dir->i_atime = CURRENT_TIME;
dir->i_nlink--;
inode->i_dirt = dir->i_dirt = 1;
mark_inode_dirty(dir);
mark_inode_dirty(inode);
de->name[0] = DELETED_FLAG;
fat_mark_buffer_dirty(sb, bh, 1);
iput(inode);
......@@ -1196,7 +1197,8 @@ static int vfat_unlink_free_ino(struct inode *dir,struct buffer_head *bh,
inode->i_atime = dir->i_atime = CURRENT_TIME;
dir->i_version = ++event;
MSDOS_I(inode)->i_busy = 1;
inode->i_dirt = dir->i_dirt = 1;
mark_inode_dirty(dir);
mark_inode_dirty(inode);
de->name[0] = DELETED_FLAG;
fat_mark_buffer_dirty(sb, bh, 1);
......@@ -1478,7 +1480,7 @@ int vfat_rename(struct inode *old_dir,const char *old_name,int old_len,
MSDOS_I(new_inode)->i_oldlink = old_inode;
fat_cache_inval_inode(old_inode);
PRINTK(("vfat_rename 15: old_slots=%d\n",old_slots));
old_inode->i_dirt = 1;
mark_inode_dirty(old_inode);
old_dir->i_version = ++event;
/* remove the old entry */
......@@ -1511,7 +1513,7 @@ int vfat_rename(struct inode *old_dir,const char *old_name,int old_len,
}
dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
MSDOS_I(new_dir)->i_start;
dotdot_inode->i_dirt = 1;
mark_inode_dirty(dotdot_inode);
fat_mark_buffer_dirty(sb, dotdot_bh, 1);
old_dir->i_nlink--;
new_dir->i_nlink++;
......
......@@ -65,7 +65,7 @@ struct dentry {
* to invalidate a dentry for some reason (NFS
* timeouts or autofs deletes).
*/
inline void d_drop(struct dentry * dentry)
static inline void d_drop(struct dentry * dentry)
{
list_del(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_hash);
......
......@@ -483,6 +483,7 @@ extern int ext2_getcluster (struct inode * inode, long block);
extern void ext2_read_inode (struct inode *);
extern void ext2_write_inode (struct inode *);
extern void ext2_put_inode (struct inode *);
extern void ext2_delete_inode (struct inode *);
extern int ext2_sync_inode (struct inode *);
extern void ext2_discard_prealloc (struct inode *);
......@@ -492,7 +493,7 @@ extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
/* namei.c */
extern void ext2_release (struct inode *, struct file *);
extern int ext2_lookup (struct inode *,struct qstr *, struct inode **);
extern int ext2_lookup (struct inode *, struct dentry *);
extern int ext2_create (struct inode *,struct dentry *,int);
extern int ext2_mkdir (struct inode *,struct dentry *,int);
extern int ext2_rmdir (struct inode *,struct dentry *);
......
......@@ -304,7 +304,7 @@ struct inode {
unsigned long i_ino;
kdev_t i_dev;
atomic_t i_count;
unsigned short i_count;
umode_t i_mode;
nlink_t i_nlink;
uid_t i_uid;
......@@ -358,6 +358,7 @@ struct inode {
/* Inode state bits.. */
#define I_DIRTY 0
#define I_LOCK 1
#define I_FREEING 2
extern void __mark_inode_dirty(struct inode *);
static inline void mark_inode_dirty(struct inode *inode)
......@@ -542,7 +543,7 @@ struct file_operations {
struct inode_operations {
struct file_operations * default_file_ops;
int (*create) (struct inode *,struct dentry *,int);
int (*lookup) (struct inode *,struct qstr *name,struct inode **);
int (*lookup) (struct inode *,struct dentry *);
int (*link) (struct inode *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
......@@ -565,9 +566,10 @@ struct inode_operations {
struct super_operations {
void (*read_inode) (struct inode *);
int (*notify_change) (struct inode *, struct iattr *);
void (*write_inode) (struct inode *);
void (*put_inode) (struct inode *);
void (*delete_inode) (struct inode *);
int (*notify_change) (struct inode *, struct iattr *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*statfs) (struct super_block *, struct statfs *, int);
......@@ -744,7 +746,6 @@ extern struct inode * get_empty_inode(void);
extern struct inode * get_empty_inode_hashed(dev_t i_dev, unsigned long i_ino);
extern void insert_inode_hash(struct inode *);
extern struct inode * get_pipe_inode(void);
extern int get_unused_fd(void);
extern void put_unused_fd(int);
extern struct file * get_empty_filp(void);
......
......@@ -152,8 +152,7 @@ extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inod
extern int isofs_open(struct inode * inode, struct file * filp);
extern void isofs_release(struct inode * inode, struct file * filp);
extern int isofs_lookup(struct inode * dir, struct qstr *dentry,
struct inode ** result);
extern int isofs_lookup(struct inode * dir, struct dentry *);
extern unsigned long isofs_count_free_inodes(struct super_block *sb);
extern int isofs_new_block(int dev);
extern int isofs_free_block(int dev, int block);
......
......@@ -6,7 +6,6 @@
*/
struct iso_inode_info {
unsigned int i_first_extent;
unsigned int i_backlink;
unsigned char i_file_format;
};
......
......@@ -121,7 +121,7 @@ extern int minix_remount (struct super_block * sb, int * flags, char * data);
extern void minix_read_inode(struct inode *);
extern void minix_write_inode(struct inode *);
extern void minix_put_inode(struct inode *);
extern void minix_statfs(struct super_block *, struct statfs *, int);
extern int minix_statfs(struct super_block *, struct statfs *, int);
extern int minix_sync_inode(struct inode *);
extern int minix_sync_file(struct inode *, struct file *);
......
......@@ -215,7 +215,7 @@ extern void fat_put_super(struct super_block *sb);
extern void fat_read_inode(struct inode *inode, struct inode_operations *dir_ops);
extern struct super_block *fat_read_super(struct super_block *s, void *data, int silent);
extern void msdos_put_super(struct super_block *sb);
extern void fat_statfs(struct super_block *sb,struct statfs *buf, int);
extern int fat_statfs(struct super_block *sb,struct statfs *buf, int);
extern void fat_write_inode(struct inode *inode);
/* dir.c */
......
......@@ -57,7 +57,7 @@ struct knfs_fh {
typedef struct svc_fh {
struct knfs_fh fh_handle; /* FH data */
struct svc_export * fh_export; /* export pointer */
struct inode * fh_inode; /* inode */
struct dentry * fh_dentry; /* file */
size_t fh_pre_size; /* size before operation */
time_t fh_pre_mtime; /* mtime before oper */
time_t fh_pre_ctime; /* ctime before oper */
......@@ -98,7 +98,7 @@ fh_init(struct svc_fh *fhp)
static inline void
fh_lock(struct svc_fh *fhp)
{
struct inode *inode = fhp->fh_inode;
struct inode *inode = fhp->fh_dentry->d_inode;
/*
dfprintk(FILEOP, "nfsd: fh_lock(%x/%ld) locked = %d\n",
......@@ -118,7 +118,7 @@ fh_lock(struct svc_fh *fhp)
static inline void
fh_unlock(struct svc_fh *fhp)
{
struct inode *inode = fhp->fh_inode;
struct inode *inode = fhp->fh_dentry->d_inode;
if (fhp->fh_locked) {
if (!fhp->fh_post_version)
......@@ -135,9 +135,9 @@ fh_unlock(struct svc_fh *fhp)
static inline void
fh_put(struct svc_fh *fhp)
{
if (fhp->fh_inode) {
if (fhp->fh_dentry) {
fh_unlock(fhp);
iput(fhp->fh_inode);
dput(fhp->fh_dentry);
}
}
#else
......@@ -146,19 +146,19 @@ fh_put(struct svc_fh *fhp)
static inline void
__fh_put(struct svc_fh *fhp, char *file, int line)
{
struct inode *inode;
struct dentry *dentry;
if (!(inode = fhp->fh_inode))
if (!(dentry = fhp->fh_dentry))
return;
if (!atomic_read(&inode->i_count)) {
printk("nfsd: trying to free free inode in %s:%d\n"
" dev %04x ino %ld, mode %07o\n",
file, line, inode->i_dev,
inode->i_ino, inode->i_mode);
if (!dentry->d_count) {
printk("nfsd: trying to free free dentry in %s:%d\n"
" file %s/%s\n",
file, line,
dentry->d_parent->d_name.name, dentry->d_name.name);
} else {
fh_unlock(fhp);
iput(inode);
dput(dentry);
}
}
#endif
......
......@@ -5,7 +5,6 @@ struct pipe_inode_info {
struct wait_queue * wait;
char * base;
unsigned int start;
unsigned int len;
unsigned int lock;
unsigned int rd_openers;
unsigned int wr_openers;
......@@ -16,7 +15,7 @@ struct pipe_inode_info {
#define PIPE_WAIT(inode) ((inode).u.pipe_i.wait)
#define PIPE_BASE(inode) ((inode).u.pipe_i.base)
#define PIPE_START(inode) ((inode).u.pipe_i.start)
#define PIPE_LEN(inode) ((inode).u.pipe_i.len)
#define PIPE_LEN(inode) ((inode).i_size)
#define PIPE_RD_OPENERS(inode) ((inode).u.pipe_i.rd_openers)
#define PIPE_WR_OPENERS(inode) ((inode).u.pipe_i.wr_openers)
#define PIPE_READERS(inode) ((inode).u.pipe_i.readers)
......
......@@ -323,7 +323,7 @@ extern int proc_match(int, const char *,struct proc_dir_entry *);
* of the /proc/<pid> subdirectories.
*/
extern int proc_readdir(struct inode *, struct file *, void *, filldir_t);
extern int proc_lookup(struct inode *, struct qstr *, struct inode **);
extern int proc_lookup(struct inode *, struct dentry *);
struct openpromfs_dev {
struct openpromfs_dev *next;
......
......@@ -372,8 +372,8 @@ extern int sysv_symlink(struct inode * inode, const char * name, int len,
const char * symname);
extern int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, int len);
extern int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rdev);
extern int sysv_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len);
extern int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
struct inode * new_dir, struct dentry * new_dentry);
extern struct inode * sysv_new_inode(const struct inode * dir);
extern void sysv_free_inode(struct inode * inode);
extern unsigned long sysv_count_free_inodes(struct super_block *sb);
......@@ -396,7 +396,7 @@ extern void sysv_read_inode(struct inode *);
extern int sysv_notify_change(struct inode *, struct iattr *);
extern void sysv_write_inode(struct inode *);
extern void sysv_put_inode(struct inode *);
extern void sysv_statfs(struct super_block *, struct statfs *, int);
extern int sysv_statfs(struct super_block *, struct statfs *, int);
extern int sysv_sync_inode(struct inode *);
extern int sysv_sync_file(struct inode *, struct file *);
extern int sysv_mmap(struct inode *, struct file *, struct vm_area_struct *);
......
......@@ -180,6 +180,7 @@ EXPORT_SYMBOL(posix_lock_file);
EXPORT_SYMBOL(posix_test_lock);
EXPORT_SYMBOL(posix_block_lock);
EXPORT_SYMBOL(posix_unblock_lock);
EXPORT_SYMBOL(dput);
#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
EXPORT_SYMBOL(do_nfsservctl);
......
......@@ -206,6 +206,19 @@ static int get_fd(struct inode *inode)
return -ENFILE;
}
file->f_dentry = d_alloc_root(inode, NULL);
if (!file->f_dentry) {
put_filp(file);
put_unused_fd(fd);
return -ENOMEM;
}
/*
* The socket maintains a reference to the inode, so we
* have to increment the count.
*/
inode->i_count++;
current->files->fd[fd] = file;
file->f_op = &socket_file_ops;
file->f_mode = 3;
......
......@@ -544,7 +544,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
err = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
inode = dentry->d_inode;
atomic_inc(&inode->i_count);
inode->i_count++; /* HATEFUL - we should use the dentry */
dput(dentry);
err = 0;
}
......@@ -794,7 +794,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
}
if (sk->protinfo.af_unix.inode)
{
atomic_inc(&sk->protinfo.af_unix.inode->i_count);
sk->protinfo.af_unix.inode->i_count++; /* Should use dentry */
newsk->protinfo.af_unix.inode=sk->protinfo.af_unix.inode;
}
......
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