lkml.org 
[lkml]   [1997]   [Apr]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectMisc. patches against 2.1.30
I've been looking at the filesystem code, and found several things that looked
inefficient or broken. It seems that a lot of cruft has accumulated over the
years.

What these patches do:
- optimize get_write_access(): this used to loop over all tasks and
their vma's to determine whether it could open a file for writing. Yuck.
I have a silly test program that gets sped up 60 times by this patch.
- move redundant code (the "subdir" routine) out of the filesystems and into
the VFS code.
- delete some more redundant/dead code in the fs-specific "lookup" routines.
No need to check that "dir" is NULL if we are always called with
dir->i_op->lookup (dir, ...), and also no need to check that it is a
directory - if lookup isn't valid, then the "lookup" field of the inode
operations should be NULL.
- delete dead code in truncate routines: since about 0.99.something Linux
uses semaphores to lock files during truncates/writes, so there should be
no need to check for races that often (and the code in the ext2 truncate
routine is _really_ dead or I'm blind).
- The recent problems with unlink left me wondering whether rename could
also be affected. This patch adds more semaphore locks in the VFS rename
routine: There is now a rename semaphore in struct super which is used to
limit the number of concurrent renames per filesystem to 1 (there used to
be code in every filesystem to achieve the same effect). This is the first
semaphore locked by rename, it then goes on to lock both involved
directories. This should be deadlock-safe, since the global per-filesystem
rename semaphore protects against two renames deadlocking.
This should make the filesystem-specific rename routines safer, and also
simpler (I half-heartedly removed some code from ext2/minix, I'm sure
there's more that could be deleted)
- remove two unused fields in struct inode
- the buffer cache patch that's floating around on this list is also in
- remove some verify_areas from ipc/shm.c
- make mkdep.c compile with glibc

Not all of it is tested... especially ipc/shm.c is untested. I've been using
a kernel with this patch without problems (at least without problems that seem
to be related to this patch).

Bernd

--- ./fs/msdos/namei.c.orig-1 Sun Mar 16 21:59:56 1997
+++ ./fs/msdos/namei.c Fri Mar 28 16:47:29 1997
@@ -202,12 +202,6 @@
PRINTK (("msdos_lookup\n"));

*result = NULL;
- if (!dir) return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
- PRINTK (("msdos_lookup 2\n"));
if (len == 1 && name[0] == '.') {
*result = dir;
return 0;
--- ./fs/minix/namei.c.orig-1 Sun Mar 16 21:54:34 1997
+++ ./fs/minix/namei.c Fri Mar 28 19:53:41 1997
@@ -112,12 +112,6 @@
struct buffer_head * bh;

*result = NULL;
- if (!dir)
- return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
if (!(bh = minix_find_entry(dir,name,len,&de))) {
iput(dir);
return -ENOENT;
@@ -634,30 +628,6 @@
return 0;
}

-static int subdir(struct inode * new_inode, struct inode * old_inode)
-{
- int ino;
- int result;
-
- new_inode->i_count++;
- result = 0;
- for (;;) {
- if (new_inode == old_inode) {
- result = 1;
- break;
- }
- if (new_inode->i_dev != old_inode->i_dev)
- break;
- ino = new_inode->i_ino;
- if (minix_lookup(new_inode,"..",2,&new_inode))
- break;
- if (new_inode->i_ino == ino)
- break;
- }
- iput(new_inode);
- return result;
-}
-
#define PARENT_INO(buffer) \
(((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode)

@@ -724,7 +694,7 @@
if (!S_ISDIR(old_inode->i_mode))
goto end_rename;
retval = -EINVAL;
- if (subdir(new_dir, old_inode))
+ if (subdir(minix_lookup, new_dir, old_inode))
goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir(new_inode))
@@ -743,7 +713,7 @@
if (new_inode && !S_ISDIR(new_inode->i_mode))
goto end_rename;
retval = -EINVAL;
- if (subdir(new_dir, old_inode))
+ if (subdir(minix_lookup, new_dir, old_inode))
goto end_rename;
retval = -EIO;
dir_bh = minix_bread(old_inode,0,0);
@@ -808,29 +778,10 @@
return retval;
}

-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- */
int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len,
int must_be_dir)
{
- static struct wait_queue * wait = NULL;
- static int lock = 0;
- int result;
-
- while (lock)
- sleep_on(&wait);
- lock = 1;
- result = do_minix_rename(old_dir, old_name, old_len,
- new_dir, new_name, new_len, must_be_dir);
- lock = 0;
- wake_up(&wait);
- return result;
+ return do_minix_rename(old_dir, old_name, old_len,
+ new_dir, new_name, new_len, must_be_dir);
}
--- ./fs/isofs/namei.c.orig-1 Sun Mar 16 21:54:33 1997
+++ ./fs/isofs/namei.c Fri Mar 28 16:47:29 1997
@@ -227,13 +227,6 @@
printk("lookup: %x %d\n",dir->i_ino, len);
#endif
*result = NULL;
- if (!dir)
- return -ENOENT;
-
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }

ino = 0;

--- ./fs/ext2/super.c.orig-1 Thu Mar 27 21:39:48 1997
+++ ./fs/ext2/super.c Thu Mar 27 21:40:05 1997
@@ -495,8 +495,6 @@
else
sb->u.ext2_sb.s_resgid = le16_to_cpu(es->s_def_resgid);
sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state);
- sb->u.ext2_sb.s_rename_lock = 0;
- sb->u.ext2_sb.s_rename_wait = NULL;
sb->u.ext2_sb.s_addr_per_block_bits =
log2 (EXT2_ADDR_PER_BLOCK(sb));
sb->u.ext2_sb.s_desc_per_block_bits =
--- ./fs/ext2/namei.c.orig-1 Thu Mar 27 21:39:48 1997
+++ ./fs/ext2/namei.c Fri Mar 28 16:47:29 1997
@@ -162,12 +162,6 @@
struct buffer_head * bh;

