fix getdent name length calculation

This commit is contained in:
Antonio SJ Musumeci 2020-03-12 14:42:08 -04:00
parent b5fae4b356
commit 698c4147fc
9 changed files with 101 additions and 87 deletions

View File

@ -40,7 +40,7 @@ USE_XATTR = 1
UGID_USE_RWLOCK = 0
ifeq ($(DEBUG),1)
DEBUG_FLAGS := -g
DEBUG_FLAGS := -O0 -g
else
DEBUG_FLAGS :=
endif

View File

@ -1,7 +1,7 @@
VERSION = 2.9.7-mergerfs_2.29.0
ifeq ($(DEBUG),1)
DEBUG_FLAGS := -g
DEBUG_FLAGS := -O0 -g
else
DEBUG_FLAGS :=
endif

View File

@ -25,6 +25,7 @@ extern "C" {
#include "fuse_dirent.h"
#include "fuse_direntplus.h"
#include "fuse_entry.h"
#include "linux_dirent64.h"
#include <dirent.h>
#include <stdint.h>
@ -55,20 +56,21 @@ void fuse_dirents_free(fuse_dirents_t *d);
void fuse_dirents_reset(fuse_dirents_t *d);
int fuse_dirents_add(fuse_dirents_t *d,
const struct dirent *de);
const struct dirent *de,
const uint64_t namelen);
int fuse_dirents_add_plus(fuse_dirents_t *d,
const struct dirent *de,
const uint64_t namelen,
const fuse_entry_t *entry,
const struct stat *st);
#ifdef __linux__
struct linux_dirent64;
int fuse_dirents_add_linux(fuse_dirents_t *d,
const struct linux_dirent64 *de);
int fuse_dirents_add_linux(fuse_dirents_t *d,
const struct linux_dirent64 *de,
const uint64_t namelen);
int fuse_dirents_add_linux_plus(fuse_dirents_t *d,
const struct linux_dirent64 *de,
const uint64_t namelen,
const fuse_entry_t *entry,
const struct stat *st);
#endif
void *fuse_dirents_find(fuse_dirents_t *d,
const uint64_t ino);

View File

@ -0,0 +1,12 @@
#pragma once
#include <stdint.h>
struct linux_dirent64
{
uint64_t d_ino;
int64_t d_off;
uint16_t d_reclen;
uint8_t d_type;
char d_name[];
};

View File

