Add more info to python test
[yaffs2.git] / yaffs_fs.c
index dfa94a2955d0bec53a9af4a3d2d31129e2f1b7c6..ab123f7bd5ee04064a9e1f57d0d02c2f6def73de 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 const char *yaffs_fs_c_version =
-    "$Id: yaffs_fs.c,v 1.87 2009-11-11 02:11:13 charles Exp $";
+    "$Id: yaffs_fs.c,v 1.89 2009-11-29 21:50:10 charles Exp $";
 extern const char *yaffs_guts_c_version;
 
 #include <linux/version.h>
@@ -365,68 +365,135 @@ static const struct super_operations yaffs_super_ops = {
        .write_super = yaffs_write_super,
 };
 
-/* YAFFS uses two locks per yaffs_Device.
- * dirLock: r/w lock Must be held when accessing directory structure.
- * grossLock: Lock when accessing yaffs internals.
- *
- * Locking rules:
- *  If you're going to take dirLock then you must take if before
- *  taking grossLock.
- *  ie. Don't call yaffs_DirLockxxx()  while holding grossLock.
- *
- * Todo:
- *   Investigate changing to mutexes etc and improve debugging.
- */
-static void yaffs_DirLockInitialise(yaffs_Device *dev)
+static void yaffs_GrossLock(yaffs_Device *dev)
 {
-       init_rwsem(&dev->dirLock);
+       T(YAFFS_TRACE_OS, ("yaffs locking %p\n", current));
+       down(&dev->grossLock);
+       T(YAFFS_TRACE_OS, ("yaffs locked %p\n", current));
 }
 
-static void yaffs_DirLockRead(yaffs_Device *dev)
+static void yaffs_GrossUnlock(yaffs_Device *dev)
 {
-       T(YAFFS_TRACE_OS, ("yaffs locking dir read %p\n", current));
-       down_read(&dev->dirLock);
-       T(YAFFS_TRACE_OS, ("yaffs locked dir read %p\n", current));
+       T(YAFFS_TRACE_OS, ("yaffs unlocking %p\n", current));
+       up(&dev->grossLock);
 }
 
-static void yaffs_DirUnlockRead(yaffs_Device *dev)
-{
-       T(YAFFS_TRACE_OS, ("yaffs unlocking dir read %p\n", current));
-       up_read(&dev->dirLock);
-}
 
-static void yaffs_DirLockWrite(yaffs_Device *dev)
-{
-       T(YAFFS_TRACE_OS, ("yaffs locking dir write %p\n", current));
-       down_write(&dev->dirLock);
-       T(YAFFS_TRACE_OS, ("yaffs locked dir write %p\n", current));
-}
+/*-----------------------------------------------------------------*/
+/* Directory search context allows us to unlock access to yaffs during
+ * filldir without causing problems with the directory being modified.
+ * This is similar to the tried and tested mechanism used in yaffs direct.
+ *
+ * A search context iterates along a doubly linked list of siblings in the
+ * directory. If the iterating object is deleted then this would corrupt
+ * the list iteration, likely causing a crash. The search context avoids
+ * this by using the removeObjectCallback to move the search context to the
+ * next object before the object is deleted.
+ *
+ * Many readdirs (and thus seach conexts) may be alive simulateously so
+ * each yaffs_Device has a list of these.
+ *
+ * A seach context lives for the duration of a readdir.
+ *
+ * All these functions must be called while yaffs is locked.
+ */
 
