linux-8086.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Juan Perez-Sanchez <lithoxs@gmail.com>
To: linux-8086 <linux-8086@vger.kernel.org>
Subject: [PATCH] Fix for bug in inode list
Date: Fri, 16 Nov 2012 18:27:14 -0600	[thread overview]
Message-ID: <CAD6VGuYvR7xSXYQj99=7FOmQeBGpTSE43BbT_OQcZtQUGROReQ@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2545 bytes --]

Hi,

    Patch 4 of 5.

Juan

PREVIOUS OPERATION AND BUGS

1. In file fs/inode.c, in the initialization of the inode list,
functions inode_init() and setup_inodes(), pointer "first_inode" is
set to NULL  and  then all inode structures are inserted from there.
This results on dereferencing a null pointer, reading and writing to
the first memory  locations of the kernel data segment, and a corrupt
inode list right from the boot.

2. The list always contain all the inode structures. If a structure is
removed from the list, it is immediately inserted at the beginning if
  the inode is free, or at the end if busy. It is unclear whether the
inode list should be a linear list or a circular list. Function
remove_inode_free() checks if the inode to be removed is the last of
the linear list. On the other hand, sync_inodes() walks through the
list twice!!? the total of available inodes, obviously only possible
with a circular list.

3. Despite ordering free inodes at the beginning of the list, and busy
inodes at the end, all functions always walks though the complete
list. Function get_empty_inode() even dispenses altogether of the list
and looks for a free inode directly from the inode_block[] array.

4. In file arch/i86/drivers/block/doshd.c, the number of floppy and
hard drives is needed at several places, and each time it is
calculated   from the drive_info[] array, wasting time and space.

NEW OPERATION

1. Assumed that the inode list is a circular list. Otherwise, fixing
the problem would require many modifications to inode.c.
Initialization of    inode list is fixed and at the same time reducing
code size. Also slightly modified some other functions to make them
faster and smaller.

2. In file arch/i86/drivers/block/doshd.c the number of drives is
saved in variables after being calculated the first time. From then
on, they are read from those variables.

3. In file arch/i86/drivers/block/doshd.c, function "bioshd_open()",
fixed a mess of conditional compilation statements involving the
CONFIG_BLK_DEV_BFD macro.

4. Fixed a bug in printk() function, when printing strings.

OTHER CHANGES

   Modified a misleading comment in file arch/i86/kernel/process.c,
suggesting that a syscall might not use more then 3 parameters.
Indeed, at least sys_select() requires 5 parameters.

   Simplified two functions in fs directory to remove unnecesary checks.

   Code size reduced by 96 bytes.

 The Image builded without errors. The kernel was tested with QEMU and
dioscuri emulators. Also in a PPro pc booting from floppy.

[-- Attachment #2: elksR.patch --]
[-- Type: application/octet-stream, Size: 8048 bytes --]

diff -Nurb elks.orig/arch/i86/drivers/block/doshd.c elks/arch/i86/drivers/block/doshd.c
--- elks.orig/arch/i86/drivers/block/doshd.c	2012-10-24 10:24:14.000000000 -0500
+++ elks/arch/i86/drivers/block/doshd.c	2012-10-24 10:55:48.000000000 -0500
@@ -43,7 +43,6 @@
 
 #define MAJOR_NR BIOSHD_MAJOR
 #define BIOSDISK
-#define NR_HD ((drive_info[1].heads)?2:((drive_info[0].heads)?1:0))
 
 #include "blk.h"
 
@@ -129,6 +128,12 @@
     0x00, 0x01			/* fd0, fd1 */
 };
 
+#ifdef CONFIG_BLK_DEV_BHD
+
+static int hdcount = 0;
+
+#endif
+
 static int bioshd_sizes[4 << 6] = { 0, };
 
 static void bioshd_geninit(void);
@@ -241,9 +246,6 @@
 
 #endif
 
