root/fs/isofs/inode.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. isofs_put_super
  2. parse_options
  3. isofs_read_super
  4. isofs_statfs
  5. isofs_bmap
  6. isofs_read_inode
  7. isofs_lookup_grandparent
  8. leak_check_malloc
  9. leak_check_free_s
  10. leak_check_bread
  11. leak_check_brelse

   1 /*
   2  *  linux/fs/isofs/inode.c
   3  * 
   4  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
   5  *
   6  *  (C) 1991  Linus Torvalds - minix filesystem
   7  */
   8 #include <linux/config.h>
   9 #include <linux/stat.h>
  10 #include <linux/sched.h>
  11 #include <linux/iso_fs.h>
  12 #include <linux/kernel.h>
  13 #include <linux/mm.h>
  14 #include <linux/string.h>
  15 #include <linux/locks.h>
  16 
  17 #include <asm/system.h>
  18 #include <asm/segment.h>
  19 #include <linux/errno.h>
  20 
  21 #ifndef CONFIG_BLK_DEV_SR
  22 #error The iso9660 filesystem can only be used with CDROM.
  23 #endif
  24 
  25 extern int check_cdrom_media_change(int, int);
  26 
  27 #ifdef LEAK_CHECK
  28 static int check_malloc = 0;
  29 static int check_bread = 0;
  30 #endif
  31 
  32 void isofs_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34         lock_super(sb);
  35 
  36 #ifdef LEAK_CHECK
  37         printk("Outstanding mallocs:%d, outstanding buffers: %d\n", 
  38                check_malloc, check_bread);
  39 #endif
  40         sb->s_dev = 0;
  41         unlock_super(sb);
  42         return;
  43 }
  44 
  45 static struct super_operations isofs_sops = { 
  46         isofs_read_inode,
  47         NULL,                   /* notify_change */
  48         NULL,                   /* write_inode */
  49         NULL,                   /* put_inode */
  50         isofs_put_super,
  51         NULL,                   /* write_super */
  52         isofs_statfs
  53 };
  54 
  55 
  56 
  57 static int parse_options(char *options,char *map,char *conversion, char * rock, char * cruft)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         char *this,*value;
  60 
  61         *map = 'n';
  62         *rock = 'y';
  63         *cruft = 'n';
  64         *conversion = 'a';
  65         if (!options) return 1;
  66         for (this = strtok(options,","); this; this = strtok(NULL,",")) {
  67                 if (strncmp(this,"norock",6) == 0) {
  68                   *rock = 'n';
  69                   continue;
  70                 };
  71                 if (strncmp(this,"cruft",5) == 0) {
  72                   *cruft = 'y';
  73                   continue;
  74                 };
  75                 if ((value = strchr(this,'=')) != NULL)
  76                         *value++ = 0;
  77                 if (!strcmp(this,"map") && value) {
  78                         if (value[0] && !value[1] && strchr("on",*value))
  79                                 *map = *value;
  80                         else if (!strcmp(value,"off")) *map = 'o';
  81                         else if (!strcmp(value,"normal")) *map = 'n';
  82                         else return 0;
  83                 }
  84                 else if (!strcmp(this,"conv") && value) {
  85                         if (value[0] && !value[1] && strchr("bta",*value))
  86                                 *conversion = *value;
  87                         else if (!strcmp(value,"binary")) *conversion = 'b';
  88                         else if (!strcmp(value,"text")) *conversion = 't';
  89                         else if (!strcmp(value,"mtext")) *conversion = 'm';
  90                         else if (!strcmp(value,"auto")) *conversion = 'a';
  91                         else return 0;
  92                 }
  93                 else return 0;
  94         }
  95         return 1;
  96 }
  97 
  98 struct super_block *isofs_read_super(struct super_block *s,void *data)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100         struct buffer_head *bh;
 101         int iso_blknum;
 102         int high_sierra;
 103         int dev=s->s_dev;
 104         struct iso_volume_descriptor *vdp;
 105         struct hs_volume_descriptor *hdp;
 106 
 107         struct iso_primary_descriptor *pri = NULL;
 108         struct hs_primary_descriptor *h_pri = NULL;
 109 
 110         struct iso_directory_record *rootp;
 111 
 112         char map, conversion, rock, cruft;
 113 
 114         if (!parse_options((char *) data,&map,&conversion, &rock, &cruft)) {
 115                 s->s_dev = 0;
 116                 return NULL;
 117         }
 118 
 119         lock_super(s);
 120 
 121         s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
 122 
 123         for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
 124                 if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-ISOFS_BUFFER_BITS), ISOFS_BUFFER_SIZE))) {
 125                         s->s_dev=0;
 126                         printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
 127                                dev, iso_blknum);
 128                         unlock_super(s);
 129                         return NULL;
 130                 }
 131 
 132                 vdp = (struct iso_volume_descriptor *)bh->b_data;
 133                 hdp = (struct hs_volume_descriptor *)bh->b_data;
 134 
 135                 
 136                 if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
 137                   if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
 138                         goto out;
 139                   if (isonum_711 (hdp->type) == ISO_VD_END)
 140                         goto out;
 141                 
 142                         s->u.isofs_sb.s_high_sierra = 1;
 143                         high_sierra = 1;
 144                         rock = 'n';
 145                         h_pri = (struct hs_primary_descriptor *)vdp;
 146                         break;
 147                 };
 148                 
 149                 if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
 150                   if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
 151                         goto out;
 152                   if (isonum_711 (vdp->type) == ISO_VD_END)
 153                         goto out;
 154                 
 155                         pri = (struct iso_primary_descriptor *)vdp;
 156                         break;
 157                 };
 158 
 159                 brelse(bh);
 160               }
 161         if(iso_blknum == 100) {
 162                 printk("Unable to identify CD-ROM format.\n");
 163                 s->s_dev = 0;
 164                 unlock_super(s);
 165                 return NULL;
 166         };
 167         
 168         
 169         if(high_sierra){
 170           rootp = (struct iso_directory_record *) h_pri->root_directory_record;
 171           if (isonum_723 (h_pri->volume_set_size) != 1) {
 172             printk("Multi-volume disks not (yet) supported.\n");
 173             goto out;
 174           };
 175           s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
 176           s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
 177           s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
 178         } else {
 179           rootp = (struct iso_directory_record *) pri->root_directory_record;
 180           if (isonum_723 (pri->volume_set_size) != 1) {
 181             printk("Multi-volume disks not (yet) supported.\n");
 182             goto out;
 183           };
 184           s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
 185           s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
 186           s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
 187         }
 188         
 189         s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
 190         
 191         s->u.isofs_sb.s_firstdatazone = isonum_733( rootp->extent) << 
 192                 (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
 193         s->s_magic = ISOFS_SUPER_MAGIC;
 194         
 195         /* The CDROM is read-only, has no nodes (devices) on it, and since
 196            all of the files appear to be owned by root, we really do not want
 197            to allow suid.  (suid or devices will not show up unless we have
 198            Rock Ridge extensions) */
 199         
 200         s->s_flags = MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
 201         
 202         if(s->u.isofs_sb.s_log_zone_size != (1 << ISOFS_BLOCK_BITS)) {
 203                 printk("1 <<Block bits != Block size\n");
 204                 goto out;
 205         };
 206         
 207         brelse(bh);
 208         
 209         printk("Max size:%d   Log zone size:%d\n",s->u.isofs_sb.s_max_size, 
 210                s->u.isofs_sb.s_log_zone_size);
 211         printk("First datazone:%d   Root inode number %d\n",s->u.isofs_sb.s_firstdatazone,
 212                isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
 213         if(high_sierra) printk("Disc in High Sierra format.\n");
 214         unlock_super(s);
 215         /* set up enough so that it can read an inode */
 216         
 217         s->s_dev = dev;
 218         s->s_op = &isofs_sops;
 219         s->u.isofs_sb.s_mapping = map;
 220         s->u.isofs_sb.s_rock = (rock == 'y' ? 1 : 0);
 221         s->u.isofs_sb.s_conversion = conversion;
 222         s->u.isofs_sb.s_cruft = cruft;
 223         s->s_blocksize = ISOFS_BUFFER_SIZE;
 224         s->s_mounted = iget(s, isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
 225         unlock_super(s);
 226 
 227         if (!(s->s_mounted)) {
 228                 s->s_dev=0;
 229                 printk("get root inode failed\n");
 230                 return NULL;
 231         }
 232         if(MAJOR(s->s_dev) == 11) {
 233                 /* Chech this one more time. */
 234                 if(check_cdrom_media_change(s->s_dev, 0))
 235                   goto out;
 236         };
 237         return s;
 238  out: /* Kick out for various error conditions */
 239         brelse(bh);
 240         s->s_dev = 0;
 241         unlock_super(s);
 242         return NULL;
 243 }
 244 
 245 void isofs_statfs (struct super_block *sb, struct statfs *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247         put_fs_long(ISOFS_SUPER_MAGIC, &buf->f_type);
 248         put_fs_long(1 << ISOFS_BLOCK_BITS, &buf->f_bsize);
 249         put_fs_long(sb->u.isofs_sb.s_nzones, &buf->f_blocks);
 250         put_fs_long(0, &buf->f_bfree);
 251         put_fs_long(0, &buf->f_bavail);
 252         put_fs_long(sb->u.isofs_sb.s_ninodes, &buf->f_files);
 253         put_fs_long(0, &buf->f_ffree);
 254         /* Don't know what value to put in buf->f_fsid */
 255 }
 256 
 257 int isofs_bmap(struct inode * inode,int block)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259 
 260         if (block<0) {
 261                 printk("_isofs_bmap: block<0");
 262                 return 0;
 263         }
 264         return inode->u.isofs_i.i_first_extent + block;
 265 }
 266 
 267 void isofs_read_inode(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 268 {
 269         struct buffer_head * bh;
 270         unsigned char * pnt, *cpnt = 0;
 271         struct iso_directory_record * raw_inode;
 272         int high_sierra;
 273         int block;
 274         int i;
 275         
 276         block = inode->i_ino >> ISOFS_BUFFER_BITS;
 277         if (!(bh=bread(inode->i_dev,block, ISOFS_BUFFER_SIZE)))
 278                 panic("unable to read i-node block");
 279         
 280         pnt = ((char *) bh->b_data) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
 281         
 282         raw_inode = ((struct iso_directory_record *) pnt);
 283         high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
 284 
 285         if ((inode->i_ino & (ISOFS_BUFFER_SIZE - 1)) + *pnt > ISOFS_BUFFER_SIZE){
 286                 cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
 287                 memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
 288                 brelse(bh);
 289                 if (!(bh = bread(inode->i_dev,++block, ISOFS_BUFFER_SIZE)))
 290                         panic("unable to read i-node block");
 291                 memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
 292                 pnt = ((char *) cpnt) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
 293                 raw_inode = ((struct iso_directory_record *) pnt);
 294         };
 295         
 296 
 297         inode->i_mode = 0444; /* Everybody gets to read the file. */
 298         inode->i_nlink = 1;
 299         
 300         if (raw_inode->flags[-high_sierra] & 2) {
 301                 inode->i_mode = 0555 | S_IFDIR;
 302                 inode->i_nlink = 2; /* There are always at least 2.  It is
 303                                        hard to figure out what is correct*/
 304         } else {
 305                 inode->i_mode = 0444; /* Everybody gets to read the file. */
 306                 inode->i_nlink = 1;
 307                 inode->i_mode |= S_IFREG;
 308 /* If there are no periods in the name, then set the execute permission bit */
 309                 for(i=0; i< raw_inode->name_len[0]; i++)
 310                         if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
 311                                 break;
 312                 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') 
 313                         inode->i_mode |= 0111; /* execute permission */
 314         };
 315         inode->i_uid = 0;
 316         inode->i_gid = 0;
 317         inode->i_size = isonum_733 (raw_inode->size);
 318 
 319 /* Some dipshit decided to store some other bit of information in the high
 320    byte of the file length.  Catch this and holler.  WARNING: this will make
 321    it impossible for a file to be > 16Mb on the CDROM!!!*/
 322 
 323         if(inode->i_sb->u.isofs_sb.s_cruft == 'y' && 
 324            inode->i_size & 0xff000000){
 325 /*        printk("Illegal format on cdrom.  Pester manufacturer.\n"); */
 326           inode->i_size &= 0x00ffffff;
 327         };
 328         
 329         if (isonum_723 (raw_inode->volume_sequence_number) != 1) {
 330                 panic("Multi volume CD somehow got mounted.\n");
 331         };
 332 
 333         if (raw_inode->interleave[0]) {
 334                 printk("Interleaved files not (yet) supported.\n");
 335                 inode->i_size = 0;
 336         };
 337 
 338 #ifdef DEBUG
 339         /* I have no idea what extended attributes are used for, so
 340            we will flag it for now */
 341         if(raw_inode->ext_attr_length[0] != 0){
 342                 printk("Extended attributes present for ISO file (%d).\n",
 343                        inode->i_ino);
 344         }
 345 #endif
 346         
 347         /* I have no idea what file_unit_size is used for, so
 348            we will flag it for now */
 349         if(raw_inode->file_unit_size[0] != 0){
 350                 printk("File unit size != 0 for ISO file.(%d)\n",inode->i_ino);
 351         }
 352 
 353         /* I have no idea what other flag bits are used for, so
 354            we will flag it for now */
 355         if((raw_inode->flags[-high_sierra] & ~2)!= 0){
 356                 printk("Unusual flag settings for ISO file.(%d %x)\n",
 357                        inode->i_ino, raw_inode->flags[-high_sierra]);
 358         }
 359 
 360 #ifdef DEBUG
 361         printk("Get inode %d: %d %d: %d\n",inode->i_ino, block, 
 362                ((int)pnt) & 0x3ff, inode->i_size);
 363 #endif
 364         
 365         inode->i_mtime = inode->i_atime = inode->i_ctime = 
 366           iso_date(raw_inode->date, high_sierra);
 367 
 368         inode->u.isofs_i.i_first_extent = isonum_733 (raw_inode->extent) << 
 369                 (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
 370         
 371         inode->u.isofs_i.i_backlink = -1; /* Will be used for previous directory */
 372         switch (inode->i_sb->u.isofs_sb.s_conversion){
 373         case 'a':
 374           inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
 375           break;
 376         case 'b':
 377           inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */
 378           break;
 379         case 't':
 380           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */
 381           break;
 382         case 'm':
 383           inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */
 384           break;
 385         };
 386         
 387 
 388 /* Now test for possible Rock Ridge extensions which will override some of
 389    these numbers in the inode structure. */
 390 
 391         if (!high_sierra)
 392           parse_rock_ridge_inode(raw_inode, inode);
 393         
 394 #ifdef DEBUG
 395         printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
 396 #endif
 397         brelse(bh);
 398         
 399         if (cpnt) {
 400                 kfree_s (cpnt, 1 << ISOFS_BLOCK_BITS);
 401                 cpnt = 0;
 402         };
 403         
 404         inode->i_op = NULL;
 405         if (S_ISREG(inode->i_mode))
 406                 inode->i_op = &isofs_file_inode_operations;
 407         else if (S_ISDIR(inode->i_mode))
 408                 inode->i_op = &isofs_dir_inode_operations;
 409         else if (S_ISLNK(inode->i_mode))
 410                 inode->i_op = &isofs_symlink_inode_operations;
 411         else if (S_ISCHR(inode->i_mode))
 412                 inode->i_op = &isofs_chrdev_inode_operations;
 413         else if (S_ISBLK(inode->i_mode))
 414                 inode->i_op = &isofs_blkdev_inode_operations;
 415 }
 416 
 417 /* There are times when we need to know the inode number of a parent of
 418    a particular directory.  When control passes through a routine that
 419    has access to the parent information, it fills it into the inode structure,
 420    but sometimes the inode gets flushed out of the queue, and someone
 421    remmembers the number.  When they try to open up again, we have lost
 422    the information.  The '..' entry on the disc points to the data area
 423    for a particular inode, so we can follow these links back up, but since
 424    we do not know the inode number, we do not actually know how large the
 425    directory is.  The disc is almost always correct, and there is
 426    enough error checking on the drive itself, but an open ended search
 427    makes me a little nervous.
 428 
 429    The bsd iso filesystem uses the extent number for an inode, and this
 430    would work really nicely for us except that the read_inode function
 431    would not have any clean way of finding the actual directory record
 432    that goes with the file.  If we had such info, then it would pay
 433    to change the inode numbers and eliminate this function.
 434 */
 435 
 436 int isofs_lookup_grandparent(struct inode * parent, int extent) {
     /* [previous][next][first][last][top][bottom][index][help] */
 437         unsigned int block,offset;
 438         int parent_dir, inode_number;
 439         int old_offset;
 440         char * cpnt = 0;
 441         int result;
 442         struct buffer_head * bh;
 443         struct iso_directory_record * de;
 444         
 445         offset = 0;
 446         block = extent << (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
 447         if (!(bh = bread(parent->i_dev, block, ISOFS_BUFFER_SIZE)))  return 0;
 448         
 449         while (1 == 1) {
 450                 de = (struct iso_directory_record *) (offset + bh->b_data);
 451                 
 452                 if (*((char*) de) == 0) 
 453                         {
 454                                 brelse(bh);
 455                                 return -1;
 456                         }
 457                 
 458                 offset += *((unsigned char*) de);
 459                 
 460                 if (offset >=  ISOFS_BUFFER_SIZE) 
 461                         {
 462                                 printk(".. Directory not in first block of directory.\n");
 463                                 brelse(bh);
 464                                 return -1;
 465                         }
 466                 
 467                 if (de->name_len[0] == 1 && de->name[0] == 1) 
 468                         {
 469                                 brelse(bh);
 470                                 parent_dir = find_rock_ridge_relocation(de, parent);
 471                                 break;
 472                         };
 473         }
 474 #ifdef DEBUG
 475         printk("Parent dir:%x\n",parent_dir);
 476 #endif
 477         /* Now we know the extent where the parent dir starts on.  We have no
 478            idea how long it is, so we just start reading until we either find it
 479            or we find some kind of unreasonable circumstance. */
 480         
 481         result = -1;
 482         
 483         offset = 0;
 484         block = parent_dir << (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
 485         if (!block || !(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
 486                 return 0;
 487         
 488         while (1==1) {
 489                 de = (struct iso_directory_record *) (offset + bh->b_data);
 490                 inode_number = (block << ISOFS_BUFFER_BITS)+(offset & (ISOFS_BUFFER_SIZE - 1));
 491                 
 492                 /* If the length byte is zero, we should move on to the next CDROM sector.
 493                    If we are at the end of the directory, we kick out of the while loop. */
 494                 
 495                 if (*((char*) de) == 0) 
 496                         {
 497                                 brelse(bh);
 498                                 offset = 0;
 499                                 block++;
 500                                 if(block & 1) return -1;
 501                                 if (!block || !(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
 502                                         return -1;
 503                                 continue;
 504                         }
 505                 
 506                 /* Make sure that the entire directory record is in the current bh block.
 507                    If not, we malloc a buffer, and put the two halves together, so that
 508                    we can cleanly read the block */
 509                 
 510                 old_offset = offset;
 511                 offset += *((unsigned char*) de);
 512                 if (offset >=  ISOFS_BUFFER_SIZE) 
 513                         {
 514                                 cpnt = kmalloc(1<<ISOFS_BLOCK_BITS,GFP_KERNEL);
 515                                 memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
 516                                 de = (struct iso_directory_record *) (old_offset + cpnt);
 517                                 brelse(bh);
 518                                 offset -= ISOFS_BUFFER_SIZE;
 519                                 block++;
 520                                 if((block & 1) == 0) return -1;
 521                                 if (!(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
 522                                         return -1;
 523                                 memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
 524                         }
 525                 
 526                 if (find_rock_ridge_relocation(de, parent) == extent){
 527                         result = inode_number;
 528                         goto out;
 529                 };
 530                 
 531                 if (cpnt) {
 532                         kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
 533                         cpnt = 0;
 534                 };
 535         }
 536         /* We go here for any condition we cannot handle.  We also drop through
 537            to here at the end of the directory. */
 538         
 539  out:
 540         if (cpnt) {
 541                 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
 542                 cpnt = 0;
 543         };
 544         brelse(bh);
 545 #ifdef DEBUG
 546         printk("Resultant Inode %d\n",result);
 547 #endif
 548         return result;
 549 }
 550     
 551 #ifdef LEAK_CHECK
 552 #undef malloc
 553 #undef free_s
 554 #undef bread
 555 #undef brelse
 556 
 557 void * leak_check_malloc(unsigned int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 558   void * tmp;
 559   check_malloc++;
 560   tmp = kmalloc(size, GFP_KERNEL);
 561   return tmp;
 562 }
 563 
 564 void leak_check_free_s(void * obj, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 565   check_malloc--;
 566   return kfree_s(obj, size);
 567 }
 568 
 569 struct buffer_head * leak_check_bread(int dev, int block, int size){
     /* [previous][next][first][last][top][bottom][index][help] */
 570   check_bread++;
 571   return bread(dev, block, size);
 572 }
 573 
 574 void leak_check_brelse(struct buffer_head * bh){
     /* [previous][next][first][last][top][bottom][index][help] */
 575   check_bread--;
 576   return brelse(bh);
 577 }
 578 
 579 #endif

/* [previous][next][first][last][top][bottom][index][help] */