]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.46 2.1.46
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:13:37 +0000 (15:13 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:13:37 +0000 (15:13 -0500)
15 files changed:
Makefile
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/exec.c
fs/ext2/ialloc.c
fs/file_table.c
fs/inode.c
fs/minix/inode.c
fs/minix/namei.c
fs/namei.c
fs/open.c
include/linux/fs.h
include/linux/minix_fs.h
kernel/ksyms.c
net/appletalk/sysctl_net_atalk.c

index f73ec99c4af78473f61f0d44b00aa1ddf5c6131b..4fcf1a91586c14086f5bf916e47e070fec634066 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 45
+SUBLEVEL = 46
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
index ca5c98014ad9262a56c7cd027edbc294c42da3b2..c5c7998cfc49a92c09d606911a33607d48fa1d03 100644 (file)
@@ -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;
index b3f86ff393ab9490129ec9fdc78abbeaad1019b3..1529525186c4853b8209e13d4b7740aafc031b0e 100644 (file)
@@ -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;
index 9a86b41582867b670d52babcb7705e0bc59ee5e1..5b3c3f458c990f55b7a99f2039cecdae2def2201 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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)
index 57984fa41d4d537ac89f8fa33383f482234625c0..d39c8a907b4878acb21c552b39c09a6c8b513370 100644 (file)
@@ -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);
index cbcdd596434e1d4ea304a6d6e1035c0f17336bd3..6413218fff7f1af64b5aca2a840224c0ac60a3f9 100644 (file)
@@ -102,6 +102,24 @@ again:
        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)
index 4a666eaf5ae8053573f90a04bf2163a580b46fdc..8813bbd4571615c3c86642273f7a912ee2d7cd5e 100644 (file)
@@ -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));
index 185fd28f957a6f1b2327c139c6cdec0e9c86cf6c..898f56f199fe1fdd45cf1ebb7e3b5bafec97039b 100644 (file)
 #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,
index f25dbc9f1205eb83c59f826da61e1e4fad25c530..718d3dd070fd452c4966e0e77620e05c0056e549 100644 (file)
@@ -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 @@ start_up:
                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 @@ start_up:
                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);
index 5b1740631b2bea9963626f77c3293b578e62a3de..2ec173f0d3f8dad182dd6bb7158291af5ae71139 100644 (file)
@@ -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))
index 628aa00145d1558155d823d818988202370f4daa..3408fb2a6de87338289996eaf6be493823daa0ec 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -487,22 +487,17 @@ out:
        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
index 27b85d5516a35efc09d791d16af079b4f362b012..b459e966c446eb768f3bdbeb05f28150b151ed8e 100644 (file)
@@ -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 */
index 4a410735c1647d1b8c852b32d2a34af3e507c469..8c75cc3c5feac1beffac2d6c634b83442a6e9e1c 100644 (file)
@@ -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 *);
index 5235f9d39508300dbd27acf2b54f58d936a5a5d9..fff97a75a7472f7170bd302eff08dfdfe8135dd6 100644 (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);
index 10be9e17a55a61a753dbdbabf7d68c22507f5d7e..c2c1a8c64c98149aaf65e635bf9c8c68d2bd079e 100644 (file)
@@ -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>