]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.45pre6 2.1.45pre6
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:13:31 +0000 (15:13 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:13:31 +0000 (15:13 -0500)
18 files changed:
arch/alpha/mm/fault.c
arch/i386/kernel/process.c
arch/i386/mm/fault.c
drivers/block/loop.c
drivers/block/rd.c
drivers/scsi/sg.c
drivers/sound/soundcard.c
fs/autofs/inode.c
fs/autofs/waitq.c
fs/binfmt_elf.c
fs/binfmt_java.c
fs/binfmt_misc.c
fs/dcache.c
fs/devices.c
fs/inode.c
fs/namei.c
fs/pipe.c
fs/super.c

index 891dc5ff8905d37e8e07c458736a341f2a7d9bb7..72d4224f7ec1df789323af4224bc36c12bf3bea8 100644 (file)
@@ -67,8 +67,7 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
                              long cause, struct pt_regs *regs)
 {
        struct vm_area_struct * vma;
-       struct task_struct *tsk = current;
-       struct mm_struct *mm = tsk->mm;
+       struct mm_struct *mm = current->mm;
        unsigned fixup;
 
        down(&mm->mmap_sem);
@@ -97,7 +96,7 @@ good_area:
                if (!(vma->vm_flags & VM_WRITE))
                        goto bad_area;
        }
-       handle_mm_fault(tsk, vma, address, cause > 0);
+       handle_mm_fault(current, vma, address, cause > 0);
        up(&mm->mmap_sem);
        return;
 
@@ -109,7 +108,7 @@ bad_area:
        up(&mm->mmap_sem);
 
        if (user_mode(regs)) {
-               force_sig(SIGSEGV, tsk);
+               force_sig(SIGSEGV, current);
                return;
        }
 
@@ -117,7 +116,7 @@ bad_area:
        if ((fixup = search_exception_table(regs->pc)) != 0) {
                unsigned long newpc;
                newpc = fixup_exception(dpf_reg, fixup, regs->pc);
-               printk("Taking exception at [<%lx>] (%lx)\n", regs->pc, newpc);
+               printk("%s: Exception at [<%lx>] (%lx)\n", current->comm, regs->pc, newpc);
                regs->pc = newpc;
                return;
        }
index eec1ba62ee0d7f6b04a286a4ebfc50c4bd61831c..a8fe0315bd359640b2da203bdb2ed5843d05beab 100644 (file)
@@ -625,7 +625,7 @@ asmlinkage int sys_execve(struct pt_regs regs)
        lock_kernel();
        filename = getname((char *) regs.ebx);
        error = PTR_ERR(filename);
-       if (IS_ERR(filename)
+       if (IS_ERR(filename))
                goto out;
        error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
        putname(filename);
index d0b2d58fed0caf7302d550f260e2f298ebe3e72b..e4847c0701b4d06e91abc464d9d88737ed91a857 100644 (file)
@@ -173,7 +173,7 @@ bad_area:
        /* Are we prepared to handle this kernel fault?  */
        if ((fixup = search_exception_table(regs->eip)) != 0) {
                printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n",
-                       current->comm,
+                       tsk->comm,
                        regs->eip,
                        fixup);
                regs->eip = fixup;
index 53fef9b744f2fe5d852f25f0ecca75dbf1a06c2f..025dc0df4331d156412b91a6b89131980f88fc3b 100644 (file)
@@ -292,7 +292,7 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg)
                return -EBADF;
        if (lo->lo_inode)
                return -EBUSY;