@ -5,6 +5,7 @@
#include "fuse_direntplus.h"
#include "fuse_dirents.h"
#include "fuse_entry.h"
#include "linux_dirent64.h"
#include "stat_utils.h"
#include <dirent.h>
@ -17,26 +18,6 @@
#define DEFAULT_SIZE (1024 * 16)
static
uint64_t
dirent_exact_namelen(const struct dirent *d_)
{
#ifdef _D_EXACT_NAMELEN
return _D_EXACT_NAMELEN(d_);
#elif defined _DIRENT_HAVE_D_NAMLEN
return d_->d_namlen;
#else
return strlen(d_->d_name);
#endif
}
static
uint64_t
dirent_alloc_namelen(const struct dirent *d_)
{
return (dirent_exact_namelen(d_) + 1);
}
static
uint64_t
align_uint64_t(uint64_t v_)
@ -254,10 +235,10 @@ fuse_dirents_convert_plus2normal(fuse_dirents_t *d_)
int
fuse_dirents_add(fuse_dirents_t *d_,
const struct dirent *dirent_)
const struct dirent *dirent_,
const uint64_t namelen_)
{
uint64_t size;
uint64_t namelen;
fuse_dirent_t *d;
switch(d_->type)
@ -271,8 +252,7 @@ fuse_dirents_add(fuse_dirents_t *d_,
return -EINVAL;
}
namelen = dirent_alloc_namelen(dirent_);
size = fuse_dirent_size(namelen);
size = fuse_dirent_size(namelen_);
d = fuse_dirents_alloc(d_,size);
if(d == NULL)
@ -280,9 +260,9 @@ fuse_dirents_add(fuse_dirents_t *d_,
d->ino = dirent_->d_ino;
d->off = d_->data_len;
d->namelen = namelen;
d->namelen = namelen_;
d->type = dirent_->d_type;
memcpy(d->name,dirent_->d_name,namelen);
memcpy(d->name,dirent_->d_name,namelen_);
return 0;
}
@ -290,11 +270,11 @@ fuse_dirents_add(fuse_dirents_t *d_,
int
fuse_dirents_add_plus(fuse_dirents_t *d_,
const struct dirent *dirent_,
const uint64_t namelen_,
const fuse_entry_t *entry_,
const struct stat *st_)
{
uint64_t size;
uint64_t namelen;
fuse_direntplus_t *d;
switch(d_->type)
@ -308,8 +288,7 @@ fuse_dirents_add_plus(fuse_dirents_t *d_,
break;
}
namelen = dirent_alloc_namelen(dirent_);
size = fuse_direntplus_size(namelen);
size = fuse_direntplus_size(namelen_);
d = fuse_dirents_alloc(d_,size);
if(d == NULL)
@ -317,9 +296,9 @@ fuse_dirents_add_plus(fuse_dirents_t *d_,
d->dirent.ino = dirent_->d_ino;
d->dirent.off = d_->data_len;
d->dirent.namelen = namelen;
d->dirent.namelen = namelen_;
d->dirent.type = dirent_->d_type;
memcpy(d->dirent.name,dirent_->d_name,namelen);
memcpy(d->dirent.name,dirent_->d_name,namelen_);
d->entry = *entry_;
@ -328,22 +307,12 @@ fuse_dirents_add_plus(fuse_dirents_t *d_,
return 0;
}
#ifdef __linux__
struct linux_dirent64
{
uint64_t d_ino;
int64_t d_off;
uint16_t d_reclen;
uint8_t d_type;
char d_name[];
};
int
fuse_dirents_add_linux(fuse_dirents_t *d_,
const struct linux_dirent64 *dirent_)
const struct linux_dirent64 *dirent_,
const uint64_t namelen_)
{
uint64_t size;
uint64_t namelen;
fuse_dirent_t *d;
switch(d_->type)
@ -357,8 +326,7 @@ fuse_dirents_add_linux(fuse_dirents_t *d_,
return -EINVAL;
}
namelen = (dirent_->d_reclen - offsetof(struct linux_dirent64,d_name));
size = fuse_dirent_size(namelen);
size = fuse_dirent_size(namelen_);
d = fuse_dirents_alloc(d_,size);
if(d == NULL)
@ -366,9 +334,9 @@ fuse_dirents_add_linux(fuse_dirents_t *d_,
d->ino = dirent_->d_ino;
d->off = d_->data_len;
d->namelen = namelen;
d->namelen = namelen_;
d->type = dirent_->d_type;
memcpy(d->name,dirent_->d_name,namelen);
memcpy(d->name,dirent_->d_name,namelen_);
return 0;
}
@ -376,11 +344,11 @@ fuse_dirents_add_linux(fuse_dirents_t *d_,
int
fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
const struct linux_dirent64 *dirent_,
const uint64_t namelen_,
const fuse_entry_t *entry_,
const struct stat *st_)
{
uint64_t size;
uint64_t namelen;
fuse_direntplus_t *d;
switch(d_->type)
@ -394,8 +362,7 @@ fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
break;
}
namelen = (dirent_->d_reclen - offsetof(struct linux_dirent64,d_name));
size = fuse_direntplus_size(namelen);
size = fuse_direntplus_size(namelen_);
d = fuse_dirents_alloc(d_,size);
if(d == NULL)
@ -403,9 +370,9 @@ fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
d->dirent.ino = dirent_->d_ino;
d->dirent.off = d_->data_len;
d->dirent.namelen = namelen;
d->dirent.namelen = namelen_;
d->dirent.type = dirent_->d_type;
memcpy(d->dirent.name,dirent_->d_name,namelen);
memcpy(d->dirent.name,dirent_->d_name,namelen_);
d->entry = *entry_;
@ -413,7 +380,6 @@ fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
return 0;
}
#endif
void
fuse_dirents_reset(fuse_dirents_t *d_)

View File

@ -26,6 +26,7 @@
#include "fs_inode.hpp"
#include "fs_path.hpp"
#include "hashset.hpp"
#include "linux_dirent64.h"
#include "mempools.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
@ -42,15 +43,6 @@
using std::string;
using std::vector;
struct linux_dirent64
{
uint64_t d_ino;
int64_t d_off;
uint16_t d_reclen;
uint8_t d_type;
char d_name[];
};
namespace l
{
static
@ -84,6 +76,7 @@ namespace l
char *buf;
HashSet names;
string basepath;
uint64_t namelen;
struct linux_dirent64 *d;
buf = (char*)g_DENTS_BUF_POOL.alloc();
@ -116,14 +109,15 @@ namespace l
for(int64_t pos = 0; pos < nread; pos += d->d_reclen)
{
d = (struct linux_dirent64*)(buf + pos);
namelen = (strlen(d->d_name) + 1);
rv = names.put(d->d_name);
rv = names.put(d->d_name,namelen);
if(rv == 0)
continue;
d->d_ino = fs::inode::recompute(d->d_ino,dev);
rv = fuse_dirents_add_linux(buf_,d);
rv = fuse_dirents_add_linux(buf_,d,namelen);
if(rv)
return close_free_ret_enomem(dirfd,buf);
}

View File

@ -27,6 +27,7 @@
#include "fs_inode.hpp"
#include "fs_path.hpp"
#include "hashset.hpp"
#include "linux_dirent64.h"
#include "mempools.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
@ -43,15 +44,6 @@
using std::string;
using std::vector;
struct linux_dirent64
{
uint64_t d_ino;
int64_t d_off;
uint16_t d_reclen;
uint8_t d_type;
char d_name[];
};
namespace l
{
static
@ -84,6 +76,7 @@ namespace l
char *buf;
HashSet names;
string basepath;
uint64_t namelen;
struct stat st;
fuse_entry_t entry;
struct linux_dirent64 *d;
@ -122,8 +115,9 @@ namespace l
for(int64_t pos = 0; pos < nread; pos += d->d_reclen)
{
d = (struct linux_dirent64*)(buf + pos);
namelen = (strlen(d->d_name) + 1);
rv = names.put(d->d_name);
rv = names.put(d->d_name,namelen);
if(rv == 0)
continue;
@ -134,7 +128,7 @@ namespace l
d->d_ino = fs::inode::recompute(d->d_ino,dev);
st.st_ino = d->d_ino;
rv = fuse_dirents_add_linux_plus(buf_,d,&entry,&st);
rv = fuse_dirents_add_linux_plus(buf_,d,namelen,&entry,&st);
if(rv)
return close_free_ret_enomem(dirfd,buf);
}

View File

@ -45,6 +45,26 @@ using std::vector;
namespace l
{
static
uint64_t
dirent_exact_namelen(const struct dirent *d_)
{
#ifdef _D_EXACT_NAMLEN
return _D_EXACT_NAMLEN(d_);
#elif defined _DIRENT_HAVE_D_NAMLEN
return d_->d_namlen;
#else
return strlen(d_->d_name);
#endif
}
static
uint64_t
dirent_alloc_namelen(const struct dirent *d_)
{
return (dirent_exact_namelen(d_) + 1);
}
static
int
readdir_plus(const Branches &branches_,
@ -55,6 +75,7 @@ namespace l
HashSet names;
string basepath;
struct stat st;
uint64_t namelen;
fuse_entry_t entry;
entry.nodeid = 0;
@ -83,7 +104,9 @@ namespace l
rv = 0;
for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh))
{
rv = names.put(de->d_name);
namelen = l::dirent_alloc_namelen(de);
rv = names.put(de->d_name,namelen);
if(rv == 0)
continue;
@ -94,7 +117,7 @@ namespace l
de->d_ino = fs::inode::recompute(de->d_ino,dev);
st.st_ino = de->d_ino;
rv = fuse_dirents_add_plus(buf_,de,&entry,&st);
rv = fuse_dirents_add_plus(buf_,de,namelen,&entry,&st);
if(rv)
return (fs::closedir(dh),-ENOMEM);
}

View File

@ -44,6 +44,26 @@ using std::vector;
namespace l
{
static
uint64_t
dirent_exact_namelen(const struct dirent *d_)
{
#ifdef _D_EXACT_NAMLEN
return _D_EXACT_NAMLEN(d_);
#elif defined _DIRENT_HAVE_D_NAMLEN
return d_->d_namlen;
#else
return strlen(d_->d_name);
#endif
}
static
uint64_t
dirent_alloc_namelen(const struct dirent *d_)
{
return (dirent_exact_namelen(d_) + 1);
}
static
int
readdir(const Branches &branches_,
@ -53,6 +73,7 @@ namespace l
dev_t dev;
HashSet names;
string basepath;
uint64_t namelen;
for(size_t i = 0, ei = branches_.size(); i != ei; i++)
{
@ -74,13 +95,15 @@ namespace l
rv = 0;
for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh))
{
rv = names.put(de->d_name);
namelen = l::dirent_alloc_namelen(de);
rv = names.put(de->d_name,namelen);
if(rv == 0)
continue;
de->d_ino = fs::inode::recompute(de->d_ino,dev);
rv = fuse_dirents_add(buf_,de);
rv = fuse_dirents_add(buf_,de,namelen);
if(rv)
return (fs::closedir(dh),-ENOMEM);
}