-    printk("doshd: found %d floppy drive%c\n",
-	   ndrives, ndrives == 1 ? ' ' : 's');
-
     for (drive = 0; drive < ndrives; drive++) {
 	BD_AX = BIOSHD_DRIVE_PARMS;
 	BD_DX = drive;
@@ -395,7 +397,6 @@
 
 #ifdef CONFIG_BLK_DEV_BFD
     if (target >= 2) {		/* 2,3 are the floppydrives */
-#endif
 
 /* probing range can be easily extended by adding more values to these
  * two lists and adjusting for loop' parameters in line 420 and 435 (or
@@ -404,9 +405,6 @@
 
 	static char sector_probe[5] = { 8, 9, 15, 18, 36 };
 	static char track_probe[2] = { 40, 80 };
-
-#ifdef CONFIG_BLK_DEV_BFD
-
 	int count;
 
 	printk("fd: probing disc in /dev/fd%d\n", target % 2);
@@ -417,7 +415,6 @@
 	while (!dma_avail)
 	    sleep_on(&dma_wait);
 	dma_avail = 0;
-#endif
 
 /* First probe for cylinder number. We probe on sector 1, which is
  * safe for all formats, and if we get a seek error, we assume that
@@ -466,8 +463,6 @@
 
 #endif
 
-#ifdef CONFIG_BLK_DEV_BFD
-
 /* DMA code belongs out of the loop. */
 
 	dma_avail = 1;
@@ -516,50 +511,30 @@
 #endif
 #endif
 
-void init_bioshd(void)
+int init_bioshd(void)
 {
     register struct gendisk *ptr;
     register struct drive_infot *drivep;
     int count = 0, i;
 
-#ifdef CONFIG_BLK_DEV_BHD
-
-    int hdcount = 0;
-
-#endif
-
     printk("hd Driver Copyright (C) 1994 Yggdrasil Computing, Inc.\n"
 	   "Extended and modified for Linux 8086 by Alan Cox.\n");
 
 #ifdef CONFIG_BLK_DEV_BFD
-    bioshd_getfdinfo();
-#endif
-
-#ifdef CONFIG_BLK_DEV_BHD
-    bioshd_gethdinfo();
+    count = bioshd_getfdinfo();
+    printk("doshd: found %d floppy drive%c\n",
+	   count, count == 1 ? ' ' : 's');
 #endif
 
-    for (i = 0; i < 4; i++)
-	if (drive_info[i].heads) {
-	    count++;
-
 #ifdef CONFIG_BLK_DEV_BHD
-	    if (i <= 1)
-		hdcount++;
-#endif
-
-	}
-
-    if (!count)
-	return;
-
-#ifdef CONFIG_BLK_DEV_BHD
-
+    hdcount = bioshd_gethdinfo();
     printk("doshd: found %d hard drive%c\n", hdcount,
 	   hdcount == 1 ? ' ' : 's');
-
 #endif
 
+    if (!(count + hdcount))
+	return 0;
+
 #ifdef TEMP_PRINT_DRIVES_MAX
     for (i = 0; i < TEMP_PRINT_DRIVES_MAX; i++) {
 	drivep = drive_info + i;
@@ -609,8 +584,11 @@
 	    bioshd_gendisk.next = NULL;
 	}
 	bioshd_initialized = 1;
-    } else
+    } else {
 	printk("hd: unable to register\n");
+	return -1;
+    }
+    return 0;
 }
 
 static int bioshd_ioctl(struct inode *inode,
@@ -624,7 +602,7 @@
 	return -EINVAL;
     dev = DEVICE_NR(inode->i_rdev);
     drivep = &drive_info[dev];
-    if (dev >= NR_HD)
+    if (dev >= hdcount)
 	return -ENODEV;
     switch (cmd) {
     case HDIO_GETGEO:
diff -Nurb elks.orig/arch/i86/kernel/process.c elks/arch/i86/kernel/process.c
--- elks.orig/arch/i86/kernel/process.c	2012-08-18 13:28:59.000000000 -0500
+++ elks/arch/i86/kernel/process.c	2012-10-24 10:26:07.000000000 -0500
@@ -116,8 +116,8 @@
 	.globl _syscall_int
 
 !
-!	System calls enter here with ax as function and bx,cx,dx as
-!	parameters (and di,si if elks_syscall in elksemu is to be believed)
+!	System calls enter here with ax as function and bx,cx,dx,di and si
+!	as parameters.
 !	syscall returns a value in ax
 !
 
diff -Nurb elks.orig/fs/inode.c elks/fs/inode.c
--- elks.orig/fs/inode.c	2012-08-18 13:28:59.000000000 -0500
+++ elks/fs/inode.c	2012-10-24 10:26:07.000000000 -0500
@@ -29,9 +29,9 @@
 
 static void insert_inode_free(register struct inode *inode)
 {
-    register struct inode *in;
-    in = inode->i_next = first_inode;
-    inode->i_prev = first_inode->i_prev;
+    register struct inode *in = first_inode;
+    inode->i_next = in;
+    inode->i_prev = in->i_prev;
     in->i_prev = inode;
     inode->i_prev->i_next = inode;
     first_inode = inode;
@@ -42,9 +42,7 @@
     register struct inode *in;
     if (first_inode == inode)
 	first_inode = first_inode->i_next;
-    if ((in = inode->i_next))
-	in->i_prev = inode->i_prev;
-    if (inode->i_prev)
+    inode->i_next->i_prev = inode->i_prev;
 	inode->i_prev->i_next = inode->i_next;
     inode->i_next = inode->i_prev = NULL;
 }
@@ -52,31 +50,21 @@
 static void put_last_free(register struct inode *inode)
 {
     remove_inode_free(inode);
-    if (first_inode) {
+    inode->i_next = first_inode;
 	inode->i_prev = first_inode->i_prev;
 	inode->i_prev->i_next = inode;
-    } else
-	inode->i_prev = NULL;
-    inode->i_next = first_inode;
     inode->i_next->i_prev = inode;
 }
 
-static void setup_inodes(void)
+void inode_init(void)
 {
     register struct inode *inode = inode_block;
-    register char *pi;
-
-    pi = (char *)(nr_inodes = nr_free_inodes = NR_INODE);
 
+    nr_inodes = nr_free_inodes = NR_INODE;
+    first_inode = inode->i_next = inode->i_prev = inode;
     do {
-	insert_inode_free(inode++);
-    } while (--pi);
-}
-
-void inode_init(void)
-{
-    first_inode = NULL;
-    setup_inodes();
+	insert_inode_free(++inode);
+    } while (inode < &inode_block[NR_INODE-1]);
 }
 
 /*
@@ -125,7 +113,7 @@
     remove_inode_free(inode);
     if (inode->i_count)
 	nr_free_inodes++;
-    memset(inode, 0, sizeof(*inode));
+    memset(inode, 0, sizeof(struct inode));
     insert_inode_free(inode);
 }
 
@@ -135,7 +123,8 @@
     int i;
 
     next = first_inode;
-    for (i = nr_inodes; i > 0; i--) {
+    i = nr_inodes;
+    do {
 	inode = next;
 	next = inode->i_next;	/* clear_inode() changes the queues.. */
 	if (inode->i_dev != dev)
@@ -143,7 +132,7 @@
 	if (inode->i_count || inode->i_dirt || inode->i_lock)
 	    return 0;
 	clear_inode(inode);
-    }
+    } while(--i);
     return 1;
 }
 
