1 /* 2 * linux/fs/isofs/rock.c 3 * 4 * (C) 1992, 1993 Eric Youngdale 5 * 6 * Rock Ridge Extensions to iso9660 7 */ 8 9 #include <linux/slab.h> 10 #include <linux/pagemap.h> 11 12 #include "isofs.h" 13 #include "rock.h" 14 15 /* 16 * These functions are designed to read the system areas of a directory record 17 * and extract relevant information. There are different functions provided 18 * depending upon what information we need at the time. One function fills 19 * out an inode structure, a second one extracts a filename, a third one 20 * returns a symbolic link name, and a fourth one returns the extent number 21 * for the file. 22 */ 23 24 #define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */ 25 26 struct rock_state { 27 void *buffer; 28 unsigned char *chr; 29 int len; 30 int cont_size; 31 int cont_extent; 32 int cont_offset; 33 struct inode *inode; 34 }; 35 36 /* 37 * This is a way of ensuring that we have something in the system 38 * use fields that is compatible with Rock Ridge. Return zero on success. 39 */ 40 41 static int check_sp(struct rock_ridge *rr, struct inode *inode) 42 { 43 if (rr->u.SP.magic[0] != 0xbe) 44 return -1; 45 if (rr->u.SP.magic[1] != 0xef) 46 return -1; 47 ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip; 48 return 0; 49 } 50 51 static void setup_rock_ridge(struct iso_directory_record *de, 52 struct inode *inode, struct rock_state *rs) 53 { 54 rs->len = sizeof(struct iso_directory_record) + de->name_len[0]; 55 if (rs->len & 1) 56 (rs->len)++; 57 rs->chr = (unsigned char *)de + rs->len; 58 rs->len = *((unsigned char *)de) - rs->len; 59 if (rs->len < 0) 60 rs->len = 0; 61 62 if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) { 63 rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset; 64 rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset; 65 if (rs->len < 0) 66 rs->len = 0; 67 } 68 } 69 70 static void init_rock_state(struct rock_state *rs, struct inode *inode) 71 { 72 memset(rs, 0, sizeof(*rs)); 73 rs->inode = inode; 74 } 75 76 /* 77 * Returns 0 if the caller should continue scanning, 1 if the scan must end 78 * and -ve on error. 79 */ 80 static int rock_continue(struct rock_state *rs) 81 { 82 int ret = 1; 83 int blocksize = 1 << rs->inode->i_blkbits; 84 const int min_de_size = offsetof(struct rock_ridge, u); 85 86 kfree(rs->buffer); 87 rs->buffer = NULL; 88 89 if ((unsigned)rs->cont_offset > blocksize - min_de_size || 90 (unsigned)rs->cont_size > blocksize || 91 (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) { 92 printk(KERN_NOTICE "rock: corrupted directory entry. " 93 "extent=%d, offset=%d, size=%d\n", 94 rs->cont_extent, rs->cont_offset, rs->cont_size); 95 ret = -EIO; 96 goto out; 97 } 98 99 if (rs->cont_extent) { 100 struct buffer_head *bh; 101 102 rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL); 103 if (!rs->buffer) { 104 ret = -ENOMEM; 105 goto out; 106 } 107 ret = -EIO; 108 bh = sb_bread(rs->inode->i_sb, rs->cont_extent); 109 if (bh) { 110 memcpy(rs->buffer, bh->b_data + rs->cont_offset, 111 rs->cont_size); 112 put_bh(bh); 113 rs->chr = rs->buffer; 114 rs->len = rs->cont_size; 115 rs->cont_extent = 0; 116 rs->cont_size = 0; 117 rs->cont_offset = 0; 118 return 0; 119 } 120 printk("Unable to read rock-ridge attributes\n"); 121 } 122 out: 123 kfree(rs->buffer); 124 rs->buffer = NULL; 125 return ret; 126 } 127 128 /* 129 * We think there's a record of type `sig' at rs->chr. Parse the signature 130 * and make sure that there's really room for a record of that type. 131 */ 132 static int rock_check_overflow(struct rock_state *rs, int sig) 133 { 134 int len; 135 136 switch (sig) { 137 case SIG('S', 'P'): 138 len = sizeof(struct SU_SP_s); 139 break; 140 case SIG('C', 'E'): 141 len = sizeof(struct SU_CE_s); 142 break; 143 case SIG('E', 'R'): 144 len = sizeof(struct SU_ER_s); 145 break; 146 case SIG('R', 'R'): 147 len = sizeof(struct RR_RR_s); 148 break; 149 case SIG('P', 'X'): 150 len = sizeof(struct RR_PX_s); 151 break; 152 case SIG('P', 'N'): 153 len = sizeof(struct RR_PN_s); 154 break; 155 case SIG('S', 'L'): 156 len = sizeof(struct RR_SL_s); 157 break; 158 case SIG('N', 'M'): 159 len = sizeof(struct RR_NM_s); 160 break; 161 case SIG('C', 'L'): 162 len = sizeof(struct RR_CL_s); 163 break; 164 case SIG('P', 'L'): 165 len = sizeof(struct RR_PL_s); 166 break; 167 case SIG('T', 'F'): 168 len = sizeof(struct RR_TF_s); 169 break; 170 case SIG('Z', 'F'): 171 len = sizeof(struct RR_ZF_s); 172 break; 173 default: 174 len = 0; 175 break; 176 } 177 len += offsetof(struct rock_ridge, u); 178 if (len > rs->len) { 179 printk(KERN_NOTICE "rock: directory entry would overflow " 180 "storage\n"); 181 printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n", 182 sig, len, rs->len); 183 return -EIO; 184 } 185 return 0; 186 } 187 188 /* 189 * return length of name field; 0: not found, -1: to be ignored 190 */ 191 int get_rock_ridge_filename(struct iso_directory_record *de, 192 char *retname, struct inode *inode) 193 { 194 struct rock_state rs; 195 struct rock_ridge *rr; 196 int sig; 197 int retnamlen = 0; 198 int truncate = 0; 199 int ret = 0; 200 201 if (!ISOFS_SB(inode->i_sb)->s_rock) 202 return 0; 203 *retname = 0; 204 205 init_rock_state(&rs, inode); 206 setup_rock_ridge(de, inode, &rs); 207 repeat: 208 209 while (rs.len > 2) { /* There may be one byte for padding somewhere */ 210 rr = (struct rock_ridge *)rs.chr; 211 /* 212 * Ignore rock ridge info if rr->len is out of range, but 213 * don't return -EIO because that would make the file 214 * invisible. 215 */ 216 if (rr->len < 3) 217 goto out; /* Something got screwed up here */ 218 sig = isonum_721(rs.chr); 219 if (rock_check_overflow(&rs, sig)) 220 goto eio; 221 rs.chr += rr->len; 222 rs.len -= rr->len; 223 /* 224 * As above, just ignore the rock ridge info if rr->len 225 * is bogus. 226 */ 227 if (rs.len < 0) 228 goto out; /* Something got screwed up here */ 229 230 switch (sig) { 231 case SIG('R', 'R'): 232 if ((rr->u.RR.flags[0] & RR_NM) == 0) 233 goto out; 234 break; 235 case SIG('S', 'P'): 236 if (check_sp(rr, inode)) 237 goto out; 238 break; 239 case SIG('C', 'E'): 240 rs.cont_extent = isonum_733(rr->u.CE.extent); 241 rs.cont_offset = isonum_733(rr->u.CE.offset); 242 rs.cont_size = isonum_733(rr->u.CE.size); 243 break; 244 case SIG('N', 'M'): 245 if (truncate) 246 break; 247 if (rr->len < 5) 248 break; 249 /* 250 * If the flags are 2 or 4, this indicates '.' or '..'. 251 * We don't want to do anything with this, because it 252 * screws up the code that calls us. We don't really 253 * care anyways, since we can just use the non-RR 254 * name. 255 */ 256 if (rr->u.NM.flags & 6) 257 break; 258 259 if (rr->u.NM.flags & ~1) { 260 printk("Unsupported NM flag settings (%d)\n", 261 rr->u.NM.flags); 262 break; 263 } 264 if ((strlen(retname) + rr->len - 5) >= 254) { 265 truncate = 1; 266 break; 267 } 268 strncat(retname, rr->u.NM.name, rr->len - 5); 269 retnamlen += rr->len - 5; 270 break; 271 case SIG('R', 'E'): 272 kfree(rs.buffer); 273 return -1; 274 default: 275 break; 276 } 277 } 278 ret = rock_continue(&rs); 279 if (ret == 0) 280 goto repeat; 281 if (ret == 1) 282 return retnamlen; /* If 0, this file did not have a NM field */ 283 out: 284 kfree(rs.buffer); 285 return ret; 286 eio: 287 ret = -EIO; 288 goto out; 289 } 290 291 #define RR_REGARD_XA 1 292 #define RR_RELOC_DE 2 293 294 static int 295 parse_rock_ridge_inode_internal(struct iso_directory_record *de, 296 struct inode *inode, int flags) 297 { 298 int symlink_len = 0; 299 int cnt, sig; 300 unsigned int reloc_block; 301 struct inode *reloc; 302 struct rock_ridge *rr; 303 int rootflag; 304 struct rock_state rs; 305 int ret = 0; 306 307 if (!ISOFS_SB(inode->i_sb)->s_rock) 308 return 0; 309 310 init_rock_state(&rs, inode); 311 setup_rock_ridge(de, inode, &rs); 312 if (flags & RR_REGARD_XA) { 313 rs.chr += 14; 314 rs.len -= 14; 315 if (rs.len < 0) 316 rs.len = 0; 317 } 318 319 repeat: 320 while (rs.len > 2) { /* There may be one byte for padding somewhere */ 321 rr = (struct rock_ridge *)rs.chr; 322 /* 323 * Ignore rock ridge info if rr->len is out of range, but 324 * don't return -EIO because that would make the file 325 * invisible. 326 */ 327 if (rr->len < 3) 328 goto out; /* Something got screwed up here */ 329 sig = isonum_721(rs.chr); 330 if (rock_check_overflow(&rs, sig)) 331 goto eio; 332 rs.chr += rr->len; 333 rs.len -= rr->len; 334 /* 335 * As above, just ignore the rock ridge info if rr->len 336 * is bogus. 337 */ 338 if (rs.len < 0) 339 goto out; /* Something got screwed up here */ 340 341 switch (sig) { 342 #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ 343 case SIG('R', 'R'): 344 if ((rr->u.RR.flags[0] & 345 (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) 346 goto out; 347 break; 348 #endif 349 case SIG('S', 'P'): 350 if (check_sp(rr, inode)) 351 goto out; 352 break; 353 case SIG('C', 'E'): 354 rs.cont_extent = isonum_733(rr->u.CE.extent); 355 rs.cont_offset = isonum_733(rr->u.CE.offset); 356 rs.cont_size = isonum_733(rr->u.CE.size); 357 break; 358 case SIG('E', 'R'): 359 ISOFS_SB(inode->i_sb)->s_rock = 1; 360 printk(KERN_DEBUG "ISO 9660 Extensions: "); 361 { 362 int p; 363 for (p = 0; p < rr->u.ER.len_id; p++) 364 printk("%c", rr->u.ER.data[p]); 365 } 366 printk("\n"); 367 break; 368 case SIG('P', 'X'): 369 inode->i_mode = isonum_733(rr->u.PX.mode); 370 set_nlink(inode, isonum_733(rr->u.PX.n_links)); 371 i_uid_write(inode, isonum_733(rr->u.PX.uid)); 372 i_gid_write(inode, isonum_733(rr->u.PX.gid)); 373 break; 374 case SIG('P', 'N'): 375 { 376 int high, low; 377 high = isonum_733(rr->u.PN.dev_high); 378 low = isonum_733(rr->u.PN.dev_low); 379 /* 380 * The Rock Ridge standard specifies that if 381 * sizeof(dev_t) <= 4, then the high field is 382 * unused, and the device number is completely 383 * stored in the low field. Some writers may 384 * ignore this subtlety, 385 * and as a result we test to see if the entire 386 * device number is 387 * stored in the low field, and use that. 388 */ 389 if ((low & ~0xff) && high == 0) { 390 inode->i_rdev = 391 MKDEV(low >> 8, low & 0xff); 392 } else { 393 inode->i_rdev = 394 MKDEV(high, low); 395 } 396 } 397 break; 398 case SIG('T', 'F'): 399 /* 400 * Some RRIP writers incorrectly place ctime in the 401 * TF_CREATE field. Try to handle this correctly for 402 * either case. 403 */ 404 /* Rock ridge never appears on a High Sierra disk */ 405 cnt = 0; 406 if (rr->u.TF.flags & TF_CREATE) { 407 inode->i_ctime.tv_sec = 408 iso_date(rr->u.TF.times[cnt++].time, 409 0); 410 inode->i_ctime.tv_nsec = 0; 411 } 412 if (rr->u.TF.flags & TF_MODIFY) { 413 inode->i_mtime.tv_sec = 414 iso_date(rr->u.TF.times[cnt++].time, 415 0); 416 inode->i_mtime.tv_nsec = 0; 417 } 418 if (rr->u.TF.flags & TF_ACCESS) { 419 inode->i_atime.tv_sec = 420 iso_date(rr->u.TF.times[cnt++].time, 421 0); 422 inode->i_atime.tv_nsec = 0; 423 } 424 if (rr->u.TF.flags & TF_ATTRIBUTES) { 425 inode->i_ctime.tv_sec = 426 iso_date(rr->u.TF.times[cnt++].time, 427 0); 428 inode->i_ctime.tv_nsec = 0; 429 } 430 break; 431 case SIG('S', 'L'): 432 { 433 int slen; 434 struct SL_component *slp; 435 struct SL_component *oldslp; 436 slen = rr->len - 5; 437 slp = &rr->u.SL.link; 438 inode->i_size = symlink_len; 439 while (slen > 1) { 440 rootflag = 0; 441 switch (slp->flags & ~1) { 442 case 0: 443 inode->i_size += 444 slp->len; 445 break; 446 case 2: 447 inode->i_size += 1; 448 break; 449 case 4: 450 inode->i_size += 2; 451 break; 452 case 8: 453 rootflag = 1; 454 inode->i_size += 1; 455 break; 456 default: 457 printk("Symlink component flag " 458 "not implemented\n"); 459 } 460 slen -= slp->len + 2; 461 oldslp = slp; 462 slp = (struct SL_component *) 463 (((char *)slp) + slp->len + 2); 464 465 if (slen < 2) { 466 if (((rr->u.SL. 467 flags & 1) != 0) 468 && 469 ((oldslp-> 470 flags & 1) == 0)) 471 inode->i_size += 472 1; 473 break; 474 } 475 476 /* 477 * If this component record isn't 478 * continued, then append a '/'. 479 */ 480 if (!rootflag 481 && (oldslp->flags & 1) == 0) 482 inode->i_size += 1; 483 } 484 } 485 symlink_len = inode->i_size; 486 break; 487 case SIG('R', 'E'): 488 printk(KERN_WARNING "Attempt to read inode for " 489 "relocated directory\n"); 490 goto out; 491 case SIG('C', 'L'): 492 if (flags & RR_RELOC_DE) { 493 printk(KERN_ERR 494 "ISOFS: Recursive directory relocation " 495 "is not supported\n"); 496 goto eio; 497 } 498 reloc_block = isonum_733(rr->u.CL.location); 499 if (reloc_block == ISOFS_I(inode)->i_iget5_block && 500 ISOFS_I(inode)->i_iget5_offset == 0) { 501 printk(KERN_ERR 502 "ISOFS: Directory relocation points to " 503 "itself\n"); 504 goto eio; 505 } 506 ISOFS_I(inode)->i_first_extent = reloc_block; 507 reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0); 508 if (IS_ERR(reloc)) { 509 ret = PTR_ERR(reloc); 510 goto out; 511 } 512 inode->i_mode = reloc->i_mode; 513 set_nlink(inode, reloc->i_nlink); 514 inode->i_uid = reloc->i_uid; 515 inode->i_gid = reloc->i_gid; 516 inode->i_rdev = reloc->i_rdev; 517 inode->i_size = reloc->i_size; 518 inode->i_blocks = reloc->i_blocks; 519 inode->i_atime = reloc->i_atime; 520 inode->i_ctime = reloc->i_ctime; 521 inode->i_mtime = reloc->i_mtime; 522 iput(reloc); 523 break; 524 #ifdef CONFIG_ZISOFS 525 case SIG('Z', 'F'): { 526 int algo; 527 528 if (ISOFS_SB(inode->i_sb)->s_nocompress) 529 break; 530 algo = isonum_721(rr->u.ZF.algorithm); 531 if (algo == SIG('p', 'z')) { 532 int block_shift = 533 isonum_711(&rr->u.ZF.parms[1]); 534 if (block_shift > 17) { 535 printk(KERN_WARNING "isofs: " 536 "Can't handle ZF block " 537 "size of 2^%d\n", 538 block_shift); 539 } else { 540 /* 541 * Note: we don't change 542 * i_blocks here 543 */ 544 ISOFS_I(inode)->i_file_format = 545 isofs_file_compressed; 546 /* 547 * Parameters to compression 548 * algorithm (header size, 549 * block size) 550 */ 551 ISOFS_I(inode)->i_format_parm[0] = 552 isonum_711(&rr->u.ZF.parms[0]); 553 ISOFS_I(inode)->i_format_parm[1] = 554 isonum_711(&rr->u.ZF.parms[1]); 555 inode->i_size = 556 isonum_733(rr->u.ZF. 557 real_size); 558 } 559 } else { 560 printk(KERN_WARNING 561 "isofs: Unknown ZF compression " 562 "algorithm: %c%c\n", 563 rr->u.ZF.algorithm[0], 564 rr->u.ZF.algorithm[1]); 565 } 566 break; 567 } 568 #endif 569 default: 570 break; 571 } 572 } 573 ret = rock_continue(&rs); 574 if (ret == 0) 575 goto repeat; 576 if (ret == 1) 577 ret = 0; 578 out: 579 kfree(rs.buffer); 580 return ret; 581 eio: 582 ret = -EIO; 583 goto out; 584 } 585 586 static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) 587 { 588 int slen; 589 int rootflag; 590 struct SL_component *oldslp; 591 struct SL_component *slp; 592 slen = rr->len - 5; 593 slp = &rr->u.SL.link; 594 while (slen > 1) { 595 rootflag = 0; 596 switch (slp->flags & ~1) { 597 case 0: 598 if (slp->len > plimit - rpnt) 599 return NULL; 600 memcpy(rpnt, slp->text, slp->len); 601 rpnt += slp->len; 602 break; 603 case 2: 604 if (rpnt >= plimit) 605 return NULL; 606 *rpnt++ = '.'; 607 break; 608 case 4: 609 if (2 > plimit - rpnt) 610 return NULL; 611 *rpnt++ = '.'; 612 *rpnt++ = '.'; 613 break; 614 case 8: 615 if (rpnt >= plimit) 616 return NULL; 617 rootflag = 1; 618 *rpnt++ = '/'; 619 break; 620 default: 621 printk("Symlink component flag not implemented (%d)\n", 622 slp->flags); 623 } 624 slen -= slp->len + 2; 625 oldslp = slp; 626 slp = (struct SL_component *)((char *)slp + slp->len + 2); 627 628 if (slen < 2) { 629 /* 630 * If there is another SL record, and this component 631 * record isn't continued, then add a slash. 632 */ 633 if ((!rootflag) && (rr->u.SL.flags & 1) && 634 !(oldslp->flags & 1)) { 635 if (rpnt >= plimit) 636 return NULL; 637 *rpnt++ = '/'; 638 } 639 break; 640 } 641 642 /* 643 * If this component record isn't continued, then append a '/'. 644 */ 645 if (!rootflag && !(oldslp->flags & 1)) { 646 if (rpnt >= plimit) 647 return NULL; 648 *rpnt++ = '/'; 649 } 650 } 651 return rpnt; 652 } 653 654 int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode, 655 int relocated) 656 { 657 int flags = relocated ? RR_RELOC_DE : 0; 658 int result = parse_rock_ridge_inode_internal(de, inode, flags); 659 660 /* 661 * if rockridge flag was reset and we didn't look for attributes 662 * behind eventual XA attributes, have a look there 663 */ 664 if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1) 665 && (ISOFS_SB(inode->i_sb)->s_rock == 2)) { 666 result = parse_rock_ridge_inode_internal(de, inode, 667 flags | RR_REGARD_XA); 668 } 669 return result; 670 } 671 672 /* 673 * readpage() for symlinks: reads symlink contents into the page and either 674 * makes it uptodate and returns 0 or returns error (-EIO) 675 */ 676 static int rock_ridge_symlink_readpage(struct file *file, struct page *page) 677 { 678 struct inode *inode = page->mapping->host; 679 struct iso_inode_info *ei = ISOFS_I(inode); 680 struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb); 681 char *link = kmap(page); 682 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); 683 struct buffer_head *bh; 684 char *rpnt = link; 685 unsigned char *pnt; 686 struct iso_directory_record *raw_de; 687 unsigned long block, offset; 688 int sig; 689 struct rock_ridge *rr; 690 struct rock_state rs; 691 int ret; 692 693 if (!sbi->s_rock) 694 goto error; 695 696 init_rock_state(&rs, inode); 697 block = ei->i_iget5_block; 698 bh = sb_bread(inode->i_sb, block); 699 if (!bh) 700 goto out_noread; 701 702 offset = ei->i_iget5_offset; 703 pnt = (unsigned char *)bh->b_data + offset; 704 705 raw_de = (struct iso_directory_record *)pnt; 706 707 /* 708 * If we go past the end of the buffer, there is some sort of error. 709 */ 710 if (offset + *pnt > bufsize) 711 goto out_bad_span; 712 713 /* 714 * Now test for possible Rock Ridge extensions which will override 715 * some of these numbers in the inode structure. 716 */ 717 718 setup_rock_ridge(raw_de, inode, &rs); 719 720 repeat: 721 while (rs.len > 2) { /* There may be one byte for padding somewhere */ 722 rr = (struct rock_ridge *)rs.chr; 723 if (rr->len < 3) 724 goto out; /* Something got screwed up here */ 725 sig = isonum_721(rs.chr); 726 if (rock_check_overflow(&rs, sig)) 727 goto out; 728 rs.chr += rr->len; 729 rs.len -= rr->len; 730 if (rs.len < 0) 731 goto out; /* corrupted isofs */ 732 733 switch (sig) { 734 case SIG('R', 'R'): 735 if ((rr->u.RR.flags[0] & RR_SL) == 0) 736 goto out; 737 break; 738 case SIG('S', 'P'): 739 if (check_sp(rr, inode)) 740 goto out; 741 break; 742 case SIG('S', 'L'): 743 rpnt = get_symlink_chunk(rpnt, rr, 744 link + (PAGE_SIZE - 1)); 745 if (rpnt == NULL) 746 goto out; 747 break; 748 case SIG('C', 'E'): 749 /* This tells is if there is a continuation record */ 750 rs.cont_extent = isonum_733(rr->u.CE.extent); 751 rs.cont_offset = isonum_733(rr->u.CE.offset); 752 rs.cont_size = isonum_733(rr->u.CE.size); 753 default: 754 break; 755 } 756 } 757 ret = rock_continue(&rs); 758 if (ret == 0) 759 goto repeat; 760 if (ret < 0) 761 goto fail; 762 763 if (rpnt == link) 764 goto fail; 765 brelse(bh); 766 *rpnt = '\0'; 767 SetPageUptodate(page); 768 kunmap(page); 769 unlock_page(page); 770 return 0; 771 772 /* error exit from macro */ 773 out: 774 kfree(rs.buffer); 775 goto fail; 776 out_noread: 777 printk("unable to read i-node block"); 778 goto fail; 779 out_bad_span: 780 printk("symlink spans iso9660 blocks\n"); 781 fail: 782 brelse(bh); 783 error: 784 SetPageError(page); 785 kunmap(page); 786 unlock_page(page); 787 return -EIO; 788 } 789 790 const struct address_space_operations isofs_symlink_aops = { 791 .readpage = rock_ridge_symlink_readpage 792 }; 793