]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-isofs-128GB.patch
- moving config-* fixed.
[packages/kernel.git] / kernel-isofs-128GB.patch
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
4 @@ -106,7 +106,7 @@
5  {
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;
12         int len;
13 @@ -116,8 +116,9 @@
14         struct iso_directory_record *de;
15         struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
16  
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);
22  
23         while (filp->f_pos < inode->i_size) {
24                 int de_len;
25 @@ -129,8 +130,13 @@
26                 }
27  
28                 de = (struct iso_directory_record *) (bh->b_data + offset);
29 -               if (first_de)
30 -                       inode_number = (bh->b_blocknr << bufbits) + offset;
31 +               if (first_de) {
32 +                       if (bh->b_blocknr > ISOFS_BLOCK_MAX) {
33 +                               printk(KERN_ERR "isofs: dir.c Attempt to set inode to an unsupported block.\n");
34 +                               break;
35 +                       }
36 +                       inode_number = (bh->b_blocknr << 6) + isofs_offset_to_nrec(bh, offset);
37 +               }
38  
39                 de_len = *(unsigned char *) de;
40  
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
44 @@ -7,6 +7,7 @@
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
49   */
50  
51  #include <linux/config.h>
52 @@ -738,19 +739,37 @@
53         /* Set this for reference. Its not currently used except on write
54            which we don't have .. */
55            
56 -       /* RDE: data zone now byte offset! */
57 -
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.
69 +        *
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");
82 +               goto out_freebh;
83 +       }
84         sbi->s_firstdatazone = first_data_zone;
85  #ifndef BEQUIET
86         printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
87                sbi->s_max_size,
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");
96  #endif
97 @@ -767,9 +786,13 @@
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");
109 +                       goto out_freebh;
110 +               }
111         }
112  
113         /*
114 @@ -835,7 +858,7 @@
115          * the s_rock flag. Once we have the final s_rock value,
116          * we then decide whether to use the Joliet descriptor.
117          */
118 -       inode = iget(s, sbi->s_firstdatazone);
119 +       inode = iget(s, sbi->s_firstdatazone << 6);
120  
121         /*
122          * If this disk has both Rock Ridge and Joliet on it, then we
123 @@ -854,7 +877,7 @@
124                         printk(KERN_DEBUG 
125                                 "ISOFS: changing to secondary root\n");
126                         iput(inode);
127 -                       inode = iget(s, sbi->s_firstdatazone);
128 +                       inode = iget(s, sbi->s_firstdatazone << 6);
129                 }
130         }
131  
132 @@ -1044,7 +1067,7 @@
133         return isofs_get_blocks(inode, iblock, &bh_result, 1) ? 0 : -EIO;
134  }
135  
136 -static int isofs_bmap(struct inode *inode, int block)
137 +static int isofs_bmap(struct inode *inode, sector_t block)
138  {
139         struct buffer_head dummy;
140         int error;
141 @@ -1097,11 +1120,10 @@
142  
143  static int isofs_read_level3_size(struct inode * inode)
144  {
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;
151         int i = 0;
152         int more_entries = 0;
153         struct iso_directory_record * tmpde = NULL;
154 @@ -1110,8 +1132,9 @@
155         inode->i_size = 0;
156         ei->i_next_section_ino = 0;
157  
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 */
163  
164         do {
165                 struct iso_directory_record * de;
166 @@ -1121,6 +1144,7 @@
167                         bh = sb_bread(inode->i_sb, block);
168                         if (!bh)
169                                 goto out_noread;
170 +                       offset = isofs_nrec_to_offset(bh, nrec);
171                 }
172                 de = (struct iso_directory_record *) (bh->b_data + offset);
173                 de_len = *(unsigned char *) de;
174 @@ -1128,12 +1152,16 @@
175                 if (de_len == 0) {
176                         brelse(bh);
177                         bh = NULL;
178 -                       f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
179 -                       block = f_pos >> ISOFS_BUFFER_BITS(inode);
180 -                       offset = 0;
181 +                       ++block;
182 +                       nrec = 0;
183                         continue;
184                 }
185  
186 +               if (block > ISOFS_BLOCK_MAX) {
187 +                       goto out_toofar;
188 +               }
189 +
190 +               first_block = block;
191                 offset += de_len;
192  
193                 /* Make sure we have a full directory entry */
194 @@ -1160,11 +1188,11 @@
195  
196                 inode->i_size += isonum_733(de->size);
197                 if (i == 1)
198 -                       ei->i_next_section_ino = f_pos;
199 +                       ei->i_next_section_ino = (first_block << 6) + nrec;
200  
201                 more_entries = de->flags[-high_sierra] & 0x80;
202  
203 -               f_pos += de_len;
204 +               ++nrec;
205                 i++;
206                 if(i > 100)
207                         goto out_toomany;
208 @@ -1176,6 +1204,12 @@
209                 brelse(bh);
210         return 0;
211  
212 +out_toofar:
213 +       printk(KERN_ERR "isofs: inode.c: Attempt to set inode to unsupported block.\n");
214 +       if (bh)
215 +               brelse(bh);
216 +       return -EIO;
217 +
218  out_nomem:
219         if (bh)
220                 brelse(bh);
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);
227         goto out;
228  }
229  
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 @@
241         if (!bh)
242                 goto out_badread;
243  
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;
248  
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
252 @@ -63,8 +63,7 @@
253  {
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);
261  
262 @@ -74,6 +73,7 @@
263         f_pos = 0;
264         offset = 0;
265         block = 0;
266 +       nrec = 0;   /* zero-based */
267  
268         while (f_pos < dir->i_size) {
269                 struct iso_directory_record * de;
270 @@ -86,21 +86,28 @@
271                                 return 0;
272                 }
273  
274 +               if (bh->b_blocknr > ISOFS_BLOCK_MAX) {
275 +                       printk(KERN_ERR "isofs: namei.c: Attempt to set inode to an unsupported block.\n");
276 +                       break;
277 +               }
278 +
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;
282  
283                 de_len = *(unsigned char *) de;
284                 if (!de_len) {
285                         brelse(bh);
286                         bh = NULL;
287                         f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
288 -                       block = f_pos >> bufbits;
289 +                       ++block;
290                         offset = 0;
291 +                       nrec = 0;
292                         continue;
293                 }
294  
295                 offset += de_len;
296                 f_pos += de_len;
297 +               ++nrec;
298  
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
304 @@ -306,9 +306,7 @@
305         goto out;
306        case SIG('C','L'):
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));
312         if (!reloc)
313                 goto out;
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;
321         char *rpnt = link;
322         unsigned char *pnt;
323         struct iso_directory_record *raw_inode;
324         CONTINUE_DECLS;
325 -       int block;
326 +       unsigned long block, offset;
327         int sig;
328         int len;
329         unsigned char *chr;
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");
333  
334 -       block = inode->i_ino >> bufbits;
335 +       block = inode->i_ino >> 6;
336         lock_kernel();
337         bh = sb_bread(inode->i_sb, block);
338         if (!bh)
339                 goto out_noread;
340  
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;
344  
345         raw_inode = (struct iso_directory_record *) pnt;
346  
347         /*
348          * If we go past the end of the buffer, there is some sort of error.
349          */
350 -       if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
351 +       if (offset + *pnt > bufsize)
352                 goto out_bad_span;
353  
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
358 @@ -3,6 +3,7 @@
359  #define _ISOFS_FS_H
360  
361  #include <linux/types.h>
362 +#include <linux/buffer_head.h>
363  /*
364   * The isofs filesystem constants/structures
365   */
366 @@ -158,6 +159,9 @@
367  #define ISOFS_BLOCK_BITS 11
368  #define ISOFS_BLOCK_SIZE 2048
369  
370 +/* The current implementation can only address ISOFS_BLOCK_MAX blocks. */
371 +#define ISOFS_BLOCK_MAX 0x3ffffff
372 +
373  #define ISOFS_BUFFER_SIZE(INODE) ((INODE)->i_sb->s_blocksize)
374  #define ISOFS_BUFFER_BITS(INODE) ((INODE)->i_sb->s_blocksize_bits)
375  
376 @@ -216,6 +220,49 @@
377         /* Ignore bigendian datum due to broken mastering programs */
378         return le32_to_cpu(get_unaligned((u32 *)p));
379  }
380 +
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)
385 +{
386 +       unsigned long rv = 0;
387 +       for ( ; nrec && (rv < bh->b_size) ; --nrec) {
388 +               rv += (unsigned char)bh->b_data[rv];
389 +       }
390 +       /* See the comment below in isofs_offset_to_nrec() regarding
391 +        * BUG_ON(rv > 60). */
392 +       BUG_ON(rv > 2014);
393 +       BUG_ON(rv >= bh->b_size);
394 +       return rv;
395 +}
396 +
397 +/* Find the record number "nrec" given the offset into the buffer "bh"
398 + * where this directory record is located.  Remember that "nrec" is
399 + * zero-based. */
400 +static inline unsigned long isofs_offset_to_nrec(struct buffer_head *bh,
401 +                                                unsigned long offset)
402 +{
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] ) {
407 +               ++rv;           
408 +       }
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. */
419 +       BUG_ON(rv > 60);
420 +       BUG_ON(i != offset);
421 +       return rv;
422 +}
423  extern int iso_date(char *, int);
424  
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
429 @@ -13,7 +13,7 @@
430   * iso fs inode data in memory
431   */
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;
This page took 0.0594 seconds and 3 git commands to generate.