*result = NULL;
- if (!dir)
- return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput (dir);
- return -ENOTDIR;
- }
if (len > EXT2_NAME_LEN) {
iput (dir);
return -ENAMETOOLONG;
@@ -900,30 +894,6 @@
return 0;
}

-static int subdir (struct inode * new_inode, struct inode * old_inode)
-{
- int ino;
- int result;
-
- new_inode->i_count++;
- result = 0;
- for (;;) {
- if (new_inode == old_inode) {
- result = 1;
- break;
- }
- if (new_inode->i_dev != old_inode->i_dev)
- break;
- ino = new_inode->i_ino;
- if (ext2_lookup (new_inode, "..", 2, &new_inode))
- break;
- if (new_inode->i_ino == ino)
- break;
- }
- iput (new_inode);
- return result;
-}
-
#define PARENT_INO(buffer) \
((struct ext2_dir_entry *) ((char *) buffer + \
le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->inode
@@ -953,20 +923,6 @@
struct ext2_dir_entry * old_de, * new_de;
int retval;

- goto start_up;
-try_again:
- if (new_bh && new_de) {
- ext2_delete_entry(new_de, new_bh);
- new_dir->i_version = ++event;
- }
- brelse (old_bh);
- brelse (new_bh);
- brelse (dir_bh);
- iput (old_inode);
- iput (new_inode);
- current->counter = 0;
- schedule ();
-start_up:
old_inode = new_inode = NULL;
old_bh = new_bh = dir_bh = NULL;
new_de = NULL;
@@ -1010,7 +966,7 @@
if (!S_ISDIR(old_inode->i_mode))
goto end_rename;
retval = -EINVAL;
- if (subdir (new_dir, old_inode))
+ if (subdir (ext2_lookup, new_dir, old_inode))
goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir (new_inode))
@@ -1029,7 +985,7 @@
if (new_inode && !S_ISDIR(new_inode->i_mode))
goto end_rename;
retval = -EINVAL;
- if (subdir (new_dir, old_inode))
+ if (subdir (ext2_lookup, new_dir, old_inode))
goto end_rename;
dir_bh = ext2_bread (old_inode, 0, 0, &retval);
if (!dir_bh)
@@ -1050,11 +1006,11 @@
* sanity checking before doing the rename - avoid races
*/
if (new_inode && (le32_to_cpu(new_de->inode) != new_inode->i_ino))
- goto try_again;
+ ext2_panic (old_inode->i_sb, "ext2_rename", "file disappeared");
if (le32_to_cpu(new_de->inode) && !new_inode)
- goto try_again;
+ ext2_panic (old_inode->i_sb, "ext2_rename", "file disappeared");
if (le32_to_cpu(old_de->inode) != old_inode->i_ino)
- goto try_again;
+ ext2_panic (old_inode->i_sb, "ext2_rename", "file disappeared");
/*
* ok, that's it
*/
@@ -1062,7 +1018,7 @@
dcache_add(new_dir, new_de->name, le16_to_cpu(new_de->name_len), le32_to_cpu(new_de->inode));
retval = ext2_delete_entry (old_de, old_bh);
if (retval == -ENOENT)
- goto try_again;
+ ext2_panic (old_inode->i_sb, "ext2_rename", "file disappeared");
if (retval)
goto end_rename;
old_dir->i_version = ++event;
@@ -1109,31 +1065,13 @@
return retval;
}