-static void yaffs_DirUnlockWrite(yaffs_Device *dev)
-{
-       T(YAFFS_TRACE_OS, ("yaffs unlocking dir write %p\n", current));
-       up_write(&dev->dirLock);
+struct yaffs_SearchContext {
+       yaffs_Device *dev;
+       yaffs_Object *dirObj;
+       yaffs_Object *nextReturn;
+       struct ylist_head others;
+};
+
+/*
+ * yaffs_NewSearch() creates a new search context, initialises it and
+ * adds it to the device's search context list.
+ *
+ * Called at start of readdir.
+ */
+static struct yaffs_SearchContext * yaffs_NewSearch(yaffs_Object *dir)
+{
+       yaffs_Device *dev = dir->myDev;
+       struct yaffs_SearchContext *sc = YMALLOC(sizeof(struct yaffs_SearchContext));
+       if(sc){
+               sc->dirObj = dir;
+               sc->dev = dev;
+               if( ylist_empty(&sc->dirObj->variant.directoryVariant.children))
+                       sc->nextReturn = NULL;
+               else
+                       sc->nextReturn = ylist_entry(
+                                dir->variant.directoryVariant.children.next,
+                               yaffs_Object,siblings);
+               YINIT_LIST_HEAD(&sc->others);
+               ylist_add(&sc->others,&dev->searchContexts);
+       }
+       return sc;
 }
 
-static void yaffs_GrossLockInitialise(yaffs_Device *dev)
+/*
+ * yaffs_EndSearch() disposes of a search context and cleans up.
+ */
+static void yaffs_EndSearch(struct yaffs_SearchContext * sc)
 {
-       init_MUTEX(&dev->grossLock);
+       if(sc){
+               ylist_del(&sc->others);
+               YFREE(sc);
+       }
 }
 
-static void yaffs_GrossLock(yaffs_Device *dev)
+/*
+ * yaffs_SearchAdvance() moves a search context to the next object.
+ * Called when the search iterates or when an object removal causes
+ * the search context to be moved to the next object.
+ */
+static void yaffs_SearchAdvance(struct yaffs_SearchContext *sc)
 {
-       T(YAFFS_TRACE_OS, ("yaffs locking %p\n", current));
-       down(&dev->grossLock);
-       T(YAFFS_TRACE_OS, ("yaffs locked %p\n", current));
+        if(!sc)
+                return;
+
+        if( sc->nextReturn == NULL ||
+                ylist_empty(&sc->dirObj->variant.directoryVariant.children))
+                sc->nextReturn = NULL;
+        else {
+                struct ylist_head *next = sc->nextReturn->siblings.next;
+
+                if( next == &sc->dirObj->variant.directoryVariant.children)
+                        sc->nextReturn = NULL; /* end of list */
+                else
+                        sc->nextReturn = ylist_entry(next,yaffs_Object,siblings);
+        }
 }
 
-static void yaffs_GrossUnlock(yaffs_Device *dev)
+/*
+ * yaffs_RemoveObjectCallback() is called when an object is unlinked.
+ * We check open search contexts and advance any which are currently
+ * on the object being iterated.
+ */
+static void yaffs_RemoveObjectCallback(yaffs_Object *obj)
 {
-       T(YAFFS_TRACE_OS, ("yaffs unlocking %p\n", current));
-       up(&dev->grossLock);
+
+        struct ylist_head *i;
+        struct yaffs_SearchContext *sc;
+        struct ylist_head *search_contexts = &obj->myDev->searchContexts;
+
+
+        /* Iterate through the directory search contexts.
+         * If any are currently on the object being removed, then advance
+         * the search context to the next object to prevent a hanging pointer.
+         */
+         ylist_for_each(i, search_contexts) {
+                if (i) {
+                        sc = ylist_entry(i, struct yaffs_SearchContext,others);
+                        if(sc->nextReturn == obj)
+                                yaffs_SearchAdvance(sc);
+                }
+       }
+
 }
 
 
+/*-----------------------------------------------------------------*/
+
 static int yaffs_readlink(struct dentry *dentry, char __user *buffer,
                        int buflen)
 {
@@ -434,14 +501,12 @@ static int yaffs_readlink(struct dentry *dentry, char __user *buffer,
        int ret;
 
        yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
-       
-       yaffs_DirLockRead(dev);
+
        yaffs_GrossLock(dev);
 
        alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
 
        if (!alias)
                return -ENOMEM;
@@ -461,13 +526,11 @@ static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
        int ret;
        yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
 
        if (!alias) {
                ret = -ENOMEM;
@@ -503,7 +566,6 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
 
        yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev;
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        T(YAFFS_TRACE_OS,
@@ -517,7 +579,6 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
 
        /* Can't hold gross lock when calling yaffs_get_inode() */
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
 
        if (obj) {
                T(YAFFS_TRACE_OS,
@@ -581,7 +642,6 @@ static void yaffs_clear_inode(struct inode *inode)
 
        if (obj) {
                dev = obj->myDev;
-               yaffs_DirLockRead(dev);
                yaffs_GrossLock(dev);
 
                /* Clear the association between the inode and
@@ -598,7 +658,6 @@ static void yaffs_clear_inode(struct inode *inode)
                yaffs_HandleDeferedFree(obj);
 
                yaffs_GrossUnlock(dev);
-               yaffs_DirUnlockRead(dev);
        }
 
 }
@@ -620,11 +679,9 @@ static void yaffs_delete_inode(struct inode *inode)
 
        if (obj) {
                dev = obj->myDev;
-               yaffs_DirLockWrite(dev);
                yaffs_GrossLock(dev);
                yaffs_DeleteObject(obj);
                yaffs_GrossUnlock(dev);
-               yaffs_DirUnlockWrite(dev);
        }
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
        truncate_inode_pages(&inode->i_data, 0);
@@ -646,13 +703,11 @@ static int yaffs_file_flush(struct file *file)
                ("yaffs_file_flush object %d (%s)\n", obj->objectId,
                obj->dirty ? "dirty" : "clean"));
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        yaffs_FlushFile(obj, 1,0);
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
 
        return 0;
 }
@@ -685,7 +740,6 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)
        pg_buf = kmap(pg);
        /* FIXME: Can kmap fail? */
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        ret = yaffs_ReadDataFromFile(obj, pg_buf,
@@ -693,7 +747,6 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)
                                PAGE_CACHE_SIZE);
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
 
        if (ret >= 0)
                ret = 0;
@@ -772,7 +825,6 @@ static int yaffs_writepage(struct page *page)
        buffer = kmap(page);
 
        obj = yaffs_InodeToObject(inode);
-       yaffs_DirLockRead(obj->myDev);
        yaffs_GrossLock(obj->myDev);
 
        T(YAFFS_TRACE_OS,
@@ -790,7 +842,6 @@ static int yaffs_writepage(struct page *page)
                (int)obj->variant.fileVariant.fileSize, (int)inode->i_size));
 
        yaffs_GrossUnlock(obj->myDev);
-       yaffs_DirUnlockRead(obj->myDev);
 
        kunmap(page);
        SetPageUptodate(page);
@@ -1106,7 +1157,6 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
 
        dev = obj->myDev;
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        inode = f->f_dentry->d_inode;
@@ -1146,8 +1196,6 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
 
        }
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
-
        return (nWritten == 0) && (n > 0) ? -ENOSPC : nWritten;
 }
 
@@ -1167,54 +1215,66 @@ static ssize_t yaffs_hold_space(struct file *f)
 
        dev = obj->myDev;
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        nFreeChunks = yaffs_GetNumberOfFreeChunks(dev);
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
 
        return (nFreeChunks > 20) ? 1 : 0;
 }
 
 static void yaffs_release_space(struct file *f)
 {
+       yaffs_Object *obj;
+       yaffs_Device *dev;
+
+
+       obj = yaffs_DentryToObject(f->f_dentry);
+
+       dev = obj->myDev;
+
+       yaffs_GrossLock(dev);
+
+
+       yaffs_GrossUnlock(dev);
 }
 
 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
 {
        yaffs_Object *obj;
        yaffs_Device *dev;
+        struct yaffs_SearchContext *sc;
        struct inode *inode = f->f_dentry->d_inode;
        unsigned long offset, curoffs;
-       struct ylist_head *i;
        yaffs_Object *l;
+        int retVal = 0;
 
        char name[YAFFS_MAX_NAME_LENGTH + 1];
 
        obj = yaffs_DentryToObject(f->f_dentry);
        dev = obj->myDev;
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        offset = f->f_pos;
 
+        sc = yaffs_NewSearch(obj);
+        if(!sc){
+                retVal = -ENOMEM;
+                goto unlock_out;
+        }
+
        T(YAFFS_TRACE_OS, ("yaffs_readdir: starting at %d\n", (int)offset));
 
        if (offset == 0) {
                T(YAFFS_TRACE_OS,
                        ("yaffs_readdir: entry . ino %d \n",
                        (int)inode->i_ino));
-
                yaffs_GrossUnlock(dev);
-               
                if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0)
                        goto out;
-
                yaffs_GrossLock(dev);
-
                offset++;
                f->f_pos++;
        }
@@ -1222,15 +1282,11 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
                T(YAFFS_TRACE_OS,
                        ("yaffs_readdir: entry .. ino %d \n",
                        (int)f->f_dentry->d_parent->d_inode->i_ino));
-
                yaffs_GrossUnlock(dev);
-
                if (filldir(dirent, "..", 2, offset,
                        f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
                        goto out;
-
                yaffs_GrossLock(dev);
-
                offset++;
                f->f_pos++;
        }
@@ -1246,10 +1302,12 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
                f->f_version = inode->i_version;
        }
 
-       ylist_for_each(i, &obj->variant.directoryVariant.children) {
+       while(sc->nextReturn){
                curoffs++;
+                l = sc->nextReturn;
                if (curoffs >= offset) {
-                       l = ylist_entry(i, yaffs_Object, siblings);
+                        int this_inode = yaffs_GetObjectInode(l);
+                        int this_type = yaffs_GetObjectType(l);
 
                        yaffs_GetObjectName(l, name,
                                            YAFFS_MAX_NAME_LENGTH + 1);
@@ -1257,28 +1315,30 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
                          ("yaffs_readdir: %s inode %d\n", name,
                           yaffs_GetObjectInode(l)));
 
-                       yaffs_GrossUnlock(dev);
+                        yaffs_GrossUnlock(dev);
 
                        if (filldir(dirent,
                                        name,
                                        strlen(name),
                                        offset,
-                                       yaffs_GetObjectInode(l),
-                                       yaffs_GetObjectType(l)) < 0)
+                                       this_inode,
+                                       this_type) < 0)
                                goto out;
 
-                       yaffs_GrossLock(dev);
+                        yaffs_GrossLock(dev);
 
                        offset++;
                        f->f_pos++;
                }
+                yaffs_SearchAdvance(sc);
        }
 
+unlock_out:
        yaffs_GrossUnlock(dev);
 out:
-       yaffs_DirUnlockRead(dev);
+        yaffs_EndSearch(sc);
 
-       return 0;
+       return retVal;
 }
 
 /*
@@ -1329,7 +1389,6 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 
        dev = parent->myDev;
 
-       yaffs_DirLockWrite(dev);
        yaffs_GrossLock(dev);
 
        switch (mode & S_IFMT) {
@@ -1363,7 +1422,6 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 
        /* Can not call yaffs_get_inode() with gross lock held */
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockWrite(dev);
 
        if (obj) {
                inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
@@ -1413,7 +1471,6 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
 
        dev = yaffs_InodeToObject(dir)->myDev;
 
-       yaffs_DirLockWrite(dev); 
        yaffs_GrossLock(dev);
 
        retVal = yaffs_Unlink(yaffs_InodeToObject(dir), dentry->d_name.name);
@@ -1421,17 +1478,12 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
        if (retVal == YAFFS_OK) {
                dentry->d_inode->i_nlink--;
                dir->i_version++;
-       }
-
-       yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockWrite(dev);
-
-       if( retVal == YAFFS_OK){
+               yaffs_GrossUnlock(dev);
                mark_inode_dirty(dentry->d_inode);
                update_dir_time(dir);
                return 0;
        }
-
+       yaffs_GrossUnlock(dev);
        return -ENOTEMPTY;
 }
 
