[Yaffs] Rewind readdir when entries deleted

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Todd Poynor
Date:  
To: yaffs
Subject: [Yaffs] Rewind readdir when entries deleted
busybox rm -rf <dir>, bonnie++, and other applications that do not
rewinddir after each file removal, may fail to remove all files when
multiple readdir calls are needed due to the number of dentries. The
file position passed into the subsequent readdir calls no longer
describes the list position of the "next" entry to be returned.

The below solution causes a subsequent readdir to restart whenever a
file is deleted from that directory since the previous call. In some
uses this will cause dentries to be returned twice, but it is a quick
solution for rm -rf. If the inode version bumping introduced below
remains the sole situation in which a version would be bumped by yaffs,
it would be possible to compute the proper index to restart at.

Other suggestions welcomed. Note some shells introduce a rewinddir into
the rm -r code to avoid this problem.

Signed-off-by: Todd Poynor <>

Index: yaffs_fs.c
===================================================================
RCS file: /home/aleph1/cvs/yaffs2/yaffs_fs.c,v
retrieving revision 1.33
diff -u -r1.33 yaffs_fs.c
--- yaffs_fs.c    27 Oct 2005 22:24:04 -0000    1.33
+++ yaffs_fs.c    5 Nov 2005 00:28:27 -0000
@@ -814,6 +814,15 @@


     curoffs = 1;


+    /* If the directory has changed since the open or last call to
+       readdir, rewind to after the 2 canned entries. */
+
+    if (f->f_version != inode->i_version) {
+        offset = 2;
+        f->f_pos = offset;
+        f->f_version = inode->i_version;
+    }
+
     list_for_each(i, &obj->variant.directoryVariant.children) {
         curoffs++;
         if (curoffs >= offset) {
@@ -981,15 +990,15 @@


     retVal = yaffs_Unlink(yaffs_InodeToObject(dir), dentry->d_name.name);


-    yaffs_GrossUnlock(dev);
-
     if (retVal == YAFFS_OK) {
         dentry->d_inode->i_nlink--;
+        dir->i_version++;
+        yaffs_GrossUnlock(dev);
         mark_inode_dirty(dentry->d_inode);
         return 0;
-    } else {
-        return -ENOTEMPTY;
     }
+    yaffs_GrossUnlock(dev);
+    return -ENOTEMPTY;
 }


/*