Merge pull request #19684 from taoCH/wip-librgw-symbolic-link

librgw: support symbolic link

Reviewed-by: Matt Benjamin <mbenjami@redhat.com>
This commit is contained in:
Yuri Weinstein 2018-11-20 14:00:41 -08:00 committed by GitHub
commit e682970f35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 214 additions and 2 deletions

View File

@ -27,7 +27,7 @@ extern "C" {
#define LIBRGW_FILE_VER_MAJOR 1
#define LIBRGW_FILE_VER_MINOR 1
#define LIBRGW_FILE_VER_EXTRA 6
#define LIBRGW_FILE_VER_EXTRA 7
#define LIBRGW_FILE_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra)
#define LIBRGW_FILE_VERSION_CODE LIBRGW_FILE_VERSION(LIBRGW_FILE_VER_MAJOR, LIBRGW_FILE_VER_MINOR, LIBRGW_FILE_VER_EXTRA)
@ -39,6 +39,7 @@ enum rgw_fh_type {
RGW_FS_TYPE_NIL = 0,
RGW_FS_TYPE_FILE,
RGW_FS_TYPE_DIRECTORY,
RGW_FS_TYPE_SYMBOLIC_LINK,
};
/*
@ -178,6 +179,15 @@ int rgw_create(struct rgw_fs *rgw_fs, struct rgw_file_handle *parent_fh,
struct rgw_file_handle **fh, uint32_t posix_flags,
uint32_t flags);
/*
create a symbolic link
*/
#define RGW_CREATELINK_FLAG_NONE 0x0000
int rgw_symlink(struct rgw_fs *rgw_fs, struct rgw_file_handle *parent_fh,
const char *name, const char *link_path, struct stat *st,
uint32_t mask, struct rgw_file_handle **fh, uint32_t posix_flags,
uint32_t flags);
/*
create a new directory
*/
@ -293,6 +303,16 @@ int rgw_read(struct rgw_fs *rgw_fs,
size_t length, size_t *bytes_read, void *buffer,
uint32_t flags);
/*
read symbolic link
*/
#define RGW_READLINK_FLAG_NONE 0x0000
int rgw_readlink(struct rgw_fs *rgw_fs,
struct rgw_file_handle *fh, uint64_t offset,
size_t length, size_t *bytes_read, void *buffer,
uint32_t flags);
/*
write data to file
*/

View File

@ -261,6 +261,29 @@ namespace rgw {
return rc;
}
int RGWLibFS::readlink(RGWFileHandle* rgw_fh, uint64_t offset, size_t length,
size_t* bytes_read, void* buffer, uint32_t flags)
{
if (! rgw_fh->is_link())
return -EINVAL;
if (rgw_fh->deleted())
return -ESTALE;
RGWReadRequest req(get_context(), get_user(), rgw_fh, offset, length,
buffer);
int rc = rgwlib.get_fe()->execute_req(&req);
if ((rc == 0) &&
(req.get_ret() == 0)) {
lock_guard(rgw_fh->mtx);
rgw_fh->set_atime(real_clock::to_timespec(real_clock::now()));
*bytes_read = req.nread;
}
return rc;
}
int RGWLibFS::unlink(RGWFileHandle* rgw_fh, const char* name, uint32_t flags)
{
int rc = 0;
@ -669,6 +692,103 @@ namespace rgw {
return mkr;
} /* RGWLibFS::create */
MkObjResult RGWLibFS::symlink(RGWFileHandle* parent, const char *name,
const char* link_path, struct stat *st, uint32_t mask, uint32_t flags)
{
int rc, rc2;
using std::get;
rgw_file_handle *lfh;
rc = rgw_lookup(get_fs(), parent->get_fh(), name, &lfh,
RGW_LOOKUP_FLAG_NONE);
if (! rc) {
/* conflict! */
rc = rgw_fh_rele(get_fs(), lfh, RGW_FH_RELE_FLAG_NONE);
return MkObjResult{nullptr, -EEXIST};
}
MkObjResult mkr{nullptr, -EINVAL};
LookupFHResult fhr;
RGWFileHandle* rgw_fh = nullptr;
buffer::list ux_key, ux_attrs;
fhr = lookup_fh(parent, name,
RGWFileHandle::FLAG_CREATE|
RGWFileHandle::FLAG_SYMBOLIC_LINK|
RGWFileHandle::FLAG_LOCK);
rgw_fh = get<0>(fhr);
if (rgw_fh) {
rgw_fh->create_stat(st, mask);
rgw_fh->set_times(real_clock::now());
/* save attrs */
rgw_fh->encode_attrs(ux_key, ux_attrs);
if (st)
rgw_fh->stat(st);
get<0>(mkr) = rgw_fh;
} else {
get<1>(mkr) = -EIO;
return mkr;
}
/* need valid S3 name (characters, length <= 1024, etc) */
rc = valid_fs_object_name(name);
if (rc != 0) {
rgw_fh->flags |= RGWFileHandle::FLAG_DELETED;
fh_cache.remove(rgw_fh->fh.fh_hk.object, rgw_fh,
RGWFileHandle::FHCache::FLAG_LOCK);
rgw_fh->mtx.unlock();
unref(rgw_fh);
get<0>(mkr) = nullptr;
get<1>(mkr) = rc;
return mkr;
}
string obj_name = std::string(name);
/* create an object representing the directory */
buffer::list bl;
/* XXXX */
#if 0
bl.push_back(
buffer::create_static(len, static_cast<char*>(buffer)));
#else
bl.push_back(
buffer::copy(link_path, strlen(link_path)));
#endif
RGWPutObjRequest req(get_context(), get_user(), parent->bucket_name(),
obj_name, bl);
/* save attrs */
req.emplace_attr(RGW_ATTR_UNIX_KEY1, std::move(ux_key));
req.emplace_attr(RGW_ATTR_UNIX1, std::move(ux_attrs));
rc = rgwlib.get_fe()->execute_req(&req);
rc2 = req.get_ret();
if (! ((rc == 0) &&
(rc2 == 0))) {
/* op failed */
rgw_fh->flags |= RGWFileHandle::FLAG_DELETED;
rgw_fh->mtx.unlock(); /* !LOCKED */
unref(rgw_fh);
get<0>(mkr) = nullptr;
/* fixup rc */
if (!rc)
rc = rc2;
} else {
real_time t = real_clock::now();
parent->set_mtime(real_clock::to_timespec(t));
parent->set_ctime(real_clock::to_timespec(t));
rgw_fh->mtx.unlock(); /* !LOCKED */
}
get<1>(mkr) = rc;
return mkr;
} /* RGWLibFS::symlink */
int RGWLibFS::getattr(RGWFileHandle* rgw_fh, struct stat* st)
{
switch(rgw_fh->fh.fh_type) {
@ -1664,6 +1784,35 @@ int rgw_create(struct rgw_fs *rgw_fs, struct rgw_file_handle *parent_fh,
return get<1>(fhr);
} /* rgw_create */
/*
create a symbolic link
*/
int rgw_symlink(struct rgw_fs *rgw_fs, struct rgw_file_handle *parent_fh,
const char *name, const char *link_path, struct stat *st, uint32_t mask,
struct rgw_file_handle **fh, uint32_t posix_flags,
uint32_t flags)
{
using std::get;
RGWLibFS *fs = static_cast<RGWLibFS*>(rgw_fs->fs_private);
RGWFileHandle* parent = get_rgwfh(parent_fh);
if ((! parent) ||
(parent->is_root()) ||
(parent->is_file())) {
/* bad parent */
return -EINVAL;
}
MkObjResult fhr = fs->symlink(parent, name, link_path, st, mask, flags);
RGWFileHandle *nfh = get<0>(fhr); // nullptr if !success
if (nfh)
*fh = nfh->get_fh();
return get<1>(fhr);
} /* rgw_symlink */
/*
create a new directory
*/
@ -1978,6 +2127,20 @@ int rgw_read(struct rgw_fs *rgw_fs,
return fs->read(rgw_fh, offset, length, bytes_read, buffer, flags);
}
/*
read symbolic link
*/
int rgw_readlink(struct rgw_fs *rgw_fs,
struct rgw_file_handle *fh, uint64_t offset,
size_t length, size_t *bytes_read, void *buffer,
uint32_t flags)
{
RGWLibFS *fs = static_cast<RGWLibFS*>(rgw_fs->fs_private);
RGWFileHandle* rgw_fh = get_rgwfh(fh);
return fs->readlink(rgw_fh, offset, length, bytes_read, buffer, flags);
}
/*
write data to file
*/

View File

@ -247,6 +247,7 @@ namespace rgw {
static constexpr uint32_t FLAG_ROOT = 0x0002;
static constexpr uint32_t FLAG_CREATE = 0x0004;
static constexpr uint32_t FLAG_CREATING = 0x0008;
static constexpr uint32_t FLAG_SYMBOLIC_LINK = 0x0009;
static constexpr uint32_t FLAG_DIRECTORY = 0x0010;
static constexpr uint32_t FLAG_BUCKET = 0x0020;
static constexpr uint32_t FLAG_LOCK = 0x0040;
@ -318,7 +319,10 @@ namespace rgw {
if (flags & FLAG_DIRECTORY) {
fh.fh_type = RGW_FS_TYPE_DIRECTORY;
variant_type = directory();
} else {
} else if(flags & FLAG_SYMBOLIC_LINK) {
fh.fh_type = RGW_FS_TYPE_SYMBOLIC_LINK;
variant_type = file();
} else {
fh.fh_type = RGW_FS_TYPE_FILE;
variant_type = file();
}
@ -338,6 +342,10 @@ namespace rgw {
break;
case RGW_FS_TYPE_FILE:
state.unix_mode = RGW_RWMODE|S_IFREG;
break;
case RGW_FS_TYPE_SYMBOLIC_LINK:
state.unix_mode = RGW_RWMODE|S_IFLNK;
break;
default:
break;
}
@ -388,6 +396,10 @@ namespace rgw {
break;
case RGW_FS_TYPE_FILE:
state.unix_mode = st->st_mode|S_IFREG;
break;
case RGW_FS_TYPE_SYMBOLIC_LINK:
state.unix_mode = st->st_mode|S_IFLNK;
break;
default:
break;
}
@ -431,6 +443,13 @@ namespace rgw {
st->st_blksize = 4096;
st->st_size = state.size;
st->st_blocks = (state.size) / 512;
break;
case RGW_FS_TYPE_SYMBOLIC_LINK:
st->st_nlink = 1;
st->st_blksize = 4096;
st->st_size = state.size;
st->st_blocks = (state.size) / 512;
break;
default:
break;
}
@ -542,6 +561,7 @@ namespace rgw {
bool is_object() const { return !is_bucket(); }
bool is_file() const { return (fh.fh_type == RGW_FS_TYPE_FILE); }
bool is_dir() const { return (fh.fh_type == RGW_FS_TYPE_DIRECTORY); }
bool is_link() const { return (fh.fh_type == RGW_FS_TYPE_SYMBOLIC_LINK); }
bool creating() const { return flags & FLAG_CREATING; }
bool deleted() const { return flags & FLAG_DELETED; }
bool stateless_open() const { return flags & FLAG_STATELESS_OPEN; }
@ -639,6 +659,9 @@ namespace rgw {
DECODE_START(2, bl);
uint32_t fh_type;
decode(fh_type, bl);
if ((fh.fh_type != fh_type) &&
(fh_type == RGW_FS_TYPE_SYMBOLIC_LINK))
fh.fh_type = RGW_FS_TYPE_SYMBOLIC_LINK;
ceph_assert(fh.fh_type == fh_type);
decode(state.dev, bl);
decode(state.size, bl);
@ -1135,11 +1158,17 @@ namespace rgw {
int read(RGWFileHandle* rgw_fh, uint64_t offset, size_t length,
size_t* bytes_read, void* buffer, uint32_t flags);
int readlink(RGWFileHandle* rgw_fh, uint64_t offset, size_t length,
size_t* bytes_read, void* buffer, uint32_t flags);
int rename(RGWFileHandle* old_fh, RGWFileHandle* new_fh,
const char *old_name, const char *new_name);
MkObjResult create(RGWFileHandle* parent, const char *name, struct stat *st,
uint32_t mask, uint32_t flags);
MkObjResult symlink(RGWFileHandle* parent, const char *name,
const char *link_path, struct stat *st, uint32_t mask, uint32_t flags);
MkObjResult mkdir(RGWFileHandle* parent, const char *name, struct stat *st,
uint32_t mask, uint32_t flags);