Commit 344c062e authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.46

parent 295e4b4b
VERSION = 2
PATCHLEVEL = 1
SUBLEVEL = 45
SUBLEVEL = 46
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
......
......@@ -127,16 +127,8 @@ do_aout_core_dump(long signr, struct pt_regs * regs)
goto end_coredump;
if (get_write_access(inode))
goto end_coredump;
file.f_mode = 3;
file.f_flags = 0;
file.f_count = 1;
file.f_dentry = dentry;
file.f_pos = 0;
file.f_reada = 0;
file.f_op = inode->i_op->default_file_ops;
if (file.f_op->open)
if (file.f_op->open(inode,&file))
goto done_coredump;
if (init_private_file(&file, dentry, 3))
goto end_coredump;
if (!file.f_op->write)
goto close_coredump;
has_dumped = 1;
......
......@@ -1091,16 +1091,8 @@ static int elf_core_dump(long signr, struct pt_regs * regs)
goto end_coredump;
if (!inode->i_op || !inode->i_op->default_file_ops)
goto end_coredump;
file.f_mode = 3;
file.f_flags = 0;
file.f_count = 1;
file.f_dentry = dentry;
file.f_pos = 0;
file.f_reada = 0;
file.f_op = inode->i_op->default_file_ops;
if (file.f_op->open)
if (file.f_op->open(inode,&file))
goto end_coredump;
if (init_private_file(&file, dentry, 3))
goto end_coredump;
if (!file.f_op->write)
goto close_coredump;
has_dumped = 1;
......
......@@ -352,17 +352,9 @@ int read_exec(struct dentry *dentry, unsigned long offset,
if (!inode->i_op || !inode->i_op->default_file_ops)
goto end_readexec;
file.f_mode = 1;
file.f_flags = 0;
file.f_count = 1;
file.f_dentry = dentry;
file.f_pos = 0;
file.f_reada = 0;
file.f_op = inode->i_op->default_file_ops;
if (file.f_op->open)
if (file.f_op->open(inode,&file))
goto end_readexec;
if (!file.f_op || !file.f_op->read)
if (init_private_file(&file, dentry, 1))
goto end_readexec;
if (!file.f_op->read)
goto close_readexec;
if (file.f_op->llseek) {
if (file.f_op->llseek(inode,&file,offset,0) != offset)
......
......@@ -154,6 +154,22 @@ static int load_inode_bitmap (struct super_block * sb,
return 0;
}
/*
* NOTE! When we get the inode, we're the only people
* that have access to it, and as such there are no
* race conditions we have to worry about. The inode
* is not on the hash-lists, and it cannot be reached
* through the filesystem because the directory entry
* has been deleted earlier.
*
* HOWEVER: we must make sure that we get no aliases,
* which means that we have to call "clear_inode()"
* _before_ we mark the inode not in use in the inode
* bitmaps. Otherwise a newly created file might use
* the same inode number (not actually the same pointer
* though), and then we'd have two inodes sharing the
* same inode number and space on the harddisk.
*/
void ext2_free_inode (struct inode * inode)
{
int is_directory;
......@@ -207,10 +223,12 @@ void ext2_free_inode (struct inode * inode)
is_directory = S_ISDIR(inode->i_mode);
/* Do this BEFORE marking the inode not in use */
if (sb->dq_op)
sb->dq_op->free_inode (inode, 1);
clear_inode (inode);
/* Ok, now we can actually update the inode bitmaps.. */
if (!ext2_clear_bit (bit, bh->b_data))
ext2_warning (sb, "ext2_free_inode",
"bit already cleared for inode %lu", ino);
......
......@@ -102,6 +102,24 @@ struct file * get_empty_filp(void)
return f;
}
/*
* Clear and initialize a (private) struct file for the given dentry,
* and call the open function (if any). The caller must verify that
* inode->i_op and inode->i_op->default_file_ops are not NULL.
*/
int init_private_file(struct file *filp, struct dentry *dentry, int mode)
{
memset(filp, 0, sizeof(*filp));
filp->f_mode = mode;
filp->f_count = 1;
filp->f_dentry = dentry;
filp->f_op = dentry->d_inode->i_op->default_file_ops;
if (filp->f_op->open)
return filp->f_op->open(dentry->d_inode, filp);
else
return 0;
}
#ifdef CONFIG_QUOTA
void add_dquot_ref(kdev_t dev, short type)
......
......@@ -296,7 +296,7 @@ void clean_inode(struct inode *inode)
memset(&inode->u, 0, sizeof(inode->u));
inode->i_sock = 0;
inode->i_op = NULL;
inode->i_nlink = 0;
inode->i_nlink = 1;
inode->i_writecount = 0;
inode->i_size = 0;
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
......
......@@ -24,10 +24,8 @@
#include <asm/uaccess.h>
#include <asm/bitops.h>
void minix_put_inode(struct inode *inode)
static void minix_delete_inode(struct inode *inode)
{
if (inode->i_nlink)
return;
inode->i_size = 0;
minix_truncate(inode);
minix_free_inode(inode);
......@@ -77,9 +75,10 @@ void minix_put_super(struct super_block *sb)
static struct super_operations minix_sops = {
minix_read_inode,
NULL,
minix_write_inode,
minix_put_inode,
NULL, /* put_inode */
minix_delete_inode,
NULL, /* notify_change */
minix_put_super,
minix_write_super,
minix_statfs,
......
......@@ -47,9 +47,6 @@ static int minix_match(int len, const char * name,
*offset += info->s_dirsize;
if (!de->inode || len > info->s_namelen)
return 0;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
return 1;
return namecompare(len,info->s_namelen,name,de->name);
}
......@@ -104,24 +101,22 @@ static struct buffer_head * minix_find_entry(struct inode * dir,
return NULL;
}
int minix_lookup(struct inode * dir, struct qstr *name,
struct inode ** result)
int minix_lookup(struct inode * dir, struct dentry *dentry)
{
int ino;
struct inode * inode = NULL;
struct minix_dir_entry * de;
struct buffer_head * bh;
*result = NULL;
if (!dir)
return -ENOENT;
if (!S_ISDIR(dir->i_mode))
return -ENOENT;
if (!(bh = minix_find_entry(dir, name->name, name->len, &de)))
return -ENOENT;
ino = de->inode;
brelse(bh);
if (!(*result = iget(dir->i_sb,ino)))
return -EACCES;
bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
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;
}
......@@ -602,29 +597,21 @@ int minix_link(struct inode * inode, struct inode * dir,
return 0;
}
static int subdir(struct inode * new_inode, struct inode * old_inode)
static int subdir(struct dentry * new_dentry, struct dentry * old_dentry)
{
int ino;
int result;
int result = 0;
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 (minix_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;
}
......@@ -690,7 +677,7 @@ static int do_minix_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))
......@@ -709,7 +696,7 @@ static int do_minix_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;
retval = -EIO;
dir_bh = minix_bread(old_inode,0,0);
......
......@@ -379,7 +379,7 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
}
if (!*name)
return base;
goto return_base;
/* At this point we know we have a real path component. */
for(;;) {
......@@ -388,9 +388,6 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
struct qstr this;
char c, follow;
dentry = base;
if (IS_ERR(base))
break;
dentry = ERR_PTR(-ENOENT);
if (!base->d_inode)
break;
......@@ -424,9 +421,10 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
break;
base = do_follow_link(base, dentry);
if (c)
if (c && !IS_ERR(base))
continue;
return_base:
return base;
}
dput(base);
......@@ -744,7 +742,7 @@ static inline int do_rmdir(const char * name)
struct inode *dir;
struct dentry *dentry;
dentry = lookup_dentry(name, NULL, 1);
dentry = lookup_dentry(name, NULL, 0);
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto exit;
......@@ -1053,13 +1051,13 @@ static inline int do_rename(const char * oldname, const char * newname)
struct inode * old_dir, * new_dir;
struct dentry * old_dentry, *new_dentry;
old_dentry = lookup_dentry(oldname, NULL, 1);
old_dentry = lookup_dentry(oldname, NULL, 0);
error = PTR_ERR(old_dentry);
if (IS_ERR(old_dentry))
goto exit;
new_dentry = lookup_dentry(newname, NULL, 1);
new_dentry = lookup_dentry(newname, NULL, 0);
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
......
......@@ -487,22 +487,17 @@ asmlinkage int sys_chmod(const char * filename, mode_t mode)
return error;
}
asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
{
struct inode * inode;
struct dentry * dentry;
struct file * file;
struct iattr newattrs;
int error = -EBADF;
int error;
lock_kernel();
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
goto out;
error = -ENOENT;
if (!(dentry = file->f_dentry))
goto out;
if (!(inode = dentry->d_inode))
if (!(inode = dentry->d_inode)) {
printk("chown_common: NULL inode\n");
goto out;
}
error = -EROFS;
if (IS_RDONLY(inode))
goto out;
......@@ -545,16 +540,33 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
} else
error = notify_change(inode, &newattrs);
out:
unlock_kernel();
return error;
}
asmlinkage int sys_lchown(const char * filename, uid_t user, gid_t group)
{
struct dentry * dentry;
int error;
lock_kernel();
dentry = lnamei(filename);
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto out;
error = chown_common(dentry, user, group);
dput(dentry);
out:
unlock_kernel();
return(error);
}
asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
{
struct dentry * dentry;
struct inode * inode;
int error;
struct iattr newattrs;
lock_kernel();
dentry = namei(filename);
......@@ -562,58 +574,35 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto out;
inode = dentry->d_inode;
error = -EROFS;
if (IS_RDONLY(inode))
goto dput_and_out;
error = chown_common(dentry, user, group);
error = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
goto dput_and_out;
if (user == (uid_t) -1)
user = inode->i_uid;
if (group == (gid_t) -1)
group = inode->i_gid;
newattrs.ia_mode = inode->i_mode;
newattrs.ia_uid = user;
newattrs.ia_gid = group;
newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
/*
* If the owner has been changed, remove the setuid bit
*/
if (inode->i_mode & S_ISUID) {
newattrs.ia_mode &= ~S_ISUID;
newattrs.ia_valid |= ATTR_MODE;
}
/*
* If the group has been changed, remove the setgid bit
*
* Don't remove the setgid bit if no group execute bit.
* This is a file marked for mandatory locking.
*/
if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
newattrs.ia_mode &= ~S_ISGID;
newattrs.ia_valid |= ATTR_MODE;
}
if (inode->i_sb->dq_op) {
inode->i_sb->dq_op->initialize(inode, -1);
error = -EDQUOT;
if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
goto dput_and_out;
error = notify_change(inode, &newattrs);
if (error)
inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
} else
error = notify_change(inode, &newattrs);
dput_and_out:
dput(dentry);
out:
unlock_kernel();
return(error);
}
asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
{
struct dentry * dentry;
struct file * file;
int error = -EBADF;
lock_kernel();
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
goto out;
error = -ENOENT;
if (!(dentry = file->f_dentry))
goto out;
error = chown_common(dentry, user, group);
out:
unlock_kernel();
return error;
}
/*
* Note that while the flag value (low two bits) for sys_open means:
* 00 - read-only
......
......@@ -385,6 +385,8 @@ struct file {
void *private_data;
};
extern int init_private_file(struct file *, struct dentry *, int);
#define FL_POSIX 1
#define FL_FLOCK 2
#define FL_BROKEN 4 /* broken flock() emulation */
......
......@@ -88,8 +88,7 @@ struct minix_dir_entry {
#ifdef __KERNEL__
extern int minix_lookup(struct inode * dir, struct qstr *name,
struct inode ** result);
extern int minix_lookup(struct inode * dir, struct dentry *dentry);
extern int minix_create(struct inode * dir, struct dentry *dentry, int mode);
extern int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode);
extern int minix_rmdir(struct inode * dir, struct dentry *dentry);
......@@ -120,7 +119,6 @@ extern void minix_write_super(struct super_block *);
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 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 *);
......
......@@ -150,6 +150,10 @@ EXPORT_SYMBOL(sys_close);
EXPORT_SYMBOL(close_fp);
EXPORT_SYMBOL(d_alloc_root);
EXPORT_SYMBOL(d_delete);
EXPORT_SYMBOL(d_add);
EXPORT_SYMBOL(d_move);
EXPORT_SYMBOL(d_instantiate);
EXPORT_SYMBOL(__mark_inode_dirty);
EXPORT_SYMBOL(insert_file_free);
EXPORT_SYMBOL(check_disk_change);
EXPORT_SYMBOL(invalidate_buffers);
......
......@@ -6,6 +6,7 @@
* Dynamic registration, added aarp entries. (5/30/97 Chris Horn)
*/
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
......
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