smp8671/android上yaffs2文件莫名丢失及挂起有关问题分析1
smp8671/android下yaffs2文件莫名丢失及挂起问题分析1
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打印出来,可以看出何时链表被破坏)。
1,现象:
在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 .............." rebootlogcat_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 0x92cd2200H)分析前一步日志,检查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"))); } #endifI)分析发现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); } } }