-/*
- * Ok, rename also locks out other renames, as they can change the parent of
- * a directory, and we don't want any races. Other races are checked for by
- * "do_rename()", which restarts if there are inconsistencies.
- *
- * Note that there is no race between different filesystems: it's only within
- * the same device that races occur: many renames can happen at once, as long
- * as they are on different partitions.
- *
- * In the second extended file system, we use a lock flag stored in the memory
- * super-block. This way, we really lock other renames only if they occur
- * on the same file system
- */
int ext2_rename (struct inode * old_dir, const char * old_name, int old_len,
struct inode * new_dir, const char * new_name, int new_len,
int must_be_dir)
{
int result;

- while (old_dir->i_sb->u.ext2_sb.s_rename_lock)
- sleep_on (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
- old_dir->i_sb->u.ext2_sb.s_rename_lock = 1;
result = do_ext2_rename (old_dir, old_name, old_len, new_dir,
new_name, new_len, must_be_dir);
- old_dir->i_sb->u.ext2_sb.s_rename_lock = 0;
- wake_up (&old_dir->i_sb->u.ext2_sb.s_rename_wait);
return result;
}
--- ./fs/ext2/truncate.c.orig-1 Thu Mar 27 21:43:10 1997
+++ ./fs/ext2/truncate.c Thu Mar 27 21:51:22 1997
@@ -72,7 +72,6 @@
inode->i_sb->s_blocksize)
int direct_block = DIRECT_BLOCK;

