Re: CD Filesystem still broken!

Gordon Chaffee (chaffee@dilbert.cs.berkeley.edu)
Thu, 30 Oct 1997 02:58:18 -0800


Steven N. Hirsch writes:
> The symptoms are simple: About 2/3 of the directory entries are simply
> missing. What is there seems to be correct.

With the data you sent me, I was able to find a problem. Here is a patch
that should fix it. Let me know if there are any new problems that it
causes. I've run it through some quick tests, and it seems fine.

- Gordon

--- linux-2.1.60-clean/fs/isofs/namei.c Sat Oct 25 02:46:35 1997
+++ linux/fs/isofs/namei.c Thu Oct 30 03:45:52 1997
@@ -66,7 +66,7 @@
unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
unsigned int block, i, f_pos, offset,
inode_number = 0; /* shut gcc up */
- struct buffer_head * bh;
+ struct buffer_head * bh , * retval = NULL;
unsigned int old_offset;
int dlen, match;
char * dpnt;
@@ -86,7 +86,7 @@
block = isofs_bmap(dir,f_pos >> bufbits);

if (!block || !(bh = bread(dir->i_dev,block,bufsize))) return NULL;
-
+
while (f_pos < dir->i_size) {

/* if de is in kmalloc'd memory, do not point to the
@@ -118,13 +118,14 @@
+ ISOFS_BLOCK_SIZE);
}
brelse(bh);
+ bh = NULL;

if (f_pos >= dir->i_size)
- return 0;
+ break;

block = isofs_bmap(dir,f_pos>>bufbits);
if (!block || !(bh = bread(dir->i_dev,block,bufsize)))
- return NULL;
+ break;

continue; /* Will kick out if past end of directory */
}
@@ -145,7 +146,7 @@
block = isofs_bmap(dir,f_pos>>bufbits);
if (!block ||
!(bh_next = bread(dir->i_dev,block,bufsize)))
- return NULL;
+ break;

de = (struct iso_directory_record *)
kmalloc(offset - old_offset, GFP_KERNEL);
@@ -162,14 +163,14 @@

if (dir->i_sb->u.isofs_sb.s_rock ||
dir->i_sb->u.isofs_sb.s_joliet_level) {
- page = (unsigned char *)
- __get_free_page(GFP_KERNEL);
- if (!page) return NULL;
+ if (! page) {
+ page = (unsigned char *)
+ __get_free_page(GFP_KERNEL);
+ if (!page) break;
+ }
}
if (dir->i_sb->u.isofs_sb.s_rock &&
((i = get_rock_ridge_filename(de, page, dir)))) {
- if (i == -1)
- goto out;/* Relocated deep directory */
dlen = i;
dpnt = page;
#ifdef CONFIG_JOLIET
@@ -203,8 +204,6 @@
{
match = isofs_match(namelen,name,dpnt,dlen);
}
-
- if (page) free_page((unsigned long) page);
if (match) {
if(inode_number == -1) {
/* Should only happen for the '..' entry */
@@ -213,16 +212,17 @@
find_rock_ridge_relocation(de,dir));
}
*ino = inode_number;
- if(de_not_in_buf)
- kfree(de);
- return bh;
+ retval = bh;
+ bh = NULL;
+ break;
}
}
- out:
- brelse(bh);
+ if (page) free_page((unsigned long) page);
+ if (bh) brelse(bh);
if(de_not_in_buf)
kfree(de);
- return NULL;
+ return retval;
+
}

int isofs_lookup(struct inode * dir, struct dentry * dentry)