[Devel] [PATCH RHEL7 COMMIT] fuse kio: Introduce cached_op
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Oct 9 11:50:44 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-862.14.4.vz7.72.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.14.4.vz7.72.4
------>
commit da5f2dcfd2f0a68b9493718ec8898ca2fce033d9
Author: Kirill Tkhai <ktkhai at virtuozzo.com>
Date: Tue Oct 9 11:50:41 2018 +0300
fuse kio: Introduce cached_op
Next patches introduce kio version fallback.
There are at least two approach. First one
is to clear fc->kio.op in case of version
mismatch in process_pcs_init_reply(). The
second one is to assign kio.op there.
I choose the second one, since it allows
to leave places like:
if (fc->kio.op && fc->kio.op->req_send)
as is, and not to worry, that fc->kio.op become
zero and freed in between of them. This allows
to avoid some additional synchronization around
such the places, like in would have been in the
first approach.
Normally, we mustn't be near such the places
before we're initialized (I've reviewed all of them),
but this additional protection won't excess (I think).
Note, that going to !kio path before kio is enabled
is bad thing anyway. For example, we may lose kio
file initialization in that case. But, again, all
current places go thru req allocation and they will
sleep till connection is initialized.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
Reviewed-by: Pavel Butsykin <pbutsykin at virtuozzo.com>
Changes:
v2: Add cached_op to destroy_inode for safety
v2.1: Fix spelling
---
fs/fuse/fuse_i.h | 1 +
fs/fuse/inode.c | 20 ++++++++++----------
fs/fuse/kio/pcs/pcs_fuse_kdirect.c | 6 ++++++
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 4ececf9acff5..69dfd0c318fe 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -766,6 +766,7 @@ struct fuse_conn {
/** Kdirect io operations */
struct {
struct fuse_kio_ops *op;
+ struct fuse_kio_ops *cached_op;
void *ctx;
} kio;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 409dc5abd461..ca9a146d39fa 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -131,8 +131,8 @@ static void fuse_destroy_inode(struct inode *inode)
kfree(fi->forget);
/* TODO: Probably kio context should be released inside fuse forget */
- if (fc->kio.op && fc->kio.op->inode_release)
- fc->kio.op->inode_release(fi);
+ if (fc->kio.cached_op && fc->kio.cached_op->inode_release)
+ fc->kio.cached_op->inode_release(fi);
call_rcu(&inode->i_rcu, fuse_i_callback);
}
@@ -512,8 +512,8 @@ static void fuse_kio_put(struct fuse_kio_ops *ops)
static void fuse_kdirect_put(struct fuse_conn *fc)
{
- if (fc->kio.op)
- fuse_kio_put(fc->kio.op);
+ if (fc->kio.cached_op)
+ fuse_kio_put(fc->kio.cached_op);
}
static void fuse_put_super(struct super_block *sb)
@@ -753,8 +753,8 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root)
seq_printf(m, ",blksize=%lu", sb->s_blocksize);
if (fc->writeback_cache)
seq_puts(m, ",writeback_enable");
- if (fc->kio.op)
- seq_printf(m, ",kdirect=%s", fc->kio.op->name);
+ if (fc->kio.cached_op)
+ seq_printf(m, ",kdirect=%s", fc->kio.cached_op->name);
return 0;
}
@@ -1113,8 +1113,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
fc->max_write = max_t(unsigned, 4096, fc->max_write);
fc->conn_init = 1;
- if (fc->kio.op) {
- if (!fc->kio.op->conn_init(fc))
+ if (fc->kio.cached_op) {
+ if (!fc->kio.cached_op->conn_init(fc))
return;
fc->conn_error = 1;
}
@@ -1327,8 +1327,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
err = -EINVAL;
if (!fc->writeback_cache)
goto err_dev_free;
- fc->kio.op = fuse_kio_get(fc, d.kio_name);
- if (!fc->kio.op)
+ fc->kio.cached_op = fuse_kio_get(fc, d.kio_name);
+ if (!fc->kio.cached_op)
goto err_dev_free;
}
/* Used by get_root_inode() */
diff --git a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
index 431df2419e65..6512107bdafb 100644
--- a/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
+++ b/fs/fuse/kio/pcs/pcs_fuse_kdirect.c
@@ -86,6 +86,12 @@ static void process_pcs_init_reply(struct fuse_conn *fc, struct fuse_req *req)
goto out;
}
+ /*
+ * It looks like all potential tasks, which can dereference
+ * fc->kio.op, are waiting for fuse_set_initialized().
+ */
+ fc->kio.op = fc->kio.cached_op;
+
pfc = kvmalloc(sizeof(*pfc), GFP_KERNEL);
if (!pfc) {
fc->conn_error = 1;
More information about the Devel
mailing list