summaryrefslogtreecommitdiffstats
path: root/src/client
diff options
context:
space:
mode:
authorPatrick Donnelly <pdonnell@redhat.com>2018-08-02 06:42:22 +0200
committerPatrick Donnelly <pdonnell@redhat.com>2018-08-02 06:42:22 +0200
commit2480ace1e3766bb6858612738c6f103569d61c52 (patch)
treebfe315c3c89734f6a8c80b0e4b106cc38e1e77d8 /src/client
parentMerge PR #23290 into master (diff)
parentclient: LAZY_IO support (diff)
downloadceph-2480ace1e3766bb6858612738c6f103569d61c52.tar.xz
ceph-2480ace1e3766bb6858612738c6f103569d61c52.zip
Merge PR #22450 into master
* refs/pull/22450/head: client: LAZY_IO support Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
Diffstat (limited to 'src/client')
-rw-r--r--src/client/Client.cc133
-rw-r--r--src/client/Client.h3
-rw-r--r--src/client/Inode.cc4
3 files changed, 116 insertions, 24 deletions
diff --git a/src/client/Client.cc b/src/client/Client.cc
index e585ed90164..cd694b361c5 100644
--- a/src/client/Client.cc
+++ b/src/client/Client.cc
@@ -3360,6 +3360,35 @@ static bool is_max_size_approaching(Inode *in)
return false;
}
+static int adjust_caps_used_for_lazyio(int used, int issued, int implemented)
+{
+ if (!(used & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_BUFFER)))
+ return used;
+ if (!(implemented & CEPH_CAP_FILE_LAZYIO))
+ return used;
+
+ if (issued & CEPH_CAP_FILE_LAZYIO) {
+ if (!(issued & CEPH_CAP_FILE_CACHE)) {
+ used &= ~CEPH_CAP_FILE_CACHE;
+ used |= CEPH_CAP_FILE_LAZYIO;
+ }
+ if (!(issued & CEPH_CAP_FILE_BUFFER)) {
+ used &= ~CEPH_CAP_FILE_BUFFER;
+ used |= CEPH_CAP_FILE_LAZYIO;
+ }
+ } else {
+ if (!(implemented & CEPH_CAP_FILE_CACHE)) {
+ used &= ~CEPH_CAP_FILE_CACHE;
+ used |= CEPH_CAP_FILE_LAZYIO;
+ }
+ if (!(implemented & CEPH_CAP_FILE_BUFFER)) {
+ used &= ~CEPH_CAP_FILE_BUFFER;
+ used |= CEPH_CAP_FILE_LAZYIO;
+ }
+ }
+ return used;
+}
+
/**
* check_caps
*
@@ -3386,6 +3415,9 @@ void Client::check_caps(Inode *in, unsigned flags)
int issued = in->caps_issued(&implemented);
int revoking = implemented & ~issued;
+ int orig_used = used;
+ used = adjust_caps_used_for_lazyio(used, issued, implemented);
+
int retain = wanted | used | CEPH_CAP_PIN;
if (!unmounting) {
if (wanted)
@@ -3408,10 +3440,10 @@ void Client::check_caps(Inode *in, unsigned flags)
if (in->caps.empty())
return; // guard if at end of func
- if ((revoking & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) &&
- (used & CEPH_CAP_FILE_CACHE) && !(used & CEPH_CAP_FILE_BUFFER)) {
+ if (!(orig_used & CEPH_CAP_FILE_BUFFER) &&
+ (revoking & used & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO))) {
if (_release(in))
- used &= ~CEPH_CAP_FILE_CACHE;
+ used &= ~(CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO);
}
if (!in->cap_snaps.empty())
@@ -5135,10 +5167,11 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClient
else if (revoked & ceph_deleg_caps_for_type(CEPH_DELEGATION_WR))
in->recall_deleg(true);
- if ((used & revoked & CEPH_CAP_FILE_BUFFER) &&
+ used = adjust_caps_used_for_lazyio(used, cap->issued, cap->implemented);
+ if ((used & revoked & (CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO)) &&
!_flush(in, new C_Client_FlushComplete(this, in))) {
// waitin' for flush
- } else if (revoked & CEPH_CAP_FILE_CACHE) {
+ } else if (used & revoked & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) {
if (_release(in))
check = true;
} else {
@@ -8596,9 +8629,11 @@ int Client::_open(Inode *in, int flags, mode_t mode, Fh **fhp,
}
// use normalized flags to generate cmode
- int cmode = ceph_flags_to_mode(ceph_flags_sys2wire(flags));
- if (cmode < 0)
- return -EINVAL;
+ int cflags = ceph_flags_sys2wire(flags);
+ if (cct->_conf.get_val<bool>("client_force_lazyio"))
+ cflags |= CEPH_O_LAZY;
+
+ int cmode = ceph_flags_to_mode(cflags);
int want = ceph_caps_for_mode(cmode);
int result = 0;
@@ -8613,7 +8648,7 @@ int Client::_open(Inode *in, int flags, mode_t mode, Fh **fhp,
filepath path;
in->make_nosnap_relative_path(path);
req->set_filepath(path);
- req->head.args.open.flags = ceph_flags_sys2wire(flags & ~O_CREAT);
+ req->head.args.open.flags = cflags & ~CEPH_O_CREAT;
req->head.args.open.mode = mode;
req->head.args.open.pool = -1;
if (cct->_conf->client_debug_getattr_caps)
@@ -8898,7 +8933,7 @@ int Client::preadv(int fd, const struct iovec *iov, int iovcnt, loff_t offset)
int64_t Client::_read(Fh *f, int64_t offset, uint64_t size, bufferlist *bl)
{
- int have = 0;
+ int want, have = 0;
bool movepos = false;
std::unique_ptr<C_SaferCond> onuninline;
int64_t r = 0;
@@ -8925,13 +8960,16 @@ int64_t Client::_read(Fh *f, int64_t offset, uint64_t size, bufferlist *bl)
}
retry:
- have = 0;
- r = get_caps(in, CEPH_CAP_FILE_RD, CEPH_CAP_FILE_CACHE, &have, -1);
+ if (f->mode & CEPH_FILE_MODE_LAZY)
+ want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
+ else
+ want = CEPH_CAP_FILE_CACHE;
+ r = get_caps(in, CEPH_CAP_FILE_RD, want, &have, -1);
if (r < 0) {
goto done;
}
if (f->flags & O_DIRECT)
- have &= ~CEPH_CAP_FILE_CACHE;
+ have &= ~(CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO);
if (in->inline_version < CEPH_INLINE_NONE) {
if (!(have & CEPH_CAP_FILE_CACHE)) {
@@ -8962,7 +9000,8 @@ retry:
}
if (!conf->client_debug_force_sync_read &&
- (conf->client_oc && (have & CEPH_CAP_FILE_CACHE))) {
+ conf->client_oc &&
+ (have & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO))) {
if (f->flags & O_RSYNC) {
_flush_range(in, offset, size);
@@ -9350,9 +9389,12 @@ int64_t Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf,
utime_t lat;
uint64_t totalwritten;
- int have;
- int r = get_caps(in, CEPH_CAP_FILE_WR|CEPH_CAP_AUTH_SHARED,
- CEPH_CAP_FILE_BUFFER, &have, endoff);
+ int want, have;
+ if (f->mode & CEPH_FILE_MODE_LAZY)
+ want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
+ else
+ want = CEPH_CAP_FILE_BUFFER;
+ int r = get_caps(in, CEPH_CAP_FILE_WR|CEPH_CAP_AUTH_SHARED, want, &have, endoff);
if (r < 0)
return r;
@@ -9369,7 +9411,7 @@ int64_t Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf,
}
if (f->flags & O_DIRECT)
- have &= ~CEPH_CAP_FILE_BUFFER;
+ have &= ~(CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO);
ldout(cct, 10) << " snaprealm " << *in->snaprealm << dendl;
@@ -9403,7 +9445,8 @@ int64_t Client::_write(Fh *f, int64_t offset, uint64_t size, const char *buf,
}
}
- if (cct->_conf->client_oc && (have & CEPH_CAP_FILE_BUFFER)) {
+ if (cct->_conf->client_oc &&
+ (have & (CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO))) {
// do buffered write
if (!in->oset.dirty_or_tx)
get_cap_ref(in, CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_BUFFER);
@@ -10277,6 +10320,48 @@ int64_t Client::drop_caches()
return objectcacher->release_all();
}
+int Client::_lazyio(Fh *fh, int enable)
+{
+ Inode *in = fh->inode.get();
+ ldout(cct, 20) << __func__ << " " << *in << " " << !!enable << dendl;
+
+ if (!!(fh->mode & CEPH_FILE_MODE_LAZY) == !!enable)
+ return 0;
+
+ int orig_mode = fh->mode;
+ if (enable) {
+ fh->mode |= CEPH_FILE_MODE_LAZY;
+ in->get_open_ref(fh->mode);
+ in->put_open_ref(orig_mode);
+ check_caps(in, CHECK_CAPS_NODELAY);
+ } else {
+ fh->mode &= ~CEPH_FILE_MODE_LAZY;
+ in->get_open_ref(fh->mode);
+ in->put_open_ref(orig_mode);
+ check_caps(in, 0);
+ }
+
+ return 0;
+}
+
+int Client::lazyio(int fd, int enable)
+{
+ Mutex::Locker l(client_lock);
+ Fh *f = get_filehandle(fd);
+ if (!f)
+ return -EBADF;
+
+ return _lazyio(f, enable);
+}
+
+int Client::ll_lazyio(Fh *fh, int enable)
+{
+ Mutex::Locker lock(client_lock);
+ ldout(cct, 3) << __func__ << " " << fh << " " << fh->inode->ino << " " << !!enable << dendl;
+ tout(cct) << __func__ << std::endl;
+
+ return _lazyio(fh, enable);
+}
int Client::lazyio_propogate(int fd, loff_t offset, size_t count)
{
@@ -11882,9 +11967,11 @@ int Client::_create(Inode *dir, const char *name, int flags, mode_t mode,
}
// use normalized flags to generate cmode
- int cmode = ceph_flags_to_mode(ceph_flags_sys2wire(flags));
- if (cmode < 0)
- return -EINVAL;
+ int cflags = ceph_flags_sys2wire(flags);
+ if (cct->_conf.get_val<bool>("client_force_lazyio"))
+ cflags |= CEPH_O_LAZY;
+
+ int cmode = ceph_flags_to_mode(cflags);
int64_t pool_id = -1;
if (data_pool && *data_pool) {
@@ -11903,7 +11990,7 @@ int Client::_create(Inode *dir, const char *name, int flags, mode_t mode,
path.push_dentry(name);
req->set_filepath(path);
req->set_inode(dir);
- req->head.args.open.flags = ceph_flags_sys2wire(flags | O_CREAT);
+ req->head.args.open.flags = cflags | CEPH_O_CREAT;
req->head.args.open.stripe_unit = stripe_unit;
req->head.args.open.stripe_count = stripe_count;
diff --git a/src/client/Client.h b/src/client/Client.h
index 5e005082dca..208ff92e5d9 100644
--- a/src/client/Client.h
+++ b/src/client/Client.h
@@ -848,6 +848,7 @@ private:
int _getlk(Fh *fh, struct flock *fl, uint64_t owner);
int _setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep);
int _flock(Fh *fh, int cmd, uint64_t owner);
+ int _lazyio(Fh *fh, int enable);
int get_or_create(Inode *dir, const char* name,
Dentry **pdn, bool expect_null=false);
@@ -1108,6 +1109,7 @@ public:
int64_t drop_caches();
// hpc lazyio
+ int lazyio(int fd, int enable);
int lazyio_propogate(int fd, loff_t offset, size_t count);
int lazyio_synchronize(int fd, loff_t offset, size_t count);
@@ -1239,6 +1241,7 @@ public:
int ll_getlk(Fh *fh, struct flock *fl, uint64_t owner);
int ll_setlk(Fh *fh, struct flock *fl, uint64_t owner, int sleep);
int ll_flock(Fh *fh, int cmd, uint64_t owner);
+ int ll_lazyio(Fh *fh, int enable);
int ll_file_layout(Fh *fh, file_layout_t *layout);
void ll_interrupt(void *d);
bool ll_handle_umask() {
diff --git a/src/client/Inode.cc b/src/client/Inode.cc
index a4b09538790..6e76fcfddaa 100644
--- a/src/client/Inode.cc
+++ b/src/client/Inode.cc
@@ -134,7 +134,9 @@ void Inode::get_open_ref(int mode)
bool Inode::put_open_ref(int mode)
{
//cout << "open_by_mode[" << mode << "] " << open_by_mode[mode] << " -> " << (open_by_mode[mode]-1) << std::endl;
- if (--open_by_mode[mode] == 0)
+ auto& ref = open_by_mode.at(mode);
+ assert(ref > 0);
+ if (--ref == 0)
return true;
return false;
}