diff -u --recursive dist-2.1.24/Makefile linux/Makefile --- dist-2.1.24/Makefile Wed Jan 29 00:11:38 1997 +++ linux/Makefile Wed Jan 29 00:12:17 1997 @@ -38,7 +38,7 @@ AR =$(CROSS_COMPILE)ar NM =$(CROSS_COMPILE)nm STRIP =$(CROSS_COMPILE)strip -MAKE =make +MAKE =make -j8 GENKSYMS=/sbin/genksyms all: do-it-all diff -u --recursive dist-2.1.24/Rules.make linux/Rules.make --- dist-2.1.24/Rules.make Sun Jan 26 12:38:23 1997 +++ linux/Rules.make Sun Jan 26 12:40:07 1997 @@ -45,7 +45,16 @@ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -S $< -o $@ %.o: %.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -o tmp.$@ $< + pick_host "cd /tmp && cat >tmp.$@.c && $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c tmp.$@.c -o tmp.$@ 1>&2 && cat tmp.$@ && rm tmp.$@.c tmp.$@" $@ + rm tmp.$@ + +# pick_host "cd `pwd` && $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<" + +# $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -o - $< | \ +# pick_host "cd /tmp && cat >tmp.$@.c && $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c tmp.$@.c -o tmp.$@ 1>&2 && cat tmp.$@ && rm tmp.$@.c tmp.$@" >$@ + +# $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< %.o: %.s $(AS) $(ASFLAGS) $(EXTRA_CFLAGS) -o $@ $< diff -u --recursive dist-2.1.24/drivers/block/md.c linux/drivers/block/md.c --- dist-2.1.24/drivers/block/md.c Tue Jan 21 01:19:51 1997 +++ linux/drivers/block/md.c Wed Jan 29 00:25:54 1997 @@ -216,9 +216,12 @@ } /* Remove locks. */ - for (i=0; if_pos = 0; f->f_reada = 0; f->f_op = inode->i_op->default_file_ops; + inode->i_count++; if (f->f_op->open) { int error = f->f_op->open(inode,f); if (error) { f->f_count--; put_unused_fd(fd); + iput(inode); return error; } } current->files->fd[fd] = f; - inode->i_count++; } return fd; } diff -u --recursive dist-2.1.24/fs/inode.c linux/fs/inode.c --- dist-2.1.24/fs/inode.c Tue Jan 21 01:19:51 1997 +++ linux/fs/inode.c Wed Jan 29 00:25:54 1997 @@ -145,13 +145,13 @@ __wait_on_inode(inode); } -static inline void lock_inode(struct inode * inode) +void lock_inode(struct inode * inode) { wait_on_inode(inode); inode->i_lock = 1; } -static inline void unlock_inode(struct inode * inode) +void unlock_inode(struct inode * inode) { inode->i_lock = 0; wake_up(&inode->i_wait); @@ -159,7 +159,8 @@ /* * Note that we don't want to disturb any wait-queues when we discard - * an inode. + * an inode. Note also that the inode must be locked when clear_inode + * is called. * * Argghh. Got bitten by a gcc problem with inlining: no way to tell * the compiler that the inline asm function 'memset' changes 'inode'. @@ -168,13 +169,16 @@ * * The solution is the weird use of 'volatile'. Ho humm. Have to report * it to the gcc lists, and hope we can do this more cleanly some day.. + * + * Doh!!! This has been another one of those places where races are + * bound to occur. Just remember that the inode must remain locked + * whenever we can sleep... Please!!! --blah */ void clear_inode(struct inode * inode) { struct wait_queue * wait; - truncate_inode_pages(inode, 0); - wait_on_inode(inode); + truncate_inode_pages(inode, 0); /* may sleep */ if (IS_WRITABLE(inode)) { if (inode->i_sb && inode->i_sb->dq_op) inode->i_sb->dq_op->drop(inode); @@ -185,6 +189,7 @@ if (inode->i_count) nr_free_inodes++; memset(inode,0,sizeof(*inode)); + inode->i_lock = 1; ((volatile struct inode *) inode)->i_wait = wait; insert_inode_free(inode); } @@ -202,7 +207,9 @@ continue; if (inode->i_count || inode->i_dirt || inode->i_lock) return 0; + lock_inode(inode); clear_inode(inode); + unlock_inode(inode); } return 1; } @@ -395,7 +402,9 @@ kdevname(dev)); continue; } + lock_inode(inode); clear_inode(inode); + unlock_inode(inode); } } @@ -441,7 +450,9 @@ } if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode) { - inode->i_sb->s_op->put_inode(inode); + inode->i_lock = 1; + inode->i_sb->s_op->put_inode(inode); /* sleeps here were once bad */ + unlock_inode(inode); if (!inode->i_nlink) return; } @@ -523,6 +534,7 @@ if (best->i_count) goto repeat; found_good: + lock_inode(best); clear_inode(best); best->i_count = 1; best->i_nlink = 1; @@ -530,6 +542,7 @@ best->i_sem.count = 1; best->i_ino = ++ino; best->i_dev = 0; + unlock_inode(best); nr_free_inodes--; if (nr_free_inodes < 0) { printk ("VFS: get_empty_inode: bad free inode count.\n"); diff -u --recursive dist-2.1.24/fs/namei.c linux/fs/namei.c --- dist-2.1.24/fs/namei.c Sun Jan 26 12:38:52 1997 +++ linux/fs/namei.c Wed Jan 29 00:25:54 1997 @@ -160,7 +160,7 @@ struct inode ** result) { struct super_block * sb; - int perm; + int perm, err = 0; *result = NULL; if (!dir) @@ -172,11 +172,12 @@ *result = dir; return 0; } else if ((sb = dir->i_sb) && (dir == sb->s_mounted)) { + if (sb->s_covered) + sb->s_covered->i_count++; /* avoid the race */ iput(dir); dir = sb->s_covered; if (!dir) return -ENOENT; - dir->i_count++; } } if (!dir->i_op || !dir->i_op->lookup) { diff -u --recursive dist-2.1.24/fs/open.c linux/fs/open.c --- dist-2.1.24/fs/open.c Sun Jan 26 12:38:53 1997 +++ linux/fs/open.c Wed Jan 29 00:30:11 1997 @@ -290,7 +290,7 @@ asmlinkage int sys_chdir(const char * filename) { - struct inode * inode; + struct inode * inode, *tmp; int error; lock_kernel(); @@ -306,8 +306,9 @@ iput(inode); goto out; } - iput(current->fs->pwd); + tmp = current->fs->pwd; current->fs->pwd = inode; + iput(tmp); error = 0; out: unlock_kernel(); @@ -316,7 +317,7 @@ asmlinkage int sys_fchdir(unsigned int fd) { - struct inode * inode; + struct inode * inode, *tmp; struct file * file; int error = -EBADF; @@ -331,9 +332,10 @@ goto out; if ((error = permission(inode,MAY_EXEC)) != 0) goto out; - iput(current->fs->pwd); + tmp = current->fs->pwd; current->fs->pwd = inode; inode->i_count++; + iput(tmp); error = 0; out: unlock_kernel(); diff -u --recursive dist-2.1.24/include/linux/fs.h linux/include/linux/fs.h --- dist-2.1.24/include/linux/fs.h Sun Jan 26 12:38:58 1997 +++ linux/include/linux/fs.h Wed Jan 29 00:25:54 1997 @@ -620,6 +620,8 @@ struct inode ** res_inode, struct inode * base); extern int do_mknod(const char * filename, int mode, dev_t dev); extern int do_pipe(int *); +extern void lock_inode(struct inode * inode); +extern void unlock_inode(struct inode * inode); extern void iput(struct inode * inode); extern struct inode * __iget(struct super_block * sb,int nr,int crsmnt); extern struct inode * get_empty_inode(void);