1,现象:
在smp8671-android数字电视系统开发过程中,系统启动过程中偶尔会出现系统停止的情形。串口中有时会打印(link_image[2329]: failed to link libGLESv1_CM.so,有时还能运行shell命令,有时不能。
2,重现问题
为了抓取系统停止时的日志,特地做了一个不停重启,并且将日志打印到串口的一个init.rc。期望在正常情况下机器能够不停的重启,未正常运行到animation结束时,机器将保留当时状态。
3,分析
A)由于怀疑程序的启动过程有问题,可执行程序的某些库未正常加载,故打开了bionic/linker中的日志开关LOCAL_CFLAGS += -DLINKER_DEBUG=1,打开此开关后,发现并非是linker的问题,问题在于某些so文件确实找不到。
B)在分析链接库丢失过程中,偶然有一次进入了shell。提示信息为link_image[2329]: failed to link libGLESv1_CM.so。根据日志判断运行mediaserver未成功。
为此,特地写一个程序去读一个文件夹的内容。文件名为test_folder.cpp。此程序首先readdir得到其下所有节点,并且lstat查看这些entry。从运行结果判断是文件系统出了问题,从lstat系统调用开始查起,判断问题大概出在了yaffs驱动中。
C)打开yaffs驱动中的调试信息,修改yaffs_vfs_glue.c文件,打开YAFFS_TRACE_OS信息。
unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS | YAFFS_TRACE_OS;
D)出现新现象,一直打印flushing obj 1027,分析代码发现unlink和flush同时对ip-up-vpn进行了操作。
E)分析代码,怀疑是fs/yaffs2/yaffs_vfs_glue.c中的yaffs_flush_inodes函数有问题。将list_for_each_entry改为list_for_each_entry_safe测试。
F)改过代码后,问题依旧,仍然不停打印flushing obj,分析代码发现,可能是链表被破坏了,导致一直在flushing某一个节点。修改yaffs_flush_inodes为如下,打印出链表的节点(曾经是只打印之后一个节点,证实了我的猜测,为了确定是什么地方改坏链表,特定将next_next打印出来,可以看出何时链表被破坏)。
在smp8671-android数字电视系统开发过程中,系统启动过程中偶尔会出现系统停止的情形。串口中有时会打印(link_image[2329]: failed to link libGLESv1_CM.so,有时还能运行shell命令,有时不能。
2,重现问题
为了抓取系统停止时的日志,特地做了一个不停重启,并且将日志打印到串口的一个init.rc。期望在正常情况下机器能够不停的重启,未正常运行到animation结束时,机器将保留当时状态。
在init.rc中添加如下内容:
on property:init.svc.bootanim=stopped
start reboot_a
service windlogcat /system/bin/logcat_daemon -f /dev/ttyS0 -v time
oneshot
service reboot_a /reboot.sh
disabled
reboot.sh的内容为:
#! /system/bin/sh
echo "waitting 100s to reboot"
sleep 50
echo "reboot now .............."
reboot
logcat_daemon只是对logcat做的一个包装,将logcat作为后台进程在运行。
3,分析
A)由于怀疑程序的启动过程有问题,可执行程序的某些库未正常加载,故打开了bionic/linker中的日志开关LOCAL_CFLAGS += -DLINKER_DEBUG=1,打开此开关后,发现并非是linker的问题,问题在于某些so文件确实找不到。
B)在分析链接库丢失过程中,偶然有一次进入了shell。提示信息为link_image[2329]: failed to link libGLESv1_CM.so。根据日志判断运行mediaserver未成功。
我手动运行mediaserver,得到打印
mediaserver
01-01 01:01:27.228 E/DCCHD ( 6764): [src/CMediaAccess.cpp:395] [Global]MediaAccess object created
link_image[2329]: failed to link mediaserver
CANNOT LINK EXECUTABLE
根据提示failed to link mediaserver,判断是有个so没有找到。后到一个正常的机器查看mediaserver所链接的库,发现是没有找到libGLESv1_CM.so。
然后cd /; busybox find -name "libGLES*",得到如下打印:
cd /;
busybox find -name "libGLES*"
./system/lib/egl/libGLES_android.so
find: ./system/lib/libGLESv1_CM.so: No such file or directory
./system/lib/libGLESv2.so
很奇怪的打印,libGLESv1_CM.so为何会有如此打印?find的时候竟然能发现这个文件。
为此,特地写一个程序去读一个文件夹的内容。文件名为test_folder.cpp。此程序首先readdir得到其下所有节点,并且lstat查看这些entry。从运行结果判断是文件系统出了问题,从lstat系统调用开始查起,判断问题大概出在了yaffs驱动中。
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main (int argc, const char* argv[]) {
DIR *pDir = NULL;
struct dirent *ent = NULL;
char pathname[2048]= {0};
const char* folder = argv[1];
pDir = opendir (folder);
if (pDir) {
while ((ent = readdir (pDir)) != NULL) {
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..") == 0)
continue;
printf ("d_name=%s, d_reclen=%d, d_type=%u, d_off=%lld, d_ino=%llu\n", ent->d_name, ent->d_reclen, ent->d_type, ent->d_off, ent->d_ino);
memset (pathname, 0, sizeof(pathname));
strcpy (pathname, folder);
strcat (pathname, "/");
strcat (pathname, ent->d_name);
struct stat buf;
if (lstat (pathname, &buf) < 0) {
printf ("%s!\n", strerror (errno));
continue;
}
switch (buf.st_mode & S_IFMT) {
case S_IFBLK:
break;
case S_IFCHR:
break;
case S_IFDIR:
//INFO ("directory %s, not return to filelist", ent->d_name);
//filelist.push_back(ent->d_name);
break;
case S_IFIFO:
break;
case S_IFLNK:
break;
case S_IFREG:
//printf ("regular file\n");
//filelist.push_back(ent->d_name);
break;
case S_IFSOCK:
break;
default:
break;
}
}
closedir (pDir);
return 0;
} else {
printf ("opendir error(%s)!\n", folder);
return -1;
}
}
该程序运行结果:
d_name=libjni_file_manager_cmd.so, d_reclen=48, d_type=8, d_off=3, d_ino=399
d_name=libFFTEm.so, d_reclen=32, d_type=8, d_off=4, d_ino=398
d_name=libandroid_servers.so, d_reclen=48, d_type=8, d_off=5, d_ino=397
d_name=libstagefright_color_conversion.so, d_reclen=56, d_type=8, d_off=6, d_ino=396
d_name=libicudata.so, d_reclen=40, d_type=8, d_off=7, d_ino=395
d_name=libbinder.so, d_reclen=32, d_type=8, d_off=8, d_ino=394
d_name=libnetutils.so, d_reclen=40, d_type=8, d_off=9, d_ino=393
d_name=libopencore_mp4local.so, d_reclen=48, d_type=8, d_off=10, d_ino=392
d_name=libomx_m4vdec_sharedlibrary.so, d_reclen=56, d_type=8, d_off=11, d_ino=391
d_name=libutils.so, d_reclen=32, d_type=8, d_off=12, d_ino=390
d_name=libjni_latinime.so, d_reclen=40, d_type=8, d_off=13, d_ino=389
d_name=libhardware_legacy.so, d_reclen=48, d_type=8, d_off=14, d_ino=388
d_name=libsystem_server.so, d_reclen=40, d_type=8, d_off=15, d_ino=387
d_name=libomx_aacdec_sharedlibrary.so, d_reclen=56, d_type=8, d_off=16, d_ino=386
d_name=libffi.so, d_reclen=32, d_type=8, d_off=17, d_ino=385
d_name=libomx_mp3dec_sharedlibrary.so, d_reclen=56, d_type=8, d_off=18, d_ino=384
d_name=libstdc++.so, d_reclen=32, d_type=8, d_off=19, d_ino=383
d_name=libOMX.Sigma.Mp3.Decoder.so, d_reclen=48, d_type=8, d_off=20, d_ino=382
d_name=libxml2wbxml.so, d_reclen=40, d_type=8, d_off=21, d_ino=381
d_name=libomx_avcdec_sharedlibrary.so, d_reclen=56, d_type=8, d_off=22, d_ino=380
d_name=libsqlite.so, d_reclen=32, d_type=8, d_off=23, d_ino=379
d_name=libOMX.Sigma.Aac.Decoder.so, d_reclen=48, d_type=8, d_off=24, d_ino=378
d_name=librmlibplay_default_plugin.so, d_reclen=56, d_type=8, d_off=25, d_ino=377
d_name=libsmartinput_oem.so, d_reclen=40, d_type=8, d_off=26, d_ino=376
d_name=libstagefright_avc_common.so, d_reclen=48, d_type=8, d_off=27, d_ino=375
d_name=libSR_AudioIn.so, d_reclen=40, d_type=8, d_off=28, d_ino=374
d_name=libopencore_common.so, d_reclen=48, d_type=8, d_off=29, d_ino=373
d_name=libsurfaceflinger_client.so, d_reclen=48, d_type=8, d_off=30, d_ino=372
d_name=libjnigraphics.so, d_reclen=40, d_type=8, d_off=31, d_ino=371
d_name=libdcchd_android.so, d_reclen=40, d_type=8, d_off=32, d_ino=370
d_name=libiprouteutil.so, d_reclen=40, d_type=8, d_off=33, d_ino=369
d_name=libterm.so, d_reclen=32, d_type=8, d_off=34, d_ino=368
d_name=librdhdmi.so, d_reclen=32, d_type=8, d_off=35, d_ino=367
d_name=libhomecfg.so, d_reclen=40, d_type=8, d_off=36, d_ino=366
d_name=libexif.so, d_reclen=32, d_type=8, d_off=37, d_ino=365
d_name=libomx_amrenc_sharedlibrary.so, d_reclen=56, d_type=8, d_off=38, d_ino=364
d_name=libomx_amrdec_sharedlibrary.so, d_reclen=56, d_type=8, d_off=39, d_ino=363
d_name=liblog.so, d_reclen=32, d_type=8, d_off=40, d_ino=362
d_name=libthread_db.so, d_reclen=40, d_type=8, d_off=41, d_ino=361
d_name=libopencore_player.so, d_reclen=48, d_type=8, d_off=42, d_ino=360
d_name=libdrm1.so, d_reclen=32, d_type=8, d_off=43, d_ino=359
d_name=libskiagl.so, d_reclen=32, d_type=8, d_off=44, d_ino=358
d_name=libntp_server.so, d_reclen=40, d_type=8, d_off=45, d_ino=357
d_name=libemoji.so, d_reclen=32, d_type=8, d_off=46, d_ino=356
d_name=libstagefright.so, d_reclen=40, d_type=8, d_off=47, d_ino=355
d_name=libssl.so, d_reclen=32, d_type=8, d_off=48, d_ino=354
d_name=librmlibplay_realmedia_plugin.so, d_reclen=56, d_type=8, d_off=49, d_ino=353
d_name=libstlport.so, d_reclen=40, d_type=8, d_off=50, d_ino=352
d_name=libvorbisidec.so, d_reclen=40, d_type=8, d_off=51, d_ino=351
d_name=libEGL.so, d_reclen=32, d_type=8, d_off=52, d_ino=350
d_name=libfrontpanel.so, d_reclen=40, d_type=8, d_off=53, d_ino=349
d_name=libcore.so, d_reclen=32, d_type=8, d_off=54, d_ino=348
d_name=egl, d_reclen=24, d_type=4, d_off=55, d_ino=346
d_name=libsoundpool.so, d_reclen=40, d_type=8, d_off=56, d_ino=345
d_name=librs_jni.so, d_reclen=32, d_type=8, d_off=57, d_ino=344
d_name=invoke_mock_media_player.so, d_reclen=48, d_type=8, d_off=58, d_ino=343
d_name=libctest.so, d_reclen=32, d_type=8, d_off=59, d_ino=342
d_name=libdl.so, d_reclen=32, d_type=8, d_off=60, d_ino=341
d_name=libc_malloc_debug_qemu.so, d_reclen=48, d_type=8, d_off=61, d_ino=340
d_name=libwebcore.so, d_reclen=40, d_type=8, d_off=62, d_ino=339
d_name=libreference-cdma-sms.so, d_reclen=48, d_type=8, d_off=63, d_ino=338
d_name=libcrypto.so, d_reclen=32, d_type=8, d_off=64, d_ino=337
d_name=librmomx.so, d_reclen=32, d_type=8, d_off=65, d_ino=336
d_name=libstagefright_amrnb_common.so, d_reclen=56, d_type=8, d_off=66, d_ino=335
d_name=libsrec_jni.so, d_reclen=40, d_type=8, d_off=67, d_ino=334
d_name=libdiskconfig.so, d_reclen=40, d_type=8, d_off=68, d_ino=333
d_name=libstagefright_omx.so, d_reclen=48, d_type=8, d_off=69, d_ino=332
d_name=libnativehelper.so, d_reclen=40, d_type=8, d_off=70, d_ino=331
d_name=libdbus.so, d_reclen=32, d_type=8, d_off=71, d_ino=330
d_name=libjni_synctime.so, d_reclen=40, d_type=8, d_off=72, d_ino=329
d_name=libmedia_jni.so, d_reclen=40, d_type=8, d_off=73, d_ino=328
d_name=libc.so, d_reclen=32, d_type=8, d_off=74, d_ino=327
d_name=libz.so, d_reclen=32, d_type=8, d_off=75, d_ino=326
d_name=libhwdata.so, d_reclen=32, d_type=8, d_off=76, d_ino=325
d_name=libopencore_author.so, d_reclen=48, d_type=8, d_off=77, d_ino=324
d_name=libsurfaceflinger.so, d_reclen=40, d_type=8, d_off=78, d_ino=323
d_name=libGLESv1_CM.so, d_reclen=40, d_type=8, d_off=79, d_ino=322
No such file or directory!
d_name=libui.so, d_reclen=32, d_type=8, d_off=80, d_ino=321
d_name=libfactorytest.so, d_reclen=40, d_type=8, d_off=81, d_ino=320
d_name=libc_malloc_debug_leak.so, d_reclen=48, d_type=8, d_off=82, d_ino=319
d_name=libETC1.so, d_reclen=32, d_type=8, d_off=83, d_ino=318
d_name=libdrm.so, d_reclen=32, d_type=8, d_off=84, d_ino=317
d_name=libicui18n.so, d_reclen=40, d_type=8, d_off=85, d_ino=316
d_name=libopencore_rtsp.so, d_reclen=40, d_type=8, d_off=86, d_ino=315
d_name=libandroid_runtime.so, d_reclen=48, d_type=8, d_off=87, d_ino=314
d_name=libsysutils.so, d_reclen=40, d_type=8, d_off=88, d_ino=313
d_name=libttssynthproxy.so, d_reclen=40, d_type=8, d_off=89, d_ino=312
d_name=libmediaplayerservice.so, d_reclen=48, d_type=8, d_off=90, d_ino=311
d_name=libmedia.so, d_reclen=32, d_type=8, d_off=91, d_ino=310
d_name=libcamera_client.so, d_reclen=40, d_type=8, d_off=92, d_ino=309
d_name=libpagemap.so, d_reclen=40, d_type=8, d_off=93, d_ino=308
d_name=libhardware.so, d_reclen=40, d_type=8, d_off=94, d_ino=307
d_name=libfrontpaneljni.so, d_reclen=40, d_type=8, d_off=95, d_ino=306
d_name=libjni_pinyinime.so, d_reclen=40, d_type=8, d_off=96, d_ino=305
d_name=libjni_system_cmd.so, d_reclen=40, d_type=8, d_off=97, d_ino=304
d_name=libudhcp.so, d_reclen=32, d_type=8, d_off=98, d_ino=303
d_name=libreference-ril.so, d_reclen=40, d_type=8, d_off=99, d_ino=302
d_name=libttspico.so, d_reclen=40, d_type=8, d_off=100, d_ino=301
d_name=libopencore_rtspreg.so, d_reclen=48, d_type=8, d_off=101, d_ino=300
d_name=libacc.so, d_reclen=32, d_type=8, d_off=102, d_ino=299
d_name=libopencore_mp4localreg.so, d_reclen=48, d_type=8, d_off=103, d_ino=298
d_name=libril.so, d_reclen=32, d_type=8, d_off=104, d_ino=297
d_name=libpixelflinger.so, d_reclen=40, d_type=8, d_off=105, d_ino=296
d_name=libopencore_download.so, d_reclen=48, d_type=8, d_off=106, d_ino=295
d_name=libwpa_client.so, d_reclen=40, d_type=8, d_off=107, d_ino=294
d_name=libopencore_net_support.so, d_reclen=48, d_type=8, d_off=108, d_ino=293
d_name=libnetlink.so, d_reclen=40, d_type=8, d_off=109, d_ino=292
d_name=libcameraservice.so, d_reclen=40, d_type=8, d_off=110, d_ino=291
d_name=libGLESv2.so, d_reclen=32, d_type=8, d_off=111, d_ino=290
d_name=libplayback.so, d_reclen=40, d_type=8, d_off=112, d_ino=289
d_name=libcutils.so, d_reclen=32, d_type=8, d_off=113, d_ino=288
d_name=libOMX_Core.so, d_reclen=40, d_type=8, d_off=114, d_ino=287
d_name=libdvm.so, d_reclen=32, d_type=8, d_off=115, d_ino=286
d_name=libskia.so, d_reclen=32, d_type=8, d_off=116, d_ino=285
d_name=libdisplay.so, d_reclen=40, d_type=8, d_off=117, d_ino=284
d_name=libwbxml_jni.so, d_reclen=40, d_type=8, d_off=118, d_ino=283
d_name=libcurl.so, d_reclen=32, d_type=8, d_off=119, d_ino=282
d_name=libm.so, d_reclen=32, d_type=8, d_off=120, d_ino=281
d_name=libRS.so, d_reclen=32, d_type=8, d_off=121, d_ino=280
d_name=libmeterreader.so, d_reclen=40, d_type=8, d_off=122, d_ino=279
d_name=libdrm1_jni.so, d_reclen=40, d_type=8, d_off=123, d_ino=278
d_name=libopencore_downloadreg.so, d_reclen=48, d_type=8, d_off=124, d_ino=277
d_name=libaudioflinger.so, d_reclen=40, d_type=8, d_off=125, d_ino=276
d_name=hw, d_reclen=24, d_type=4, d_off=126, d_ino=271
d_name=CVS, d_reclen=24, d_type=4, d_off=127, d_ino=267
d_name=libicuuc.so, d_reclen=32, d_type=8, d_off=128, d_ino=266
d_name=libhw.so, d_reclen=32, d_type=8, d_off=129, d_ino=265
d_name=libOMX.Sigma.Video.Decoder.so, d_reclen=56, d_type=8, d_off=130, d_ino=264
d_name=libomx_sharedlibrary.so, d_reclen=48, d_type=8, d_off=131, d_ino=263
d_name=libsonivox.so, d_reclen=40, d_type=8, d_off=132, d_ino=262
d_name=librmlibrealmedia.so, d_reclen=40, d_type=8, d_off=133, d_ino=261
d_name=libsampleplugin.so, d_reclen=40, d_type=8, d_off=134, d_ino=260
d_name=libexpat.so, d_reclen=32, d_type=8, d_off=135, d_ino=259
C)打开yaffs驱动中的调试信息,修改yaffs_vfs_glue.c文件,打开YAFFS_TRACE_OS信息。
unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS | YAFFS_TRACE_OS;
D)出现新现象,一直打印flushing obj 1027,分析代码发现unlink和flush同时对ip-up-vpn进行了操作。
[ 24.296000] flushing obj 516
[ 24.300000] yaffs_lookup for 276:ip-up-vpn
[ 24.308000] flushing obj 515
[ 24.312000] flushing obj 514
[ 24.316000] flushing obj 513
[ 24.320000] flushing obj 262
[ 24.324000] flushing obj 267
[ 24.328000] flushing obj 518
[ 24.332000] flushing obj 295
[ 24.336000] flushing obj 292
[ 24.340000] flushing obj 260
[ 24.344000] flushing obj 1025
[ 24.348000] flushing obj 259
[ 24.356000] flushing obj 269
[ 24.360000] flushing obj 261
[ 24.364000] yaffs_lookup found 1027
[ 24.368000] flushing obj 270
[ 24.372000] yaffs_get_inode for object 1027
[ 24.376000] flushing obj 1
[ 24.380000] yaffs_iget for 1027
[ 24.388000] yaffs_write_super
[ 24.392000] yaffs_do_sync_fs: gc-urgency 0 dirty no checkpoint
[ 24.400000] yaffs_fill_inode mode 816d uid 0 gid 0 size 5248 count 1
[ 24.408000] yaffs_loookup dentry
[ 24.412000] flushing obj 257
[ 24.416000] yaffs_unlink 276:ip-up-vpn
[ 24.420000] flushing obj 1
[ 24.424000] yaffs_write_super
[ 24.428000] yaffs_do_sync_fs: gc-urgency 0 dirty no checkpoint
[ 24.436000] yaffs_touch_super() sb = 92c89000
[ 24.448000] flushing obj 1027
[ 24.452000] yaffs_delete_inode: ino 1027, count 0 object exists
[ 24.460000] flushing obj 1027
[ 24.464000] flushing obj 1027
[ 24.468000] flushing obj 1027
[ 24.472000] flushing obj 1027
[ 24.476000] flushing obj 1027
[ 24.480000] flushing obj 1027
[ 24.484000] flushing obj 1027
[ 24.488000] flushing obj 1027
[ 24.492000] yaffs_file_flush object 865 (clean)
[ 24.500000] yaffs_file_flush object 865 (clean)
[ 24.504000] flushing obj 1027
[ 24.508000] flushing obj 1027
E)分析代码,怀疑是fs/yaffs2/yaffs_vfs_glue.c中的yaffs_flush_inodes函数有问题。将list_for_each_entry改为list_for_each_entry_safe测试。
F)改过代码后,问题依旧,仍然不停打印flushing obj,分析代码发现,可能是链表被破坏了,导致一直在flushing某一个节点。修改yaffs_flush_inodes为如下,打印出链表的节点(曾经是只打印之后一个节点,证实了我的猜测,为了确定是什么地方改坏链表,特定将next_next打印出来,可以看出何时链表被破坏)。
static void yaffs_flush_inodes(struct super_block *sb)
{
struct inode *iptr, *next, *next_next;
yaffs_obj_t *obj;
list_for_each_entry_safe(iptr,next,&sb->s_inodes, i_sb_list){
obj = yaffs_InodeToObject(iptr);
if(obj){
yaffs_dev_t *dev = obj->my_dev;
if (next)
next_next = list_entry(next->i_sb_list.next, typeof(*iptr), i_sb_list);
else
next_next = NULL;
T(YAFFS_TRACE_OS, (TSTR("flushing obj %d, iptr 0x%p(0x%p, 0x%p), dev 0x%p, sb 0x%p\n"),
obj->obj_id, iptr, next, next_next, dev, sb));
//yaffs_gross_lock(dev); //本来试图在这里加锁,发现程序不能运行,查代码发现外层已经加锁了,所以这里不需要加锁
yaffs_flush_file(obj, 1, 0);
//yaffs_gross_unlock(dev);
}
}
}
G)增加打印后,出现状况时的日志如下,可以发现sync_supers内核进程开始做文件系统同步时,来了一个yaffs_delete_inode,出现这个之后就发现链表已经不对了。
[ 48.000000] windsome sync_supers
[ 48.008000] yaffs_write_super
[ 48.012000] yaffs_touch_super() sb = 92cd2200
[ 48.024000] Added object 295 to dirty directories
[ 48.032000] yaffs_do_sync_fs: gc-urgency 0 dirty no checkpoint
[ 48.048000] yaffs_touch_super() sb = 92cd2200
[ 48.052000] yaffs_background
[ 48.052000] Update dirty directories
[ 48.064000] yaffs_touch_super() sb = 92cd2200
[ 48.072000] flushing obj 1031, iptr 0x935622e0(0x93562408, 0x93562d48), dev 0x92d51000, sb 0x92cd2200
[ 48.080000] yaffs_delete_inode: ino 1033, count 0 object exists
[ 48.100000] flushing obj 1033, iptr 0x93562408(0x93562408, 0x93562408), dev 0x92d51000, sb 0x92cd2200
[ 48.128000] flushing obj 1033, iptr 0x93562408(0x93562408, 0x93562408), dev 0x92d51000, sb 0x92cd2200
[ 48.156000] flushing obj 1033, iptr 0x93562408(0x93562408, 0x93562408), dev 0x92d51000, sb 0x92cd2200
[ 48.184000] flushing obj 1033, iptr 0x93562408(0x93562408, 0x93562408), dev 0x92d51000, sb 0x92cd2200
[ 48.212000] flushing obj 1033, iptr 0x93562408(0x93562408, 0x93562408), dev 0x92d51000, sb 0x92cd2200
H)分析前一步日志,检查yaffs_delete_inode函数,发现此在此时应该被阻塞着。继续查调用此函数的地方。
static void yaffs_delete_inode(struct inode *inode)
{
yaffs_obj_t *obj = yaffs_InodeToObject(inode);
yaffs_dev_t *dev;
T(YAFFS_TRACE_OS,
(TSTR("yaffs_delete_inode: ino %d, count %d %s\n"), (int)inode->i_ino,
atomic_read(&inode->i_count),
obj ? "object exists" : "null object"));
if (obj) {
dev = obj->my_dev;
yaffs_gross_lock(dev);
//T(YAFFS_TRACE_OS, (TSTR("yaffs_delete_inode: windsome step 1\n")));
yaffs_del_obj(obj);
//T(YAFFS_TRACE_OS, (TSTR("yaffs_delete_inode: windsome step 2\n")));
yaffs_gross_unlock(dev);
}
T(YAFFS_TRACE_OS, (TSTR("yaffs_delete_inode: return from lock\n")));
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
truncate_inode_pages(&inode->i_data, 0);
#endif
clear_inode(inode);
T(YAFFS_TRACE_OS,
(TSTR("yaffs_delete_inode: end\n")));
}
#endif
I)分析发现yaffs_delete_inode是在fs/inode.c中被generic_delete_inode调用,此函数在调用delete_inode之前,已经调用list_del_init(&inode->i_sb_list);重新设置了此inode的指针,将此inode从链表中剔除了。调用 list_del_init后,inode已经指向自己,所以从程序上看就一直在循环了。
void generic_delete_inode(struct inode *inode)
{
const struct super_operations *op = inode->i_sb->s_op;
list_del_init(&inode->i_list);
list_del_init(&inode->i_sb_list);
WARN_ON(inode->i_state & I_NEW);
inode->i_state |= I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
security_inode_delete(inode);
if (op->delete_inode) {
void (*delete)(struct inode *) = op->delete_inode;
if (!is_bad_inode(inode))
vfs_dq_init(inode);
/* Filesystems implementing their own
* s_op->delete_inode are required to call
* truncate_inode_pages and clear_inode()
* internally */
delete(inode);
} else {
truncate_inode_pages(&inode->i_data, 0);
clear_inode(inode);
}
spin_lock(&inode_lock);
hlist_del_init(&inode->i_hash);
spin_unlock(&inode_lock);
wake_up_inode(inode);
BUG_ON(inode->i_state != I_CLEAR);
destroy_inode(inode);
}
EXPORT_SYMBOL(generic_delete_inode);
J)到了这一步,我们就知道怎么改了,inode已经从链表中剔除,也就不再需要做flushing了,修改yaffs_flush_inodes函数,如下:
static void yaffs_flush_inodes(struct super_block *sb)
{
struct inode *iptr, *next;
yaffs_obj_t *obj;
list_for_each_entry_safe(iptr,next,&sb->s_inodes, i_sb_list){
obj = yaffs_InodeToObject(iptr);
if(obj){
yaffs_dev_t *dev = obj->my_dev;
T(YAFFS_TRACE_OS, (TSTR("yaffs_flush_inodes: flushing obj %d, iptr 0x%p(0x%p), dev 0x%p, sb 0x%p\n"),
obj->obj_id, iptr, next, dev, sb));
if (next == iptr) {
T(YAFFS_TRACE_OS, (TSTR("yaffs_flush_inodes: point to self! break to next time flushing\n")));
break;
}
yaffs_flush_file(obj, 1, 0);
}
}
}
有问题可以联系 agooou@gmail.com