]> arthur.barton.de Git - netatalk.git/commitdiff
Reintroduce explicit adouble refcounting
authorFrank Lahm <franklahm@googlemail.com>
Wed, 12 Jan 2011 15:23:34 +0000 (16:23 +0100)
committerFrank Lahm <franklahm@googlemail.com>
Wed, 12 Jan 2011 15:23:34 +0000 (16:23 +0100)
etc/afpd/desktop.c
etc/afpd/file.c
etc/afpd/ofork.c
include/atalk/adouble.h
libatalk/adouble/ad_flush.c
libatalk/adouble/ad_open.c

index 369b4aaa4ab7b8bc5d0ae11c71a7a12513726799..b5e4f876abba3dea525f54ff0248305620da564a 100644 (file)
@@ -712,8 +712,7 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
         memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
         ad_flush( adp );
     }
-    if (adp == &ad)
-        ad_close_metadata( adp);
+    ad_close_metadata( adp);
     return( AFP_OK );
 }
 
index ba930108f89ebde3a7ae079b6ee6b5815fb6cb62..ebe61e12885cbc6e112078fdd9d167bc00b99537 100644 (file)
@@ -618,7 +618,7 @@ int getfilparams(struct vol *vol,
 
     if (opened) {
         char *upath;
-        int  flags = (bitmap & (1 << FILPBIT_ATTR))?ADFLAGS_OPENFORKS:0;
+        int  flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0;
 
         adp = of_ad(vol, path, &ad);
         upath = path->u_name;
@@ -640,9 +640,7 @@ int getfilparams(struct vol *vol,
         }
     }
     rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp);
-    if ( adp == &ad ) {
-        ad_close_metadata( adp);
-    }
+    ad_close_metadata( adp);
 
     return( rc );
 }
@@ -1055,8 +1053,7 @@ setfilparam_done:
 
     if (isad) {
         ad_flush( adp);
-        if (adp == &ad)
-            ad_close_metadata( adp);
+        ad_close_metadata( adp);
     }
 
     if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) {
@@ -1345,8 +1342,7 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si
     setvoltime(obj, d_vol );
 
 copy_exit:
-    if (adp == &ad)
-        ad_close( adp, ADFLAGS_DF |ADFLAGS_HF );
+    ad_close( adp, ADFLAGS_DF |ADFLAGS_HF );
     return( retvalue );
 }
 
@@ -1614,7 +1610,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib)
          * moreover sometimes deletefile is called with a no existent file and 
          * ad_open would create a 0 byte resource fork
         */
-        if ( ad_metadataat(dirfd, file, ADFLAGS_OPENFORKS, &ad) == 0 ) {
+        if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) {
             if ((err = check_attrib(&ad))) {
                ad_close_metadata(&ad);
                return err;
index 5a2449028074bd248e9e2a4f692dd0033a802159..d92fb27a9242adafdec3abaaba6cacc1f0371810 100644 (file)
@@ -225,6 +225,7 @@ of_alloc(struct vol *vol,
         strlcpy( ad->ad_m_name, path, ad->ad_m_namelen);
     }
 
+    ad_ref(ad);
     of->of_ad = ad;
     of->of_vol = vol;
     of->of_did = dir->d_did;
@@ -427,8 +428,12 @@ int of_closefork(struct ofork *ofork)
         }
     }
     ret = 0;
-    if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
-        ret = -1;
+
+    
+    if (ad_unref(ofork->of_ad) == 0) {
+        if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
+            ret = -1;
+        }
     }
 
     of_dealloc( ofork );