-repeat:
for (i = direct_block ; i < EXT2_NDIR_BLOCKS ; i++) {
p = inode->u.ext2_i.i_data + i;
tmp = *p;
@@ -80,10 +79,6 @@
continue;
bh = get_hash_table (inode->i_dev, tmp,
inode->i_sb->s_blocksize);
- if (i < direct_block) {
- brelse (bh);
- goto repeat;
- }
if ((bh && bh->b_count != 1) || tmp != *p) {
retry = 1;
brelse (bh);
@@ -136,22 +131,16 @@
*p = 0;
return 0;
}
-repeat:
+
for (i = indirect_block ; i < addr_per_block ; i++) {
if (i < 0)
i = 0;
- if (i < indirect_block)
- goto repeat;
ind = i + (u32 *) ind_bh->b_data;
tmp = le32_to_cpu(*ind);
if (!tmp)
continue;
bh = get_hash_table (inode->i_dev, tmp,
inode->i_sb->s_blocksize);
- if (i < indirect_block) {
- brelse (bh);
- goto repeat;
- }
if ((bh && bh->b_count != 1) || tmp != le32_to_cpu(*ind)) {
retry = 1;
brelse (bh);
@@ -223,22 +212,16 @@
*p = cpu_to_le32(0);
return 0;
}
-repeat:
+
for (i = indirect_block ; i < addr_per_block ; i++) {
if (i < 0)
i = 0;
- if (i < indirect_block)
- goto repeat;
ind = i + (u32 *) ind_bh->b_data;
tmp = le32_to_cpu(*ind);
if (!tmp)
continue;
bh = get_hash_table (inode->i_dev, tmp,
inode->i_sb->s_blocksize);
- if (i < indirect_block) {
- brelse (bh);
- goto repeat;
- }
if ((bh && bh->b_count != 1) || tmp != le32_to_cpu(*ind)) {
retry = 1;
brelse (bh);
@@ -309,12 +292,10 @@
*p = 0;
return 0;
}
-repeat:
+
for (i = dindirect_block ; i < addr_per_block ; i++) {
if (i < 0)
i = 0;
- if (i < dindirect_block)
- goto repeat;
dind = i + (u32 *) dind_bh->b_data;
tmp = le32_to_cpu(*dind);
if (!tmp)
@@ -368,12 +349,10 @@
*p = cpu_to_le32(0);
return 0;
}
-repeat:
+
for (i = dindirect_block ; i < addr_per_block ; i++) {
if (i < 0)
i = 0;
- if (i < dindirect_block)
- goto repeat;
dind = i + (u32 *) dind_bh->b_data;
tmp = le32_to_cpu(*dind);
if (!tmp)
@@ -429,12 +408,10 @@
*p = 0;
return 0;
}
-repeat:
+
for (i = tindirect_block ; i < addr_per_block ; i++) {
if (i < 0)
i = 0;
- if (i < tindirect_block)
- goto repeat;
tind = i + (u32 *) tind_bh->b_data;
retry |= trunc_dindirect_swab32(inode, EXT2_NDIR_BLOCKS +
addr_per_block + (i + 1) * addr_per_block * addr_per_block,
--- ./fs/sysv/namei.c.orig-1 Wed Jul 3 11:06:03 1996
+++ ./fs/sysv/namei.c Fri Mar 28 16:47:29 1997
@@ -108,12 +108,6 @@
struct buffer_head * bh;

*result = NULL;
- if (!dir)
- return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
if (!(bh = sysv_find_entry(dir,name,len,&de))) {
iput(dir);
return -ENOENT;
@@ -629,31 +623,6 @@
return 0;
}

-/* return 1 if `new' is a subdir of `old' on the same device */
-static int subdir(struct inode * new_inode, struct inode * old_inode)
-{
- int ino;
- int result;
-
- new_inode->i_count++;
- result = 0;
- for (;;) {
- if (new_inode == old_inode) {
- result = 1;
- break;
- }
- if (new_inode->i_dev != old_inode->i_dev)
- break;
- ino = new_inode->i_ino;
- if (sysv_lookup(new_inode,"..",2,&new_inode))
- break;
- if (new_inode->i_ino == ino) /* root dir reached ? */
- break;
- }
- iput(new_inode);
- return result;
-}
-
#define PARENT_INO(buffer) \
(((struct sysv_dir_entry *) ((buffer) + 1*SYSV_DIRSIZE))->inode)

@@ -718,7 +687,7 @@
if (!S_ISDIR(old_inode->i_mode))
goto end_rename;
retval = -EINVAL;
- if (subdir(new_dir, old_inode))
+ if (subdir(sysv_lookup, new_dir, old_inode))
goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir(new_inode))
--- ./fs/vfat/namei.c.orig-1 Sun Mar 16 22:01:50 1997
+++ ./fs/vfat/namei.c Fri Mar 28 16:47:30 1997
@@ -917,12 +917,6 @@
PRINTK (("vfat_lookup: name=%s, len=%d\n", name, len));

*result = NULL;
- if (!dir) return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
- PRINTK (("vfat_lookup 2\n"));
if (len == 1 && name[0] == '.') {
*result = dir;
return 0;
--- ./fs/affs/namei.c.orig-1 Sun Mar 16 21:54:32 1997
+++ ./fs/affs/namei.c Fri Mar 28 16:47:29 1997
@@ -151,20 +151,16 @@
pr_debug("AFFS: lookup(%.*s)\n",len,name);

*result = NULL;
- if (!dir)
- return -ENOENT;

res = -ENOENT;
- if (S_ISDIR(dir->i_mode)) {
- if ((bh = affs_find_entry(dir,name,len,&ino))) {
- if (FILE_END(bh->b_data,dir)->original)
- ino = htonl(FILE_END(bh->b_data,dir)->original);
- affs_brelse(bh);
- if ((*result = iget(dir->i_sb,ino)))
- res = 0;
- else
- res = -EACCES;
- }
+ if ((bh = affs_find_entry(dir,name,len,&ino))) {
+ if (FILE_END(bh->b_data,dir)->original)
+ ino = htonl(FILE_END(bh->b_data,dir)->original);
+ affs_brelse(bh);
+ if ((*result = iget(dir->i_sb,ino)))
+ res = 0;
+ else
+ res = -EACCES;
}
iput(dir);
return res;
@@ -506,31 +502,6 @@
return error;
}

-static int
-subdir(struct inode * new_inode, struct inode * old_inode)
-{
- int ino;
- int result;
-
- new_inode->i_count++;
- result = 0;
- for (;;) {
- if (new_inode == old_inode) {
- result = 1;
- break;
- }
- if (new_inode->i_dev != old_inode->i_dev)
- break;
- ino = new_inode->i_ino;
- if (affs_lookup(new_inode,"..",2,&new_inode))
- break;
- if (new_inode->i_ino == ino)
- break;
- }
- iput(new_inode);
- return result;
-}
-
/* I'm afraid this might not be race proof. Maybe next time. */

int
@@ -589,7 +560,7 @@
if (!S_ISDIR(old_inode->i_mode))
goto end_rename;
retval = -EINVAL;
- if (subdir(new_dir,old_inode))
+ if (subdir(affs_lookup,new_dir,old_inode))
goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode)))
@@ -603,7 +574,7 @@
if (new_inode && !S_ISDIR(new_inode->i_mode))
goto end_rename;
retval = -EINVAL;
- if (subdir(new_dir,old_inode))
+ if (subdir(affs_lookup,new_dir,old_inode))
goto end_rename;
if (affs_parent_ino(old_inode) != old_dir->i_ino)
goto end_rename;
--- ./fs/buffer.c.orig-1 Fri Mar 28 16:25:59 1997
+++ ./fs/buffer.c Sat Mar 29 11:06:01 1997
@@ -582,6 +582,8 @@
of other sizes, this is necessary now that we
no longer have the lav code. */
try_to_free_buffer(bh,&bh,1);
+ if (!bh)
+ break;
continue;
}

--- ./fs/inode.c.orig-1 Sat Mar 29 11:05:29 1997
+++ ./fs/inode.c Sat Mar 29 11:07:03 1997
@@ -160,14 +160,6 @@
/*
* Note that we don't want to disturb any wait-queues when we discard
* an inode.
- *
- * Argghh. Got bitten by a gcc problem with inlining: no way to tell
- * the compiler that the inline asm function 'memset' changes 'inode'.
- * I've been searching for the bug for days, and was getting desperate.
- * Finally looked at the assembler output... Grrr.
- *
- * 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..
*/
void clear_inode(struct inode * inode)
{
@@ -181,11 +173,11 @@
}
remove_inode_hash(inode);
remove_inode_free(inode);
- wait = ((volatile struct inode *) inode)->i_wait;
+ wait = inode->i_wait;
if (inode->i_count)
nr_free_inodes++;
memset(inode,0,sizeof(*inode));
- ((volatile struct inode *) inode)->i_wait = wait;
+ inode->i_wait = wait;
insert_inode_free(inode);
}