-       inode = file->f_inode;
+       inode = file->f_dentry->d_inode;
        if (!inode) {
                printk("loop_set_fd: NULL inode?!?\n");
                return -EINVAL;
index fea666f7cfb332ba51fb5ded1e12092d338070e7..7d7a3931ca8b85c0583fda20c98e25335cdf7df6 100644 (file)
@@ -444,8 +444,9 @@ done:
  */
 __initfunc(static void rd_load_image(kdev_t device,int offset))
 {
-       struct inode inode, out_inode;
+       struct inode inode, out_inode;
        struct file infile, outfile;
+       struct dentry in_dentry, out_dentry;
        unsigned short fs;
        kdev_t ram_device;
        int nblocks, i;
@@ -457,15 +458,19 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
 
        memset(&infile, 0, sizeof(infile));
        memset(&inode, 0, sizeof(inode));
+       memset(&in_dentry, 0, sizeof(in_dentry));
        inode.i_rdev = device;
        infile.f_mode = 1; /* read only */
-       infile.f_inode = &inode;
+       infile.f_dentry = &in_dentry;
+       in_dentry.d_inode = &inode;
 
        memset(&outfile, 0, sizeof(outfile));
        memset(&out_inode, 0, sizeof(out_inode));
+       memset(&out_dentry, 0, sizeof(out_dentry));
        out_inode.i_rdev = ram_device;
        outfile.f_mode = 3; /* read/write */
-       outfile.f_inode = &out_inode;
+       outfile.f_dentry = &out_dentry;
+       out_dentry.d_inode = &out_inode;
 
        if (blkdev_open(&inode, &infile) != 0) return;
        if (blkdev_open(&out_inode, &outfile) != 0) return;
@@ -506,9 +511,9 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
 
        printk(KERN_NOTICE "RAMDISK: Loading %d blocks into ram disk... ", nblocks);
        for (i=0; i < nblocks; i++) {
-               infile.f_op->read(infile.f_inode, &infile, buf,
+               infile.f_op->read(infile.f_dentry->d_inode, &infile, buf,
                                  BLOCK_SIZE);
-               outfile.f_op->write(outfile.f_inode, &outfile, buf,
+               outfile.f_op->write(outfile.f_dentry->d_inode, &outfile, buf,
                                    BLOCK_SIZE);
                if (!(i % 16)) {
                        printk("%c\b", rotator[rotate & 0x3]);
@@ -637,7 +642,7 @@ __initfunc(static int fill_inbuf(void))
 {
        if (exit_code) return -1;
        
-       insize = crd_infp->f_op->read(crd_infp->f_inode, crd_infp,
+       insize = crd_infp->f_op->read(crd_infp->f_dentry->d_inode, crd_infp,
                                      inbuf, INBUFSIZ);
        if (insize == 0) return -1;
 
@@ -656,7 +661,7 @@ __initfunc(static void flush_window(void))
     unsigned n;
     uch *in, ch;
     
-    crd_outfp->f_op->write(crd_outfp->f_inode, crd_outfp, window,
+    crd_outfp->f_op->write(crd_outfp->f_dentry->d_inode, crd_outfp, window,
                           outcnt);
     in = window;
     for (n = 0; n < outcnt; n++) {
index eb9e7fec33ff48e4a5f79cb77a4b9dcb449f19c6..d83b94e26aa30d0ea9960cd5999258e4e724fe4c 100644 (file)
@@ -488,7 +488,7 @@ static long sg_write(struct inode *inode,struct file *filp,const char *buf,unsig
 
 static unsigned int sg_poll(struct file *file, poll_table * wait)
 {
-        int dev = MINOR(file->f_inode->i_rdev);
+        int dev = MINOR(file->f_dentry->d_inode->i_rdev);
         struct scsi_generic *device = &scsi_generics[dev];
         unsigned int mask = 0;
 
index 957150f7bb8476c487e147bd9e29347721cf51ab..a9af5956bdbef2d635adc967b1989427c7e5e4a5 100644 (file)
@@ -246,7 +246,7 @@ sound_poll (struct file *file, poll_table * wait)
   struct inode   *inode;
   int             ret = 0;
 
-  inode = file->f_inode;
+  inode = file->f_dentry->d_inode;
 
   if (sound_select (inode, file, SEL_IN, wait))
     ret |= POLLIN;
@@ -326,8 +326,7 @@ sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
                        vma->vm_page_prot))
     return -EAGAIN;
 
-  vma->vm_inode = inode;
-  atomic_inc(&inode->i_count);
+  vma->vm_dentry = dget(file->f_dentry);
 
   dmap->mapping_flags |= DMA_MAP_MAPPED;
 
index f7c8977c5e236ce6f58c01f28fa6774f49cf2597..58997a0610bdc17c057bd00986d6359167917379 100644 (file)
@@ -194,7 +194,7 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
        sbi->pipe = fget(pipefd);
        if ( !sbi->pipe || !sbi->pipe->f_op || !sbi->pipe->f_op->write ) {
                if ( sbi->pipe ) {
-                       fput(sbi->pipe, sbi->pipe->f_inode);
+                       fput(sbi->pipe);
                        printk("autofs: pipe file descriptor does not contain proper ops\n");
                } else {
                        printk("autofs: could not open pipe file descriptor\n");
index ec222d61cd2a04617c8150d9b617a2a3db2b7ebe..39beed699f5993217bed1d59f96fcb9d9044a50e 100644 (file)
@@ -37,7 +37,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
                wake_up(&wq->queue);
                wq = nwq;
        }
-       fput(sbi->pipe, sbi->pipe->f_inode);    /* Close the pipe */
+       fput(sbi->pipe);        /* Close the pipe */
 }
 
 static int autofs_write(struct file *file, const void *addr, int bytes)
@@ -55,7 +55,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes)
 
        old_signal = current->signal;
 
-       while ( bytes && (written = file->f_op->write(file->f_inode,file,data,bytes)) > 0 ) {
+       while ( bytes && (written = file->f_op->write(file->f_dentry->d_inode,file,data,bytes)) > 0 ) {
                data += written;
                bytes -= written;
        }
index e85c286f32b7c2a3840e75890267ae55753a4fd7..b3f86ff393ab9490129ec9fdc78abbeaad1019b3 100644 (file)
@@ -678,8 +678,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                __MOD_INC_USE_COUNT(current->binfmt->module);
 
 #ifndef VM_STACK_FLAGS
-       current->executable = bprm->dentry;
-       atomic_inc(&bprm->dentry->i_count);
+       current->executable = dget(bprm->dentry);
 #endif
 #ifdef LOW_ELF_STACK
        current->start_stack = bprm->p = elf_stack - 4;
index 4f995b0d12d72f72b561bb353a993cefcf12b3d9..41e66a21a28576b4b1da713a68bb23985b93d91a 100644 (file)
@@ -28,7 +28,9 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
        char *i_name;
        int len;
        int retval;
+       struct dentry * dentry;
        unsigned char *ucp = (unsigned char *) bprm->buf;
+
        if ((ucp[0] != 0xca) || (ucp[1] != 0xfe) || (ucp[2] != 0xba) || (ucp[3] != 0xbe)) 
                return -ENOEXEC;
 
@@ -42,8 +44,8 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
 
        bprm->java = 1;
 
-       iput(bprm->inode);
-       bprm->dont_iput=1;
+       dput(bprm->dentry);
+       bprm->dentry = NULL;
 
        /*
         * Set args: [0] the name of the java interpreter
@@ -75,15 +77,17 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
        if (!bprm->p) 
                return -E2BIG;
        /*
-        * OK, now restart the process with the interpreter's inode.
+        * OK, now restart the process with the interpreter's dentry.
         */
        bprm->filename = binfmt_java_interpreter;
-       retval = open_namei(binfmt_java_interpreter, 0, 0, &bprm->inode);
-       if (retval)
+       dentry = open_namei(binfmt_java_interpreter, 0, 0);
+       retval = PTR_ERR(dentry);
+       if (IS_ERR(dentry))
                return retval;
-       bprm->dont_iput=0;
-       retval=prepare_binprm(bprm);
-       if(retval<0)
+
+       bprm->dentry = dentry;
+       retval = prepare_binprm(bprm);
+       if (retval < 0)
                return retval;
 
        return search_binary_handler(bprm,regs);
@@ -92,12 +96,14 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs)
 static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs)
 {
        char *i_name;
+       struct dentry * dentry;
        int retval;
+
        if (strncmp (bprm->buf, "<!--applet", 10))
                return -ENOEXEC;
 
-       iput(bprm->inode);
-       bprm->dont_iput=1;
+       dput(bprm->dentry);
+       bprm->dentry = NULL;
 
        /*
         * Set args: [0] the name of the appletviewer
@@ -118,15 +124,17 @@ static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs)
        if (!bprm->p) 
                return -E2BIG;
        /*
-        * OK, now restart the process with the interpreter's inode.
+        * OK, now restart the process with the interpreter's dentry.
         */
        bprm->filename = binfmt_java_appletviewer;
-       retval = open_namei(binfmt_java_appletviewer, 0, 0, &bprm->inode);
-       if (retval)
+       dentry = open_namei(binfmt_java_appletviewer, 0, 0);
+       retval = PTR_ERR(dentry);
+       if (IS_ERR(dentry))
                return retval;
-       bprm->dont_iput=0;
-       retval=prepare_binprm(bprm);
-       if(retval<0)
+
+       bprm->dentry = dentry;
+       retval = prepare_binprm(bprm);
+       if (retval < 0)
                return retval;
 
        return search_binary_handler(bprm,regs);
index 27499e1f1d58f22dbae0a960b02b1ede5f8a490a..72ebd42de0c37a41c83a04aa48524795c1ec1a9e 100644 (file)
@@ -157,6 +157,7 @@ static struct binfmt_entry *check_file(struct linux_binprm *bprm)
 static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 {
        struct binfmt_entry *fmt;
+       struct dentry * dentry;
        char iname[128];
        char *iname_addr = iname, *p;
        int retval, fmt_flags = 0;
@@ -179,8 +180,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                goto _ret;
        }
 
-       iput(bprm->inode);
-       bprm->dont_iput = 1;
+       dput(bprm->dentry);
+       bprm->dentry = NULL;
 
        /* Build args for interpreter */
        if ((fmt_flags & ENTRY_STRIP_EXT) &&
@@ -197,11 +198,14 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        }
        bprm->filename = iname; /* for binfmt_script */
 
-       if ((retval = open_namei(iname, 0, 0, &bprm->inode)))
+       dentry = open_namei(iname, 0, 0);
+       retval = PTR_ERR(dentry);
+       if (IS_ERR(dentry))
                goto _ret;
-       bprm->dont_iput = 0;
+       bprm->dentry = dentry;
 
-       if ((retval = prepare_binprm(bprm)) >= 0)
+       retval = prepare_binprm(bprm);
+       if (retval >= 0)
                retval = search_binary_handler(bprm, regs);
 _ret:
        return retval;
index 13f33871f3aaa2b9fdf4768abda355b59812229e..a141eefe8048f01a7636cd3b34a8f5d4faed238f 100644 (file)
@@ -186,7 +186,7 @@ struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root)
        if (root_inode) {
                res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 });
                res->d_parent = res;
-               res->d_count = 2;
+               res->d_count = 1;
                d_instantiate(res, root_inode);
        }
        return res;
index d3b1d68460ff94d21721c1f5e1dab13728190bfb..26f668e7fade0a807bd9a6478ed03203c29305fc 100644 (file)
@@ -209,9 +209,7 @@ int check_disk_change(kdev_t dev)
 
        printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
                kdevname(dev));
-       for (i=0 ; i<NR_SUPER ; i++)
-               if (super_blocks[i].s_dev == dev)
-                       put_super(super_blocks[i].s_dev);
+
        invalidate_inodes(dev);
        invalidate_buffers(dev);
 
index 109099ffbc0bad7224d9272960a88dcff7463916..6602de949e92e711ef56bae67b718d90a3514141 100644 (file)
@@ -509,7 +509,8 @@ int fs_may_mount(kdev_t dev)
 
 int fs_may_umount(kdev_t dev, struct dentry * root)
 {
-       return 0;
+       shrink_dcache();
+       return root->d_count == 1;
 }
 
 int fs_may_remount_ro(kdev_t dev)
index c53dd99667adaceaa4cd108d127bd015c73b376b..173a399bcee5c8214100ba28d6c6878cfc153ca8 100644 (file)
@@ -275,7 +275,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
 }
 
 /* Internal lookup() using the new generic dcache. */
-static inline struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
 {
        struct dentry * dentry = d_lookup(parent, name);
 
@@ -318,33 +318,16 @@ static struct dentry * reserved_lookup(struct dentry * parent, struct qstr * nam
                        if (name->name[1] != '.')
                                break;
 
-                       if (parent != current->fs->root) {
+                       if (parent != current->fs->root)
                                parent = parent->d_covers->d_parent;
-                       }
                        /* fallthrough */
                case 1:
-                       result = dget(parent);
-                       break;
+                       result = parent;
                }
        }
        return result;
 }
 
-static inline int is_reserved(struct dentry *dentry)
-{
-       if (dentry->d_name.name[0] == '.') {
-               switch (dentry->d_name.len) {
-               case 2:
-                       if (dentry->d_name.name[1] != '.')
-                               break;
-                       /* fallthrough */
-               case 1:
-                       return 1;
-               }
-       }
-       return 0;
-}
-
 /* In difference to the former version, lookup() no longer eats the dir. */
 static struct dentry * lookup(struct dentry * dir, struct qstr * name)
 {
@@ -355,23 +338,23 @@ static struct dentry * lookup(struct dentry * dir, struct qstr * name)
        err = permission(dir->d_inode, MAY_EXEC);
        result = ERR_PTR(err);
        if (err)
-               goto done;
+               goto done_error;
 
        result = reserved_lookup(dir, name);
        if (result)
-               goto done;
+               goto done_noerror;
 
        result = cached_lookup(dir, name);
        if (result)
-               goto done;
+               goto done_noerror;
 
        result = real_lookup(dir, name);
-       if (!result)
-               result = ERR_PTR(-ENOTDIR);
-done:
-       if (!IS_ERR(result))
-               result = dget(result->d_mounts);
 
+       if (!IS_ERR(result)) {
+done_noerror:
+               result = dget(result->d_mounts);
+       }
+done_error:
        return result;
 }
 
@@ -382,7 +365,7 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry
 {
        struct inode * inode = dentry->d_inode;
 
-       if (inode->i_op && inode->i_op->follow_link) {
+       if (inode && inode->i_op && inode->i_op->follow_link) {
                struct dentry *result;
 
                /* This eats the base */
@@ -415,7 +398,7 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
                base = dget(current->fs->pwd);
        }
 
-       if (*name == '\0')
+       if (!*name)
                return base;
 
        /* At this point we know we have a real path component. */
@@ -423,37 +406,45 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, int follo
                int len;
                unsigned long hash;
                struct qstr this;
-               char c, trailing;
+               char c, follow;
 
+               dentry = ERR_PTR(-ENOENT);
+               if (!base->d_inode)
+                       break;
                this.name = name;
                hash = init_name_hash();
-               for (len = 0; (c = *name++) && (c != '/') ; len++)
+               len = 0;
+               c = *name;
+               do {
+                       len++; name++;
                        hash = partial_name_hash(c, hash);
+                       c = *name;
+               } while (c && (c != '/'));
 
                this.len = len;
                this.hash = end_name_hash(hash);
 
                /* remove trailing slashes? */
-               trailing = c;
+               follow = follow_link;
                if (c) {
-                       while ((c = *name) == '/')
-                               name++;
+                       follow |= c;
+                       do {
+                               c = *++name;
+                       } while (c == '/');
                }
 
                dentry = lookup(base, &this);
                if (IS_ERR(dentry))
                        break;
-               if (!dentry->d_inode)
-                       break;
 
-               /* Last component? */
-               if (!c) {
-                       if (!trailing && !follow_link)
-                               break;
-                       return do_follow_link(base, dentry);
-               }
+               if (!follow)
+                       break;
 
                base = do_follow_link(base, dentry);
+               if (c)
+                       continue;
+
+               return base;
        }
        dput(base);
        return dentry;
@@ -491,17 +482,13 @@ struct dentry * __namei(const char *pathname, int follow_link)
 
 static inline struct inode *get_parent(struct dentry *dentry)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
-
-       atomic_inc(&dir->i_count);
-       return dir;
+       return dentry->d_parent->d_inode;
 }
 
 static inline struct inode *lock_parent(struct dentry *dentry)
 {
        struct inode *dir = dentry->d_parent->d_inode;
 
-       atomic_inc(&dir->i_count);
        down(&dir->i_sem);
        return dir;
 }
@@ -557,7 +544,6 @@ struct dentry * open_namei(const char * pathname, int flag, int mode)
                        acc_mode = 0;
                }
                up(&dir->i_sem);
-               iput(dir);
                if (error)
                        goto exit;
        }
@@ -669,7 +655,6 @@ struct dentry * do_mknod(const char * filename, int mode, dev_t dev)
 
 exit_lock:
        up(&dir->i_sem);
-       iput(dir);
        dput(dentry);
        return retval;
 }