index 176f934ce6766250ef62ddf100d905dbaa80f4bf..1151e2f49299ae4d31aea9f40ac981ed397d2bed 100644 (file)
@@ -196,8 +196,9 @@ struct adouble {
     struct ad_fd        *ad_md;           /* either ad_resource or ad_metadata        */
     int                 ad_flags;         /* Our adouble version info (AD_VERSION*)   */
     int                 ad_adflags;       /* ad_open flags adflags like ADFLAGS_DIR   */
-    unsigned int        ad_inited;
+    uint32_t            ad_inited;
     int                 ad_options;
+    int                 ad_refcount;       /* multiple forks may open one adouble     */
     void                *ad_resforkbuf;    /* buffer for AD_VERSION_EA ressource fork */
     size_t              ad_resforkbufsize; /* size of ad_resforkbuf                   */
     off_t               ad_rlen;           /* ressource fork len with AFP 3.0         *
@@ -215,7 +216,7 @@ struct adouble {
 #define ADFLAGS_HF        (1<<2)
 #define ADFLAGS_DIR       (1<<3)
 #define ADFLAGS_NOHF      (1<<4)  /* not an error if no ressource fork */
-#define ADFLAGS_OPENFORKS (1<<5)  /* check for open fork in ad_metadata function */
+#define ADFLAGS_CHECK_OF  (1<<6)  /* check for open forks from us and other afpd's */
 
 #define ADVOL_NODEV      (1 << 0)
 #define ADVOL_CACHE      (1 << 1)
@@ -342,6 +343,10 @@ struct adouble {
 #define ad_get_RF_flags(ad) ((ad)->ad_resource_fork.adf_flags)
 #define ad_get_MD_flags(ad) ((ad)->ad_md->adf_flags)
 
+/* Refcounting open forks using one struct adouble */
+#define ad_ref(ad)   (ad)->ad_refcount++
+#define ad_unref(ad) (ad)->ad_refcount--
+
 /* ad_flush.c */
 extern int ad_rebuild_adouble_header (struct adouble *);
 extern int ad_rebuild_sfm_header (struct adouble *);
index 5853c48caa0ef2e3a87c70d20c7bb1d32a57ce64..9c9c3891d522aaeca8259902f24a440c305d8e7b 100644 (file)
@@ -198,6 +198,12 @@ int ad_close( struct adouble *ad, int adflags)
         cfrombstr(ad->ad_fullpath),
         adflags2logstr(adflags));
 
+    if (ad->ad_refcount) {
+        LOG(log_debug, logtype_default, "ad_close(\"%s\"): adouble in use by fork, not closing",
+            cfrombstr(ad->ad_fullpath));
+        return 0;
+    }
+
     if (ad_data_fileno(ad) != -1) {
         if ((ad_data_fileno(ad) == -2) && (ad->ad_data_fork.adf_syml != NULL)) {
             free(ad->ad_data_fork.adf_syml);
index d9f56712c3993a711a661fac3f603457cb81904c..c85026c5921ef936255e4715a9882a7da6bbd0a3 100644 (file)
@@ -1002,7 +1002,7 @@ const char *adflags2logstr(int adflags)
         strlcat(buf, "DIR", 64);
         first = 0;
     }
-    if (adflags & ADFLAGS_OPENFORKS) {
+    if (adflags & ADFLAGS_CHECK_OF) {
         if (!first)
             strlcat(buf, "|", 64);
         strlcat(buf, "OF", 64);
@@ -1053,6 +1053,7 @@ const char *oflags2logstr(int oflags)
  * @endcode
  *
  * Open a files data fork, metadata fork or ressource fork.
+ *
  * For each fork to be opened specify the open flags and mode in case you want to create it
  * (O_CREAT in open flags). The order in which forks are opened is:
  * 1) ADFLAGS_DF, 2) ADFLAGS_HF, 3) ADFLAGS_RF.
@@ -1063,6 +1064,12 @@ const char *oflags2logstr(int oflags)
  * 2. Store the full path to the object the first time ad_open is called for it.
  * 3. Check if the fork has already been opened.
  *
+ * ad_close accompanies ad_open and closes a struct adouble. In order to tigh together the
+ * semantics of struct adouble/ad_open/ad_close and versus forks, which use and keep a ref to
+ * the according struct adouble for the fork, we open forks refcount their struct adouble
+ * in struct adouble.ad_refcount. An ad_close is ignored when ad_refcount != 0, because
+ * ad_refcount != 0 means an open fork is using this very struct adouble.
+ *
  * @param ad        (rw) pointer to struct adouble
  * @param path      (r)  Path to file or directory
  * @param adflags   (r)  ADFLAGS_DF:        open data fork \n
@@ -1071,7 +1078,7 @@ const char *oflags2logstr(int oflags)
  *                       ADFLAGS_NOHF:      it's not an error if header file couldn't be created \n
  *                       ADFLAGS_DIR:       if path is a directory you MUST or ADFLAGS_DIR to adflags \n
  *                       ADFLAGS_RDONLY:    dont upgrade mode from r to rw with adouble:v2 headerfile \n
- *                       ADFLAGS_OPENFORKS: check for open forks from other processes
+ *                       ADFLAGS_CHECK_OF:  check for open forks from us and other afpd's
  *
  * @returns 0 on success, any other value indicates an error
  */
@@ -1159,7 +1166,7 @@ int ad_open(struct adouble *ad, const char *path, int adflags, ...)
  *
  * @param name  name of file/dir
  * @param flags ADFLAGS_DIR: name is a directory \n
- *              ADFLAGS_OPENFORKS: test if name is open by another afpd process
+ *              ADFLAGS_CHECK_OF: test if name is open by us or another afpd process
  *
  * @param adp   pointer to struct adouble
  */
@@ -1187,7 +1194,7 @@ int ad_metadata(const char *name, int flags, struct adouble *adp)
         errno = err;
     }
 
-    if (!ret && (ADFLAGS_OPENFORKS & flags)) {
+    if (!ret && (ADFLAGS_CHECK_OF & flags)) {
         /*
           we need to check if the file is open by another process.
           it's slow so we only do it if we have to: