1 diff -uNr linux-2.6.7-rc1/fs/isofs.orig/dir.c linux-2.6.7-rc1/fs/isofs/dir.c
2 --- linux-2.6.7-rc1/fs/isofs.orig/dir.c 2004-05-23 07:54:43.000000000 +0200
3 +++ linux-2.6.7-rc1/fs/isofs/dir.c 2004-05-28 13:39:16.235408536 +0200
6 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
7 unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
8 - unsigned int block, offset;
9 + unsigned long block, offset;
10 int inode_number = 0; /* Quiet GCC */
11 struct buffer_head *bh = NULL;
14 struct iso_directory_record *de;
15 struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
17 - offset = filp->f_pos & (bufsize - 1);
18 - block = filp->f_pos >> bufbits;
19 + /* ISO 9660 limits file sizes to 32 bits. */
20 + offset = (unsigned long)(filp->f_pos & (bufsize - 1));
21 + block = (unsigned long)(filp->f_pos >> bufbits);
23 while (filp->f_pos < inode->i_size) {
28 de = (struct iso_directory_record *) (bh->b_data + offset);
30 - inode_number = (bh->b_blocknr << bufbits) + offset;
32 + if (bh->b_blocknr > ISOFS_BLOCK_MAX) {
33 + printk(KERN_ERR "isofs: dir.c Attempt to set inode to an unsupported block.\n");
36 + inode_number = (bh->b_blocknr << 6) + isofs_offset_to_nrec(bh, offset);
39 de_len = *(unsigned char *) de;
41 diff -uNr linux-2.6.7-rc1/fs/isofs.orig/inode.c linux-2.6.7-rc1/fs/isofs/inode.c
42 --- linux-2.6.7-rc1/fs/isofs.orig/inode.c 2004-05-28 13:01:10.000000000 +0200
43 +++ linux-2.6.7-rc1/fs/isofs/inode.c 2004-05-28 14:00:34.163133992 +0200
45 * 1995 Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs.
46 * 1997 Gordon Chaffee - Joliet CDs
47 * 1998 Eric Lammerts - ISO 9660 Level 3
48 + * 2004 Paul Serice - Inodes up tp 128GB
51 #include <linux/config.h>
53 /* Set this for reference. Its not currently used except on write
54 which we don't have .. */
56 - /* RDE: data zone now byte offset! */
58 - first_data_zone = ((isonum_733 (rootp->extent) +
59 - isonum_711 (rootp->ext_attr_length))
60 - << sbi->s_log_zone_size);
61 + /* The inode number is encoded with the lower 6 bits dedicated
62 + * to storing the relative count of the directory record that
63 + * holds the meta-data for this directory entry. The
64 + * remaining bits hold the block number where the directory
65 + * record can be found. The relative count of the directory
66 + * record is zero-based. Thus, the first directory record is
67 + * given a relative count of 0. The second directory record
68 + * is given a relative count of 1 and so on.
70 + * This scheme (suggested by Sergey Vlasov) allows us to
71 + * access meta-data up to the first 128GB in the common case
72 + * where the logical block size is 2048 bytes and an inode
73 + * number is 32 bits. This is an improvement over the old
74 + * scheme where the meta-data could only live in the first
75 + * 4GB. This should buy us a number of years. */
76 + first_data_zone = isonum_733 (rootp->extent) +
77 + isonum_711 (rootp->ext_attr_length);
78 + sbi->s_firstdatazone = first_data_zone;
79 + if (first_data_zone > ISOFS_BLOCK_MAX) {
80 + printk(KERN_ERR "isofs: inode.c: Attempt to set "
81 + "root inode to an unsupported block.\n");
84 sbi->s_firstdatazone = first_data_zone;
86 printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n",
88 1UL << sbi->s_log_zone_size);
89 printk(KERN_DEBUG "First datazone:%ld Root inode number:%ld\n",
90 - sbi->s_firstdatazone >> sbi->s_log_zone_size,
91 - sbi->s_firstdatazone);
92 + sbi->s_firstdatazone,
93 + sbi->s_firstdatazone << 6);
94 if(sbi->s_high_sierra)
95 printk(KERN_DEBUG "Disc in High Sierra format.\n");
98 pri = (struct iso_primary_descriptor *) sec;
99 rootp = (struct iso_directory_record *)
100 pri->root_directory_record;
101 - first_data_zone = ((isonum_733 (rootp->extent) +
102 - isonum_711 (rootp->ext_attr_length))
103 - << sbi->s_log_zone_size);
104 + first_data_zone = isonum_733 (rootp->extent) +
105 + isonum_711 (rootp->ext_attr_length);
106 + if (first_data_zone > ISOFS_BLOCK_MAX) {
107 + printk(KERN_ERR "isofs: inode.c: Attempt to set "
108 + "root inode to an unsupported block.\n");
115 * the s_rock flag. Once we have the final s_rock value,
116 * we then decide whether to use the Joliet descriptor.
118 - inode = iget(s, sbi->s_firstdatazone);
119 + inode = iget(s, sbi->s_firstdatazone << 6);
122 * If this disk has both Rock Ridge and Joliet on it, then we
125 "ISOFS: changing to secondary root\n");
127 - inode = iget(s, sbi->s_firstdatazone);
128 + inode = iget(s, sbi->s_firstdatazone << 6);
132 @@ -1044,7 +1067,7 @@
133 return isofs_get_blocks(inode, iblock, &bh_result, 1) ? 0 : -EIO;
136 -static int isofs_bmap(struct inode *inode, int block)
137 +static int isofs_bmap(struct inode *inode, sector_t block)
139 struct buffer_head dummy;
141 @@ -1097,11 +1120,10 @@
143 static int isofs_read_level3_size(struct inode * inode)
145 - unsigned long f_pos = inode->i_ino;
146 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
147 int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
148 struct buffer_head * bh = NULL;
149 - unsigned long block, offset;
150 + unsigned long block, offset, nrec, first_block;
152 int more_entries = 0;
153 struct iso_directory_record * tmpde = NULL;
154 @@ -1110,8 +1132,9 @@
156 ei->i_next_section_ino = 0;
158 - block = f_pos >> ISOFS_BUFFER_BITS(inode);
159 - offset = f_pos & (bufsize-1);
160 + block = inode->i_ino >> 6;
161 + nrec = inode->i_ino & 63;
162 + offset = 0; /* Quiet GCC */
165 struct iso_directory_record * de;
166 @@ -1121,6 +1144,7 @@
167 bh = sb_bread(inode->i_sb, block);
170 + offset = isofs_nrec_to_offset(bh, nrec);
172 de = (struct iso_directory_record *) (bh->b_data + offset);
173 de_len = *(unsigned char *) de;
174 @@ -1128,12 +1152,16 @@
178 - f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
179 - block = f_pos >> ISOFS_BUFFER_BITS(inode);
186 + if (block > ISOFS_BLOCK_MAX) {
190 + first_block = block;
193 /* Make sure we have a full directory entry */
194 @@ -1160,11 +1188,11 @@
196 inode->i_size += isonum_733(de->size);
198 - ei->i_next_section_ino = f_pos;
199 + ei->i_next_section_ino = (first_block << 6) + nrec;
201 more_entries = de->flags[-high_sierra] & 0x80;
208 @@ -1176,6 +1204,12 @@
213 + printk(KERN_ERR "isofs: inode.c: Attempt to set inode to unsupported block.\n");
221 @@ -1191,7 +1225,7 @@
222 printk(KERN_INFO "isofs_read_level3_size: "
223 "More than 100 file sections ?!?, aborting...\n"
224 "isofs_read_level3_size: inode=%lu ino=%lu\n",
225 - inode->i_ino, f_pos);
226 + inode->i_ino, (first_block << 6) + nrec);
230 @@ -1200,7 +1234,8 @@
231 struct super_block *sb = inode->i_sb;
232 struct isofs_sb_info *sbi = ISOFS_SB(sb);
233 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
234 - int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
235 + unsigned long block = inode->i_ino >> 6;
236 + unsigned long nrec = inode->i_ino & 0x3f;
237 int high_sierra = sbi->s_high_sierra;
238 struct buffer_head * bh = NULL;
239 struct iso_directory_record * de;
240 @@ -1214,7 +1249,7 @@
244 - offset = (inode->i_ino & (bufsize - 1));
245 + offset = isofs_nrec_to_offset(bh, nrec);
246 de = (struct iso_directory_record *) (bh->b_data + offset);
247 de_len = *(unsigned char *) de;
249 diff -uNr linux-2.6.7-rc1/fs/isofs.orig/namei.c linux-2.6.7-rc1/fs/isofs/namei.c
250 --- linux-2.6.7-rc1/fs/isofs.orig/namei.c 2004-05-23 07:54:29.000000000 +0200
251 +++ linux-2.6.7-rc1/fs/isofs/namei.c 2004-05-28 14:05:24.063062504 +0200
254 unsigned long inode_number;
255 unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
256 - unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
257 - unsigned int block, f_pos, offset;
258 + unsigned long block, f_pos, offset, nrec;
259 struct buffer_head * bh = NULL;
260 struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
266 + nrec = 0; /* zero-based */
268 while (f_pos < dir->i_size) {
269 struct iso_directory_record * de;
274 + if (bh->b_blocknr > ISOFS_BLOCK_MAX) {
275 + printk(KERN_ERR "isofs: namei.c: Attempt to set inode to an unsupported block.\n");
279 de = (struct iso_directory_record *) (bh->b_data + offset);
280 - inode_number = (bh->b_blocknr << bufbits) + offset;
281 + inode_number = (bh->b_blocknr << 6) + nrec;
283 de_len = *(unsigned char *) de;
287 f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
288 - block = f_pos >> bufbits;
299 /* Make sure we have a full directory entry */
300 if (offset >= bufsize) {
301 diff -uNr linux-2.6.7-rc1/fs/isofs.orig/rock.c linux-2.6.7-rc1/fs/isofs/rock.c
302 --- linux-2.6.7-rc1/fs/isofs.orig/rock.c 2004-05-23 07:54:19.000000000 +0200
303 +++ linux-2.6.7-rc1/fs/isofs/rock.c 2004-05-28 14:09:36.574674904 +0200
307 ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
308 - reloc = iget(inode->i_sb,
309 - (ISOFS_I(inode)->i_first_extent <<
310 - ISOFS_SB(inode->i_sb)->s_log_zone_size));
311 + reloc = iget(inode->i_sb, (ISOFS_I(inode)->i_first_extent << 6));
314 inode->i_mode = reloc->i_mode;
315 @@ -449,13 +447,12 @@
316 struct inode *inode = page->mapping->host;
317 char *link = kmap(page);
318 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
319 - unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
320 struct buffer_head *bh;
323 struct iso_directory_record *raw_inode;
326 + unsigned long block, offset;
330 @@ -464,20 +461,21 @@
331 if (!ISOFS_SB(inode->i_sb)->s_rock)
332 panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
334 - block = inode->i_ino >> bufbits;
335 + block = inode->i_ino >> 6;
337 bh = sb_bread(inode->i_sb, block);
341 - pnt = (unsigned char *) bh->b_data + (inode->i_ino & (bufsize - 1));
342 + offset = isofs_nrec_to_offset(bh, inode->i_ino & 0x3f);
343 + pnt = (unsigned char *) bh->b_data + offset;
345 raw_inode = (struct iso_directory_record *) pnt;
348 * If we go past the end of the buffer, there is some sort of error.
350 - if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
351 + if (offset + *pnt > bufsize)
354 /* Now test for possible Rock Ridge extensions which will override
355 diff -uNr linux-2.6.7-rc1/include/linux.orig/iso_fs.h linux-2.6.7-rc1/include/linux/iso_fs.h
356 --- linux-2.6.7-rc1/include/linux.orig/iso_fs.h 2004-05-23 07:54:21.000000000 +0200
357 +++ linux-2.6.7-rc1/include/linux/iso_fs.h 2004-05-28 14:19:14.746779384 +0200
361 #include <linux/types.h>
362 +#include <linux/buffer_head.h>
364 * The isofs filesystem constants/structures
367 #define ISOFS_BLOCK_BITS 11
368 #define ISOFS_BLOCK_SIZE 2048
370 +/* The current implementation can only address ISOFS_BLOCK_MAX blocks. */
371 +#define ISOFS_BLOCK_MAX 0x3ffffff
373 #define ISOFS_BUFFER_SIZE(INODE) ((INODE)->i_sb->s_blocksize)
374 #define ISOFS_BUFFER_BITS(INODE) ((INODE)->i_sb->s_blocksize_bits)
377 /* Ignore bigendian datum due to broken mastering programs */
378 return le32_to_cpu(get_unaligned((u32 *)p));
381 +/* Find the offset into the buffer "bh" where this directory record is
382 + * located given the record number "nrec". */
383 +static inline unsigned long isofs_nrec_to_offset(struct buffer_head *bh,
384 + unsigned long nrec)
386 + unsigned long rv = 0;
387 + for ( ; nrec && (rv < bh->b_size) ; --nrec) {
388 + rv += (unsigned char)bh->b_data[rv];
390 + /* See the comment below in isofs_offset_to_nrec() regarding
391 + * BUG_ON(rv > 60). */
393 + BUG_ON(rv >= bh->b_size);
397 +/* Find the record number "nrec" given the offset into the buffer "bh"
398 + * where this directory record is located. Remember that "nrec" is
400 +static inline unsigned long isofs_offset_to_nrec(struct buffer_head *bh,
401 + unsigned long offset)
403 + unsigned long i = 0;
404 + unsigned long rv = 0;
405 + for ( ; (i < offset) && (i < bh->b_size) ;
406 + i += (unsigned char)bh->b_data[i] ) {
409 + /* If you trip the BUG_ON(rv > 60) bug, it probably means your
410 + * block size is greater than 2048 bytes. You will want to
411 + * read Section 6.1 of the ISO 9660 standard. I think it is
412 + * technically possible for the block size to be greater than
413 + * 2048 bytes. Our inode scheme of using the lower 6 bits to
414 + * store the count of the directory record depends on this as
415 + * the limiting factor that 6 bits is enough to address each
416 + * directory record in a single block. However at this time,
417 + * conventional wisdom says iso9660 blocks are always 2048
418 + * bytes so maybe I've misread the standard. */
420 + BUG_ON(i != offset);
423 extern int iso_date(char *, int);
425 struct inode; /* To make gcc happy */
426 diff -uNr linux-2.6.7-rc1/include/linux.orig/iso_fs_i.h linux-2.6.7-rc1/include/linux/iso_fs_i.h
427 --- linux-2.6.7-rc1/include/linux.orig/iso_fs_i.h 2004-05-23 07:53:57.000000000 +0200
428 +++ linux-2.6.7-rc1/include/linux/iso_fs_i.h 2004-05-28 14:19:34.432786656 +0200
430 * iso fs inode data in memory
432 struct iso_inode_info {
433 - unsigned int i_first_extent;
434 + unsigned long i_first_extent;
435 unsigned char i_file_format;
436 unsigned char i_format_parm[3];
437 unsigned long i_next_section_ino;