@@ -1451,7 +1503,6 @@ static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
        obj = yaffs_InodeToObject(inode);
        dev = obj->myDev;
 
-       yaffs_DirLockWrite(dev);
        yaffs_GrossLock(dev);
 
        if (!S_ISDIR(inode->i_mode))            /* Don't link directories */
@@ -1469,7 +1520,6 @@ static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
        }
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockWrite(dev);
 
        if (link){
                update_dir_time(dir);
@@ -1490,12 +1540,10 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
        T(YAFFS_TRACE_OS, ("yaffs_symlink\n"));
 
        dev = yaffs_InodeToObject(dir)->myDev;
-       yaffs_DirLockWrite(dev);
        yaffs_GrossLock(dev);
        obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name,
                                S_IFLNK | S_IRWXUGO, uid, gid, symname);
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockWrite(dev);
 
        if (obj) {
                struct inode *inode;
@@ -1524,11 +1572,9 @@ static int yaffs_sync_object(struct file *file, struct dentry *dentry,
        dev = obj->myDev;
 
        T(YAFFS_TRACE_OS, ("yaffs_sync_object\n"));
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
        yaffs_FlushFile(obj, 1, datasync);
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
        return 0;
 }
 
@@ -1547,7 +1593,6 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        T(YAFFS_TRACE_OS, ("yaffs_rename\n"));
        dev = yaffs_InodeToObject(old_dir)->myDev;
 
-       yaffs_DirLockWrite(dev);
        yaffs_GrossLock(dev);
 
        /* Check if the target is an existing directory that is not empty. */
@@ -1572,7 +1617,6 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                new_dentry->d_name.name);
        }
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockWrite(dev);
 
        if (retVal == YAFFS_OK) {
                if (target) {
@@ -1602,7 +1646,6 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
        error = inode_change_ok(inode, attr);
        if (error == 0) {
                dev = yaffs_InodeToObject(inode)->myDev;
-               yaffs_DirLockRead(dev);
                yaffs_GrossLock(dev);
                if (yaffs_SetAttributes(yaffs_InodeToObject(inode), attr) ==
                                YAFFS_OK) {
@@ -1611,7 +1654,6 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
                        error = -EPERM;
                }
                yaffs_GrossUnlock(dev);
-               yaffs_DirUnlockRead(dev);
                if (!error)
                        error = inode_setattr(inode, attr);
        }
@@ -1635,7 +1677,6 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
 
        T(YAFFS_TRACE_OS, ("yaffs_statfs\n"));
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        buf->f_type = YAFFS_MAGIC;
@@ -1686,7 +1727,6 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
        buf->f_bavail = buf->f_bfree;
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
        return 0;
 }
 
@@ -1713,7 +1753,6 @@ static int yaffs_do_sync_fs(struct super_block *sb)
        T(YAFFS_TRACE_OS, ("yaffs_do_sync_fs\n"));
 
        if (sb->s_dirt) {
-               yaffs_DirLockRead(dev);
                yaffs_GrossLock(dev);
 
                if (dev) {
@@ -1723,7 +1762,6 @@ static int yaffs_do_sync_fs(struct super_block *sb)
                }
 
                yaffs_GrossUnlock(dev);
-               yaffs_DirUnlockRead(dev);
 
                sb->s_dirt = 0;
        }
@@ -1783,7 +1821,6 @@ static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
         * need to lock again.
         */
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
@@ -1791,7 +1828,6 @@ static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
        yaffs_FillInodeFromObject(inode, obj);
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
 
        unlock_new_inode(inode);
        return inode;
@@ -1812,7 +1848,6 @@ static void yaffs_read_inode(struct inode *inode)
        T(YAFFS_TRACE_OS,
                ("yaffs_read_inode for %d\n", (int)inode->i_ino));
 
-       yaffs_DirLockRead(dev);
        yaffs_GrossLock(dev);
 
        obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
@@ -1820,7 +1855,6 @@ static void yaffs_read_inode(struct inode *inode)
        yaffs_FillInodeFromObject(inode, obj);
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockRead(dev);
 }
 
 #endif
@@ -1837,7 +1871,7 @@ static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
 
                T(YAFFS_TRACE_OS,
                        ("yaffs_remount_fs: %s: RO\n", dev->name));
-               yaffs_DirLockWrite(dev);
+
                yaffs_GrossLock(dev);
 
                yaffs_FlushEntireDeviceCache(dev);
@@ -1848,7 +1882,6 @@ static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
                        mtd->sync(mtd);
 
                yaffs_GrossUnlock(dev);
-               yaffs_DirUnlockWrite(dev);
        } else {
                T(YAFFS_TRACE_OS,
                        ("yaffs_remount_fs: %s: RW\n", dev->name));
@@ -1864,7 +1897,6 @@ static void yaffs_put_super(struct super_block *sb)
 
        T(YAFFS_TRACE_OS, ("yaffs_put_super\n"));
 
-       yaffs_DirLockWrite(dev);
        yaffs_GrossLock(dev);
 
        yaffs_FlushEntireDeviceCache(dev);
@@ -1877,7 +1909,6 @@ static void yaffs_put_super(struct super_block *sb)
        yaffs_Deinitialise(dev);
 
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockWrite(dev);
 
        /* we assume this is protected by lock_kernel() in mount/umount */
        ylist_del(&dev->devList);
@@ -2261,11 +2292,13 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
 
        /* we assume this is protected by lock_kernel() in mount/umount */
        ylist_add_tail(&dev->devList, &yaffs_dev_list);
-       
-       yaffs_DirLockInitialise(dev);
-       yaffs_GrossLockInitialise(dev);
 
-       yaffs_DirLockWrite(dev);
+        /* Directory search handling...*/
+        YINIT_LIST_HEAD(&dev->searchContexts);
+        dev->removeObjectCallback = yaffs_RemoveObjectCallback;
+
+       init_MUTEX(&dev->grossLock);
+
        yaffs_GrossLock(dev);
 
        err = yaffs_GutsInitialise(dev);
@@ -2276,7 +2309,6 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
 
        /* Release lock before yaffs_get_inode() */
        yaffs_GrossUnlock(dev);
-       yaffs_DirUnlockWrite(dev);
 
        /* Create root inode */
        if (err == YAFFS_OK)