kern/118322: Sometimes (seldom), "panic:page fault" happens after KDE automount occur when I insert CD/DVD

Andrew Muhametshin andrew at dobrohot.org
Wed Nov 28 14:40:03 PST 2007


>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 at 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 at 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                         &sector, &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, &sector, &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:


More information about the freebsd-bugs mailing list