diff options
| author | Miklos Szeredi <mszeredi@suse.cz> | 2015-01-06 04:45:35 -0500 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@suse.cz> | 2015-01-06 04:45:35 -0500 |
| commit | 9759bd51899458af4f4bcc11046f01285642ca10 (patch) | |
| tree | 9e50d89d7772cbff8a7502a19353c984a948d1a6 | |
| parent | 21f621741a770c119e7529a3f5c0e6b7c91383a3 (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>
| -rw-r--r-- | fs/fuse/dev.c | 15 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 2 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 2 |
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 | ||
| 134 | void 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 | |||
| 134 | static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background) | 141 | static 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); | |||
| 906 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, | 906 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, |
| 907 | struct file *file); | 907 | struct file *file); |
| 908 | 908 | ||
| 909 | void 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 | ||
