}
/*
- generic create
+ generic create -- creates a regular file
*/
int rgw_create(struct rgw_fs *rgw_fs,
struct rgw_file_handle *parent_fh,
const char *name, mode_t mode, struct stat *st,
struct rgw_file_handle **fh)
{
- return -EINVAL;
+ /* XXX a CREATE operation can be a precursor to the canonical
+ * OPEN, WRITE*, CLOSE transaction which writes or overwrites
+ * an object in S3 */
+ RGWLibFS *fs = static_cast<RGWLibFS*>(rgw_fs->fs_private);
+
+ RGWFileHandle* parent = get_rgwfh(parent_fh);
+ if ((! parent) ||
+ (parent->is_root()) ||
+ (parent->is_object())) {
+ /* bad parent */
+ return -EINVAL;
+ }
+
+ using std::get;
+
+ LookupFHResult fhr = fs->lookup_fh(parent, name);
+ RGWFileHandle* rgw_fh = get<0>(fhr);
+
+ if (! rgw_fh)
+ return -EINVAL;
+
+
+ /* mark if we created it */
+ if (get<1>(fhr) & RGWFileHandle::FLAG_CREATE)
+ rgw_fh->open_for_create();
+
+ struct rgw_file_handle *rfh = rgw_fh->get_fh();
+ *fh = rfh;
+
+ return 0;
}
/*
rc = librgw.get_fe()->execute_req(&req);
/* XXX: atomicity */
- RGWFileHandle* rgw_fh = fs->lookup_fh(parent, name);
+ LookupFHResult fhr = fs->lookup_fh(parent, name);
+ RGWFileHandle* rgw_fh = get<0>(fhr);
struct rgw_file_handle *rfh = rgw_fh->get_fh();
*fh = rfh;
rgw_fh = parent->ref();
} else {
/* name lookup in root--for now) just get a handle */
- rgw_fh = fs->lookup_fh(parent, path);
+ LookupFHResult fhr = fs->lookup_fh(parent, path);
+ rgw_fh = get<0>(fhr);
+
if (! rgw_fh)
- return -ENOENT;
+ return -ENOMEM;
}
} else {
std::string object_name{path};
(! (flags & RGW_LOOKUP_FLAG_CREATE)))
return -ENOENT;
- rgw_fh = fs->lookup_fh(parent, path);
+ LookupFHResult fhr = fs->lookup_fh(parent, path);
+ rgw_fh = get<0>(fhr);
+
if (! rgw_fh)
return -ENOENT;
} /* !root */
CephContext* cct = static_cast<CephContext*>(rgw_fs->rgw);
RGWLibFS *fs = static_cast<RGWLibFS*>(rgw_fs->fs_private);
- if (!fh)
- return -ENOENT;
-
RGWFileHandle* rgw_fh = get_rgwfh(fh);
if (rgw_fh->is_root()) {
public:
const static string root_name;
- static constexpr uint32_t FLAG_NONE = 0x0000;
- static constexpr uint32_t FLAG_OPEN = 0x0001;
- static constexpr uint32_t FLAG_ROOT = 0x0002;
+ static constexpr uint32_t FLAG_NONE = 0x0000;
+ static constexpr uint32_t FLAG_OPEN = 0x0001;
+ static constexpr uint32_t FLAG_ROOT = 0x0002;
+ static constexpr uint32_t FLAG_CREATE = 0x0004;
friend class RGWLibFS;
private:
RGWFileHandle(RGWLibFS* _fs)
- : fs(_fs), parent(nullptr), flags(FLAG_ROOT)
+ : refcnt(1), fs(_fs), parent(nullptr), flags(FLAG_ROOT)
{
/* root */
fh.fh_type = RGW_FS_TYPE_DIRECTORY;
fh.fh_hk.bucket = XXH64(fsid.c_str(), fsid.length(), fh_key::seed);
fh.fh_hk.object = XXH64(object_name.c_str(), object_name.length(),
fh_key::seed);
+ fhk = fh.fh_hk;
+ name = object_name;
}
public:
bool is_root() const { return flags & FLAG_ROOT; }
bool is_bucket() const { return (fh.fh_type == RGW_FS_TYPE_DIRECTORY); }
bool is_object() const { return (fh.fh_type == RGW_FS_TYPE_FILE); }
+ bool creating() const { return flags & FLAG_CREATE; }
void open() {
flags |= FLAG_OPEN;
flags &= ~FLAG_OPEN;
}
+ void open_for_create() {
+ flags |= FLAG_CREATE;
+ }
+
friend void intrusive_ptr_add_ref(const RGWFileHandle* fh) {
fh->refcnt.fetch_add(1, std::memory_order_relaxed);
}
return static_cast<RGWFileHandle*>(fh->fh_private);
}
+ typedef std::tuple<RGWFileHandle*, uint32_t> LookupFHResult;
+
class RGWLibFS
{
CephContext* cct;
}
/* find or create an RGWFileHandle */
- RGWFileHandle* lookup_fh(RGWFileHandle* parent, const char *name) {
+ LookupFHResult lookup_fh(RGWFileHandle* parent, const char *name) {
RGWFileHandle::FHCache::Latch lat;
fh_key fhk(parent->fhk.fh_hk.object, name);
+ LookupFHResult fhr { nullptr, RGWFileHandle::FLAG_NONE };
+
+ using std::get;
RGWFileHandle* fh =
fh_cache.find_latch(fhk.fh_hk.object /* partition selector*/,
intrusive_ptr_add_ref(fh); /* sentinel ref */
fh_cache.insert_latched(fh, lat,
RGWFileHandle::FHCache::FLAG_NONE);
+ get<1>(fhr) = RGWFileHandle::FLAG_CREATE;
}
intrusive_ptr_add_ref(fh); /* call path/handle ref */
lat.lock->unlock(); /* !LATCHED */
- return fh;
+
+ get<0>(fhr) = fh;
+
+ return fhr;
}
/* find or create an RGWFileHandle */