Back to home page

OSCL-LXR

 
 

    


0001 /*
0002   FUSE: Filesystem in Userspace
0003   Copyright (C) 2001-2008  Miklos Szeredi <miklos@szeredi.hu>
0004 
0005   This program can be distributed under the terms of the GNU GPL.
0006   See the file COPYING.
0007 */
0008 
0009 #include "fuse_i.h"
0010 
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/fs_context.h>
0014 
0015 #define FUSE_CTL_SUPER_MAGIC 0x65735543
0016 
0017 /*
0018  * This is non-NULL when the single instance of the control filesystem
0019  * exists.  Protected by fuse_mutex
0020  */
0021 static struct super_block *fuse_control_sb;
0022 
0023 static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
0024 {
0025     struct fuse_conn *fc;
0026     mutex_lock(&fuse_mutex);
0027     fc = file_inode(file)->i_private;
0028     if (fc)
0029         fc = fuse_conn_get(fc);
0030     mutex_unlock(&fuse_mutex);
0031     return fc;
0032 }
0033 
0034 static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
0035                      size_t count, loff_t *ppos)
0036 {
0037     struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
0038     if (fc) {
0039         if (fc->abort_err)
0040             fc->aborted = true;
0041         fuse_abort_conn(fc);
0042         fuse_conn_put(fc);
0043     }
0044     return count;
0045 }
0046 
0047 static ssize_t fuse_conn_waiting_read(struct file *file, char __user *buf,
0048                       size_t len, loff_t *ppos)
0049 {
0050     char tmp[32];
0051     size_t size;
0052 
0053     if (!*ppos) {
0054         long value;
0055         struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
0056         if (!fc)
0057             return 0;
0058 
0059         value = atomic_read(&fc->num_waiting);
0060         file->private_data = (void *)value;
0061         fuse_conn_put(fc);
0062     }
0063     size = sprintf(tmp, "%ld\n", (long)file->private_data);
0064     return simple_read_from_buffer(buf, len, ppos, tmp, size);
0065 }
0066 
0067 static ssize_t fuse_conn_limit_read(struct file *file, char __user *buf,
0068                     size_t len, loff_t *ppos, unsigned val)
0069 {
0070     char tmp[32];
0071     size_t size = sprintf(tmp, "%u\n", val);
0072 
0073     return simple_read_from_buffer(buf, len, ppos, tmp, size);
0074 }
0075 
0076 static ssize_t fuse_conn_limit_write(struct file *file, const char __user *buf,
0077                      size_t count, loff_t *ppos, unsigned *val,
0078                      unsigned global_limit)
0079 {
0080     unsigned long t;
0081     unsigned limit = (1 << 16) - 1;
0082     int err;
0083 
0084     if (*ppos)
0085         return -EINVAL;
0086 
0087     err = kstrtoul_from_user(buf, count, 0, &t);
0088     if (err)
0089         return err;
0090 
0091     if (!capable(CAP_SYS_ADMIN))
0092         limit = min(limit, global_limit);
0093 
0094     if (t > limit)
0095         return -EINVAL;
0096 
0097     *val = t;
0098 
0099     return count;
0100 }
0101 
0102 static ssize_t fuse_conn_max_background_read(struct file *file,
0103                          char __user *buf, size_t len,
0104                          loff_t *ppos)
0105 {
0106     struct fuse_conn *fc;
0107     unsigned val;
0108 
0109     fc = fuse_ctl_file_conn_get(file);
0110     if (!fc)
0111         return 0;
0112 
0113     val = READ_ONCE(fc->max_background);
0114     fuse_conn_put(fc);
0115 
0116     return fuse_conn_limit_read(file, buf, len, ppos, val);
0117 }
0118 
0119 static ssize_t fuse_conn_max_background_write(struct file *file,
0120                           const char __user *buf,
0121                           size_t count, loff_t *ppos)
0122 {
0123     unsigned val;
0124     ssize_t ret;
0125 
0126     ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
0127                     max_user_bgreq);
0128     if (ret > 0) {
0129         struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
0130         if (fc) {
0131             spin_lock(&fc->bg_lock);
0132             fc->max_background = val;
0133             fc->blocked = fc->num_background >= fc->max_background;
0134             if (!fc->blocked)
0135                 wake_up(&fc->blocked_waitq);
0136             spin_unlock(&fc->bg_lock);
0137             fuse_conn_put(fc);
0138         }
0139     }
0140 
0141     return ret;
0142 }
0143 
0144 static ssize_t fuse_conn_congestion_threshold_read(struct file *file,
0145                            char __user *buf, size_t len,
0146                            loff_t *ppos)
0147 {
0148     struct fuse_conn *fc;
0149     unsigned val;
0150 
0151     fc = fuse_ctl_file_conn_get(file);
0152     if (!fc)
0153         return 0;
0154 
0155     val = READ_ONCE(fc->congestion_threshold);
0156     fuse_conn_put(fc);
0157 
0158     return fuse_conn_limit_read(file, buf, len, ppos, val);
0159 }
0160 
0161 static ssize_t fuse_conn_congestion_threshold_write(struct file *file,
0162                             const char __user *buf,
0163                             size_t count, loff_t *ppos)
0164 {
0165     unsigned val;
0166     struct fuse_conn *fc;
0167     ssize_t ret;
0168 
0169     ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
0170                     max_user_congthresh);
0171     if (ret <= 0)
0172         goto out;
0173     fc = fuse_ctl_file_conn_get(file);
0174     if (!fc)
0175         goto out;
0176 
0177     down_read(&fc->killsb);
0178     spin_lock(&fc->bg_lock);
0179     fc->congestion_threshold = val;
0180     spin_unlock(&fc->bg_lock);
0181     up_read(&fc->killsb);
0182     fuse_conn_put(fc);
0183 out:
0184     return ret;
0185 }
0186 
0187 static const struct file_operations fuse_ctl_abort_ops = {
0188     .open = nonseekable_open,
0189     .write = fuse_conn_abort_write,
0190     .llseek = no_llseek,
0191 };
0192 
0193 static const struct file_operations fuse_ctl_waiting_ops = {
0194     .open = nonseekable_open,
0195     .read = fuse_conn_waiting_read,
0196     .llseek = no_llseek,
0197 };
0198 
0199 static const struct file_operations fuse_conn_max_background_ops = {
0200     .open = nonseekable_open,
0201     .read = fuse_conn_max_background_read,
0202     .write = fuse_conn_max_background_write,
0203     .llseek = no_llseek,
0204 };
0205 
0206 static const struct file_operations fuse_conn_congestion_threshold_ops = {
0207     .open = nonseekable_open,
0208     .read = fuse_conn_congestion_threshold_read,
0209     .write = fuse_conn_congestion_threshold_write,
0210     .llseek = no_llseek,
0211 };
0212 
0213 static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
0214                       struct fuse_conn *fc,
0215                       const char *name,
0216                       int mode, int nlink,
0217                       const struct inode_operations *iop,
0218                       const struct file_operations *fop)
0219 {
0220     struct dentry *dentry;
0221     struct inode *inode;
0222 
0223     BUG_ON(fc->ctl_ndents >= FUSE_CTL_NUM_DENTRIES);
0224     dentry = d_alloc_name(parent, name);
0225     if (!dentry)
0226         return NULL;
0227 
0228     inode = new_inode(fuse_control_sb);
0229     if (!inode) {
0230         dput(dentry);
0231         return NULL;
0232     }
0233 
0234     inode->i_ino = get_next_ino();
0235     inode->i_mode = mode;
0236     inode->i_uid = fc->user_id;
0237     inode->i_gid = fc->group_id;
0238     inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
0239     /* setting ->i_op to NULL is not allowed */
0240     if (iop)
0241         inode->i_op = iop;
0242     inode->i_fop = fop;
0243     set_nlink(inode, nlink);
0244     inode->i_private = fc;
0245     d_add(dentry, inode);
0246 
0247     fc->ctl_dentry[fc->ctl_ndents++] = dentry;
0248 
0249     return dentry;
0250 }
0251 
0252 /*
0253  * Add a connection to the control filesystem (if it exists).  Caller
0254  * must hold fuse_mutex
0255  */
0256 int fuse_ctl_add_conn(struct fuse_conn *fc)
0257 {
0258     struct dentry *parent;
0259     char name[32];
0260 
0261     if (!fuse_control_sb || fc->no_control)
0262         return 0;
0263 
0264     parent = fuse_control_sb->s_root;
0265     inc_nlink(d_inode(parent));
0266     sprintf(name, "%u", fc->dev);
0267     parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
0268                      &simple_dir_inode_operations,
0269                      &simple_dir_operations);
0270     if (!parent)
0271         goto err;
0272 
0273     if (!fuse_ctl_add_dentry(parent, fc, "waiting", S_IFREG | 0400, 1,
0274                  NULL, &fuse_ctl_waiting_ops) ||
0275         !fuse_ctl_add_dentry(parent, fc, "abort", S_IFREG | 0200, 1,
0276                  NULL, &fuse_ctl_abort_ops) ||
0277         !fuse_ctl_add_dentry(parent, fc, "max_background", S_IFREG | 0600,
0278                  1, NULL, &fuse_conn_max_background_ops) ||
0279         !fuse_ctl_add_dentry(parent, fc, "congestion_threshold",
0280                  S_IFREG | 0600, 1, NULL,
0281                  &fuse_conn_congestion_threshold_ops))
0282         goto err;
0283 
0284     return 0;
0285 
0286  err:
0287     fuse_ctl_remove_conn(fc);
0288     return -ENOMEM;
0289 }
0290 
0291 /*
0292  * Remove a connection from the control filesystem (if it exists).
0293  * Caller must hold fuse_mutex
0294  */
0295 void fuse_ctl_remove_conn(struct fuse_conn *fc)
0296 {
0297     int i;
0298 
0299     if (!fuse_control_sb || fc->no_control)
0300         return;
0301 
0302     for (i = fc->ctl_ndents - 1; i >= 0; i--) {
0303         struct dentry *dentry = fc->ctl_dentry[i];
0304         d_inode(dentry)->i_private = NULL;
0305         if (!i) {
0306             /* Get rid of submounts: */
0307             d_invalidate(dentry);
0308         }
0309         dput(dentry);
0310     }
0311     drop_nlink(d_inode(fuse_control_sb->s_root));
0312 }
0313 
0314 static int fuse_ctl_fill_super(struct super_block *sb, struct fs_context *fsc)
0315 {
0316     static const struct tree_descr empty_descr = {""};
0317     struct fuse_conn *fc;
0318     int err;
0319 
0320     err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
0321     if (err)
0322         return err;
0323 
0324     mutex_lock(&fuse_mutex);
0325     BUG_ON(fuse_control_sb);
0326     fuse_control_sb = sb;
0327     list_for_each_entry(fc, &fuse_conn_list, entry) {
0328         err = fuse_ctl_add_conn(fc);
0329         if (err) {
0330             fuse_control_sb = NULL;
0331             mutex_unlock(&fuse_mutex);
0332             return err;
0333         }
0334     }
0335     mutex_unlock(&fuse_mutex);
0336 
0337     return 0;
0338 }
0339 
0340 static int fuse_ctl_get_tree(struct fs_context *fsc)
0341 {
0342     return get_tree_single(fsc, fuse_ctl_fill_super);
0343 }
0344 
0345 static const struct fs_context_operations fuse_ctl_context_ops = {
0346     .get_tree   = fuse_ctl_get_tree,
0347 };
0348 
0349 static int fuse_ctl_init_fs_context(struct fs_context *fsc)
0350 {
0351     fsc->ops = &fuse_ctl_context_ops;
0352     return 0;
0353 }
0354 
0355 static void fuse_ctl_kill_sb(struct super_block *sb)
0356 {
0357     struct fuse_conn *fc;
0358 
0359     mutex_lock(&fuse_mutex);
0360     fuse_control_sb = NULL;
0361     list_for_each_entry(fc, &fuse_conn_list, entry)
0362         fc->ctl_ndents = 0;
0363     mutex_unlock(&fuse_mutex);
0364 
0365     kill_litter_super(sb);
0366 }
0367 
0368 static struct file_system_type fuse_ctl_fs_type = {
0369     .owner      = THIS_MODULE,
0370     .name       = "fusectl",
0371     .init_fs_context = fuse_ctl_init_fs_context,
0372     .kill_sb    = fuse_ctl_kill_sb,
0373 };
0374 MODULE_ALIAS_FS("fusectl");
0375 
0376 int __init fuse_ctl_init(void)
0377 {
0378     return register_filesystem(&fuse_ctl_fs_type);
0379 }
0380 
0381 void __exit fuse_ctl_cleanup(void)
0382 {
0383     unregister_filesystem(&fuse_ctl_fs_type);
0384 }