]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-fs: Added fs_get_nlinks()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Sat, 23 Jul 2016 16:02:29 +0000 (12:02 -0400)
committerGitLab <gitlab@git.dovecot.net>
Mon, 1 Aug 2016 22:21:37 +0000 (01:21 +0300)
Although fs_stat() could return this, its caller can't indicate whether
it actually wants the link count. Usually fs_stat() is used only to get
the file's size. In some backends it's not cheap to get the link count,
so adding this function allows the caller to explicitly ask for it.

13 files changed:
src/lib-fs/fs-api-private.h
src/lib-fs/fs-api.c
src/lib-fs/fs-api.h
src/lib-fs/fs-dict.c
src/lib-fs/fs-metawrap.c
src/lib-fs/fs-posix.c
src/lib-fs/fs-randomfail.c
src/lib-fs/fs-sis-queue.c
src/lib-fs/fs-sis.c
src/lib-fs/fs-test.c
src/lib-fs/fs-wrapper.c
src/lib-fs/fs-wrapper.h
src/plugins/fs-compress/fs-compress.c

index 28f2c4ad9a68ded2618ff70c231455afe011c062..0d71a9a2e589a9653f6d5fa1dff792b1ea11a2ee 100644 (file)
@@ -69,6 +69,7 @@ struct fs_vfuncs {
        int (*iter_deinit)(struct fs_iter *iter);
 
        bool (*switch_ioloop)(struct fs *fs);
+       int (*get_nlinks)(struct fs_file *file, nlink_t *nlinks_r);
 };
 
 struct fs {
index bac5d161217d4779f3b9051329ac860c074f032f..e53059348ce22b9228ee604586e25f33f1475ea6 100644 (file)
@@ -848,6 +848,33 @@ int fs_stat(struct fs_file *file, struct stat *st_r)
        return ret;
 }
 
+int fs_get_nlinks(struct fs_file *file, nlink_t *nlinks_r)
+{
+       int ret;
+
+       if (file->fs->v.get_nlinks == NULL) {
+               struct stat st;
+
+               if (fs_stat(file, &st) < 0)
+                       return -1;
+               *nlinks_r = st.st_nlink;
+               return 0;
+       }
+
+       if (!file->read_or_prefetch_counted &&
+           !file->lookup_metadata_counted && !file->stat_counted) {
+               file->stat_counted = TRUE;
+               file->fs->stats.stat_count++;
+               fs_file_timing_start(file, FS_OP_STAT);
+       }
+       T_BEGIN {
+               ret = file->fs->v.get_nlinks(file, nlinks_r);
+       } T_END;
+       if (!(ret < 0 && errno == EAGAIN))
+               fs_file_timing_end(file, FS_OP_STAT);
+       return ret;
+}
+
 int fs_default_copy(struct fs_file *src, struct fs_file *dest)
 {
        /* we're going to be counting this as read+write, so remove the
index 1e42504d5ca667194e21fdeac4751a2438f932ee..cf285b1716b4cc21741ec797d65f6472ce2acab8 100644 (file)
@@ -303,6 +303,10 @@ int fs_delete(struct fs_file *file);
 /* Returns 0 if ok, -1 if error occurred (e.g. errno=ENOENT).
    All fs backends may not support all stat fields. */
 int fs_stat(struct fs_file *file, struct stat *st_r);
+/* Get number of links to the file. This is the same as using fs_stat()'s
+   st_nlinks field, except not all backends support returning it via fs_stat().
+   Returns 0 if ok, -1 if error occurred. */
+int fs_get_nlinks(struct fs_file *file, nlink_t *nlinks_r);
 /* Copy an object with possibly updated metadata. Destination parent
    directories are created automatically. Returns 0 if ok, -1 if error
    occurred. */
index 3b0ba32ea5f7e676dd7738a1aae4a367b5dc0f44..035005a758d0e1e3a558a4d4dba15271f2bec584 100644 (file)
@@ -323,6 +323,7 @@ const struct fs fs_class_dict = {
                fs_dict_iter_init,
                fs_dict_iter_next,
                fs_dict_iter_deinit,
+               NULL,
                NULL
        }
 };
index 3432df6174ac536640c4d0f33d1c89b8e0e9477e..4b6519a2cb9976588ea2ea5a49961256fa01c708 100644 (file)
@@ -496,6 +496,7 @@ const struct fs fs_class_metawrap = {
                fs_wrapper_iter_init,
                fs_wrapper_iter_next,
                fs_wrapper_iter_deinit,
-               NULL
+               NULL,
+               fs_wrapper_get_nlinks,
        }
 };
