Skip to content

Commit

Permalink
lib-fs: Added fs_get_nlinks()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sirainen authored and GitLab committed Aug 1, 2016
1 parent 6657aee commit a63cd84
Show file tree
Hide file tree
Showing 13 changed files with 64 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/lib-fs/fs-api-private.h
Expand Up @@ -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 {
Expand Down
27 changes: 27 additions & 0 deletions src/lib-fs/fs-api.c
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/lib-fs/fs-api.h
Expand Up @@ -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. */
Expand Down
1 change: 1 addition & 0 deletions src/lib-fs/fs-dict.c
Expand Up @@ -323,6 +323,7 @@ const struct fs fs_class_dict = {
fs_dict_iter_init,
fs_dict_iter_next,
fs_dict_iter_deinit,
NULL,
NULL
}
};
3 changes: 2 additions & 1 deletion src/lib-fs/fs-metawrap.c
Expand Up @@ -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,
}
};
3 changes: 2 additions & 1 deletion src/lib-fs/fs-posix.c
Expand Up @@ -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,
}
};
14 changes: 13 additions & 1 deletion src/lib-fs/fs-randomfail.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
}
};
3 changes: 2 additions & 1 deletion src/lib-fs/fs-sis-queue.c
Expand Up @@ -200,6 +200,7 @@ const struct fs fs_class_sis_queue = {
fs_wrapper_iter_init,
NULL,
NULL,
NULL
NULL,
fs_wrapper_get_nlinks,
}
};
3 changes: 2 additions & 1 deletion src/lib-fs/fs-sis.c
Expand Up @@ -351,6 +351,7 @@ const struct fs fs_class_sis = {
fs_wrapper_iter_init,
NULL,
NULL,
NULL
NULL,
fs_wrapper_get_nlinks,
}
};
3 changes: 2 additions & 1 deletion src/lib-fs/fs-test.c
Expand Up @@ -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,
}
};
5 changes: 5 additions & 0 deletions src/lib-fs/fs-wrapper.c
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/lib-fs/fs-wrapper.h
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/fs-compress/fs-compress.c
Expand Up @@ -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
}
};

0 comments on commit a63cd84

Please sign in to comment.