fusexmp_fh: avoid unnecessary seeking in readdir

This commit is contained in:
Miklos Szeredi 2008-02-08 11:26:15 +00:00
parent 667567764f
commit 30823693d6
2 changed files with 50 additions and 15 deletions

View File

@ -2,6 +2,8 @@
* Block SIGCHLD when executing mount and umount
* fusexmp_fh: avoid unnecessary seeking in readdir
2008-02-03 Csaba Henk <csaba.henk@creo.hu>
* lib/mount_bsd.c:

View File

@ -19,6 +19,7 @@
#include <fuse.h>
#include <ulockmgr.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
@ -77,36 +78,67 @@ static int xmp_readlink(const char *path, char *buf, size_t size)
return 0;
}
struct xmp_dirp {
DIR *dp;
struct dirent *entry;
off_t offset;
};
static int xmp_opendir(const char *path, struct fuse_file_info *fi)
{
DIR *dp = opendir(path);
if (dp == NULL)
return -errno;
int res;
struct xmp_dirp *d = malloc(sizeof(struct xmp_dirp));
if (d == NULL)
return -ENOMEM;
fi->fh = (unsigned long) dp;
d->dp = opendir(path);
if (d->dp == NULL) {
res = -errno;
free(d);
return res;
}
d->offset = 0;
d->entry = NULL;
fi->fh = (unsigned long) d;
return 0;
}
static inline DIR *get_dirp(struct fuse_file_info *fi)
static inline struct xmp_dirp *get_dirp(struct fuse_file_info *fi)
{
return (DIR *) (uintptr_t) fi->fh;
return (struct xmp_dirp *) (uintptr_t) fi->fh;
}
static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
DIR *dp = get_dirp(fi);
struct dirent *de;
struct xmp_dirp *d = get_dirp(fi);
(void) path;
seekdir(dp, offset);
while ((de = readdir(dp)) != NULL) {
if (offset != d->offset) {
seekdir(d->dp, offset);
d->entry = NULL;
d->offset = offset;
}
while (1) {
struct stat st;
off_t nextoff;
if (!d->entry) {
d->entry = readdir(d->dp);
if (!d->entry)
break;
}
memset(&st, 0, sizeof(st));
st.st_ino = de->d_ino;
st.st_mode = de->d_type << 12;
if (filler(buf, de->d_name, &st, telldir(dp)))
st.st_ino = d->entry->d_ino;
st.st_mode = d->entry->d_type << 12;
nextoff = telldir(d->dp);
if (filler(buf, d->entry->d_name, &st, nextoff))
break;
d->entry = NULL;
d->offset = nextoff;
}
return 0;
@ -114,9 +146,10 @@ static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
static int xmp_releasedir(const char *path, struct fuse_file_info *fi)
{
DIR *dp = get_dirp(fi);
struct xmp_dirp *d = get_dirp(fi);
(void) path;
closedir(dp);
closedir(d->dp);
free(d);
return 0;
}