@@ -153,7 +142,7 @@
     int i;
 
     inode = first_inode;
-    for (i = 0; i < nr_inodes; i++, inode = inode->i_next) {
+    for (i = nr_inodes; i > 0; i--, inode = inode->i_next) {
 	if (inode->i_dev != dev || !inode->i_count)
 	    continue;
 	if (inode == mount_rooti && inode->i_count == 1)
@@ -315,7 +304,8 @@
     int i;
 
     next = first_inode;
-    for (i = nr_inodes; i > 0; i--) {
+    i = nr_inodes;
+    do {
 	inode = next;
 	next = inode->i_next;	/* clear_inode() changes the queues.. */
 	if (inode->i_dev != dev)
@@ -325,7 +315,7 @@
 	    continue;
 	}
 	clear_inode(inode);
-    }
+    } while(--i);
 }
 
 void sync_inodes(kdev_t dev)
diff -Nurb elks.orig/fs/minix/namei.c elks/fs/minix/namei.c
--- elks.orig/fs/minix/namei.c	2012-10-17 12:12:32.000000000 -0500
+++ elks/fs/minix/namei.c	2012-10-24 10:26:07.000000000 -0500
@@ -25,7 +25,7 @@
 
 static int namecompare(size_t len, size_t max, char *name, register char *buf)
 {
-    return ((len > max) || ((len < max) && (buf[len] != 0)))
+    return ((len < max) && (buf[len] != 0))
 	? 0 : !fs_memcmp(name, buf, len);
 }
 
diff -Nurb elks.orig/fs/namei.c elks/fs/namei.c
--- elks.orig/fs/namei.c	2012-10-17 12:12:32.000000000 -0500
+++ elks/fs/namei.c	2012-10-24 10:26:07.000000000 -0500
@@ -186,8 +186,9 @@
     }
     while (1) {
 	thisname = pathname;
-	for (len = 0; (c = get_user_char(pathname++)) && (c != '/'); len++)
+	while ((c = get_user_char(pathname++)) && (c != '/'))
 	    /* Do nothing */ ;
+	len = pathname - thisname - 1;
 	if (!c)
 	    break;
 	base->i_count++;
diff -Nurb elks.orig/kernel/printk.c elks/kernel/printk.c
--- elks.orig/kernel/printk.c	2012-10-17 12:12:32.000000000 -0500
+++ elks/kernel/printk.c	2012-10-24 10:26:07.000000000 -0500
@@ -165,7 +165,7 @@
 		break;
 	    case 's':
 		cp = va_arg(p, char*);
-		while ((c == *cp++)) {
+		while ((c = *cp++)) {
 		    kputchar(c);
 		    width--;
 		}

                 reply	other threads:[~2012-11-17  0:27 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAD6VGuYvR7xSXYQj99=7FOmQeBGpTSE43BbT_OQcZtQUGROReQ@mail.gmail.com' \
    --to=lithoxs@gmail.com \
    --cc=linux-8086@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).