@@ -749,7 +734,6 @@ static inline int do_mkdir(const char * pathname, int mode)
 
 exit_lock:
        up(&dir->i_sem);
-       iput(dir);
        dput(dentry);
 exit:
        return error;
@@ -818,7 +802,6 @@ static inline int do_rmdir(const char * name)
 
 exit_lock:
         up(&dir->i_sem);
-        iput(dir);
        dput(dentry);
 exit:
        return error;
@@ -879,7 +862,6 @@ static inline int do_unlink(const char * name)
 
 exit_lock:
         up(&dir->i_sem);
-        iput(dir);
        dput(dentry);
 exit:
        return error;
@@ -937,7 +919,6 @@ static inline int do_symlink(const char * oldname, const char * newname)
 
 exit_lock:
        up(&dir->i_sem);
-       iput(dir);
        dput(dentry);
 exit:
        return error;
@@ -1021,7 +1002,6 @@ static inline int do_link(const char * oldname, const char * newname)
 
 exit_lock:
        up(&dir->i_sem);
-       iput(dir);
        dput(new_dentry);
 exit_old:
        dput(old_dentry);
@@ -1069,6 +1049,21 @@ static inline void double_down(struct semaphore *s1, struct semaphore *s2)
        }
 }
 
+static inline int is_reserved(struct dentry *dentry)
+{
+       if (dentry->d_name.name[0] == '.') {
+               switch (dentry->d_name.len) {
+               case 2:
+                       if (dentry->d_name.name[1] != '.')
+                               break;
+                       /* fallthrough */
+               case 1:
+                       return 1;
+               }
+       }
+       return 0;
+}
+
 static inline int do_rename(const char * oldname, const char * newname)
 {
        int error;
@@ -1138,8 +1133,6 @@ static inline int do_rename(const char * oldname, const char * newname)
 exit_lock:
        up(&new_dir->i_sem);
        up(&old_dir->i_sem);
-       iput(old_dir);
-       iput(new_dir);
        dput(new_dentry);
 exit_old:
        dput(old_dentry);
index 7361d619d7640cd87b2744bbd20d17033bdfb762..61223f4eb62fc51a093e5e96223d84a6dedfeaa1 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -419,7 +419,7 @@ int do_pipe(int *fd)
                goto close_f12_inode_i;
        j = error;
 
-       f1->f_dentry = f2->f_dentry = d_alloc_root(inode, NULL);
+       f1->f_dentry = f2->f_dentry = dget(d_alloc_root(inode, NULL));
 
        /* read file */
        f1->f_pos = f2->f_pos = 0;
index 933b36bb92a22c54f414195dd7a7be5e14050d7f..718b6f9059b69cf5226254430026da4fd2de6de4 100644 (file)
@@ -455,26 +455,6 @@ struct super_block * get_super(kdev_t dev)
        return NULL;
 }
 
