]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-fs: Fix fs_stats.copy_count tracking with fs_default_copy()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 17 Aug 2021 09:12:18 +0000 (12:12 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 18 Aug 2021 07:53:37 +0000 (07:53 +0000)
The copy_count could have been decreased too many times with async
operations.

src/lib-fs/fs-api-private.h
src/lib-fs/fs-api.c

index 07545253b0c0b531bae77eb1bd98b73f5dd81dcf..76eb2c5a32f0c3f40fd2bf93f29b6b8cc5862db8 100644 (file)
@@ -141,6 +141,7 @@ struct fs_file {
        bool read_or_prefetch_counted:1;
        bool lookup_metadata_counted:1;
        bool stat_counted:1;
+       bool copy_counted:1;
        bool istream_open:1;
        bool last_error_changed:1;
 };
index 048d22af6c473f1a1df99c62b8e520d2508c4ee8..1b47ded6c52182bcc7960836a9e817025b4ba694 100644 (file)
@@ -1095,9 +1095,9 @@ int fs_get_nlinks(struct fs_file *file, nlink_t *nlinks_r)
 int fs_default_copy(struct fs_file *src, struct fs_file *dest)
 {
        int tmp_errno;
-       /* we're going to be counting this as read+write, so remove the
-          copy_count we just added */
-       dest->fs->stats.copy_count--;
+       /* we're going to be counting this as read+write, so don't update
+          copy_count */
+       dest->copy_counted = TRUE;
 
        if (dest->copy_src != NULL) {
                i_assert(src == NULL || src == dest->copy_src);
@@ -1163,7 +1163,10 @@ int fs_copy(struct fs_file *src, struct fs_file *dest)
        } T_END;
        if (!(ret < 0 && errno == EAGAIN)) {
                fs_file_timing_end(dest, FS_OP_COPY);
-               dest->fs->stats.copy_count++;
+               if (dest->copy_counted)
+                       dest->copy_counted = FALSE;
+               else
+                       dest->fs->stats.copy_count++;
                dest->metadata_changed = FALSE;
        }
        return ret;
@@ -1178,7 +1181,10 @@ int fs_copy_finish_async(struct fs_file *dest)
        } T_END;
        if (!(ret < 0 && errno == EAGAIN)) {
                fs_file_timing_end(dest, FS_OP_COPY);
-               dest->fs->stats.copy_count++;
+               if (dest->copy_counted)
+                       dest->copy_counted = FALSE;
+               else
+                       dest->fs->stats.copy_count++;
                dest->metadata_changed = FALSE;
        }
        return ret;