Index: common/dir_uncached.c
===================================================================
--- common/dir_uncached.c	(revision 28570)
+++ common/dir_uncached.c	(working copy)
@@ -204,14 +204,29 @@
     char *basename;
     char *parent;
     struct dirent_uncached *entry;
-    struct fat_dir newdir;
+    int dd;
+    DIR_UNCACHED* pdir = opendirs;
+    struct fat_dir *newdir;
     int rc;

     if ( name[0] != '/' ) {
         DEBUGF("mkdir: Only absolute paths supported right now\n");
         return -1;
     }
+    /* find a free dir descriptor */
+    for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++)
+        if ( !pdir->busy )
+            break;

+    if ( dd == MAX_OPEN_DIRS ) {
+        DEBUGF("Too many dirs open\n");
+        errno = EMFILE;
+        return -5;
+    }
+
+    pdir->busy = true;
+    newdir = &pdir->fatdir;
+
     strlcpy(namecopy, name, sizeof(namecopy));

     /* Split the base name and the path */
@@ -230,11 +245,13 @@

     if(!dir) {
         DEBUGF("mkdir: can't open parent dir\n");
+        pdir->busy = false;
         return -2;
     }    

     if(basename[0] == 0) {
         DEBUGF("mkdir: Empty dir name\n");
+        pdir->busy = false;
         errno = EINVAL;
         return -3;
     }
@@ -245,14 +262,16 @@
             DEBUGF("mkdir error: file exists\n");
             errno = EEXIST;
             closedir_uncached(dir);
+            pdir->busy = false;
             return - 4;
         }
     }

-    memset(&newdir, 0, sizeof(struct fat_dir));
+    memset(newdir, 0, sizeof(struct fat_dir));

-    rc = fat_create_dir(basename, &newdir, &(dir->fatdir));
+    rc = fat_create_dir(basename, newdir, &(dir->fatdir));
     closedir_uncached(dir);
+    pdir->busy = false;

     return rc;
 }
Index: drivers/fat.c
===================================================================
--- drivers/fat.c	(revision 28570)
+++ drivers/fat.c	(working copy)
@@ -1967,7 +1967,7 @@
                 int attr)
 {
     int rc;
-    struct fat_dir olddir;
+    struct fat_file olddir_file;
     struct fat_file newfile = *file;
     unsigned char* entry = NULL;
     unsigned short* clusptr = NULL;
@@ -1988,11 +1988,6 @@
         return -2;
     }

-    /* create a temporary file handle */
-    rc = fat_opendir(IF_MV2(file->volume,) &olddir, file->dircluster, NULL);
-    if (rc < 0)
-        return rc * 10 - 1;
-
     /* create new name */
     rc = add_dir_entry(dir, &newfile, newname, false, false);
     if (rc < 0)
@@ -2016,18 +2011,17 @@
        it points to its parent directory (we don't check if it was a move) */
     if(FAT_ATTR_DIRECTORY == attr) {
         unsigned char buf[SECTOR_SIZE];
-        /* open the dir that was renamed, we re-use the olddir struct */
-        rc = fat_opendir(IF_MV2(file->volume,) &olddir, newfile.firstcluster,
-                                                                          NULL);
+        /* open the dir that was renamed, we re-use the olddir_file struct */
+        rc = fat_open(IF_MV2(volume,) newfile.firstcluster, &olddir_file, NULL);
         if (rc < 0)
             return rc * 10 - 6;

         /* get the first sector of the dir */
-        rc = fat_seek(&olddir.file, 0);
+        rc = fat_seek(&olddir_file, 0);
         if (rc < 0)
             return rc * 10 - 7;

-        rc = fat_readwrite(&olddir.file, 1, buf, false);
+        rc = fat_readwrite(&olddir_file, 1, buf, false);
         if (rc < 0)
             return rc * 10 - 8;

@@ -2051,11 +2045,11 @@
         *clusptr = htole16(parentcluster & 0xffff);

         /* write back this sector */
-        rc = fat_seek(&olddir.file, 0);
+        rc = fat_seek(&olddir_file, 0);
         if (rc < 0)
             return rc * 10 - 7;

-        rc = fat_readwrite(&olddir.file, 1, buf, true);
+        rc = fat_readwrite(&olddir_file, 1, buf, true);
         if (rc < 1)
             return rc * 10 - 8;
     }