-void put_super(kdev_t dev)
-{
-       struct super_block * sb;
-
-       if (dev == ROOT_DEV) {
-               printk("VFS: Root device %s: prepare for armageddon\n",
-                      kdevname(dev));
-               return;
-       }
-       if (!(sb = get_super(dev)))
-               return;
-       if (sb->s_root != sb->s_root->d_mounts) {
-               printk("VFS: Mounted device %s - tssk, tssk\n",
-                      kdevname(dev));
-               return;
-       }
-       if (sb->s_op && sb->s_op->put_super)
-               sb->s_op->put_super(sb);
-}
-
 asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf)
 {
         struct super_block *s;
@@ -574,14 +554,12 @@ static void d_umount(struct dentry *dentry)
 {
        struct dentry * covers = dentry->d_covers;
 
-       if (covers == dentry) {
-               printk("VFS: unmount - covers == dentry?\n");
-               return;
+       if (covers != dentry) {
+               covers->d_mounts = covers;
+               dentry->d_covers = dentry;
+               dput(covers);
+               dput(dentry);
        }
-       covers->d_mounts = covers;
-       dentry->d_covers = dentry;
-       dput(covers);
-       dput(dentry);
 }
 
 static void d_mount(struct dentry *covers, struct dentry *dentry)
@@ -590,8 +568,8 @@ static void d_mount(struct dentry *covers, struct dentry *dentry)
                printk("VFS: mount - already mounted\n");
                return;
        }
-       covers->d_mounts = dget(dentry);
-       dentry->d_covers = dget(covers);
+       covers->d_mounts = dentry;
+       dentry->d_covers = covers;
 }
 
 static int do_umount(kdev_t dev,int unmount_root)