--- ./fs/namei.c.orig-1 Thu Mar 27 21:39:48 1997
+++ ./fs/namei.c Fri Mar 28 18:12:14 1997
@@ -124,24 +124,16 @@
* put_write_access() releases this write permission.
* This is used for regular files.
* We cannot support write (and maybe mmap read-write shared) accesses and
- * MAP_DENYWRITE mmappings simultaneously.
+ * MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode
+ * can have the following values:
+ * 0: no writers, no VM_DENYWRITE mappings
+ * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist
+ * > 0: (i_writecount) users are writing to the file.
*/
int get_write_access(struct inode * inode)
{
- struct task_struct * p;
-
- if ((inode->i_count > 1) && S_ISREG(inode->i_mode)) /* shortcut */
- for_each_task(p) {
- struct vm_area_struct * mpnt;
- if (!p->mm)
- continue;
- for(mpnt = p->mm->mmap; mpnt; mpnt = mpnt->vm_next) {
- if (inode != mpnt->vm_inode)
- continue;
- if (mpnt->vm_flags & VM_DENYWRITE)
- return -ETXTBSY;
- }
- }
+ if (inode->i_writecount < 0)
+ return -ETXTBSY;
inode->i_writecount++;
return 0;
}
@@ -151,10 +143,35 @@
inode->i_writecount--;
}

+/* return 1 if `new' is a subdir of `old' on the same device */
+int subdir(int (*do_lookup) (struct inode *, const char *, int, struct inode **),
+ struct inode * new_inode, struct inode * old_inode)
+{
+ int ino;
+ int result;
+
+ new_inode->i_count++;
+ result = 0;
+ for (;;) {
+ if (new_inode == old_inode) {
+ result = 1;
+ break;
+ }
+ if (new_inode->i_dev != old_inode->i_dev)
+ break;
+ ino = new_inode->i_ino;
+ if (do_lookup(new_inode,"..",2,&new_inode))
+ break;
+ if (new_inode->i_ino == ino) /* root dir reached ? */
+ break;
+ }
+ iput(new_inode);
+ return result;
+}
+
/*
* lookup() looks up one part of a pathname, using the fs-dependent
- * routines (currently minix_lookup) for it. It also checks for
- * fathers (pseudo-roots, mount-points)
+ * routines for it. It also checks for fathers (pseudo-roots, mount-points)
*/
int lookup(struct inode * dir,const char * name, int len,
struct inode ** result)
@@ -191,6 +208,14 @@
*result = dir;
return 0;
}
+#if 0
+ /* This used to be done in all the fs-specific code. */
+ if (!S_ISDIR(dir->i_mode)) {
+ /* panic ("lookup: can't happen"); */
+ iput(dir);
+ return -ENOTDIR;
+ }
+#endif
return dir->i_op->lookup(dir, name, len, result);
}

