aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill Tkhai <ktkhai@virtuozzo.com>2018-08-27 11:29:37 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2018-09-28 10:43:22 -0400
commit2b30a533148af4f3865c0dcd619ad93ab3f4ba52 (patch)
treefd25fe80e8ff83649d05d6eda7328447909ba628
parent2a23f2b8adbe4bd584f936f7ac17a99750eed9d7 (diff)
fuse: add locking to max_background and congestion_threshold changes
Functions sequences like request_end()->flush_bg_queue() require that max_background and congestion_threshold are constant during their execution. Otherwise, checks like if (fc->num_background == fc->max_background) made in different time may behave not like expected. Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/fuse/control.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index acc35819aae6..eaa0e2b21623 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -125,7 +125,12 @@ static ssize_t fuse_conn_max_background_write(struct file *file,
125 if (ret > 0) { 125 if (ret > 0) {
126 struct fuse_conn *fc = fuse_ctl_file_conn_get(file); 126 struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
127 if (fc) { 127 if (fc) {
128 spin_lock(&fc->lock);
128 fc->max_background = val; 129 fc->max_background = val;
130 fc->blocked = fc->num_background >= fc->max_background;
131 if (!fc->blocked)
132 wake_up(&fc->blocked_waitq);
133 spin_unlock(&fc->lock);
129 fuse_conn_put(fc); 134 fuse_conn_put(fc);
130 } 135 }
131 } 136 }
@@ -155,18 +160,31 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file,
155 size_t count, loff_t *ppos) 160 size_t count, loff_t *ppos)
156{ 161{
157 unsigned uninitialized_var(val); 162 unsigned uninitialized_var(val);
163 struct fuse_conn *fc;
158 ssize_t ret; 164 ssize_t ret;
159 165
160 ret = fuse_conn_limit_write(file, buf, count, ppos, &val, 166 ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
161 max_user_congthresh); 167 max_user_congthresh);
162 if (ret > 0) { 168 if (ret <= 0)
163 struct fuse_conn *fc = fuse_ctl_file_conn_get(file); 169 goto out;
164 if (fc) { 170 fc = fuse_ctl_file_conn_get(file);
165 fc->congestion_threshold = val; 171 if (!fc)
166 fuse_conn_put(fc); 172 goto out;
173
174 spin_lock(&fc->lock);
175 fc->congestion_threshold = val;
176 if (fc->sb) {
177 if (fc->num_background < fc->congestion_threshold) {
178 clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC);
179 clear_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC);
180 } else {
181 set_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC);
182 set_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC);
167 } 183 }
168 } 184 }
169 185 spin_unlock(&fc->lock);
186 fuse_conn_put(fc);
187out:
170 return ret; 188 return ret;
171} 189}
172 190