@@ -599,13 +577,18 @@ static int do_umount(kdev_t dev,int unmount_root)
        struct super_block * sb;
        int retval;
        
+       sb = get_super(dev);
+       if (!sb)
+               return -ENOENT;
+
+       if (!sb->s_root)
+               return -ENOENT;
+
        if (dev==ROOT_DEV && !unmount_root) {
                /*
                 * Special case for "unmounting" root. We just try to remount
                 * it readonly, and sync() the device.
                 */
-               if (!(sb=get_super(dev)))
-                       return -ENOENT;
                if (!(sb->s_flags & MS_RDONLY)) {
                        /*
                         * Make sure all quotas are turned off on this device we need to mount
@@ -621,9 +604,6 @@ static int do_umount(kdev_t dev,int unmount_root)
                }
                return 0;
        }
-       sb=get_super(dev);
-       if (!sb)
-               return -ENOENT;
 
        /*
         * Before checking if the filesystem is still busy make sure the kernel
@@ -634,20 +614,41 @@ static int do_umount(kdev_t dev,int unmount_root)
        if (!fs_may_umount(dev, sb->s_root))
                return -EBUSY;
 
-       /* Clear up the dcache tree. This should be cleaner.. */
-       if (sb->s_root) {
-               d_umount(sb->s_root);
-               d_delete(sb->s_root);
-       }
-
+       /* clean up dcache .. */
+       d_umount(sb->s_root);
        sb->s_root = NULL;
-       if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
-               sb->s_op->write_super(sb);
-       put_super(dev);
+
+       if (sb->s_op) {
+               if (sb->s_op->write_super && sb->s_dirt)
+                       sb->s_op->write_super(sb);
+               if (sb->s_op->put_super)
+                       sb->s_op->put_super(sb);
+       }
        remove_vfsmnt(dev);
        return 0;
 }
 
+static int umount_dev(kdev_t dev)
+{
+       int retval;
+       struct inode * inode = get_empty_inode();
+
+       inode->i_rdev = dev;
+       if (MAJOR(dev) >= MAX_BLKDEV)
+               return -ENXIO;
+
+       retval = do_umount(dev,0);
+       if (!retval) {
+               fsync_dev(dev);
+               if (dev != ROOT_DEV) {
+                       blkdev_release(inode);
+                       put_unnamed_dev(dev);
+               }
+       }
+       iput(inode);
+       return retval;
+}
+
 /*
  * Now umount can handle mount points as well as block devices.
  * This is important for filesystems which use unnamed block devices.
@@ -662,9 +663,6 @@ static int do_umount(kdev_t dev,int unmount_root)
 asmlinkage int sys_umount(char * name)
 {
        struct dentry * dentry;
-       struct inode * inode;
-       kdev_t dev;
-       struct inode * dummy_inode = NULL;
        int retval;
 
        if (!suser())
@@ -673,45 +671,27 @@ asmlinkage int sys_umount(char * name)
        lock_kernel();
        dentry = namei(name);
        retval = PTR_ERR(dentry);
-       if (IS_ERR(dentry))
-               goto out;
-
-       inode = dentry->d_inode;
-       if (S_ISBLK(inode->i_mode)) {
-               dev = inode->i_rdev;
-               retval = -EACCES;
-               if (IS_NODEV(inode)) {
-                       dput(dentry);
-                       goto out;
-               }
-       } else {
-               retval = -EINVAL;
-               if (!inode->i_sb || inode != inode->i_sb->s_root->d_inode) {
-                       dput(dentry);
-                       goto out;
+       if (!IS_ERR(dentry)) {
+               struct inode * inode = dentry->d_inode;
+               kdev_t dev = inode->i_rdev;
+
+               retval = 0;             
+               if (S_ISBLK(inode->i_mode)) {
+                       if (IS_NODEV(inode))
+                               retval = -EACCES;
+               } else {
+                       struct super_block *sb = inode->i_sb;
+                       retval = -EINVAL;
+                       if (sb && inode == sb->s_root->d_inode) {
+                               dev = sb->s_dev;
+                               retval = 0;
+                       }
                }
-               dev = inode->i_sb->s_dev;
-               dput(dentry);
-               inode = dummy_inode = get_empty_inode();
-               inode->i_rdev = dev;
-       }
-       retval = -ENXIO;
-       if (MAJOR(dev) >= MAX_BLKDEV) {
                dput(dentry);
-               goto out;
-       }
-       retval = do_umount(dev,0);
-       if (!retval) {
-               fsync_dev(dev);
-               if (dev != ROOT_DEV) {
-                       blkdev_release (inode);
-                       put_unnamed_dev(dev);
-               }
+
+               if (!retval)
+                       retval = umount_dev(dev);
        }
-       dput(dentry);
-       if (!retval)
-               fsync_dev(dev);
-out:
        unlock_kernel();
        return retval;
 }
@@ -1101,8 +1081,7 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
 {
        kdev_t old_root_dev;
        struct vfsmount *vfsmnt;
-       struct inode *old_root,*old_pwd,*inode;
-       unsigned long old_fs;
+       struct dentry *old_root,*old_pwd,*dir_d = NULL;
        int error;
 
        old_root = current->fs->root;
@@ -1114,24 +1093,29 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
        }
        ROOT_DEV = new_root_dev;
        do_mount_root();
-       old_fs = get_fs();
-       set_fs(get_ds());
-        error = namei(put_old, &inode);
-       if (error) inode = NULL;
-       set_fs(old_fs);
-       if (!error && (atomic_read(&inode->i_count) != 1 || inode->i_mount))
+       dir_d = lookup_dentry(put_old, NULL, 1);
+       if (IS_ERR(dir_d)) {
+               error = PTR_ERR(dir_d);
+       } else if (!dir_d->d_inode) {
+               dput(dir_d);
+               error = -ENOENT;
+       } else {
+               error = 0;
+       }
+       if (!error && dir_d->d_covers != dir_d) {
+               dput(dir_d);
                error = -EBUSY;
-       if (!error && !S_ISDIR(inode->i_mode))
+       }
+       if (!error && !S_ISDIR(dir_d->d_inode->i_mode)) {
+               dput(dir_d);
                error = -ENOTDIR;
-       iput(old_root); /* current->fs->root */
-       iput(old_pwd); /* current->fs->pwd */
+       }
+       dput(old_root);
+       dput(old_pwd);
        if (error) {
                int umount_error;
 
-               if (inode) iput(inode);
                printk(KERN_NOTICE "Trying to unmount old root ... ");
-               old_root->i_mount = old_root;
-                       /* does this belong into do_mount_root ? */
                umount_error = do_umount(old_root_dev,1);
                if (umount_error) printk(KERN_ERR "error %d\n",umount_error);
                else {
@@ -1140,16 +1124,16 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
                }
                return umount_error ? error : 0;
        }
-       iput(old_root); /* sb->s_covered */
        remove_vfsmnt(old_root_dev);
        vfsmnt = add_vfsmnt(old_root_dev,"/dev/root.old",put_old);
        if (!vfsmnt) printk(KERN_CRIT "Trouble: add_vfsmnt failed\n");
        else {
-               vfsmnt->mnt_sb = old_root->i_sb;
-               vfsmnt->mnt_sb->s_covered = inode;
+               vfsmnt->mnt_sb = old_root->d_inode->i_sb;
+               d_mount(dir_d,vfsmnt->mnt_sb->s_root);
                vfsmnt->mnt_flags = vfsmnt->mnt_sb->s_flags;
        }
-       inode->i_mount = old_root;
+       d_umount(old_root);
+       d_mount(dir_d,old_root);
        return 0;
 }