Date: Wed, 28 Nov 2007 22:38:34 GMT From: Andrew Muhametshin <andrew@dobrohot.org> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/118322: Sometimes (seldom), "panic:page fault" happens after KDE automount occur when I insert CD/DVD Message-ID: <200711282238.lASMcY7D013576@www.freebsd.org> Resent-Message-ID: <200711282240.lASMe3Ck012861@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 118322 >Category: kern >Synopsis: Sometimes (seldom), "panic:page fault" happens after KDE automount occur when I insert CD/DVD >Confidential: no >Severity: critical >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Nov 28 22:40:03 UTC 2007 >Closed-Date: >Last-Modified: >Originator: Andrew Muhametshin >Release: FreeBSD-7.0-BETA1 >Organization: >Environment: FreeBSD host01.localdomain 7.0-BETA1 FreeBSD 7.0-BETA1 #2: Wed Oct 31 22:54:22 MSK 2007 root@host01.localdomain:/usr/obj/usr/src/sys/HOST01 i38 >Description: $ pkg_info -xE hal ^dbus- ^kde-3.5.8 dbus-1.0.2_2 dbus-glib-0.74 dbus-qt3-0.70_1 hal-0.5.8.20070909 hal-device-manager-0.5.8.20070909_1 kde-3.5.8 $ kgdb kernel.debug /var/crash/vmcore.3 kgdb: kvm_nlist(_stopped_cpus): kgdb: kvm_nlist(_stoppcbs): [GDB will not be able to debug user-mode threads: /usr/lib/libthread_db.so: Undefined symbol "ps_pglobal_lookup"] GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-marcel-freebsd". Unread portion of the kernel message buffer: Fatal trap 12: page fault while in kernel mode fault virtual address = 0x2c fault code = supervisor read, page not present instruction pointer = 0x20:0xc04fe598 stack pointer = 0x28:0xe5822a44 frame pointer = 0x28:0xe5822a4c code segment = base 0x0, limit 0xfffff, type 0x1b = DPL 0, pres 1, def32 1, gran 1 processor eflags = interrupt enabled, resume, IOPL = 0 current process = 14440 (kdeinit) trap number = 12 panic: page fault Uptime: 2d4h3m32s Physical memory: 878 MB Dumping 328 MB: 313 297 281 265 249 233 217 201 185 169 153 137 121 105 89 73 57 41 25 9 #0 doadump () at pcpu.h:195 195 __asm __volatile("movl %%fs:0,%0" : "=r" (td)); (kgdb) bt #0 doadump () at pcpu.h:195 #1 0xc0553784 in boot (howto=260) at /usr/src/sys/kern/kern_shutdown.c:409 #2 0xc0553984 in panic (fmt=Variable "fmt" is not available. ) at /usr/src/sys/kern/kern_shutdown.c:563 #3 0xc077226c in trap_fatal (frame=0xe5822a04, eva=44) at /usr/src/sys/i386/i386/trap.c:872 #4 0xc07724f0 in trap_pfault (frame=0xe5822a04, usermode=0, eva=44) at /usr/src/sys/i386/i386/trap.c:785 #5 0xc0772e72 in trap (frame=0xe5822a04) at /usr/src/sys/i386/i386/trap.c:463 #6 0xc0760e5b in calltrap () at /usr/src/sys/i386/i386/exception.s:139 #7 0xc04fe598 in udf_permtomode (node=0xc716699c) at /usr/src/sys/fs/udf/udf_vnops.c:124 #8 0xc04ff559 in udf_getattr (a=0xe5822aa0) at /usr/src/sys/fs/udf/udf_vnops.c:271 #9 0xc077ebe2 in VOP_GETATTR_APV (vop=0xc07d4100, a=0xe5822aa0) at vnode_if.c:530 #10 0xc05d6dc9 in vn_stat (vp=0xc8531550, sb=0xe5822b94, active_cred=0xc6234a00, file_cred=0x0, td=0xc494cc60) at vnode_if.h:286 #11 0xc05cdbb5 in kern_lstat (td=0xc494cc60, path=0x29867de0 <Address 0x29867de0 out of bounds>, pathseg=UIO_USERSPACE, sbp=0xe5822c18) at /usr/src/sys/kern/vfs_syscalls.c:2165 #12 0xc05cdc7f in lstat (td=0xc494cc60, uap=0xe5822cfc) at /usr/src/sys/kern/vfs_syscalls.c:2144 #13 0xc0772845 in syscall (frame=0xe5822d38) at /usr/src/sys/i386/i386/trap.c:1008 #14 0xc0760ec0 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception.s:196 #15 0x00000033 in ?? () Previous frame inner to this frame (corrupt stack?) (kgdb) list *0xc04fe598 0xc04fe598 is in udf_permtomode (/usr/src/sys/fs/udf/udf_vnops.c:124). 119 { 120 uint32_t perm; 121 uint16_t flags; 122 mode_t mode; 123 124 perm = le32toh(node->fentry->perm); 125 flags = le16toh(node->fentry->icbtag.flags); 126 127 mode = perm & UDF_FENTRY_PERM_USER_MASK; 128 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2); (kgdb) 129 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4); 130 mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4); 131 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6); 132 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8); 133 134 return (mode); 135 } 136 137 static int 138 udf_access(struct vop_access_args *a) (kgdb) 139 { 140 struct vnode *vp; 141 struct udf_node *node; 142 mode_t a_mode, mode; 143 144 vp = a->a_vp; 145 node = VTON(vp); 146 a_mode = a->a_mode; 147 148 if (a_mode & VWRITE) { (kgdb) 149 switch (vp->v_type) { 150 case VDIR: 151 case VLNK: 152 case VREG: 153 return (EROFS); 154 /* NOT REACHED */ 155 default: 156 break; 157 } 158 } (kgdb) 159 160 mode = udf_permtomode(node); 161 162 return (vaccess(vp->v_type, mode, node->fentry->uid, node->fentry->gid, 163 a_mode, a->a_cred, NULL)); 164 } 165 166 static int 167 udf_open(struct vop_open_args *ap) { 168 struct udf_node *np = VTON(ap->a_vp); (kgdb) 169 off_t fsize; 170 171 fsize = le64toh(np->fentry->inf_len); 172 vnode_create_vobject(ap->a_vp, fsize, ap->a_td); 173 return 0; 174 } 175 176 static int mon_lens[2][12] = { 177 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 178 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} (kgdb) 179 }; 180 181 static int 182 udf_isaleapyear(int year) 183 { 184 int i; 185 186 i = (year % 4) ? 0 : 1; 187 i &= (year % 100) ? 1 : 0; 188 i |= (year % 400) ? 0 : 1; (kgdb) 189 190 return i; 191 } 192 193 /* 194 * XXX This is just a rough hack. Daylight savings isn't calculated and tv_nsec 195 * is ignored. 196 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>. 197 */ 198 static void (kgdb) 199 udf_timetotimespec(struct timestamp *time, struct timespec *t) 200 { 201 int i, lpyear, daysinyear, year; 202 union { 203 uint16_t u_tz_offset; 204 int16_t s_tz_offset; 205 } tz; 206 207 t->tv_nsec = 0; 208 (kgdb) 209 /* DirectCD seems to like using bogus year values */ 210 year = le16toh(time->year); 211 if (year < 1970) { 212 t->tv_sec = 0; 213 return; 214 } 215 216 /* Calculate the time and day */ 217 t->tv_sec = time->second; 218 t->tv_sec += time->minute * 60; (kgdb) 219 t->tv_sec += time->hour * 3600; 220 t->tv_sec += time->day * 3600 * 24; 221 222 /* Calculate the month */ 223 lpyear = udf_isaleapyear(year); 224 for (i = 1; i < time->month; i++) 225 t->tv_sec += mon_lens[lpyear][i] * 3600 * 24; 226 227 /* Speed up the calculation */ 228 if (year > 1979) (kgdb) 229 t->tv_sec += 315532800; 230 if (year > 1989) 231 t->tv_sec += 315619200; 232 if (year > 1999) 233 t->tv_sec += 315532800; 234 for (i = 2000; i < year; i++) { 235 daysinyear = udf_isaleapyear(i) + 365 ; 236 t->tv_sec += daysinyear * 3600 * 24; 237 } 238 (kgdb) 239 /* 240 * Calculate the time zone. The timezone is 12 bit signed 2's 241 * complement, so we gotta do some extra magic to handle it right. 242 */ 243 tz.u_tz_offset = le16toh(time->type_tz); 244 tz.u_tz_offset &= 0x0fff; 245 if (tz.u_tz_offset & 0x0800) 246 tz.u_tz_offset |= 0xf000; /* extend the sign to 16 bits */ 247 if ((time->type_tz & 0x1000) && (tz.s_tz_offset != -2047)) 248 t->tv_sec -= tz.s_tz_offset * 60; (kgdb) 249 250 return; 251 } 252 253 static int 254 udf_getattr(struct vop_getattr_args *a) 255 { 256 struct vnode *vp; 257 struct udf_node *node; 258 struct vattr *vap; (kgdb) 259 struct file_entry *fentry; 260 struct timespec ts; 261 262 ts.tv_sec = 0; 263 264 vp = a->a_vp; 265 vap = a->a_vap; 266 node = VTON(vp); 267 fentry = node->fentry; 268 (kgdb) 269 vap->va_fsid = dev2udev(node->udfmp->im_dev); 270 vap->va_fileid = node->hash_id; 271 vap->va_mode = udf_permtomode(node); 272 vap->va_nlink = le16toh(fentry->link_cnt); 273 /* 274 * XXX The spec says that -1 is valid for uid/gid and indicates an 275 * invalid uid/gid. How should this be represented? 276 */ 277 vap->va_uid = (le32toh(fentry->uid) == -1) ? 0 : le32toh(fentry->uid); 278 vap->va_gid = (le32toh(fentry->gid) == -1) ? 0 : le32toh(fentry->gid); (kgdb) 279 udf_timetotimespec(&fentry->atime, &vap->va_atime); 280 udf_timetotimespec(&fentry->mtime, &vap->va_mtime); 281 vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */ 282 vap->va_rdev = 0; /* XXX */ 283 if (vp->v_type & VDIR) { 284 /* 285 * Directories that are recorded within their ICB will show 286 * as having 0 blocks recorded. Since tradition dictates 287 * that directories consume at least one logical block, 288 * make it appear so. (kgdb) 289 */ 290 if (fentry->logblks_rec != 0) { 291 vap->va_size = 292 le64toh(fentry->logblks_rec) * node->udfmp->bsize; 293 } else { 294 vap->va_size = node->udfmp->bsize; 295 } 296 } else { 297 vap->va_size = le64toh(fentry->inf_len); 298 } (kgdb) 299 vap->va_flags = 0; 300 vap->va_gen = 1; 301 vap->va_blocksize = node->udfmp->bsize; 302 vap->va_bytes = le64toh(fentry->inf_len); 303 vap->va_type = vp->v_type; 304 vap->va_filerev = 0; /* XXX */ 305 return (0); 306 } 307 308 /* (kgdb) 309 * File specific ioctls. 310 */ 311 static int 312 udf_ioctl(struct vop_ioctl_args *a) 313 { 314 printf("%s called\n", __func__); 315 return (ENOTTY); 316 } 317 318 /* (kgdb) 319 * I'm not sure that this has much value in a read-only filesystem, but 320 * cd9660 has it too. 321 */ 322 static int 323 udf_pathconf(struct vop_pathconf_args *a) 324 { 325 326 switch (a->a_name) { 327 case _PC_LINK_MAX: 328 *a->a_retval = 65535; (kgdb) 329 return (0); 330 case _PC_NAME_MAX: 331 *a->a_retval = NAME_MAX; 332 return (0); 333 case _PC_PATH_MAX: 334 *a->a_retval = PATH_MAX; 335 return (0); 336 case _PC_NO_TRUNC: 337 *a->a_retval = 1; 338 return (0); (kgdb) 339 default: 340 return (EINVAL); 341 } 342 } 343 344 #define lblkno(udfmp, loc) ((loc) >> (udfmp)->bshift) 345 #define blkoff(udfmp, loc) ((loc) & (udfmp)->bmask) 346 #define lblktosize(imp, blk) ((blk) << (udfmp)->bshift) 347 348 static int (kgdb) 349 udf_read(struct vop_read_args *ap) 350 { 351 struct vnode *vp = ap->a_vp; 352 struct uio *uio = ap->a_uio; 353 struct udf_node *node = VTON(vp); 354 struct udf_mnt *udfmp; 355 struct buf *bp; 356 daddr_t lbn, rablock; 357 off_t diff, fsize; 358 int error = 0; (kgdb) 359 long size, n, on; 360 361 if (uio->uio_resid == 0) 362 return (0); 363 if (uio->uio_offset < 0) 364 return (EINVAL); 365 fsize = le64toh(node->fentry->inf_len); 366 udfmp = node->udfmp; 367 do { 368 lbn = lblkno(udfmp, uio->uio_offset); (kgdb) 369 on = blkoff(udfmp, uio->uio_offset); 370 n = min((u_int)(udfmp->bsize - on), 371 uio->uio_resid); 372 diff = fsize - uio->uio_offset; 373 if (diff <= 0) 374 return (0); 375 if (diff < n) 376 n = diff; 377 size = udfmp->bsize; 378 rablock = lbn + 1; (kgdb) 379 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 380 if (lblktosize(udfmp, rablock) < fsize) { 381 error = cluster_read(vp, fsize, lbn, size, NOCRED, 382 uio->uio_resid, (ap->a_ioflag >> 16), &bp); 383 } else { 384 error = bread(vp, lbn, size, NOCRED, &bp); 385 } 386 } else { 387 error = bread(vp, lbn, size, NOCRED, &bp); 388 } (kgdb) 389 n = min(n, size - bp->b_resid); 390 if (error) { 391 brelse(bp); 392 return (error); 393 } 394 395 error = uiomove(bp->b_data + on, (int)n, uio); 396 brelse(bp); 397 } while (error == 0 && uio->uio_resid > 0 && n != 0); 398 return (error); (kgdb) 399 } 400 401 /* 402 * Call the OSTA routines to translate the name from a CS0 dstring to a 403 * 16-bit Unicode String. Hooks need to be placed in here to translate from 404 * Unicode to the encoding that the kernel/user expects. Return the length 405 * of the translated string. 406 */ 407 static int 408 udf_transname(char *cs0string, char *destname, int len, struct udf_mnt *udfmp) (kgdb) 409 { 410 unicode_t *transname; 411 char *unibuf, *unip; 412 int i, destlen; 413 ssize_t unilen = 0; 414 size_t destleft = MAXNAMLEN; 415 416 /* Convert 16-bit Unicode to destname */ 417 if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) { 418 /* allocate a buffer big enough to hold an 8->16 bit expansion */ (kgdb) 419 unibuf = uma_zalloc(udf_zone_trans, M_WAITOK); 420 unip = unibuf; 421 if ((unilen = (ssize_t)udf_UncompressUnicodeByte(len, cs0string, unibuf)) == -1) { 422 printf("udf: Unicode translation failed\n"); 423 uma_zfree(udf_zone_trans, unibuf); 424 return 0; 425 } 426 427 while (unilen > 0 && destleft > 0) { 428 udf_iconv->conv(udfmp->im_d2l, (const char **)&unibuf, (kgdb) 429 (size_t *)&unilen, (char **)&destname, &destleft); 430 /* Unconverted character found */ 431 if (unilen > 0 && destleft > 0) { 432 *destname++ = '?'; 433 destleft--; 434 unibuf += 2; 435 unilen -= 2; 436 } 437 } 438 uma_zfree(udf_zone_trans, unip); (kgdb) 439 *destname = '\0'; 440 destlen = MAXNAMLEN - (int)destleft; 441 } else { 442 /* allocate a buffer big enough to hold an 8->16 bit expansion */ 443 transname = uma_zalloc(udf_zone_trans, M_WAITOK); 444 445 if ((unilen = (ssize_t)udf_UncompressUnicode(len, cs0string, transname)) == -1) { 446 printf("udf: Unicode translation failed\n"); 447 uma_zfree(udf_zone_trans, transname); 448 return 0; (kgdb) 449 } 450 451 for (i = 0; i < unilen ; i++) { 452 if (transname[i] & 0xff00) { 453 destname[i] = '.'; /* Fudge the 16bit chars */ 454 } else { 455 destname[i] = transname[i] & 0xff; 456 } 457 } 458 uma_zfree(udf_zone_trans, transname); (kgdb) 459 destname[unilen] = 0; 460 destlen = (int)unilen; 461 } 462 463 return (destlen); 464 } 465 466 /* 467 * Compare a CS0 dstring with a name passed in from the VFS layer. Return 468 * 0 on a successful match, nonzero otherwise. Unicode work may need to be done (kgdb) 469 * here also. 470 */ 471 static int 472 udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct udf_mnt *udfmp) 473 { 474 char *transname; 475 int error = 0; 476 477 /* This is overkill, but not worth creating a new zone */ 478 transname = uma_zalloc(udf_zone_trans, M_WAITOK); (kgdb) 479 480 cs0len = udf_transname(cs0string, transname, cs0len, udfmp); 481 482 /* Easy check. If they aren't the same length, they aren't equal */ 483 if ((cs0len == 0) || (cs0len != cmplen)) 484 error = -1; 485 else 486 error = bcmp(transname, cmpname, cmplen); 487 488 uma_zfree(udf_zone_trans, transname); (kgdb) 489 return (error); 490 } 491 492 struct udf_uiodir { 493 struct dirent *dirent; 494 u_long *cookies; 495 int ncookies; 496 int acookies; 497 int eofflag; 498 }; (kgdb) 499 500 static int 501 udf_uiodir(struct udf_uiodir *uiodir, int de_size, struct uio *uio, long cookie) 502 { 503 if (uiodir->cookies != NULL) { 504 if (++uiodir->acookies > uiodir->ncookies) { 505 uiodir->eofflag = 0; 506 return (-1); 507 } 508 *uiodir->cookies++ = cookie; (kgdb) 509 } 510 511 if (uio->uio_resid < de_size) { 512 uiodir->eofflag = 0; 513 return (-1); 514 } 515 516 return (uiomove(uiodir->dirent, de_size, uio)); 517 } 518 (kgdb) 519 static struct udf_dirstream * 520 udf_opendir(struct udf_node *node, int offset, int fsize, struct udf_mnt *udfmp) 521 { 522 struct udf_dirstream *ds; 523 524 ds = uma_zalloc(udf_zone_ds, M_WAITOK | M_ZERO); 525 526 ds->node = node; 527 ds->offset = offset; 528 ds->udfmp = udfmp; (kgdb) 529 ds->fsize = fsize; 530 531 return (ds); 532 } 533 534 static struct fileid_desc * 535 udf_getfid(struct udf_dirstream *ds) 536 { 537 struct fileid_desc *fid; 538 int error, frag_size = 0, total_fid_size; (kgdb) 539 540 /* End of directory? */ 541 if (ds->offset + ds->off >= ds->fsize) { 542 ds->error = 0; 543 return (NULL); 544 } 545 546 /* Grab the first extent of the directory */ 547 if (ds->off == 0) { 548 ds->size = 0; (kgdb) 549 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 550 &ds->bp, &ds->data); 551 if (error) { 552 ds->error = error; 553 if (ds->bp != NULL) 554 brelse(ds->bp); 555 return (NULL); 556 } 557 } 558 (kgdb) 559 /* 560 * Clean up from a previous fragmented FID. 561 * XXX Is this the right place for this? 562 */ 563 if (ds->fid_fragment && ds->buf != NULL) { 564 ds->fid_fragment = 0; 565 FREE(ds->buf, M_UDFFID); 566 } 567 568 fid = (struct fileid_desc*)&ds->data[ds->off]; (kgdb) 569 570 /* 571 * Check to see if the fid is fragmented. The first test 572 * ensures that we don't wander off the end of the buffer 573 * looking for the l_iu and l_fi fields. 574 */ 575 if (ds->off + UDF_FID_SIZE > ds->size || 576 ds->off + le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE > ds->size){ 577 578 /* Copy what we have of the fid into a buffer */ (kgdb) 579 frag_size = ds->size - ds->off; 580 if (frag_size >= ds->udfmp->bsize) { 581 printf("udf: invalid FID fragment\n"); 582 ds->error = EINVAL; 583 return (NULL); 584 } 585 586 /* 587 * File ID descriptors can only be at most one 588 * logical sector in size. (kgdb) 589 */ 590 MALLOC(ds->buf, uint8_t*, ds->udfmp->bsize, M_UDFFID, 591 M_WAITOK | M_ZERO); 592 bcopy(fid, ds->buf, frag_size); 593 594 /* Reduce all of the casting magic */ 595 fid = (struct fileid_desc*)ds->buf; 596 597 if (ds->bp != NULL) 598 brelse(ds->bp); (kgdb) 599 600 /* Fetch the next allocation */ 601 ds->offset += ds->size; 602 ds->size = 0; 603 error = udf_readatoffset(ds->node, &ds->size, ds->offset, 604 &ds->bp, &ds->data); 605 if (error) { 606 ds->error = error; 607 return (NULL); 608 } (kgdb) 609 610 /* 611 * If the fragment was so small that we didn't get 612 * the l_iu and l_fi fields, copy those in. 613 */ 614 if (frag_size < UDF_FID_SIZE) 615 bcopy(ds->data, &ds->buf[frag_size], 616 UDF_FID_SIZE - frag_size); 617 618 /* (kgdb) 619 * Now that we have enough of the fid to work with, 620 * copy in the rest of the fid from the new 621 * allocation. 622 */ 623 total_fid_size = UDF_FID_SIZE + le16toh(fid->l_iu) + fid->l_fi; 624 if (total_fid_size > ds->udfmp->bsize) { 625 printf("udf: invalid FID\n"); 626 ds->error = EIO; 627 return (NULL); 628 } (kgdb) 629 bcopy(ds->data, &ds->buf[frag_size], 630 total_fid_size - frag_size); 631 632 ds->fid_fragment = 1; 633 } else { 634 total_fid_size = le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE; 635 } 636 637 /* 638 * Update the offset. Align on a 4 byte boundary because the (kgdb) 639 * UDF spec says so. 640 */ 641 ds->this_off = ds->off; 642 if (!ds->fid_fragment) { 643 ds->off += (total_fid_size + 3) & ~0x03; 644 } else { 645 ds->off = (total_fid_size - frag_size + 3) & ~0x03; 646 } 647 648 return (fid); (kgdb) 649 } 650 651 static void 652 udf_closedir(struct udf_dirstream *ds) 653 { 654 655 if (ds->bp != NULL) 656 brelse(ds->bp); 657 658 if (ds->fid_fragment && ds->buf != NULL) (kgdb) 659 FREE(ds->buf, M_UDFFID); 660 661 uma_zfree(udf_zone_ds, ds); 662 } 663 664 static int 665 udf_readdir(struct vop_readdir_args *a) 666 { 667 struct vnode *vp; 668 struct uio *uio; (kgdb) 669 struct dirent dir; 670 struct udf_node *node; 671 struct udf_mnt *udfmp; 672 struct fileid_desc *fid; 673 struct udf_uiodir uiodir; 674 struct udf_dirstream *ds; 675 u_long *cookies = NULL; 676 int ncookies; 677 int error = 0; 678 (kgdb) 679 vp = a->a_vp; 680 uio = a->a_uio; 681 node = VTON(vp); 682 udfmp = node->udfmp; 683 uiodir.eofflag = 1; 684 685 if (a->a_ncookies != NULL) { 686 /* 687 * Guess how many entries are needed. If we run out, this 688 * function will be called again and thing will pick up were (kgdb) 689 * it left off. 690 */ 691 ncookies = uio->uio_resid / 8; 692 MALLOC(cookies, u_long *, sizeof(u_long) * ncookies, 693 M_TEMP, M_WAITOK); 694 if (cookies == NULL) 695 return (ENOMEM); 696 uiodir.ncookies = ncookies; 697 uiodir.cookies = cookies; 698 uiodir.acookies = 0; (kgdb) 699 } else { 700 uiodir.cookies = NULL; 701 } 702 703 /* 704 * Iterate through the file id descriptors. Give the parent dir 705 * entry special attention. 706 */ 707 ds = udf_opendir(node, uio->uio_offset, le64toh(node->fentry->inf_len), 708 node->udfmp); (kgdb) 709 710 while ((fid = udf_getfid(ds)) != NULL) { 711 712 /* XXX Should we return an error on a bad fid? */ 713 if (udf_checktag(&fid->tag, TAGID_FID)) { 714 printf("Invalid FID tag\n"); 715 hexdump(fid, UDF_FID_SIZE, NULL, 0); 716 error = EIO; 717 break; 718 } (kgdb) 719 720 /* Is this a deleted file? */ 721 if (fid->file_char & UDF_FILE_CHAR_DEL) 722 continue; 723 724 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 725 /* Do up the '.' and '..' entries. Dummy values are 726 * used for the cookies since the offset here is 727 * usually zero, and NFS doesn't like that value 728 */ (kgdb) 729 dir.d_fileno = node->hash_id; 730 dir.d_type = DT_DIR; 731 dir.d_name[0] = '.'; 732 dir.d_name[1] = '\0'; 733 dir.d_namlen = 1; 734 dir.d_reclen = GENERIC_DIRSIZ(&dir); 735 uiodir.dirent = &dir; 736 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1); 737 if (error) 738 break; (kgdb) 739 740 dir.d_fileno = udf_getid(&fid->icb); 741 dir.d_type = DT_DIR; 742 dir.d_name[0] = '.'; 743 dir.d_name[1] = '.'; 744 dir.d_name[2] = '\0'; 745 dir.d_namlen = 2; 746 dir.d_reclen = GENERIC_DIRSIZ(&dir); 747 uiodir.dirent = &dir; 748 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2); (kgdb) 749 } else { 750 dir.d_namlen = udf_transname(&fid->data[fid->l_iu], 751 &dir.d_name[0], fid->l_fi, udfmp); 752 dir.d_fileno = udf_getid(&fid->icb); 753 dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ? 754 DT_DIR : DT_UNKNOWN; 755 dir.d_reclen = GENERIC_DIRSIZ(&dir); 756 uiodir.dirent = &dir; 757 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 758 ds->this_off); (kgdb) 759 } 760 if (error) { 761 printf("uiomove returned %d\n", error); 762 break; 763 } 764 765 } 766 767 /* tell the calling layer whether we need to be called again */ 768 *a->a_eofflag = uiodir.eofflag; (kgdb) 769 uio->uio_offset = ds->offset + ds->off; 770 771 if (!error) 772 error = ds->error; 773 774 udf_closedir(ds); 775 776 if (a->a_ncookies != NULL) { 777 if (error) 778 FREE(cookies, M_TEMP); (kgdb) 779 else { 780 *a->a_ncookies = uiodir.acookies; 781 *a->a_cookies = cookies; 782 } 783 } 784 785 return (error); 786 } 787 788 /* Are there any implementations out there that do soft-links? */ (kgdb) 789 static int 790 udf_readlink(struct vop_readlink_args *ap) 791 { 792 printf("%s called\n", __func__); 793 return (EOPNOTSUPP); 794 } 795 796 static int 797 udf_strategy(struct vop_strategy_args *a) 798 { (kgdb) 799 struct buf *bp; 800 struct vnode *vp; 801 struct udf_node *node; 802 int maxsize; 803 daddr_t sector; 804 struct bufobj *bo; 805 int multiplier; 806 807 bp = a->a_bp; 808 vp = a->a_vp; (kgdb) 809 node = VTON(vp); 810 811 if (bp->b_blkno == bp->b_lblkno) { 812 /* 813 * Files that are embedded in the fentry don't translate well 814 * to a block number. Reject. 815 */ 816 if (udf_bmap_internal(node, bp->b_lblkno * node->udfmp->bsize, 817 §or, &maxsize)) { 818 clrbuf(bp); (kgdb) 819 bp->b_blkno = -1; 820 } 821 822 /* bmap gives sector numbers, bio works with device blocks */ 823 multiplier = node->udfmp->bsize / DEV_BSIZE; 824 bp->b_blkno = sector * multiplier; 825 826 } 827 if ((long)bp->b_blkno == -1) { 828 bufdone(bp); (kgdb) 829 return (0); 830 } 831 bo = node->udfmp->im_bo; 832 bp->b_iooffset = dbtob(bp->b_blkno); 833 BO_STRATEGY(bo, bp); 834 return (0); 835 } 836 837 static int 838 udf_bmap(struct vop_bmap_args *a) (kgdb) 839 { 840 struct udf_node *node; 841 uint32_t max_size; 842 daddr_t lsector; 843 int error; 844 845 node = VTON(a->a_vp); 846 847 if (a->a_bop != NULL) 848 *a->a_bop = &node->udfmp->im_devvp->v_bufobj; (kgdb) 849 if (a->a_bnp == NULL) 850 return (0); 851 if (a->a_runb) 852 *a->a_runb = 0; 853 854 error = udf_bmap_internal(node, a->a_bn * node->udfmp->bsize, &lsector, 855 &max_size); 856 if (error) 857 return (error); 858 (kgdb) 859 /* Translate logical to physical sector number */ 860 *a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT); 861 862 /* Punt on read-ahead for now */ 863 if (a->a_runp) 864 *a->a_runp = 0; 865 866 return (0); 867 } 868 (kgdb) 869 /* 870 * The all powerful VOP_LOOKUP(). 871 */ 872 static int 873 udf_lookup(struct vop_cachedlookup_args *a) 874 { 875 struct vnode *dvp; 876 struct vnode *tdp = NULL; 877 struct vnode **vpp = a->a_vpp; 878 struct udf_node *node; (kgdb) 879 struct udf_mnt *udfmp; 880 struct fileid_desc *fid = NULL; 881 struct udf_dirstream *ds; 882 struct thread *td; 883 u_long nameiop; 884 u_long flags; 885 char *nameptr; 886 long namelen; 887 ino_t id = 0; 888 int offset, error = 0; (kgdb) 889 int numdirpasses, fsize; 890 891 dvp = a->a_dvp; 892 node = VTON(dvp); 893 udfmp = node->udfmp; 894 nameiop = a->a_cnp->cn_nameiop; 895 flags = a->a_cnp->cn_flags; 896 nameptr = a->a_cnp->cn_nameptr; 897 namelen = a->a_cnp->cn_namelen; 898 fsize = le64toh(node->fentry->inf_len); (kgdb) 899 td = a->a_cnp->cn_thread; 900 901 /* 902 * If this is a LOOKUP and we've already partially searched through 903 * the directory, pick up where we left off and flag that the 904 * directory may need to be searched twice. For a full description, 905 * see /sys/fs/cd9660/cd9660_lookup.c:cd9660_lookup() 906 */ 907 if (nameiop != LOOKUP || node->diroff == 0 || node->diroff > fsize) { 908 offset = 0; (kgdb) 909 numdirpasses = 1; 910 } else { 911 offset = node->diroff; 912 numdirpasses = 2; 913 nchstats.ncs_2passes++; 914 } 915 916 lookloop: 917 ds = udf_opendir(node, offset, fsize, udfmp); 918 (kgdb) 919 while ((fid = udf_getfid(ds)) != NULL) { 920 921 /* XXX Should we return an error on a bad fid? */ 922 if (udf_checktag(&fid->tag, TAGID_FID)) { 923 printf("udf_lookup: Invalid tag\n"); 924 error = EIO; 925 break; 926 } 927 928 /* Is this a deleted file? */ (kgdb) 929 if (fid->file_char & UDF_FILE_CHAR_DEL) 930 continue; 931 932 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { 933 if (flags & ISDOTDOT) { 934 id = udf_getid(&fid->icb); 935 break; 936 } 937 } else { 938 if (!(udf_cmpname(&fid->data[fid->l_iu], (kgdb) 939 nameptr, fid->l_fi, namelen, udfmp))) { 940 id = udf_getid(&fid->icb); 941 break; 942 } 943 } 944 } 945 946 if (!error) 947 error = ds->error; 948 (kgdb) 949 /* XXX Bail out here? */ 950 if (error) { 951 udf_closedir(ds); 952 return (error); 953 } 954 955 /* Did we have a match? */ 956 if (id) { 957 if (flags & ISDOTDOT) 958 VOP_UNLOCK(dvp, 0, a->a_cnp->cn_thread); (kgdb) 959 error = udf_vget(udfmp->im_mountp, id, LK_EXCLUSIVE, &tdp); 960 if (flags & ISDOTDOT) 961 vn_lock(dvp, LK_EXCLUSIVE|LK_RETRY, a->a_cnp->cn_thread); 962 if (!error) { 963 /* 964 * Remember where this entry was if it's the final 965 * component. 966 */ 967 if ((flags & ISLASTCN) && nameiop == LOOKUP) 968 node->diroff = ds->offset + ds->off; (kgdb) 969 if (numdirpasses == 2) 970 nchstats.ncs_pass2++; 971 *vpp = tdp; 972 /* Put this entry in the cache */ 973 if (flags & MAKEENTRY) 974 cache_enter(dvp, *vpp, a->a_cnp); 975 } 976 } else { 977 /* Name wasn't found on this pass. Do another pass? */ 978 if (numdirpasses == 2) { (kgdb) 979 numdirpasses--; 980 offset = 0; 981 udf_closedir(ds); 982 goto lookloop; 983 } 984 985 /* Enter name into cache as non-existant */ 986 if (flags & MAKEENTRY) 987 cache_enter(dvp, *vpp, a->a_cnp); 988 (kgdb) 989 if ((flags & ISLASTCN) && 990 (nameiop == CREATE || nameiop == RENAME)) { 991 error = EROFS; 992 } else { 993 error = ENOENT; 994 } 995 } 996 997 udf_closedir(ds); 998 return (error); (kgdb) 999 } 1000 1001 static int 1002 udf_reclaim(struct vop_reclaim_args *a) 1003 { 1004 struct vnode *vp; 1005 struct udf_node *unode; 1006 1007 vp = a->a_vp; 1008 unode = VTON(vp); (kgdb) 1009 1010 /* 1011 * Destroy the vm object and flush associated pages. 1012 */ 1013 vnode_destroy_vobject(vp); 1014 1015 if (unode != NULL) { 1016 vfs_hash_remove(vp); 1017 1018 if (unode->fentry != NULL) (kgdb) 1019 FREE(unode->fentry, M_UDFFENTRY); 1020 uma_zfree(udf_zone_node, unode); 1021 vp->v_data = NULL; 1022 } 1023 1024 return (0); 1025 } 1026 1027 static int 1028 udf_vptofh(struct vop_vptofh_args *a) (kgdb) 1029 { 1030 struct udf_node *node; 1031 struct ifid *ifhp; 1032 1033 node = VTON(a->a_vp); 1034 ifhp = (struct ifid *)a->a_fhp; 1035 ifhp->ifid_len = sizeof(struct ifid); 1036 ifhp->ifid_ino = node->hash_id; 1037 1038 return (0); (kgdb) 1039 } 1040 1041 /* 1042 * Read the block and then set the data pointer to correspond with the 1043 * offset passed in. Only read in at most 'size' bytes, and then set 'size' 1044 * to the number of bytes pointed to. If 'size' is zero, try to read in a 1045 * whole extent. 1046 * 1047 * Note that *bp may be assigned error or not. 1048 * (kgdb) 1049 */ 1050 static int 1051 udf_readatoffset(struct udf_node *node, int *size, off_t offset, 1052 struct buf **bp, uint8_t **data) 1053 { 1054 struct udf_mnt *udfmp; 1055 struct file_entry *fentry = NULL; 1056 struct buf *bp1; 1057 uint32_t max_size; 1058 daddr_t sector; (kgdb) 1059 int error; 1060 1061 udfmp = node->udfmp; 1062 1063 *bp = NULL; 1064 error = udf_bmap_internal(node, offset, §or, &max_size); 1065 if (error == UDF_INVALID_BMAP) { 1066 /* 1067 * This error means that the file *data* is stored in the 1068 * allocation descriptor field of the file entry. (kgdb) 1069 */ 1070 fentry = node->fentry; 1071 *data = &fentry->data[le32toh(fentry->l_ea)]; 1072 *size = le32toh(fentry->l_ad); 1073 return (0); 1074 } else if (error != 0) { 1075 return (error); 1076 } 1077 1078 /* Adjust the size so that it is within range */ (kgdb) 1079 if (*size == 0 || *size > max_size) 1080 *size = max_size; 1081 *size = min(*size, MAXBSIZE); 1082 1083 if ((error = udf_readlblks(udfmp, sector, *size + (offset & udfmp->bmask), bp))) { 1084 printf("warning: udf_readlblks returned error %d\n", error); 1085 /* note: *bp may be non-NULL */ 1086 return (error); 1087 } 1088 (kgdb) 1089 bp1 = *bp; 1090 *data = (uint8_t *)&bp1->b_data[offset & udfmp->bmask]; 1091 return (0); 1092 } 1093 1094 /* 1095 * Translate a file offset into a logical block and then into a physical 1096 * block. 1097 * max_size - maximum number of bytes that can be read starting from given 1098 * offset, rather than beginning of calculated sector number (kgdb) 1099 */ 1100 static int 1101 udf_bmap_internal(struct udf_node *node, off_t offset, daddr_t *sector, 1102 uint32_t *max_size) 1103 { 1104 struct udf_mnt *udfmp; 1105 struct file_entry *fentry; 1106 void *icb; 1107 struct icb_tag *tag; 1108 uint32_t icblen = 0; (kgdb) 1109 daddr_t lsector; 1110 int ad_offset, ad_num = 0; 1111 int i, p_offset; 1112 1113 udfmp = node->udfmp; 1114 fentry = node->fentry; 1115 tag = &fentry->icbtag; 1116 1117 switch (le16toh(tag->strat_type)) { 1118 case 4: (kgdb) 1119 break; 1120 1121 case 4096: 1122 printf("Cannot deal with strategy4096 yet!\n"); 1123 return (ENODEV); 1124 1125 default: 1126 printf("Unknown strategy type %d\n", tag->strat_type); 1127 return (ENODEV); 1128 } (kgdb) 1129 1130 switch (le16toh(tag->flags) & 0x7) { 1131 case 0: 1132 /* 1133 * The allocation descriptor field is filled with short_ad's. 1134 * If the offset is beyond the current extent, look for the 1135 * next extent. 1136 */ 1137 do { 1138 offset -= icblen; (kgdb) 1139 ad_offset = sizeof(struct short_ad) * ad_num; 1140 if (ad_offset > le32toh(fentry->l_ad)) { 1141 printf("File offset out of bounds\n"); 1142 return (EINVAL); 1143 } 1144 icb = GETICB(short_ad, fentry, 1145 le32toh(fentry->l_ea) + ad_offset); 1146 icblen = GETICBLEN(short_ad, icb); 1147 ad_num++; 1148 } while(offset >= icblen); (kgdb) 1149 1150 lsector = (offset >> udfmp->bshift) + 1151 le32toh(((struct short_ad *)(icb))->pos); 1152 1153 *max_size = icblen - offset; 1154 1155 break; 1156 case 1: 1157 /* 1158 * The allocation descriptor field is filled with long_ad's (kgdb) 1159 * If the offset is beyond the current extent, look for the 1160 * next extent. 1161 */ 1162 do { 1163 offset -= icblen; 1164 ad_offset = sizeof(struct long_ad) * ad_num; 1165 if (ad_offset > le32toh(fentry->l_ad)) { 1166 printf("File offset out of bounds\n"); 1167 return (EINVAL); 1168 } (kgdb) 1169 icb = GETICB(long_ad, fentry, 1170 le32toh(fentry->l_ea) + ad_offset); 1171 icblen = GETICBLEN(long_ad, icb); 1172 ad_num++; 1173 } while(offset >= icblen); 1174 1175 lsector = (offset >> udfmp->bshift) + 1176 le32toh(((struct long_ad *)(icb))->loc.lb_num); 1177 1178 *max_size = icblen - offset; (kgdb) 1179 1180 break; 1181 case 3: 1182 /* 1183 * This type means that the file *data* is stored in the 1184 * allocation descriptor field of the file entry. 1185 */ 1186 *max_size = 0; 1187 *sector = node->hash_id + udfmp->part_start; 1188 (kgdb) 1189 return (UDF_INVALID_BMAP); 1190 case 2: 1191 /* DirectCD does not use extended_ad's */ 1192 default: 1193 printf("Unsupported allocation descriptor %d\n", 1194 tag->flags & 0x7); 1195 return (ENODEV); 1196 } 1197 1198 *sector = lsector + udfmp->part_start; (kgdb) 1199 1200 /* 1201 * Check the sparing table. Each entry represents the beginning of 1202 * a packet. 1203 */ 1204 if (udfmp->s_table != NULL) { 1205 for (i = 0; i< udfmp->s_table_entries; i++) { 1206 p_offset = 1207 lsector - le32toh(udfmp->s_table->entries[i].org); 1208 if ((p_offset < udfmp->p_sectors) && (p_offset >= 0)) { (kgdb) 1209 *sector = 1210 le32toh(udfmp->s_table->entries[i].map) + 1211 p_offset; 1212 break; 1213 } 1214 } 1215 } 1216 1217 return (0); 1218 } (kgdb) >How-To-Repeat: Sometimes (seldom), "panic:page fault" happens after KDE automount occur when I insert CD/DVD. Simillar error, probably, happens in ver. 6.x >Fix: >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200711282238.lASMcY7D013576>