| .. | .. |
|---|
| 10 | 10 | |
|---|
| 11 | 11 | #include <linux/init.h> |
|---|
| 12 | 12 | #include <linux/module.h> |
|---|
| 13 | +#include <linux/fs_context.h> |
|---|
| 13 | 14 | |
|---|
| 14 | 15 | #define FUSE_CTL_SUPER_MAGIC 0x65735543 |
|---|
| 15 | 16 | |
|---|
| .. | .. |
|---|
| 35 | 36 | { |
|---|
| 36 | 37 | struct fuse_conn *fc = fuse_ctl_file_conn_get(file); |
|---|
| 37 | 38 | if (fc) { |
|---|
| 38 | | - fuse_abort_conn(fc, true); |
|---|
| 39 | + if (fc->abort_err) |
|---|
| 40 | + fc->aborted = true; |
|---|
| 41 | + fuse_abort_conn(fc); |
|---|
| 39 | 42 | fuse_conn_put(fc); |
|---|
| 40 | 43 | } |
|---|
| 41 | 44 | return count; |
|---|
| .. | .. |
|---|
| 117 | 120 | const char __user *buf, |
|---|
| 118 | 121 | size_t count, loff_t *ppos) |
|---|
| 119 | 122 | { |
|---|
| 120 | | - unsigned uninitialized_var(val); |
|---|
| 123 | + unsigned val; |
|---|
| 121 | 124 | ssize_t ret; |
|---|
| 122 | 125 | |
|---|
| 123 | 126 | ret = fuse_conn_limit_write(file, buf, count, ppos, &val, |
|---|
| .. | .. |
|---|
| 125 | 128 | if (ret > 0) { |
|---|
| 126 | 129 | struct fuse_conn *fc = fuse_ctl_file_conn_get(file); |
|---|
| 127 | 130 | if (fc) { |
|---|
| 131 | + spin_lock(&fc->bg_lock); |
|---|
| 128 | 132 | fc->max_background = val; |
|---|
| 133 | + fc->blocked = fc->num_background >= fc->max_background; |
|---|
| 134 | + if (!fc->blocked) |
|---|
| 135 | + wake_up(&fc->blocked_waitq); |
|---|
| 136 | + spin_unlock(&fc->bg_lock); |
|---|
| 129 | 137 | fuse_conn_put(fc); |
|---|
| 130 | 138 | } |
|---|
| 131 | 139 | } |
|---|
| .. | .. |
|---|
| 154 | 162 | const char __user *buf, |
|---|
| 155 | 163 | size_t count, loff_t *ppos) |
|---|
| 156 | 164 | { |
|---|
| 157 | | - unsigned uninitialized_var(val); |
|---|
| 165 | + unsigned val; |
|---|
| 166 | + struct fuse_conn *fc; |
|---|
| 167 | + struct fuse_mount *fm; |
|---|
| 158 | 168 | ssize_t ret; |
|---|
| 159 | 169 | |
|---|
| 160 | 170 | ret = fuse_conn_limit_write(file, buf, count, ppos, &val, |
|---|
| 161 | 171 | max_user_congthresh); |
|---|
| 162 | | - if (ret > 0) { |
|---|
| 163 | | - struct fuse_conn *fc = fuse_ctl_file_conn_get(file); |
|---|
| 164 | | - if (fc) { |
|---|
| 165 | | - fc->congestion_threshold = val; |
|---|
| 166 | | - fuse_conn_put(fc); |
|---|
| 172 | + if (ret <= 0) |
|---|
| 173 | + goto out; |
|---|
| 174 | + fc = fuse_ctl_file_conn_get(file); |
|---|
| 175 | + if (!fc) |
|---|
| 176 | + goto out; |
|---|
| 177 | + |
|---|
| 178 | + down_read(&fc->killsb); |
|---|
| 179 | + spin_lock(&fc->bg_lock); |
|---|
| 180 | + fc->congestion_threshold = val; |
|---|
| 181 | + |
|---|
| 182 | + /* |
|---|
| 183 | + * Get any fuse_mount belonging to this fuse_conn; s_bdi is |
|---|
| 184 | + * shared between all of them |
|---|
| 185 | + */ |
|---|
| 186 | + |
|---|
| 187 | + if (!list_empty(&fc->mounts)) { |
|---|
| 188 | + fm = list_first_entry(&fc->mounts, struct fuse_mount, fc_entry); |
|---|
| 189 | + if (fc->num_background < fc->congestion_threshold) { |
|---|
| 190 | + clear_bdi_congested(fm->sb->s_bdi, BLK_RW_SYNC); |
|---|
| 191 | + clear_bdi_congested(fm->sb->s_bdi, BLK_RW_ASYNC); |
|---|
| 192 | + } else { |
|---|
| 193 | + set_bdi_congested(fm->sb->s_bdi, BLK_RW_SYNC); |
|---|
| 194 | + set_bdi_congested(fm->sb->s_bdi, BLK_RW_ASYNC); |
|---|
| 167 | 195 | } |
|---|
| 168 | 196 | } |
|---|
| 169 | | - |
|---|
| 197 | + spin_unlock(&fc->bg_lock); |
|---|
| 198 | + up_read(&fc->killsb); |
|---|
| 199 | + fuse_conn_put(fc); |
|---|
| 200 | +out: |
|---|
| 170 | 201 | return ret; |
|---|
| 171 | 202 | } |
|---|
| 172 | 203 | |
|---|
| .. | .. |
|---|
| 244 | 275 | struct dentry *parent; |
|---|
| 245 | 276 | char name[32]; |
|---|
| 246 | 277 | |
|---|
| 247 | | - if (!fuse_control_sb) |
|---|
| 278 | + if (!fuse_control_sb || fc->no_control) |
|---|
| 248 | 279 | return 0; |
|---|
| 249 | 280 | |
|---|
| 250 | 281 | parent = fuse_control_sb->s_root; |
|---|
| .. | .. |
|---|
| 282 | 313 | { |
|---|
| 283 | 314 | int i; |
|---|
| 284 | 315 | |
|---|
| 285 | | - if (!fuse_control_sb) |
|---|
| 316 | + if (!fuse_control_sb || fc->no_control) |
|---|
| 286 | 317 | return; |
|---|
| 287 | 318 | |
|---|
| 288 | 319 | for (i = fc->ctl_ndents - 1; i >= 0; i--) { |
|---|
| .. | .. |
|---|
| 297 | 328 | drop_nlink(d_inode(fuse_control_sb->s_root)); |
|---|
| 298 | 329 | } |
|---|
| 299 | 330 | |
|---|
| 300 | | -static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent) |
|---|
| 331 | +static int fuse_ctl_fill_super(struct super_block *sb, struct fs_context *fctx) |
|---|
| 301 | 332 | { |
|---|
| 302 | 333 | static const struct tree_descr empty_descr = {""}; |
|---|
| 303 | 334 | struct fuse_conn *fc; |
|---|
| .. | .. |
|---|
| 323 | 354 | return 0; |
|---|
| 324 | 355 | } |
|---|
| 325 | 356 | |
|---|
| 326 | | -static struct dentry *fuse_ctl_mount(struct file_system_type *fs_type, |
|---|
| 327 | | - int flags, const char *dev_name, void *raw_data) |
|---|
| 357 | +static int fuse_ctl_get_tree(struct fs_context *fc) |
|---|
| 328 | 358 | { |
|---|
| 329 | | - return mount_single(fs_type, flags, raw_data, fuse_ctl_fill_super); |
|---|
| 359 | + return get_tree_single(fc, fuse_ctl_fill_super); |
|---|
| 360 | +} |
|---|
| 361 | + |
|---|
| 362 | +static const struct fs_context_operations fuse_ctl_context_ops = { |
|---|
| 363 | + .get_tree = fuse_ctl_get_tree, |
|---|
| 364 | +}; |
|---|
| 365 | + |
|---|
| 366 | +static int fuse_ctl_init_fs_context(struct fs_context *fc) |
|---|
| 367 | +{ |
|---|
| 368 | + fc->ops = &fuse_ctl_context_ops; |
|---|
| 369 | + return 0; |
|---|
| 330 | 370 | } |
|---|
| 331 | 371 | |
|---|
| 332 | 372 | static void fuse_ctl_kill_sb(struct super_block *sb) |
|---|
| .. | .. |
|---|
| 345 | 385 | static struct file_system_type fuse_ctl_fs_type = { |
|---|
| 346 | 386 | .owner = THIS_MODULE, |
|---|
| 347 | 387 | .name = "fusectl", |
|---|
| 348 | | - .mount = fuse_ctl_mount, |
|---|
| 388 | + .init_fs_context = fuse_ctl_init_fs_context, |
|---|
| 349 | 389 | .kill_sb = fuse_ctl_kill_sb, |
|---|
| 350 | 390 | }; |
|---|
| 351 | 391 | MODULE_ALIAS_FS("fusectl"); |
|---|