index a28ce22d9c45e1202cc858aff77c032ca3472565..a4baeae36d9afaec6a05fda3319ce0fc3535725e 100644 (file)
@@ -884,6 +884,7 @@ const struct fs fs_class_posix = {
                fs_posix_iter_init,
                fs_posix_iter_next,
                fs_posix_iter_deinit,
-               NULL
+               NULL,
+               NULL,
        }
 };
index e133bad3f8b5e899179ac248a0596cb65cfcf43c..484a12328b1b2f135617271461dc5270bd3c8f7e 100644 (file)
@@ -446,6 +446,17 @@ static int fs_randomfail_stat(struct fs_file *_file, struct stat *st_r)
        return fs_file_random_fail_end(file, ret, FS_OP_STAT);
 }
 
+static int fs_randomfail_get_nlinks(struct fs_file *_file, nlink_t *nlinks_r)
+{
+       struct randomfail_fs_file *file = (struct randomfail_fs_file *)_file;
+       int ret;
+
+       if (fs_file_random_fail_begin(file, FS_OP_STAT))
+               return -1;
+       ret = fs_get_nlinks(file->super, nlinks_r);
+       return fs_file_random_fail_end(file, ret, FS_OP_STAT);
+}
+
 static int fs_randomfail_copy(struct fs_file *_src, struct fs_file *_dest)
 {
        struct randomfail_fs_file *src = (struct randomfail_fs_file *)_src;
@@ -566,6 +577,7 @@ const struct fs fs_class_randomfail = {
                fs_randomfail_iter_init,
                fs_randomfail_iter_next,
                fs_randomfail_iter_deinit,
-               NULL
+               NULL,
+               fs_randomfail_get_nlinks,
        }
 };
index 588776e45f0bd07e5299f70b365a6eadf9174860..1e38d643db1868c9ade07445d9ffcbb0aaab80a1 100644 (file)
@@ -200,6 +200,7 @@ const struct fs fs_class_sis_queue = {
                fs_wrapper_iter_init,
                NULL,
                NULL,
-               NULL
+               NULL,
+               fs_wrapper_get_nlinks,
        }
 };
index 143463f0650b9692edb052e904e666b344888fd4..eb947c101f337964adef28af659a9743fd0f6d49 100644 (file)
@@ -351,6 +351,7 @@ const struct fs fs_class_sis = {
                fs_wrapper_iter_init,
                NULL,
                NULL,
-               NULL
+               NULL,
+               fs_wrapper_get_nlinks,
        }
 };
index d35caf5366413efb7d2d6ed7be1d5510114eccb9..cf912b0b9c4f42ceec4cbf47f5338960bde65f49 100644 (file)
@@ -417,6 +417,7 @@ const struct fs fs_class_test = {
                fs_test_iter_init,
                fs_test_iter_next,
                fs_test_iter_deinit,
-               NULL
+               NULL,
+               NULL,
        }
 };
index 8d90561499227c6df901868c0f64b80cd55e2a82..524f1131314c5f1612ba93ebda1578e9a50d5730 100644 (file)
@@ -108,6 +108,11 @@ int fs_wrapper_stat(struct fs_file *file, struct stat *st_r)
        return fs_stat(file->parent, st_r);
 }
 
+int fs_wrapper_get_nlinks(struct fs_file *file, nlink_t *nlinks_r)
+{
+       return fs_get_nlinks(file->parent, nlinks_r);
+}
+
 int fs_wrapper_copy(struct fs_file *src, struct fs_file *dest)
 {
        if (src != NULL)
index 992b020070fdff63428807f9b54b13e5a890faae..c6d99da06929e696a405075932d3a12028f4dabb 100644 (file)
@@ -24,6 +24,7 @@ int fs_wrapper_lock(struct fs_file *file, unsigned int secs,
 void fs_wrapper_unlock(struct fs_lock *_lock);
 int fs_wrapper_exists(struct fs_file *file);
 int fs_wrapper_stat(struct fs_file *file, struct stat *st_r);
+int fs_wrapper_get_nlinks(struct fs_file *file, nlink_t *nlinks_r);
 int fs_wrapper_copy(struct fs_file *src, struct fs_file *dest);
 int fs_wrapper_rename(struct fs_file *src, struct fs_file *dest);
 int fs_wrapper_delete(struct fs_file *file);
index e09cb5d504edc37479db88d459012d5bdef4d6f0..e1e3ceafa3739e63dc462f735ef67a583d4b7dc0 100644 (file)
@@ -254,6 +254,7 @@ const struct fs fs_class_compress = {
                fs_wrapper_iter_init,
                fs_wrapper_iter_next,
                fs_wrapper_iter_deinit,
-               NULL
+               NULL,
+               fs_wrapper_get_nlinks
        }
 };