Browse Source

Merge pull request #730 from trapexit/readdir

fix getdent name length calculation
pull/737/head
trapexit 5 years ago
committed by GitHub
parent
commit
be3499ee56
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Makefile
  2. 2
      libfuse/Makefile
  3. 12
      libfuse/include/fuse_dirents.h
  4. 12
      libfuse/include/linux_dirent64.h
  5. 72
      libfuse/lib/fuse_dirents.c
  6. 16
      src/fuse_readdir_linux.icpp
  7. 16
      src/fuse_readdir_plus_linux.icpp
  8. 27
      src/fuse_readdir_plus_posix.icpp
  9. 27
      src/fuse_readdir_posix.icpp

2
Makefile

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

2
libfuse/Makefile

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

12
libfuse/include/fuse_dirents.h

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

12
libfuse/include/linux_dirent64.h

@ -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[];
};

72
libfuse/lib/fuse_dirents.c

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

16
src/fuse_readdir_linux.icpp

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

16
src/fuse_readdir_plus_linux.icpp

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

27
src/fuse_readdir_plus_posix.icpp

@ -45,6 +45,26 @@ using std::vector;
namespace l 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 static
int int
readdir_plus(const Branches &branches_, readdir_plus(const Branches &branches_,
@ -55,6 +75,7 @@ namespace l
HashSet names; HashSet names;
string basepath; string basepath;
struct stat st; struct stat st;
uint64_t namelen;
fuse_entry_t entry; fuse_entry_t entry;
entry.nodeid = 0; entry.nodeid = 0;
@ -83,7 +104,9 @@ namespace l
rv = 0; rv = 0;
for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh)) 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) if(rv == 0)
continue; continue;
@ -94,7 +117,7 @@ namespace l
de->d_ino = fs::inode::recompute(de->d_ino,dev); de->d_ino = fs::inode::recompute(de->d_ino,dev);
st.st_ino = de->d_ino; 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) if(rv)
return (fs::closedir(dh),-ENOMEM); return (fs::closedir(dh),-ENOMEM);
} }

27
src/fuse_readdir_posix.icpp

@ -44,6 +44,26 @@ using std::vector;
namespace l 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 static
int int
readdir(const Branches &branches_, readdir(const Branches &branches_,
@ -53,6 +73,7 @@ namespace l
dev_t dev; dev_t dev;
HashSet names; HashSet names;
string basepath; string basepath;
uint64_t namelen;
for(size_t i = 0, ei = branches_.size(); i != ei; i++) for(size_t i = 0, ei = branches_.size(); i != ei; i++)
{ {
@ -74,13 +95,15 @@ namespace l
rv = 0; rv = 0;
for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh)) 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) if(rv == 0)
continue; continue;
de->d_ino = fs::inode::recompute(de->d_ino,dev); 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) if(rv)
return (fs::closedir(dh),-ENOMEM); return (fs::closedir(dh),-ENOMEM);
} }

Loading…
Cancel
Save