]> arthur.barton.de Git - netatalk.git/commitdiff
Move freeing of invalidated struct dirs to a central func using a queue
authorFrank Lahm <franklahm@googlemail.com>
Wed, 24 Nov 2010 13:39:28 +0000 (14:39 +0100)
committerFrank Lahm <franklahm@googlemail.com>
Wed, 24 Nov 2010 13:39:28 +0000 (14:39 +0100)
etc/afpd/afp_dsi.c
etc/afpd/dircache.c
etc/afpd/directory.c
etc/afpd/directory.h

index c2823ef1263df1d87e460a2058ae09ce2c60634a..963a291244bcf8b55d0d5a5fb6064c815ae2d6c2 100644 (file)
@@ -452,6 +452,9 @@ void afp_over_dsi(AFPObj *obj)
 
                 LOG(log_debug, logtype_afpd, "==> Finished AFP command: %s -> %s",
                     AfpNum2name(function), AfpErr2name(err));
+
+                dir_free_invalid_q();
+
 #ifdef FORCE_UIDGID
                /* bring everything back to old euid, egid */
                 if (obj->force_uid)
index ef776bfa329223f545df62970210b5b04d4767ee..52ef7478a3c2fc4d9379de3609c4090b90c136d5 100644 (file)
@@ -345,7 +345,7 @@ struct dir *dircache_search_by_did(const struct vol *vol, cnid_t cnid)
         dircache_stat.hits++;
     } else {
         LOG(log_debug, logtype_afpd, "dircache(cnid:%u): {not in cache}", ntohl(cnid));
-        dircache_stat.hits++;
+        dircache_stat.misses++;
     }
     
     return cdir;
@@ -552,6 +552,10 @@ int dircache_init(int reqsize)
     else
         queue_count = 0;
 
+    /* Initialize index queue */
+    if ((invalid_dircache_entries = queue_init()) == NULL)
+        return -1;
+
     /* As long as directory.c hasn't got its own initializer call, we do it for it */
     rootParent.d_did = DIRDID_ROOT_PARENT;
     rootParent.d_fullpath = bfromcstr("ROOT_PARENT");
index 4c891feebc3d3373d1641e5a646d7b9b7b721ebc..55918eaeb8ed2ef6b8fa8dd0e064d01bc6c0ebbb 100644 (file)
@@ -71,6 +71,17 @@ struct path Cur_Path = {
     {0} /* struct stat */
 };
 
+/*
+ * dir_remove queues struct dirs to be freed here. We can't just delete them immeidately
+ * eg in dircache_search_by_id, because a caller somewhere up the stack might be
+ * referencing it.
+ * So instead:
+ * - we mark it as invalid by setting d_did to CNID_INVALID (ie 0)
+ * - queue it in "invalid_dircache_entries" queue
+ * - which is finally freed at the end of every AFP func in afp_dsi.c.
+ */
+q_t *invalid_dircache_entries;
+
 
 /*******************************************************************************************
  * Locals
@@ -854,12 +865,25 @@ exit:
 }
 
 /*!
- * @brief Remove a dir from a cache and free it and any ressources with it
+ * Free the queue with invalid struct dirs
+ *
+ * This gets called at the end of every AFP func.
+ */
+void dir_free_invalid_q(void)
+{
+    struct dir *dir;
+    while (dir = (struct dir *)dequeue(invalid_dircache_entries))
+        dir_free(dir);
+}
+
+/*!
+ * @brief Remove a dir from a cache and queue it for freeing
  *
  * 1. Check if the dir is locked or has opened forks
  * 2. If it's a request to remove curdir, just chdir to volume root
  * 3. Remove it from the cache
- * 4. Remove the dir plus any allocated resources it references
+ * 4. Queue it for removal
+ * 5. Mark it as invalid
  *
  * @param (r) pointer to struct vol
  * @param (rw) pointer to struct dir
@@ -888,8 +912,8 @@ int dir_remove(const struct vol *vol, struct dir *dir)
         ntohl(dir->d_did), cfrombstr(dir->d_u_name));
 
     dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); /* 3 */
-    dir_free(dir);              /* 4 */
-
+    enqueue(invalid_dircache_entries, dir); /* 4 */
+    dir->d_did = CNID_INVALID;              /* 5 */
     return 0;
 }
 
index 4b9ed48f3ac4ad13ef163e01e854cb4fd8d979f0..76267e73b9dac151a088c175af46d8348468dae3 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: directory.h,v 1.34 2010/03/12 15:16:49 franklahm Exp $
- *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
@@ -106,10 +104,13 @@ struct maccess {
 #define        AR_UWRITE       (1<<2)
 #define        AR_UOWN         (1<<7)
 
+q_t *invalid_dircache_entries;
+
 typedef int (*dir_loop)(struct dirent *, char *, void *);
 
-extern struct dir *dir_new(const char *mname, const char *uname, const struct vol *,
-                           cnid_t pdid, cnid_t did, bstring fullpath, time_t ctime);
+extern void        dir_free_invalid_q(void);
+extern struct dir  *dir_new(const char *mname, const char *uname, const struct vol *,
+                            cnid_t pdid, cnid_t did, bstring fullpath, time_t ctime);
 extern void        dir_free (struct dir *);
 extern struct dir  *dir_add(struct vol *, const struct dir *, struct path *, int);
 extern int         dir_modify(const struct vol *vol, struct dir *dir, cnid_t pdid, cnid_t did,