Allow removal of bad direntries in VitastorFS (direntries referring non-existent inodes)
This commit is contained in:
@@ -13,6 +13,12 @@ void kv_read_inode(nfs_proxy_t *proxy, uint64_t ino,
|
||||
std::function<void(int res, const std::string & value, json11::Json ientry)> cb,
|
||||
bool allow_cache)
|
||||
{
|
||||
if (!ino)
|
||||
{
|
||||
// Zero value can not exist
|
||||
cb(-ENOENT, "", json11::Json());
|
||||
return;
|
||||
}
|
||||
auto key = kv_inode_key(ino);
|
||||
proxy->db->get(key, [=](int res, const std::string & value)
|
||||
{
|
||||
@@ -49,7 +55,7 @@ int kv_nfs3_getattr_proc(void *opaque, rpc_op_t *rop)
|
||||
auto ino = kv_fh_inode(fh);
|
||||
if (self->parent->trace)
|
||||
fprintf(stderr, "[%d] GETATTR %ju\n", self->nfs_fd, ino);
|
||||
if (!kv_fh_valid(fh))
|
||||
if (!kv_fh_valid(fh) || !ino)
|
||||
{
|
||||
*reply = (GETATTR3res){ .status = NFS3ERR_INVAL };
|
||||
rpc_queue_reply(rop);
|
||||
|
||||
@@ -43,9 +43,30 @@ int kv_nfs3_lookup_proc(void *opaque, rpc_op_t *rop)
|
||||
uint64_t ino = direntry["ino"].uint64_value();
|
||||
kv_read_inode(self->parent, ino, [=](int res, const std::string & value, json11::Json ientry)
|
||||
{
|
||||
if (res < 0)
|
||||
if (res == -ENOENT)
|
||||
{
|
||||
*reply = (LOOKUP3res){ .status = vitastor_nfs_map_err(res == -ENOENT ? -EIO : res) };
|
||||
*reply = (LOOKUP3res){
|
||||
.status = NFS3_OK,
|
||||
.resok = (LOOKUP3resok){
|
||||
.object = xdr_copy_string(rop->xdrs, kv_fh(ino)),
|
||||
.obj_attributes = {
|
||||
.attributes_follow = 1,
|
||||
.attributes = (fattr3){
|
||||
.type = (ftype3)0,
|
||||
.mode = 0666,
|
||||
.nlink = 1,
|
||||
.fsid = self->parent->fsid,
|
||||
.fileid = ino,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
rpc_queue_reply(rop);
|
||||
return;
|
||||
}
|
||||
else if (res < 0)
|
||||
{
|
||||
*reply = (LOOKUP3res){ .status = vitastor_nfs_map_err(res) };
|
||||
rpc_queue_reply(rop);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -89,12 +89,23 @@ resume_1:
|
||||
resume_2:
|
||||
if (st->res < 0)
|
||||
{
|
||||
fprintf(stderr, "error reading inode %s: %s (code %d)\n",
|
||||
kv_inode_key(st->ino).c_str(), strerror(-st->res), st->res);
|
||||
auto cb = std::move(st->cb);
|
||||
cb(st->res);
|
||||
return;
|
||||
if (st->res == -ENOENT)
|
||||
{
|
||||
// Just delete direntry and skip inode
|
||||
fprintf(stderr, "direntry %s references a non-existing inode %ju, deleting\n",
|
||||
kv_direntry_key(st->dir_ino, st->filename).c_str(), st->ino);
|
||||
st->ino = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "error reading inode %s: %s (code %d)\n",
|
||||
kv_inode_key(st->ino).c_str(), strerror(-st->res), st->res);
|
||||
auto cb = std::move(st->cb);
|
||||
cb(st->res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string err;
|
||||
st->ientry = json11::Json::parse(st->ientry_text, err);
|
||||
|
||||
@@ -165,4 +165,24 @@ if ls ./testdata/nfs | grep over1; then false; fi
|
||||
[[ "`cat ./testdata/nfs/linked1`" = "BABABA" ]]
|
||||
format_green "rename over existing file ok"
|
||||
|
||||
# check listing and removal of a bad direntry
|
||||
sudo umount ./testdata/nfs/
|
||||
build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta set d11/settings.jsonLGNmGn '{"ino": 123}'
|
||||
sudo mount localhost:/ ./testdata/nfs -o port=2050,mountport=2050,nfsvers=3,soft,nolock,tcp
|
||||
ls -l ./testdata/nfs
|
||||
ls -l ./testdata/nfs/settings.jsonLGNmGn
|
||||
rm ./testdata/nfs/settings.jsonLGNmGn
|
||||
build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)'
|
||||
ls -l ./testdata/nfs
|
||||
|
||||
# repeat with ino=0
|
||||
sudo umount ./testdata/nfs/
|
||||
build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta set d11/settings.jsonLGNmGn '{"ino": 0}'
|
||||
sudo mount localhost:/ ./testdata/nfs -o port=2050,mountport=2050,nfsvers=3,soft,nolock,tcp
|
||||
ls -l ./testdata/nfs
|
||||
ls -l ./testdata/nfs/settings.jsonLGNmGn
|
||||
rm ./testdata/nfs/settings.jsonLGNmGn
|
||||
build/src/kv/vitastor-kv --etcd_address $ETCD_URL fsmeta get d11/settings.jsonLGNmGn 2>&1 | grep '(code -2)'
|
||||
ls -l ./testdata/nfs
|
||||
|
||||
format_green OK
|
||||
|
||||
Reference in New Issue
Block a user