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

Import 2.1.46

parent 295e4b4b
VERSION = 2 VERSION = 2
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 45 SUBLEVEL = 46
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) 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) ...@@ -127,16 +127,8 @@ do_aout_core_dump(long signr, struct pt_regs * regs)
goto end_coredump; goto end_coredump;
if (get_write_access(inode)) if (get_write_access(inode))
goto end_coredump; goto end_coredump;
file.f_mode = 3; if (init_private_file(&file, dentry, 3))
file.f_flags = 0; goto end_coredump;
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 (!file.f_op->write) if (!file.f_op->write)
goto close_coredump; goto close_coredump;
has_dumped = 1; has_dumped = 1;
......
...@@ -1091,15 +1091,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs) ...@@ -1091,15 +1091,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs)
goto end_coredump; goto end_coredump;
if (!inode->i_op || !inode->i_op->default_file_ops) if (!inode->i_op || !inode->i_op->default_file_ops)
goto end_coredump; goto end_coredump;
file.f_mode = 3; if (init_private_file(&file, dentry, 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; goto end_coredump;
if (!file.f_op->write) if (!file.f_op->write)
goto close_coredump; goto close_coredump;
......
...@@ -352,17 +352,9 @@ int read_exec(struct dentry *dentry, unsigned long offset, ...@@ -352,17 +352,9 @@ int read_exec(struct dentry *dentry, unsigned long offset,
if (!inode->i_op || !inode->i_op->default_file_ops) if (!inode->i_op || !inode->i_op->default_file_ops)
goto end_readexec; goto end_readexec;
file.f_mode = 1; if (init_private_file(&file, dentry, 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; goto end_readexec;
if (!file.f_op || !file.f_op->read) if (!file.f_op->read)
goto close_readexec; goto close_readexec;
if (file.f_op->llseek) { if (file.f_op->llseek) {
if (file.f_op->llseek(inode,&file,offset,0) != offset) if (file.f_op->llseek(inode,&file,offset,0) != offset)
......
...@@ -154,6 +154,22 @@ static int load_inode_bitmap (struct super_block * sb, ...@@ -154,6 +154,22 @@ static int load_inode_bitmap (struct super_block * sb,
return 0; 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) void ext2_free_inode (struct inode * inode)
{ {
int is_directory; int is_directory;
...@@ -207,10 +223,12 @@ void ext2_free_inode (struct inode * inode) ...@@ -207,10 +223,12 @@ void ext2_free_inode (struct inode * inode)
is_directory = S_ISDIR(inode->i_mode); is_directory = S_ISDIR(inode->i_mode);
/* Do this BEFORE marking the inode not in use */
if (sb->dq_op) if (sb->dq_op)
sb->dq_op->free_inode (inode, 1); sb->dq_op->free_inode (inode, 1);
clear_inode (inode); clear_inode (inode);
/* Ok, now we can actually update the inode bitmaps.. */
if (!ext2_clear_bit (bit, bh->b_data)) if (!ext2_clear_bit (bit, bh->b_data))
ext2_warning (sb, "ext2_free_inode", ext2_warning (sb, "ext2_free_inode",
"bit already cleared for inode %lu", ino); "bit already cleared for inode %lu", ino);
......
...@@ -102,6 +102,24 @@ struct file * get_empty_filp(void) ...@@ -102,6 +102,24 @@ struct file * get_empty_filp(void)
return f; 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 #ifdef CONFIG_QUOTA
void add_dquot_ref(kdev_t dev, short type) void add_dquot_ref(kdev_t dev, short type)
......
...@@ -296,7 +296,7 @@ void clean_inode(struct inode *inode) ...@@ -296,7 +296,7 @@ void clean_inode(struct inode *inode)
memset(&inode->u, 0, sizeof(inode->u)); memset(&inode->u, 0, sizeof(inode->u));
inode->i_sock = 0; inode->i_sock = 0;
inode->i_op = NULL; inode->i_op = NULL;
inode->i_nlink = 0; inode->i_nlink = 1;
inode->i_writecount = 0; inode->i_writecount = 0;
inode->i_size = 0; inode->i_size = 0;
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot)); memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
......
...@@ -24,10 +24,8 @@ ...@@ -24,10 +24,8 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/bitops.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; inode->i_size = 0;
minix_truncate(inode); minix_truncate(inode);
minix_free_inode(inode); minix_free_inode(inode);
...@@ -77,9 +75,10 @@ void minix_put_super(struct super_block *sb) ...@@ -77,9 +75,10 @@ void minix_put_super(struct super_block *sb)
static struct super_operations minix_sops = { static struct super_operations minix_sops = {
minix_read_inode, minix_read_inode,
NULL,
minix_write_inode, minix_write_inode,
minix_put_inode, NULL, /* put_inode */
minix_delete_inode,
NULL, /* notify_change */
minix_put_super, minix_put_super,
minix_write_super, minix_write_super,
minix_statfs, minix_statfs,
......
...@@ -47,9 +47,6 @@ static int minix_match(int len, const char * name, ...@@ -47,9 +47,6 @@ static int minix_match(int len, const char * name,
*offset += info->s_dirsize; *offset += info->s_dirsize;
if (!de->inode || len > info->s_namelen) if (!de->inode || len > info->s_namelen)
return 0; 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); return namecompare(len,info->s_namelen,name,de->name);
} }
...@@ -104,24 +101,22 @@ static struct buffer_head * minix_find_entry(struct inode * dir, ...@@ -104,24 +101,22 @@ static struct buffer_head * minix_find_entry(struct inode * dir,
return NULL; return NULL;
} }
int minix_lookup(struct inode * dir, struct qstr *name, int minix_lookup(struct inode * dir, struct dentry *dentry)
struct inode ** result)
{ {
int ino; struct inode * inode = NULL;
struct minix_dir_entry * de; struct minix_dir_entry * de;
struct buffer_head * bh; struct buffer_head * bh;
*result = NULL; bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
if (!dir) if (bh) {
return -ENOENT; unsigned long ino = le32_to_cpu(de->inode);
if (!S_ISDIR(dir->i_mode)) brelse (bh);
return -ENOENT; inode = iget(dir->i_sb, ino);
if (!(bh = minix_find_entry(dir, name->name, name->len, &de)))
return -ENOENT; if (!inode)
ino = de->inode;
brelse(bh);
if (!(*result = iget(dir->i_sb,ino)))
return -EACCES; return -EACCES;
}
d_add(dentry, inode);
return 0; return 0;
} }
...@@ -602,29 +597,21 @@ int minix_link(struct inode * inode, struct inode * dir, ...@@ -602,29 +597,21 @@ int minix_link(struct inode * inode, struct inode * dir,
return 0; 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 = 0;
int result;
new_inode->i_count++;
result = 0;
for (;;) { for (;;) {
if (new_inode == old_inode) { if (new_dentry != old_dentry) {
result = 1; struct dentry * parent = new_dentry->d_parent;
if (parent == new_dentry)
break; break;
new_dentry = parent;
continue;
} }
if (new_inode->i_dev != old_inode->i_dev) result = 1;
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; break;
} }
iput(new_inode);
return result; return result;
} }
...@@ -690,7 +677,7 @@ static int do_minix_rename(struct inode * old_dir, struct dentry *old_dentry, ...@@ -690,7 +677,7 @@ static int do_minix_rename(struct inode * old_dir, struct dentry *old_dentry,
if (!S_ISDIR(old_inode->i_mode)) if (!S_ISDIR(old_inode->i_mode))
goto end_rename; goto end_rename;
retval = -EINVAL; retval = -EINVAL;
if (subdir(new_dir, old_inode)) if (subdir(new_dentry, old_dentry))
goto end_rename; goto end_rename;
retval = -ENOTEMPTY; retval = -ENOTEMPTY;
if (!empty_dir(new_inode)) if (!empty_dir(new_inode))
...@@ -709,7 +696,7 @@ static int do_minix_rename(struct inode * old_dir, struct dentry *old_dentry, ...@@ -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)) if (new_inode && !S_ISDIR(new_inode->i_mode))
goto end_rename; goto end_rename;
retval = -EINVAL; retval = -EINVAL;
if (subdir(new_dir, old_inode)) if (subdir(new_dentry, old_dentry))
goto end_rename; goto end_rename;
retval = -EIO; retval = -EIO;
dir_bh = minix_bread(old_inode,0,0); dir_bh = minix_bread(old_inode,0,0);
......
...@@ -379,7 +379,7 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo ...@@ -379,7 +379,7 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
} }
if (!*name) if (!*name)
return base; goto return_base;
/* At this point we know we have a real path component. */ /* At this point we know we have a real path component. */
for(;;) { for(;;) {
...@@ -388,9 +388,6 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo ...@@ -388,9 +388,6 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
struct qstr this; struct qstr this;
char c, follow; char c, follow;
dentry = base;
if (IS_ERR(base))
break;
dentry = ERR_PTR(-ENOENT); dentry = ERR_PTR(-ENOENT);
if (!base->d_inode) if (!base->d_inode)
break; break;
...@@ -424,9 +421,10 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo ...@@ -424,9 +421,10 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
break; break;
base = do_follow_link(base, dentry); base = do_follow_link(base, dentry);
if (c) if (c && !IS_ERR(base))
continue; continue;
return_base:
return base; return base;
} }
dput(base); dput(base);
...@@ -744,7 +742,7 @@ static inline int do_rmdir(const char * name) ...@@ -744,7 +742,7 @@ static inline int do_rmdir(const char * name)
struct inode *dir; struct inode *dir;
struct dentry *dentry; struct dentry *dentry;
dentry = lookup_dentry(name, NULL, 1); dentry = lookup_dentry(name, NULL, 0);
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto exit; goto exit;
...@@ -1053,13 +1051,13 @@ static inline int do_rename(const char * oldname, const char * newname) ...@@ -1053,13 +1051,13 @@ static inline int do_rename(const char * oldname, const char * newname)
struct inode * old_dir, * new_dir; struct inode * old_dir, * new_dir;
struct dentry * old_dentry, *new_dentry; 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); error = PTR_ERR(old_dentry);
if (IS_ERR(old_dentry)) if (IS_ERR(old_dentry))
goto exit; goto exit;
new_dentry = lookup_dentry(newname, NULL, 1); new_dentry = lookup_dentry(newname, NULL, 0);
error = PTR_ERR(new_dentry); error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry)) if (IS_ERR(new_dentry))
......
...@@ -487,22 +487,17 @@ asmlinkage int sys_chmod(const char * filename, mode_t mode) ...@@ -487,22 +487,17 @@ asmlinkage int sys_chmod(const char * filename, mode_t mode)
return error; 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 inode * inode;
struct dentry * dentry;
struct file * file;
struct iattr newattrs; struct iattr newattrs;
int error = -EBADF; int error;
lock_kernel();
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
goto out;
error = -ENOENT; error = -ENOENT;
if (!(dentry = file->f_dentry)) if (!(inode = dentry->d_inode)) {
goto out; printk("chown_common: NULL inode\n");
if (!(inode = dentry->d_inode))
goto out; goto out;
}
error = -EROFS; error = -EROFS;
if (IS_RDONLY(inode)) if (IS_RDONLY(inode))
goto out; goto out;
...@@ -545,16 +540,33 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group) ...@@ -545,16 +540,33 @@ asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
} else } else
error = notify_change(inode, &newattrs); error = notify_change(inode, &newattrs);
out: out:
unlock_kernel();
return error; 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) asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
{ {
struct dentry * dentry; struct dentry * dentry;
struct inode * inode;
int error; int error;
struct iattr newattrs;
lock_kernel(); lock_kernel();
dentry = namei(filename); dentry = namei(filename);
...@@ -562,58 +574,35 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group) ...@@ -562,58 +574,35 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto out; goto out;
inode = dentry->d_inode;
error = -EROFS; error = chown_common(dentry, user, group);
if (IS_RDONLY(inode))
goto dput_and_out;
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); dput(dentry);
out: out:
unlock_kernel(); unlock_kernel();
return(error); 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: * Note that while the flag value (low two bits) for sys_open means:
* 00 - read-only * 00 - read-only
......
...@@ -385,6 +385,8 @@ struct file { ...@@ -385,6 +385,8 @@ struct file {
void *private_data; void *private_data;
}; };
extern int init_private_file(struct file *, struct dentry *, int);
#define FL_POSIX 1 #define FL_POSIX 1
#define FL_FLOCK 2 #define FL_FLOCK 2
#define FL_BROKEN 4 /* broken flock() emulation */ #define FL_BROKEN 4 /* broken flock() emulation */
......
...@@ -88,8 +88,7 @@ struct minix_dir_entry { ...@@ -88,8 +88,7 @@ struct minix_dir_entry {
#ifdef __KERNEL__ #ifdef __KERNEL__
extern int minix_lookup(struct inode * dir, struct qstr *name, extern int minix_lookup(struct inode * dir, struct dentry *dentry);
struct inode ** result);
extern int minix_create(struct inode * dir, struct dentry *dentry, int mode); 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_mkdir(struct inode * dir, struct dentry *dentry, int mode);
extern int minix_rmdir(struct inode * dir, struct dentry *dentry); extern int minix_rmdir(struct inode * dir, struct dentry *dentry);
...@@ -120,7 +119,6 @@ extern void minix_write_super(struct super_block *); ...@@ -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 int minix_remount (struct super_block * sb, int * flags, char * data);
extern void minix_read_inode(struct inode *); extern void minix_read_inode(struct inode *);
extern void minix_write_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_statfs(struct super_block *, struct statfs *, int);
extern int minix_sync_inode(struct inode *); extern int minix_sync_inode(struct inode *);
extern int minix_sync_file(struct inode *, struct file *); extern int minix_sync_file(struct inode *, struct file *);
......
...@@ -150,6 +150,10 @@ EXPORT_SYMBOL(sys_close); ...@@ -150,6 +150,10 @@ EXPORT_SYMBOL(sys_close);
EXPORT_SYMBOL(close_fp); EXPORT_SYMBOL(close_fp);
EXPORT_SYMBOL(d_alloc_root); EXPORT_SYMBOL(d_alloc_root);
EXPORT_SYMBOL(d_delete); 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(insert_file_free);
EXPORT_SYMBOL(check_disk_change); EXPORT_SYMBOL(check_disk_change);
EXPORT_SYMBOL(invalidate_buffers); EXPORT_SYMBOL(invalidate_buffers);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Dynamic registration, added aarp entries. (5/30/97 Chris Horn) * Dynamic registration, added aarp entries. (5/30/97 Chris Horn)
*/ */
#include <linux/config.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sysctl.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