@@ -921,10 +946,16 @@
new_dir->i_count++;
if (new_dir->i_sb && new_dir->i_sb->dq_op)
new_dir->i_sb->dq_op->initialize(new_dir, -1);
+ down(&new_dir->i_sb->s_rename_sem);
down(&new_dir->i_sem);
+ if (new_dir != old_dir)
+ down(&old_dir->i_sem);
error = old_dir->i_op->rename(old_dir, old_base, old_len,
new_dir, new_base, new_len, must_be_dir);
+ if (new_dir != old_dir)
+ up(&old_dir->i_sem);
up(&new_dir->i_sem);
+ up(&new_dir->i_sb->s_rename_sem);
iput(new_dir);
return error;
}
--- ./fs/super.c.orig-1 Thu Mar 27 21:39:48 1997
+++ ./fs/super.c Thu Mar 27 21:40:06 1997
@@ -535,6 +535,7 @@
s->s_covered = NULL;
s->s_rd_only = 0;
s->s_dirt = 0;
+ s->s_rename_sem = MUTEX;
s->s_type = type;
return s;
}
--- ./kernel/fork.c.orig-1 Fri Mar 28 19:37:58 1997
+++ ./kernel/fork.c Fri Mar 28 19:29:02 1997
@@ -87,6 +87,8 @@
p = &mm->mmap;
flush_cache_mm(current->mm);
for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
+ struct inode *inode;
+
tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (!tmp) {
exit_mmap(mm);
@@ -97,8 +99,17 @@
tmp->vm_flags &= ~VM_LOCKED;
tmp->vm_mm = mm;
tmp->vm_next = NULL;
- if (tmp->vm_inode) {
- tmp->vm_inode->i_count++;
+ inode = tmp->vm_inode;
+ if (inode) {
+ inode->i_count++;
+ if (tmp->vm_flags & VM_DENYWRITE) {
+ /* printk("dup_mmap: inode %p %d\n", inode, inode->i_writecount); */
+ if (inode->i_writecount > 0)
+ printk (KERN_EMERG "dup_mmap: weirdness %p %d!\n", inode, inode->i_writecount);
+ else
+ inode->i_writecount--;
+ }
+
/* insert tmp into the share list, just after mpnt */
tmp->vm_next_share->vm_prev_share = tmp;
mpnt->vm_next_share = tmp;
--- ./mm/filemap.c.orig-1 Fri Mar 28 16:38:07 1997
+++ ./mm/filemap.c Fri Mar 28 16:38:12 1997
@@ -230,7 +230,7 @@
* Update a page cache copy, when we're doing a "write()" system call
* See also "update_vm_cache()".
*/
-void update_vm_cache(struct inode * inode, unsigned long pos, const char * buf, int count)
+void update_vm_cache(struct inode * inode, unsigned long pos, const char * buf, unsigned long count)
{
unsigned long offset, len;

--- ./mm/mmap.c.orig-1 Fri Mar 28 17:29:24 1997
+++ ./mm/mmap.c Fri Mar 28 19:31:23 1997
@@ -162,6 +162,7 @@
{
struct mm_struct * mm = current->mm;
struct vm_area_struct * vma;
+ int correct_wcount = 0;

if ((len = PAGE_ALIGN(len)) == 0)
return addr;
@@ -206,10 +207,6 @@
default:
return -EINVAL;
}
- if (flags & MAP_DENYWRITE) {
- if (file->f_inode->i_writecount > 0)
- return -ETXTBSY;
- }
} else if ((flags & MAP_TYPE) != MAP_PRIVATE)
return -EINVAL;

@@ -289,9 +286,25 @@
}

if (file) {
- int error = file->f_op->mmap(file->f_inode, file, vma);
+ int error = 0;
+ if (vma->vm_flags & VM_DENYWRITE) {
+ if (file->f_inode->i_writecount > 0)
+ error = -ETXTBSY;
+ else {
+ /* f_op->mmap might possibly sleep
+ * (generic_file_mmap doesn't, but other code
+ * might). In any case, this takes care of any
+ * race that this might cause. */
+ file->f_inode->i_writecount--;
+ correct_wcount = 1;
+ }
+ }
+ if (!error)
+ error = file->f_op->mmap(file->f_inode, file, vma);

if (error) {
+ if (correct_wcount)
+ file->f_inode->i_writecount++;
kmem_cache_free(vm_area_cachep, vma);
return error;
}
@@ -299,6 +312,8 @@

flags = vma->vm_flags;
insert_vm_struct(mm, vma);
+ if (correct_wcount)
+ file->f_inode->i_writecount++;
merge_segments(mm, vma->vm_start, vma->vm_end);

/* merge_segments might have merged our vma, so we can't use it any more */
@@ -762,12 +777,10 @@
/* Work out to one of the ends */
if (end == area->vm_end)
area->vm_end = addr;
- else
- if (addr == area->vm_start) {
+ else if (addr == area->vm_start) {
area->vm_offset += (end - area->vm_start);
area->vm_start = end;
- }
- else {
+ } else {
/* Unmapping a hole: area->vm_start < addr <= end < area->vm_end */
/* Add end mapping -- leave beginning for below */
mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
@@ -844,6 +857,7 @@
*npp = mpnt->vm_next;
mpnt->vm_next = free;
free = mpnt;
+
avl_remove(mpnt, &current->mm->mmap_avl);
}

@@ -942,7 +956,7 @@
if (mpnt->vm_start > vmp->vm_start)
break;
if (mpnt->vm_end > vmp->vm_start)
- printk("insert_vm_struct: overlapping memory areas\n");
+ printk(KERN_EMERG "insert_vm_struct: overlapping memory areas\n");
p = &mpnt->vm_next;
}
vmp->vm_next = mpnt;
@@ -952,7 +966,7 @@

avl_insert_neighbours(vmp, &mm->mmap_avl, &prev, &next);
if ((prev ? prev->vm_next : mm->mmap) != next)
- printk("insert_vm_struct: tree inconsistent with list\n");
+ printk(KERN_EMERG "insert_vm_struct: tree inconsistent with list\n");
if (prev)
prev->vm_next = vmp;
else
@@ -964,6 +978,14 @@
if (!inode)
return;

+ if (vmp->vm_flags & VM_DENYWRITE) {
+ /* printk("insert_vm_struct: inode %p %d\n", inode, inode->i_writecount); */
+ if (inode->i_writecount > 0)
+ printk (KERN_EMERG "insert_vm_struct: weirdness %p %d!\n", inode, inode->i_writecount);
+ else
+ inode->i_writecount--;
+ }
+
/* insert vmp into inode's circular share list */
if ((share = inode->i_mmap)) {
vmp->vm_next_share = share->vm_next_share;
@@ -984,9 +1006,17 @@
if (!inode)
return;

+ if (mpnt->vm_flags & VM_DENYWRITE) {
+ /* printk("remove_shared_vm_struct %p %d\n", inode, inode->i_writecount); */
+ if (inode->i_writecount >= 0)
+ printk (KERN_EMERG "remove_shared_vm_struct: weirdness %p %d!\n", inode, inode->i_writecount);
+ else
+ inode->i_writecount++;
+ }
+
if (mpnt->vm_next_share == mpnt) {
if (inode->i_mmap != mpnt)
- printk("Inode i_mmap ring corrupted\n");
+ printk(KERN_EMERG "Inode i_mmap ring corrupted\n");
inode->i_mmap = NULL;
return;
}
--- ./include/linux/ext2_fs_sb.h.orig-1 Thu Mar 27 21:39:48 1997
+++ ./include/linux/ext2_fs_sb.h Thu Mar 27 21:40:06 1997
@@ -49,8 +49,6 @@
struct buffer_head * s_inode_bitmap[EXT2_MAX_GROUP_LOADED];
unsigned long s_block_bitmap_number[EXT2_MAX_GROUP_LOADED];
struct buffer_head * s_block_bitmap[EXT2_MAX_GROUP_LOADED];
- int s_rename_lock;
- struct wait_queue * s_rename_wait;
unsigned long s_mount_opt;
unsigned short s_resuid;
unsigned short s_resgid;
--- ./include/linux/pagemap.h.orig-1 Fri Mar 28 16:38:31 1997
+++ ./include/linux/pagemap.h Fri Mar 28 17:43:43 1997
@@ -140,6 +140,6 @@
__wait_on_page(page);
}

-extern void update_vm_cache(struct inode *, unsigned long, const char *, int);
+extern void update_vm_cache(struct inode *, unsigned long, const char *, unsigned long);

#endif
--- ./include/linux/fs.h.orig-1 Thu Mar 27 21:39:48 1997
+++ ./include/linux/fs.h Fri Mar 28 17:40:41 1997
@@ -303,9 +303,7 @@
unsigned char i_dirt;
unsigned char i_pipe;
unsigned char i_sock;
- unsigned char i_seek;
- unsigned char i_update;
- unsigned short i_writecount;
+ int i_writecount;
union {
struct pipe_inode_info pipe_i;
struct minix_inode_info minix_i;
@@ -435,6 +433,7 @@
struct inode * s_covered;
struct inode * s_mounted;
struct wait_queue * s_wait;
+ struct semaphore s_rename_sem;
union {
struct minix_sb_info minix_sb;
struct ext2_sb_info ext2_sb;
@@ -611,6 +610,8 @@
extern void sync_supers(kdev_t dev);
extern int bmap(struct inode * inode,int block);
extern int notify_change(struct inode *, struct iattr *);
+extern int subdir(int (*do_lookup) (struct inode *, const char *, int, struct inode **),
+ struct inode * new_inode, struct inode * old_inode);
extern int namei(const char * pathname, struct inode ** res_inode);
extern int lnamei(const char * pathname, struct inode ** res_inode);
extern int permission(struct inode * inode,int mask);
--- ./ipc/shm.c.orig-1 Sat Mar 29 10:34:48 1997
+++ ./ipc/shm.c Sat Mar 29 10:59:39 1997
@@ -218,59 +218,41 @@
goto out;
if (cmd == IPC_SET) {
err = -EFAULT;
- if (!buf)
- goto out;
- err = verify_area (VERIFY_READ, buf, sizeof (*buf));
- if (err)
+ if (copy_from_user (&tbuf, buf, sizeof (*buf)))
goto out;
- copy_from_user (&tbuf, buf, sizeof (*buf));
}

switch (cmd) { /* replace with proc interface ? */
case IPC_INFO:
{
struct shminfo shminfo;
- err = -EFAULT;
- if (!buf)
- goto out;
shminfo.shmmni = SHMMNI;
shminfo.shmmax = SHMMAX;
shminfo.shmmin = SHMMIN;
shminfo.shmall = SHMALL;
shminfo.shmseg = SHMSEG;
- err = verify_area (VERIFY_WRITE, buf, sizeof (struct shminfo));
- if (err)
+ err = -EFAULT;
+ if (copy_to_user (buf, &shminfo, sizeof(struct shminfo)))
goto out;
- copy_to_user (buf, &shminfo, sizeof(struct shminfo));
err = max_shmid;
goto out;
}
case SHM_INFO:
{
struct shm_info shm_info;
- err = -EFAULT;
- if (!buf)
- goto out;
- err = verify_area (VERIFY_WRITE, buf, sizeof (shm_info));
- if (err)
- goto out;
shm_info.used_ids = used_segs;
shm_info.shm_rss = shm_rss;
shm_info.shm_tot = shm_tot;
shm_info.shm_swp = shm_swp;
shm_info.swap_attempts = swap_attempts;
shm_info.swap_successes = swap_successes;
- copy_to_user (buf, &shm_info, sizeof(shm_info));
+ err = -EFAULT;
+ if (copy_to_user (buf, &shm_info, sizeof(shm_info)))
+ goto out;
err = max_shmid;
goto out;
}
case SHM_STAT:
- err = -EFAULT;
- if (!buf)
- goto out;
- err = verify_area (VERIFY_WRITE, buf, sizeof (*buf));
- if (err)
- goto out;
err = -EINVAL;
if (shmid > max_shmid)
goto out;
@@ -288,8 +270,9 @@
tbuf.shm_cpid = shp->shm_cpid;
tbuf.shm_lpid = shp->shm_lpid;
tbuf.shm_nattch = shp->shm_nattch;
- copy_to_user (buf, &tbuf, sizeof(*buf));
- err = id;
+ err = -EFAULT;
+ if (!copy_to_user (buf, &tbuf, sizeof(*buf)))
+ err = id;
goto out;
}

@@ -328,12 +311,6 @@
err = -EACCES;
if (ipcperms (ipcp, S_IRUGO))
goto out;
- err = -EFAULT;
- if (!buf)
- goto out;
- err = verify_area (VERIFY_WRITE, buf, sizeof (*buf));
- if (err)
- goto out;
tbuf.shm_perm = shp->shm_perm;
tbuf.shm_segsz = shp->shm_segsz;
tbuf.shm_atime = shp->shm_atime;
@@ -342,7 +319,9 @@
tbuf.shm_cpid = shp->shm_cpid;
tbuf.shm_lpid = shp->shm_lpid;
tbuf.shm_nattch = shp->shm_nattch;
- copy_to_user (buf, &tbuf, sizeof(*buf));
+ err = -EFAULT;
+ if (copy_to_user (buf, &tbuf, sizeof(*buf)))
+ goto out;
break;
case IPC_SET:
if (suser() || current->euid == shp->shm_perm.uid ||
--- ./drivers/net/scc.c.orig-1 Sun Mar 16 22:03:55 1997
+++ ./drivers/net/scc.c Fri Mar 28 16:47:29 1997
@@ -163,10 +163,10 @@
#include <asm/uaccess.h>
#include <asm/bitops.h>

-#include <stdlib.h>
+/* #include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
-#include <time.h>
+#include <time.h> */
#include <linux/kernel.h>
#include <linux/proc_fs.h>

--- ./drivers/net/ni52.c.orig-1 Sun Mar 16 22:04:50 1997
+++ ./drivers/net/ni52.c Fri Mar 28 16:47:29 1997
@@ -990,7 +990,7 @@
}
#endif

-#ifdef 0
+#if 0
if(!at_least_one)
{
int i;
--- ./drivers/char/ftape/ecc.c.orig-1 Fri Mar 28 16:48:19 1997
+++ ./drivers/char/ftape/ecc.c Fri Mar 28 16:47:28 1997
@@ -33,7 +33,7 @@
*/

#include <linux/ftape.h>
-#include <stdio.h>
+/* #include <stdio.h> */
#include <sys/errno.h>

#include "tracing.h"
--- ./scripts/mkdep.c.orig-1 Thu Mar 27 18:54:42 1997
+++ ./scripts/mkdep.c Thu Mar 27 18:56:31 1997
@@ -7,6 +7,7 @@
#include <unistd.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
+#include <errno.h>

char *filename, *command, __depname[256] = "\n\t@touch ";
int needsconfig, hasconfig, hasmodules, hasdep;
\
 
 \ /
  Last update: 2005-03-22 13:39    [W:0.762 / U:0.056 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site