aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2015-01-06 04:45:35 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2015-01-06 04:45:35 -0500
commit9759bd51899458af4f4bcc11046f01285642ca10 (patch)
tree9e50d89d7772cbff8a7502a19353c984a948d1a6 /fs
parent21f621741a770c119e7529a3f5c0e6b7c91383a3 (diff)
fuse: add memory barrier to INIT
Theoretically we need to order setting of various fields in fc with fc->initialized. No known bug reports related to this yet. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dev.c15
-rw-r--r--fs/fuse/fuse_i.h2
-rw-r--r--fs/fuse/inode.c2
3 files changed, 16 insertions, 3 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index c847d6b225e2..ed19a7d622fa 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -131,6 +131,13 @@ static void fuse_req_init_context(struct fuse_req *req)
131 req->in.h.pid = current->pid; 131 req->in.h.pid = current->pid;
132} 132}
133 133
134void fuse_set_initialized(struct fuse_conn *fc)
135{
136 /* Make sure stores before this are seen on another CPU */
137 smp_wmb();
138 fc->initialized = 1;
139}
140
134static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background) 141static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
135{ 142{
136 return !fc->initialized || (for_background && fc->blocked); 143 return !fc->initialized || (for_background && fc->blocked);
@@ -155,6 +162,8 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
155 if (intr) 162 if (intr)
156 goto out; 163 goto out;
157 } 164 }
165 /* Matches smp_wmb() in fuse_set_initialized() */
166 smp_rmb();
158 167
159 err = -ENOTCONN; 168 err = -ENOTCONN;
160 if (!fc->connected) 169 if (!fc->connected)
@@ -253,6 +262,8 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
253 262
254 atomic_inc(&fc->num_waiting); 263 atomic_inc(&fc->num_waiting);
255 wait_event(fc->blocked_waitq, fc->initialized); 264 wait_event(fc->blocked_waitq, fc->initialized);
265 /* Matches smp_wmb() in fuse_set_initialized() */
266 smp_rmb();
256 req = fuse_request_alloc(0); 267 req = fuse_request_alloc(0);
257 if (!req) 268 if (!req)
258 req = get_reserved_req(fc, file); 269 req = get_reserved_req(fc, file);
@@ -2163,7 +2174,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
2163 if (fc->connected) { 2174 if (fc->connected) {
2164 fc->connected = 0; 2175 fc->connected = 0;
2165 fc->blocked = 0; 2176 fc->blocked = 0;
2166 fc->initialized = 1; 2177 fuse_set_initialized(fc);
2167 end_io_requests(fc); 2178 end_io_requests(fc);
2168 end_queued_requests(fc); 2179 end_queued_requests(fc);
2169 end_polls(fc); 2180 end_polls(fc);
@@ -2182,7 +2193,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
2182 spin_lock(&fc->lock); 2193 spin_lock(&fc->lock);
2183 fc->connected = 0; 2194 fc->connected = 0;
2184 fc->blocked = 0; 2195 fc->blocked = 0;
2185 fc->initialized = 1; 2196 fuse_set_initialized(fc);
2186 end_queued_requests(fc); 2197 end_queued_requests(fc);
2187 end_polls(fc); 2198 end_polls(fc);
2188 wake_up_all(&fc->blocked_waitq); 2199 wake_up_all(&fc->blocked_waitq);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index e0fc6725d1d0..1cdfb07c1376 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -906,4 +906,6 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc);
906int fuse_do_setattr(struct inode *inode, struct iattr *attr, 906int fuse_do_setattr(struct inode *inode, struct iattr *attr,
907 struct file *file); 907 struct file *file);
908 908
909void fuse_set_initialized(struct fuse_conn *fc);
910
909#endif /* _FS_FUSE_I_H */ 911#endif /* _FS_FUSE_I_H */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 6a20f2ff2c2e..f38256e4476e 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -897,7 +897,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
897 fc->max_write = max_t(unsigned, 4096, fc->max_write); 897 fc->max_write = max_t(unsigned, 4096, fc->max_write);
898 fc->conn_init = 1; 898 fc->conn_init = 1;
899 } 899 }
900 fc->initialized = 1; 900 fuse_set_initialized(fc);
901 wake_up_all(&fc->blocked_waitq); 901 wake_up_all(&fc->blocked_waitq);
902} 902}
903 903