1d8a5ba45SMiklos Szeredi /* 2d8a5ba45SMiklos Szeredi FUSE: Filesystem in Userspace 31729a16cSMiklos Szeredi Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> 4d8a5ba45SMiklos Szeredi 5d8a5ba45SMiklos Szeredi This program can be distributed under the terms of the GNU GPL. 6d8a5ba45SMiklos Szeredi See the file COPYING. 7d8a5ba45SMiklos Szeredi */ 8d8a5ba45SMiklos Szeredi 9d8a5ba45SMiklos Szeredi #include "fuse_i.h" 10d8a5ba45SMiklos Szeredi 11d8a5ba45SMiklos Szeredi #include <linux/pagemap.h> 12d8a5ba45SMiklos Szeredi #include <linux/slab.h> 13d8a5ba45SMiklos Szeredi #include <linux/file.h> 14d8a5ba45SMiklos Szeredi #include <linux/seq_file.h> 15d8a5ba45SMiklos Szeredi #include <linux/init.h> 16d8a5ba45SMiklos Szeredi #include <linux/module.h> 17487ea5afSCsaba Henk #include <linux/moduleparam.h> 18d8a5ba45SMiklos Szeredi #include <linux/parser.h> 19d8a5ba45SMiklos Szeredi #include <linux/statfs.h> 209c8ef561SMiklos Szeredi #include <linux/random.h> 21e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 22dbd561d2SMiklos Szeredi #include <linux/exportfs.h> 23d8a5ba45SMiklos Szeredi 24d8a5ba45SMiklos Szeredi MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); 25d8a5ba45SMiklos Szeredi MODULE_DESCRIPTION("Filesystem in Userspace"); 26d8a5ba45SMiklos Szeredi MODULE_LICENSE("GPL"); 27d8a5ba45SMiklos Szeredi 28e18b890bSChristoph Lameter static struct kmem_cache *fuse_inode_cachep; 29bafa9654SMiklos Szeredi struct list_head fuse_conn_list; 30bafa9654SMiklos Szeredi DEFINE_MUTEX(fuse_mutex); 31d8a5ba45SMiklos Szeredi 32487ea5afSCsaba Henk static int set_global_limit(const char *val, struct kernel_param *kp); 33487ea5afSCsaba Henk 3479a9d994SCsaba Henk unsigned max_user_bgreq; 35487ea5afSCsaba Henk module_param_call(max_user_bgreq, set_global_limit, param_get_uint, 36487ea5afSCsaba Henk &max_user_bgreq, 0644); 37487ea5afSCsaba Henk __MODULE_PARM_TYPE(max_user_bgreq, "uint"); 38487ea5afSCsaba Henk MODULE_PARM_DESC(max_user_bgreq, 39487ea5afSCsaba Henk "Global limit for the maximum number of backgrounded requests an " 40487ea5afSCsaba Henk "unprivileged user can set"); 41487ea5afSCsaba Henk 4279a9d994SCsaba Henk unsigned max_user_congthresh; 43487ea5afSCsaba Henk module_param_call(max_user_congthresh, set_global_limit, param_get_uint, 44487ea5afSCsaba Henk &max_user_congthresh, 0644); 45487ea5afSCsaba Henk __MODULE_PARM_TYPE(max_user_congthresh, "uint"); 46487ea5afSCsaba Henk MODULE_PARM_DESC(max_user_congthresh, 47487ea5afSCsaba Henk "Global limit for the maximum congestion threshold an " 48487ea5afSCsaba Henk "unprivileged user can set"); 49487ea5afSCsaba Henk 50d8a5ba45SMiklos Szeredi #define FUSE_SUPER_MAGIC 0x65735546 51d8a5ba45SMiklos Szeredi 52d1875dbaSMiklos Szeredi #define FUSE_DEFAULT_BLKSIZE 512 53d1875dbaSMiklos Szeredi 547a6d3c8bSCsaba Henk /** Maximum number of outstanding background requests */ 557a6d3c8bSCsaba Henk #define FUSE_DEFAULT_MAX_BACKGROUND 12 567a6d3c8bSCsaba Henk 577a6d3c8bSCsaba Henk /** Congestion starts at 75% of maximum */ 587a6d3c8bSCsaba Henk #define FUSE_DEFAULT_CONGESTION_THRESHOLD (FUSE_DEFAULT_MAX_BACKGROUND * 3 / 4) 597a6d3c8bSCsaba Henk 60d8a5ba45SMiklos Szeredi struct fuse_mount_data { 61d8a5ba45SMiklos Szeredi int fd; 62d8a5ba45SMiklos Szeredi unsigned rootmode; 63d8a5ba45SMiklos Szeredi unsigned user_id; 6487729a55SMiklos Szeredi unsigned group_id; 655a533682SMiklos Szeredi unsigned fd_present:1; 665a533682SMiklos Szeredi unsigned rootmode_present:1; 675a533682SMiklos Szeredi unsigned user_id_present:1; 685a533682SMiklos Szeredi unsigned group_id_present:1; 691e9a4ed9SMiklos Szeredi unsigned flags; 70db50b96cSMiklos Szeredi unsigned max_read; 71d8091614SMiklos Szeredi unsigned blksize; 72d8a5ba45SMiklos Szeredi }; 73d8a5ba45SMiklos Szeredi 7407e77dcaSMiklos Szeredi struct fuse_forget_link *fuse_alloc_forget() 7507e77dcaSMiklos Szeredi { 7607e77dcaSMiklos Szeredi return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); 7707e77dcaSMiklos Szeredi } 7807e77dcaSMiklos Szeredi 79d8a5ba45SMiklos Szeredi static struct inode *fuse_alloc_inode(struct super_block *sb) 80d8a5ba45SMiklos Szeredi { 81d8a5ba45SMiklos Szeredi struct inode *inode; 82d8a5ba45SMiklos Szeredi struct fuse_inode *fi; 83d8a5ba45SMiklos Szeredi 84e94b1766SChristoph Lameter inode = kmem_cache_alloc(fuse_inode_cachep, GFP_KERNEL); 85d8a5ba45SMiklos Szeredi if (!inode) 86d8a5ba45SMiklos Szeredi return NULL; 87d8a5ba45SMiklos Szeredi 88d8a5ba45SMiklos Szeredi fi = get_fuse_inode(inode); 890a0898cfSMiklos Szeredi fi->i_time = 0; 90d8a5ba45SMiklos Szeredi fi->nodeid = 0; 919e6268dbSMiklos Szeredi fi->nlookup = 0; 92fbee36b9SJohn Muir fi->attr_version = 0; 933be5a52bSMiklos Szeredi fi->writectr = 0; 9493a8c3cdSMiklos Szeredi INIT_LIST_HEAD(&fi->write_files); 953be5a52bSMiklos Szeredi INIT_LIST_HEAD(&fi->queued_writes); 963be5a52bSMiklos Szeredi INIT_LIST_HEAD(&fi->writepages); 973be5a52bSMiklos Szeredi init_waitqueue_head(&fi->page_waitq); 9807e77dcaSMiklos Szeredi fi->forget = fuse_alloc_forget(); 9907e77dcaSMiklos Szeredi if (!fi->forget) { 100e5e5558eSMiklos Szeredi kmem_cache_free(fuse_inode_cachep, inode); 101e5e5558eSMiklos Szeredi return NULL; 102e5e5558eSMiklos Szeredi } 103d8a5ba45SMiklos Szeredi 104d8a5ba45SMiklos Szeredi return inode; 105d8a5ba45SMiklos Szeredi } 106d8a5ba45SMiklos Szeredi 107fa0d7e3dSNick Piggin static void fuse_i_callback(struct rcu_head *head) 108fa0d7e3dSNick Piggin { 109fa0d7e3dSNick Piggin struct inode *inode = container_of(head, struct inode, i_rcu); 110fa0d7e3dSNick Piggin INIT_LIST_HEAD(&inode->i_dentry); 111fa0d7e3dSNick Piggin kmem_cache_free(fuse_inode_cachep, inode); 112fa0d7e3dSNick Piggin } 113fa0d7e3dSNick Piggin 114d8a5ba45SMiklos Szeredi static void fuse_destroy_inode(struct inode *inode) 115d8a5ba45SMiklos Szeredi { 116e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 11793a8c3cdSMiklos Szeredi BUG_ON(!list_empty(&fi->write_files)); 1183be5a52bSMiklos Szeredi BUG_ON(!list_empty(&fi->queued_writes)); 11907e77dcaSMiklos Szeredi kfree(fi->forget); 120fa0d7e3dSNick Piggin call_rcu(&inode->i_rcu, fuse_i_callback); 121d8a5ba45SMiklos Szeredi } 122d8a5ba45SMiklos Szeredi 123b57922d9SAl Viro static void fuse_evict_inode(struct inode *inode) 124d8a5ba45SMiklos Szeredi { 125b57922d9SAl Viro truncate_inode_pages(&inode->i_data, 0); 126b57922d9SAl Viro end_writeback(inode); 1271e9a4ed9SMiklos Szeredi if (inode->i_sb->s_flags & MS_ACTIVE) { 128e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 129e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 13007e77dcaSMiklos Szeredi fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup); 13107e77dcaSMiklos Szeredi fi->forget = NULL; 132e5e5558eSMiklos Szeredi } 133d8a5ba45SMiklos Szeredi } 134d8a5ba45SMiklos Szeredi 13571421259SMiklos Szeredi static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) 13671421259SMiklos Szeredi { 13771421259SMiklos Szeredi if (*flags & MS_MANDLOCK) 13871421259SMiklos Szeredi return -EINVAL; 13971421259SMiklos Szeredi 14071421259SMiklos Szeredi return 0; 14171421259SMiklos Szeredi } 14271421259SMiklos Szeredi 1433be5a52bSMiklos Szeredi void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 1443be5a52bSMiklos Szeredi u64 attr_valid) 145d8a5ba45SMiklos Szeredi { 1469ffbb916SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 147ebc14c4dSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 148d8a5ba45SMiklos Szeredi 1491fb69e78SMiklos Szeredi fi->attr_version = ++fc->attr_version; 1501fb69e78SMiklos Szeredi fi->i_time = attr_valid; 1511fb69e78SMiklos Szeredi 152d8a5ba45SMiklos Szeredi inode->i_ino = attr->ino; 153ebc14c4dSMiklos Szeredi inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 154d8a5ba45SMiklos Szeredi inode->i_nlink = attr->nlink; 155d8a5ba45SMiklos Szeredi inode->i_uid = attr->uid; 156d8a5ba45SMiklos Szeredi inode->i_gid = attr->gid; 157d8a5ba45SMiklos Szeredi inode->i_blocks = attr->blocks; 158d8a5ba45SMiklos Szeredi inode->i_atime.tv_sec = attr->atime; 159d8a5ba45SMiklos Szeredi inode->i_atime.tv_nsec = attr->atimensec; 160d8a5ba45SMiklos Szeredi inode->i_mtime.tv_sec = attr->mtime; 161d8a5ba45SMiklos Szeredi inode->i_mtime.tv_nsec = attr->mtimensec; 162d8a5ba45SMiklos Szeredi inode->i_ctime.tv_sec = attr->ctime; 163d8a5ba45SMiklos Szeredi inode->i_ctime.tv_nsec = attr->ctimensec; 164e00d2c2dSMiklos Szeredi 1650e9663eeSMiklos Szeredi if (attr->blksize != 0) 1660e9663eeSMiklos Szeredi inode->i_blkbits = ilog2(attr->blksize); 1670e9663eeSMiklos Szeredi else 1680e9663eeSMiklos Szeredi inode->i_blkbits = inode->i_sb->s_blocksize_bits; 1690e9663eeSMiklos Szeredi 170ebc14c4dSMiklos Szeredi /* 171ebc14c4dSMiklos Szeredi * Don't set the sticky bit in i_mode, unless we want the VFS 172ebc14c4dSMiklos Szeredi * to check permissions. This prevents failures due to the 173ebc14c4dSMiklos Szeredi * check in may_delete(). 174ebc14c4dSMiklos Szeredi */ 175ebc14c4dSMiklos Szeredi fi->orig_i_mode = inode->i_mode; 176ebc14c4dSMiklos Szeredi if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 177ebc14c4dSMiklos Szeredi inode->i_mode &= ~S_ISVTX; 1783be5a52bSMiklos Szeredi } 1793be5a52bSMiklos Szeredi 1803be5a52bSMiklos Szeredi void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, 1813be5a52bSMiklos Szeredi u64 attr_valid, u64 attr_version) 1823be5a52bSMiklos Szeredi { 1833be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1843be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1853be5a52bSMiklos Szeredi loff_t oldsize; 1863be5a52bSMiklos Szeredi 1873be5a52bSMiklos Szeredi spin_lock(&fc->lock); 1883be5a52bSMiklos Szeredi if (attr_version != 0 && fi->attr_version > attr_version) { 1893be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 1903be5a52bSMiklos Szeredi return; 1913be5a52bSMiklos Szeredi } 1923be5a52bSMiklos Szeredi 1933be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, attr, attr_valid); 194ebc14c4dSMiklos Szeredi 195e00d2c2dSMiklos Szeredi oldsize = inode->i_size; 196e00d2c2dSMiklos Szeredi i_size_write(inode, attr->size); 197e00d2c2dSMiklos Szeredi spin_unlock(&fc->lock); 198e00d2c2dSMiklos Szeredi 199e00d2c2dSMiklos Szeredi if (S_ISREG(inode->i_mode) && oldsize != attr->size) { 200c08d3b0eSnpiggin@suse.de truncate_pagecache(inode, oldsize, attr->size); 201b1009979SMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 202e00d2c2dSMiklos Szeredi } 203d8a5ba45SMiklos Szeredi } 204d8a5ba45SMiklos Szeredi 205d8a5ba45SMiklos Szeredi static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) 206d8a5ba45SMiklos Szeredi { 207d8a5ba45SMiklos Szeredi inode->i_mode = attr->mode & S_IFMT; 2089ffbb916SMiklos Szeredi inode->i_size = attr->size; 209e5e5558eSMiklos Szeredi if (S_ISREG(inode->i_mode)) { 210e5e5558eSMiklos Szeredi fuse_init_common(inode); 211b6aeadedSMiklos Szeredi fuse_init_file_inode(inode); 212e5e5558eSMiklos Szeredi } else if (S_ISDIR(inode->i_mode)) 213e5e5558eSMiklos Szeredi fuse_init_dir(inode); 214e5e5558eSMiklos Szeredi else if (S_ISLNK(inode->i_mode)) 215e5e5558eSMiklos Szeredi fuse_init_symlink(inode); 216e5e5558eSMiklos Szeredi else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || 217e5e5558eSMiklos Szeredi S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 218e5e5558eSMiklos Szeredi fuse_init_common(inode); 219e5e5558eSMiklos Szeredi init_special_inode(inode, inode->i_mode, 220e5e5558eSMiklos Szeredi new_decode_dev(attr->rdev)); 22139ee059aSMiklos Szeredi } else 22239ee059aSMiklos Szeredi BUG(); 223d8a5ba45SMiklos Szeredi } 224d8a5ba45SMiklos Szeredi 2253b463ae0SJohn Muir int fuse_inode_eq(struct inode *inode, void *_nodeidp) 226d8a5ba45SMiklos Szeredi { 227b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 228d8a5ba45SMiklos Szeredi if (get_node_id(inode) == nodeid) 229d8a5ba45SMiklos Szeredi return 1; 230d8a5ba45SMiklos Szeredi else 231d8a5ba45SMiklos Szeredi return 0; 232d8a5ba45SMiklos Szeredi } 233d8a5ba45SMiklos Szeredi 234d8a5ba45SMiklos Szeredi static int fuse_inode_set(struct inode *inode, void *_nodeidp) 235d8a5ba45SMiklos Szeredi { 236b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 237d8a5ba45SMiklos Szeredi get_fuse_inode(inode)->nodeid = nodeid; 238d8a5ba45SMiklos Szeredi return 0; 239d8a5ba45SMiklos Szeredi } 240d8a5ba45SMiklos Szeredi 241b48badf0SMiklos Szeredi struct inode *fuse_iget(struct super_block *sb, u64 nodeid, 2421fb69e78SMiklos Szeredi int generation, struct fuse_attr *attr, 2431fb69e78SMiklos Szeredi u64 attr_valid, u64 attr_version) 244d8a5ba45SMiklos Szeredi { 245d8a5ba45SMiklos Szeredi struct inode *inode; 2469e6268dbSMiklos Szeredi struct fuse_inode *fi; 247d8a5ba45SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 248d8a5ba45SMiklos Szeredi 249d8a5ba45SMiklos Szeredi retry: 250d8a5ba45SMiklos Szeredi inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); 251d8a5ba45SMiklos Szeredi if (!inode) 252d8a5ba45SMiklos Szeredi return NULL; 253d8a5ba45SMiklos Szeredi 254d8a5ba45SMiklos Szeredi if ((inode->i_state & I_NEW)) { 255b36c31baSMiklos Szeredi inode->i_flags |= S_NOATIME|S_NOCMTIME; 256d8a5ba45SMiklos Szeredi inode->i_generation = generation; 257d8a5ba45SMiklos Szeredi inode->i_data.backing_dev_info = &fc->bdi; 258d8a5ba45SMiklos Szeredi fuse_init_inode(inode, attr); 259d8a5ba45SMiklos Szeredi unlock_new_inode(inode); 260d8a5ba45SMiklos Szeredi } else if ((inode->i_mode ^ attr->mode) & S_IFMT) { 261d8a5ba45SMiklos Szeredi /* Inode has changed type, any I/O on the old should fail */ 262d8a5ba45SMiklos Szeredi make_bad_inode(inode); 263d8a5ba45SMiklos Szeredi iput(inode); 264d8a5ba45SMiklos Szeredi goto retry; 265d8a5ba45SMiklos Szeredi } 266d8a5ba45SMiklos Szeredi 2679e6268dbSMiklos Szeredi fi = get_fuse_inode(inode); 2688da5ff23SMiklos Szeredi spin_lock(&fc->lock); 2699e6268dbSMiklos Szeredi fi->nlookup++; 2708da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 2711fb69e78SMiklos Szeredi fuse_change_attributes(inode, attr, attr_valid, attr_version); 2721fb69e78SMiklos Szeredi 273d8a5ba45SMiklos Szeredi return inode; 274d8a5ba45SMiklos Szeredi } 275d8a5ba45SMiklos Szeredi 2763b463ae0SJohn Muir int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, 2773b463ae0SJohn Muir loff_t offset, loff_t len) 2783b463ae0SJohn Muir { 2793b463ae0SJohn Muir struct inode *inode; 2803b463ae0SJohn Muir pgoff_t pg_start; 2813b463ae0SJohn Muir pgoff_t pg_end; 2823b463ae0SJohn Muir 2833b463ae0SJohn Muir inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid); 2843b463ae0SJohn Muir if (!inode) 2853b463ae0SJohn Muir return -ENOENT; 2863b463ae0SJohn Muir 2873b463ae0SJohn Muir fuse_invalidate_attr(inode); 2883b463ae0SJohn Muir if (offset >= 0) { 2893b463ae0SJohn Muir pg_start = offset >> PAGE_CACHE_SHIFT; 2903b463ae0SJohn Muir if (len <= 0) 2913b463ae0SJohn Muir pg_end = -1; 2923b463ae0SJohn Muir else 2933b463ae0SJohn Muir pg_end = (offset + len - 1) >> PAGE_CACHE_SHIFT; 2943b463ae0SJohn Muir invalidate_inode_pages2_range(inode->i_mapping, 2953b463ae0SJohn Muir pg_start, pg_end); 2963b463ae0SJohn Muir } 2973b463ae0SJohn Muir iput(inode); 2983b463ae0SJohn Muir return 0; 2993b463ae0SJohn Muir } 3003b463ae0SJohn Muir 30142faad99SAl Viro static void fuse_umount_begin(struct super_block *sb) 30269a53bf2SMiklos Szeredi { 30342faad99SAl Viro fuse_abort_conn(get_fuse_conn_super(sb)); 30469a53bf2SMiklos Szeredi } 30569a53bf2SMiklos Szeredi 3060ec7ca41SMiklos Szeredi static void fuse_send_destroy(struct fuse_conn *fc) 3070ec7ca41SMiklos Szeredi { 3080ec7ca41SMiklos Szeredi struct fuse_req *req = fc->destroy_req; 3090ec7ca41SMiklos Szeredi if (req && fc->conn_init) { 3100ec7ca41SMiklos Szeredi fc->destroy_req = NULL; 3110ec7ca41SMiklos Szeredi req->in.h.opcode = FUSE_DESTROY; 3120ec7ca41SMiklos Szeredi req->force = 1; 313b93f858aSTejun Heo fuse_request_send(fc, req); 3140ec7ca41SMiklos Szeredi fuse_put_request(fc, req); 3150ec7ca41SMiklos Szeredi } 3160ec7ca41SMiklos Szeredi } 3170ec7ca41SMiklos Szeredi 318a325f9b9STejun Heo static void fuse_bdi_destroy(struct fuse_conn *fc) 319d8a5ba45SMiklos Szeredi { 320a325f9b9STejun Heo if (fc->bdi_initialized) 321a325f9b9STejun Heo bdi_destroy(&fc->bdi); 322a325f9b9STejun Heo } 323d8a5ba45SMiklos Szeredi 32408cbf542STejun Heo void fuse_conn_kill(struct fuse_conn *fc) 325a325f9b9STejun Heo { 326d7133114SMiklos Szeredi spin_lock(&fc->lock); 3279ba7cbbaSMiklos Szeredi fc->connected = 0; 32851eb01e7SMiklos Szeredi fc->blocked = 0; 329d7133114SMiklos Szeredi spin_unlock(&fc->lock); 330334f485dSMiklos Szeredi /* Flush all readers on this fs */ 331385a17bfSJeff Dike kill_fasync(&fc->fasync, SIGIO, POLL_IN); 332334f485dSMiklos Szeredi wake_up_all(&fc->waitq); 33351eb01e7SMiklos Szeredi wake_up_all(&fc->blocked_waitq); 334de5e3decSMiklos Szeredi wake_up_all(&fc->reserved_req_waitq); 335bafa9654SMiklos Szeredi mutex_lock(&fuse_mutex); 336bafa9654SMiklos Szeredi list_del(&fc->entry); 337bafa9654SMiklos Szeredi fuse_ctl_remove_conn(fc); 338bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 339a325f9b9STejun Heo fuse_bdi_destroy(fc); 340a325f9b9STejun Heo } 34108cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_kill); 342a325f9b9STejun Heo 343a325f9b9STejun Heo static void fuse_put_super(struct super_block *sb) 344a325f9b9STejun Heo { 345a325f9b9STejun Heo struct fuse_conn *fc = get_fuse_conn_super(sb); 346a325f9b9STejun Heo 347a325f9b9STejun Heo fuse_send_destroy(fc); 348a325f9b9STejun Heo fuse_conn_kill(fc); 349bafa9654SMiklos Szeredi fuse_conn_put(fc); 350d8a5ba45SMiklos Szeredi } 351d8a5ba45SMiklos Szeredi 352e5e5558eSMiklos Szeredi static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 353e5e5558eSMiklos Szeredi { 354e5e5558eSMiklos Szeredi stbuf->f_type = FUSE_SUPER_MAGIC; 355e5e5558eSMiklos Szeredi stbuf->f_bsize = attr->bsize; 356de5f1202SMiklos Szeredi stbuf->f_frsize = attr->frsize; 357e5e5558eSMiklos Szeredi stbuf->f_blocks = attr->blocks; 358e5e5558eSMiklos Szeredi stbuf->f_bfree = attr->bfree; 359e5e5558eSMiklos Szeredi stbuf->f_bavail = attr->bavail; 360e5e5558eSMiklos Szeredi stbuf->f_files = attr->files; 361e5e5558eSMiklos Szeredi stbuf->f_ffree = attr->ffree; 362e5e5558eSMiklos Szeredi stbuf->f_namelen = attr->namelen; 363e5e5558eSMiklos Szeredi /* fsid is left zero */ 364e5e5558eSMiklos Szeredi } 365e5e5558eSMiklos Szeredi 366726c3342SDavid Howells static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) 367e5e5558eSMiklos Szeredi { 368726c3342SDavid Howells struct super_block *sb = dentry->d_sb; 369e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 370e5e5558eSMiklos Szeredi struct fuse_req *req; 371e5e5558eSMiklos Szeredi struct fuse_statfs_out outarg; 372e5e5558eSMiklos Szeredi int err; 373e5e5558eSMiklos Szeredi 374e57ac683SMiklos Szeredi if (!fuse_allow_task(fc, current)) { 375e57ac683SMiklos Szeredi buf->f_type = FUSE_SUPER_MAGIC; 376e57ac683SMiklos Szeredi return 0; 377e57ac683SMiklos Szeredi } 378e57ac683SMiklos Szeredi 379ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 380ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 381ce1d5a49SMiklos Szeredi return PTR_ERR(req); 382e5e5558eSMiklos Szeredi 383de5f1202SMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 384e5e5558eSMiklos Szeredi req->in.numargs = 0; 385e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_STATFS; 3865b35e8e5SMiklos Szeredi req->in.h.nodeid = get_node_id(dentry->d_inode); 387e5e5558eSMiklos Szeredi req->out.numargs = 1; 388de5f1202SMiklos Szeredi req->out.args[0].size = 389de5f1202SMiklos Szeredi fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); 390e5e5558eSMiklos Szeredi req->out.args[0].value = &outarg; 391b93f858aSTejun Heo fuse_request_send(fc, req); 392e5e5558eSMiklos Szeredi err = req->out.h.error; 393e5e5558eSMiklos Szeredi if (!err) 394e5e5558eSMiklos Szeredi convert_fuse_statfs(buf, &outarg.st); 395e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 396e5e5558eSMiklos Szeredi return err; 397e5e5558eSMiklos Szeredi } 398e5e5558eSMiklos Szeredi 399d8a5ba45SMiklos Szeredi enum { 400d8a5ba45SMiklos Szeredi OPT_FD, 401d8a5ba45SMiklos Szeredi OPT_ROOTMODE, 402d8a5ba45SMiklos Szeredi OPT_USER_ID, 40387729a55SMiklos Szeredi OPT_GROUP_ID, 404d8a5ba45SMiklos Szeredi OPT_DEFAULT_PERMISSIONS, 405d8a5ba45SMiklos Szeredi OPT_ALLOW_OTHER, 406db50b96cSMiklos Szeredi OPT_MAX_READ, 407d8091614SMiklos Szeredi OPT_BLKSIZE, 408d8a5ba45SMiklos Szeredi OPT_ERR 409d8a5ba45SMiklos Szeredi }; 410d8a5ba45SMiklos Szeredi 411a447c093SSteven Whitehouse static const match_table_t tokens = { 412d8a5ba45SMiklos Szeredi {OPT_FD, "fd=%u"}, 413d8a5ba45SMiklos Szeredi {OPT_ROOTMODE, "rootmode=%o"}, 414d8a5ba45SMiklos Szeredi {OPT_USER_ID, "user_id=%u"}, 41587729a55SMiklos Szeredi {OPT_GROUP_ID, "group_id=%u"}, 416d8a5ba45SMiklos Szeredi {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, 417d8a5ba45SMiklos Szeredi {OPT_ALLOW_OTHER, "allow_other"}, 418db50b96cSMiklos Szeredi {OPT_MAX_READ, "max_read=%u"}, 419d8091614SMiklos Szeredi {OPT_BLKSIZE, "blksize=%u"}, 420d8a5ba45SMiklos Szeredi {OPT_ERR, NULL} 421d8a5ba45SMiklos Szeredi }; 422d8a5ba45SMiklos Szeredi 423d8091614SMiklos Szeredi static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) 424d8a5ba45SMiklos Szeredi { 425d8a5ba45SMiklos Szeredi char *p; 426d8a5ba45SMiklos Szeredi memset(d, 0, sizeof(struct fuse_mount_data)); 427db50b96cSMiklos Szeredi d->max_read = ~0; 428d1875dbaSMiklos Szeredi d->blksize = FUSE_DEFAULT_BLKSIZE; 429d8a5ba45SMiklos Szeredi 430d8a5ba45SMiklos Szeredi while ((p = strsep(&opt, ",")) != NULL) { 431d8a5ba45SMiklos Szeredi int token; 432d8a5ba45SMiklos Szeredi int value; 433d8a5ba45SMiklos Szeredi substring_t args[MAX_OPT_ARGS]; 434d8a5ba45SMiklos Szeredi if (!*p) 435d8a5ba45SMiklos Szeredi continue; 436d8a5ba45SMiklos Szeredi 437d8a5ba45SMiklos Szeredi token = match_token(p, tokens, args); 438d8a5ba45SMiklos Szeredi switch (token) { 439d8a5ba45SMiklos Szeredi case OPT_FD: 440d8a5ba45SMiklos Szeredi if (match_int(&args[0], &value)) 441d8a5ba45SMiklos Szeredi return 0; 442d8a5ba45SMiklos Szeredi d->fd = value; 4435a533682SMiklos Szeredi d->fd_present = 1; 444d8a5ba45SMiklos Szeredi break; 445d8a5ba45SMiklos Szeredi 446d8a5ba45SMiklos Szeredi case OPT_ROOTMODE: 447d8a5ba45SMiklos Szeredi if (match_octal(&args[0], &value)) 448d8a5ba45SMiklos Szeredi return 0; 449a5bfffacSTimo Savola if (!fuse_valid_type(value)) 450a5bfffacSTimo Savola return 0; 451d8a5ba45SMiklos Szeredi d->rootmode = value; 4525a533682SMiklos Szeredi d->rootmode_present = 1; 453d8a5ba45SMiklos Szeredi break; 454d8a5ba45SMiklos Szeredi 455d8a5ba45SMiklos Szeredi case OPT_USER_ID: 456d8a5ba45SMiklos Szeredi if (match_int(&args[0], &value)) 457d8a5ba45SMiklos Szeredi return 0; 458d8a5ba45SMiklos Szeredi d->user_id = value; 4595a533682SMiklos Szeredi d->user_id_present = 1; 460d8a5ba45SMiklos Szeredi break; 461d8a5ba45SMiklos Szeredi 46287729a55SMiklos Szeredi case OPT_GROUP_ID: 46387729a55SMiklos Szeredi if (match_int(&args[0], &value)) 46487729a55SMiklos Szeredi return 0; 46587729a55SMiklos Szeredi d->group_id = value; 4665a533682SMiklos Szeredi d->group_id_present = 1; 46787729a55SMiklos Szeredi break; 46887729a55SMiklos Szeredi 4691e9a4ed9SMiklos Szeredi case OPT_DEFAULT_PERMISSIONS: 4701e9a4ed9SMiklos Szeredi d->flags |= FUSE_DEFAULT_PERMISSIONS; 4711e9a4ed9SMiklos Szeredi break; 4721e9a4ed9SMiklos Szeredi 4731e9a4ed9SMiklos Szeredi case OPT_ALLOW_OTHER: 4741e9a4ed9SMiklos Szeredi d->flags |= FUSE_ALLOW_OTHER; 4751e9a4ed9SMiklos Szeredi break; 4761e9a4ed9SMiklos Szeredi 477db50b96cSMiklos Szeredi case OPT_MAX_READ: 478db50b96cSMiklos Szeredi if (match_int(&args[0], &value)) 479db50b96cSMiklos Szeredi return 0; 480db50b96cSMiklos Szeredi d->max_read = value; 481db50b96cSMiklos Szeredi break; 482db50b96cSMiklos Szeredi 483d8091614SMiklos Szeredi case OPT_BLKSIZE: 484d8091614SMiklos Szeredi if (!is_bdev || match_int(&args[0], &value)) 485d8091614SMiklos Szeredi return 0; 486d8091614SMiklos Szeredi d->blksize = value; 487d8091614SMiklos Szeredi break; 488d8091614SMiklos Szeredi 489d8a5ba45SMiklos Szeredi default: 490d8a5ba45SMiklos Szeredi return 0; 491d8a5ba45SMiklos Szeredi } 492d8a5ba45SMiklos Szeredi } 4935a533682SMiklos Szeredi 4945a533682SMiklos Szeredi if (!d->fd_present || !d->rootmode_present || 4955a533682SMiklos Szeredi !d->user_id_present || !d->group_id_present) 496d8a5ba45SMiklos Szeredi return 0; 497d8a5ba45SMiklos Szeredi 498d8a5ba45SMiklos Szeredi return 1; 499d8a5ba45SMiklos Szeredi } 500d8a5ba45SMiklos Szeredi 501d8a5ba45SMiklos Szeredi static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) 502d8a5ba45SMiklos Szeredi { 503d8a5ba45SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb); 504d8a5ba45SMiklos Szeredi 505d8a5ba45SMiklos Szeredi seq_printf(m, ",user_id=%u", fc->user_id); 50687729a55SMiklos Szeredi seq_printf(m, ",group_id=%u", fc->group_id); 5071e9a4ed9SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) 5081e9a4ed9SMiklos Szeredi seq_puts(m, ",default_permissions"); 5091e9a4ed9SMiklos Szeredi if (fc->flags & FUSE_ALLOW_OTHER) 5101e9a4ed9SMiklos Szeredi seq_puts(m, ",allow_other"); 511db50b96cSMiklos Szeredi if (fc->max_read != ~0) 512db50b96cSMiklos Szeredi seq_printf(m, ",max_read=%u", fc->max_read); 513d1875dbaSMiklos Szeredi if (mnt->mnt_sb->s_bdev && 514d1875dbaSMiklos Szeredi mnt->mnt_sb->s_blocksize != FUSE_DEFAULT_BLKSIZE) 515d1875dbaSMiklos Szeredi seq_printf(m, ",blksize=%lu", mnt->mnt_sb->s_blocksize); 516d8a5ba45SMiklos Szeredi return 0; 517d8a5ba45SMiklos Szeredi } 518d8a5ba45SMiklos Szeredi 519a325f9b9STejun Heo void fuse_conn_init(struct fuse_conn *fc) 520d8a5ba45SMiklos Szeredi { 5210d179aa5STejun Heo memset(fc, 0, sizeof(*fc)); 522d7133114SMiklos Szeredi spin_lock_init(&fc->lock); 523d2a85164SMiklos Szeredi mutex_init(&fc->inst_mutex); 5243b463ae0SJohn Muir init_rwsem(&fc->killsb); 525bafa9654SMiklos Szeredi atomic_set(&fc->count, 1); 526334f485dSMiklos Szeredi init_waitqueue_head(&fc->waitq); 52708a53cdcSMiklos Szeredi init_waitqueue_head(&fc->blocked_waitq); 528de5e3decSMiklos Szeredi init_waitqueue_head(&fc->reserved_req_waitq); 529334f485dSMiklos Szeredi INIT_LIST_HEAD(&fc->pending); 530334f485dSMiklos Szeredi INIT_LIST_HEAD(&fc->processing); 531d77a1d5bSMiklos Szeredi INIT_LIST_HEAD(&fc->io); 532a4d27e75SMiklos Szeredi INIT_LIST_HEAD(&fc->interrupts); 533d12def1bSMiklos Szeredi INIT_LIST_HEAD(&fc->bg_queue); 5340d179aa5STejun Heo INIT_LIST_HEAD(&fc->entry); 53507e77dcaSMiklos Szeredi fc->forget_list_tail = &fc->forget_list_head; 536095da6cbSMiklos Szeredi atomic_set(&fc->num_waiting, 0); 5377a6d3c8bSCsaba Henk fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; 5387a6d3c8bSCsaba Henk fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; 539acf99433STejun Heo fc->khctr = 0; 54095668a69STejun Heo fc->polled_files = RB_ROOT; 541334f485dSMiklos Szeredi fc->reqctr = 0; 54208a53cdcSMiklos Szeredi fc->blocked = 1; 5431fb69e78SMiklos Szeredi fc->attr_version = 1; 5449c8ef561SMiklos Szeredi get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); 545d8a5ba45SMiklos Szeredi } 5460d179aa5STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_init); 547d8a5ba45SMiklos Szeredi 548bafa9654SMiklos Szeredi void fuse_conn_put(struct fuse_conn *fc) 549bafa9654SMiklos Szeredi { 550d2a85164SMiklos Szeredi if (atomic_dec_and_test(&fc->count)) { 5510ec7ca41SMiklos Szeredi if (fc->destroy_req) 5520ec7ca41SMiklos Szeredi fuse_request_free(fc->destroy_req); 553d2a85164SMiklos Szeredi mutex_destroy(&fc->inst_mutex); 55443901aabSTejun Heo fc->release(fc); 555bafa9654SMiklos Szeredi } 556d2a85164SMiklos Szeredi } 55708cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_put); 558bafa9654SMiklos Szeredi 559bafa9654SMiklos Szeredi struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) 560bafa9654SMiklos Szeredi { 561bafa9654SMiklos Szeredi atomic_inc(&fc->count); 562bafa9654SMiklos Szeredi return fc; 563bafa9654SMiklos Szeredi } 56408cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_get); 565bafa9654SMiklos Szeredi 566b93f858aSTejun Heo static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) 567d8a5ba45SMiklos Szeredi { 568d8a5ba45SMiklos Szeredi struct fuse_attr attr; 569d8a5ba45SMiklos Szeredi memset(&attr, 0, sizeof(attr)); 570d8a5ba45SMiklos Szeredi 571d8a5ba45SMiklos Szeredi attr.mode = mode; 572d8a5ba45SMiklos Szeredi attr.ino = FUSE_ROOT_ID; 573074406faSMiklos Szeredi attr.nlink = 1; 5741fb69e78SMiklos Szeredi return fuse_iget(sb, 1, 0, &attr, 0, 0); 575d8a5ba45SMiklos Szeredi } 576d8a5ba45SMiklos Szeredi 5771729a16cSMiklos Szeredi struct fuse_inode_handle { 578dbd561d2SMiklos Szeredi u64 nodeid; 579dbd561d2SMiklos Szeredi u32 generation; 580dbd561d2SMiklos Szeredi }; 581dbd561d2SMiklos Szeredi 582dbd561d2SMiklos Szeredi static struct dentry *fuse_get_dentry(struct super_block *sb, 583dbd561d2SMiklos Szeredi struct fuse_inode_handle *handle) 584dbd561d2SMiklos Szeredi { 58533670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 586dbd561d2SMiklos Szeredi struct inode *inode; 587dbd561d2SMiklos Szeredi struct dentry *entry; 588dbd561d2SMiklos Szeredi int err = -ESTALE; 589dbd561d2SMiklos Szeredi 590dbd561d2SMiklos Szeredi if (handle->nodeid == 0) 591dbd561d2SMiklos Szeredi goto out_err; 592dbd561d2SMiklos Szeredi 593dbd561d2SMiklos Szeredi inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid); 59433670fa2SMiklos Szeredi if (!inode) { 59533670fa2SMiklos Szeredi struct fuse_entry_out outarg; 59633670fa2SMiklos Szeredi struct qstr name; 59733670fa2SMiklos Szeredi 59833670fa2SMiklos Szeredi if (!fc->export_support) 599dbd561d2SMiklos Szeredi goto out_err; 60033670fa2SMiklos Szeredi 60133670fa2SMiklos Szeredi name.len = 1; 60233670fa2SMiklos Szeredi name.name = "."; 60333670fa2SMiklos Szeredi err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg, 60433670fa2SMiklos Szeredi &inode); 60533670fa2SMiklos Szeredi if (err && err != -ENOENT) 60633670fa2SMiklos Szeredi goto out_err; 60733670fa2SMiklos Szeredi if (err || !inode) { 60833670fa2SMiklos Szeredi err = -ESTALE; 60933670fa2SMiklos Szeredi goto out_err; 61033670fa2SMiklos Szeredi } 61133670fa2SMiklos Szeredi err = -EIO; 61233670fa2SMiklos Szeredi if (get_node_id(inode) != handle->nodeid) 61333670fa2SMiklos Szeredi goto out_iput; 61433670fa2SMiklos Szeredi } 615dbd561d2SMiklos Szeredi err = -ESTALE; 616dbd561d2SMiklos Szeredi if (inode->i_generation != handle->generation) 617dbd561d2SMiklos Szeredi goto out_iput; 618dbd561d2SMiklos Szeredi 61944003728SChristoph Hellwig entry = d_obtain_alias(inode); 620*c35eebe9SAl Viro if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) 621dbd561d2SMiklos Szeredi fuse_invalidate_entry_cache(entry); 622dbd561d2SMiklos Szeredi 623dbd561d2SMiklos Szeredi return entry; 624dbd561d2SMiklos Szeredi 625dbd561d2SMiklos Szeredi out_iput: 626dbd561d2SMiklos Szeredi iput(inode); 627dbd561d2SMiklos Szeredi out_err: 628dbd561d2SMiklos Szeredi return ERR_PTR(err); 629dbd561d2SMiklos Szeredi } 630dbd561d2SMiklos Szeredi 631dbd561d2SMiklos Szeredi static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, 632dbd561d2SMiklos Szeredi int connectable) 633dbd561d2SMiklos Szeredi { 634dbd561d2SMiklos Szeredi struct inode *inode = dentry->d_inode; 635dbd561d2SMiklos Szeredi bool encode_parent = connectable && !S_ISDIR(inode->i_mode); 636dbd561d2SMiklos Szeredi int len = encode_parent ? 6 : 3; 637dbd561d2SMiklos Szeredi u64 nodeid; 638dbd561d2SMiklos Szeredi u32 generation; 639dbd561d2SMiklos Szeredi 640dbd561d2SMiklos Szeredi if (*max_len < len) 641dbd561d2SMiklos Szeredi return 255; 642dbd561d2SMiklos Szeredi 643dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(inode)->nodeid; 644dbd561d2SMiklos Szeredi generation = inode->i_generation; 645dbd561d2SMiklos Szeredi 646dbd561d2SMiklos Szeredi fh[0] = (u32)(nodeid >> 32); 647dbd561d2SMiklos Szeredi fh[1] = (u32)(nodeid & 0xffffffff); 648dbd561d2SMiklos Szeredi fh[2] = generation; 649dbd561d2SMiklos Szeredi 650dbd561d2SMiklos Szeredi if (encode_parent) { 651dbd561d2SMiklos Szeredi struct inode *parent; 652dbd561d2SMiklos Szeredi 653dbd561d2SMiklos Szeredi spin_lock(&dentry->d_lock); 654dbd561d2SMiklos Szeredi parent = dentry->d_parent->d_inode; 655dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(parent)->nodeid; 656dbd561d2SMiklos Szeredi generation = parent->i_generation; 657dbd561d2SMiklos Szeredi spin_unlock(&dentry->d_lock); 658dbd561d2SMiklos Szeredi 659dbd561d2SMiklos Szeredi fh[3] = (u32)(nodeid >> 32); 660dbd561d2SMiklos Szeredi fh[4] = (u32)(nodeid & 0xffffffff); 661dbd561d2SMiklos Szeredi fh[5] = generation; 662dbd561d2SMiklos Szeredi } 663dbd561d2SMiklos Szeredi 664dbd561d2SMiklos Szeredi *max_len = len; 665dbd561d2SMiklos Szeredi return encode_parent ? 0x82 : 0x81; 666dbd561d2SMiklos Szeredi } 667dbd561d2SMiklos Szeredi 668dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_dentry(struct super_block *sb, 669dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 670dbd561d2SMiklos Szeredi { 671dbd561d2SMiklos Szeredi struct fuse_inode_handle handle; 672dbd561d2SMiklos Szeredi 673dbd561d2SMiklos Szeredi if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3) 674dbd561d2SMiklos Szeredi return NULL; 675dbd561d2SMiklos Szeredi 676dbd561d2SMiklos Szeredi handle.nodeid = (u64) fid->raw[0] << 32; 677dbd561d2SMiklos Szeredi handle.nodeid |= (u64) fid->raw[1]; 678dbd561d2SMiklos Szeredi handle.generation = fid->raw[2]; 679dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &handle); 680dbd561d2SMiklos Szeredi } 681dbd561d2SMiklos Szeredi 682dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_parent(struct super_block *sb, 683dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 684dbd561d2SMiklos Szeredi { 685dbd561d2SMiklos Szeredi struct fuse_inode_handle parent; 686dbd561d2SMiklos Szeredi 687dbd561d2SMiklos Szeredi if (fh_type != 0x82 || fh_len < 6) 688dbd561d2SMiklos Szeredi return NULL; 689dbd561d2SMiklos Szeredi 690dbd561d2SMiklos Szeredi parent.nodeid = (u64) fid->raw[3] << 32; 691dbd561d2SMiklos Szeredi parent.nodeid |= (u64) fid->raw[4]; 692dbd561d2SMiklos Szeredi parent.generation = fid->raw[5]; 693dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &parent); 694dbd561d2SMiklos Szeredi } 695dbd561d2SMiklos Szeredi 69633670fa2SMiklos Szeredi static struct dentry *fuse_get_parent(struct dentry *child) 69733670fa2SMiklos Szeredi { 69833670fa2SMiklos Szeredi struct inode *child_inode = child->d_inode; 69933670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(child_inode); 70033670fa2SMiklos Szeredi struct inode *inode; 70133670fa2SMiklos Szeredi struct dentry *parent; 70233670fa2SMiklos Szeredi struct fuse_entry_out outarg; 70333670fa2SMiklos Szeredi struct qstr name; 70433670fa2SMiklos Szeredi int err; 70533670fa2SMiklos Szeredi 70633670fa2SMiklos Szeredi if (!fc->export_support) 70733670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 70833670fa2SMiklos Szeredi 70933670fa2SMiklos Szeredi name.len = 2; 71033670fa2SMiklos Szeredi name.name = ".."; 71133670fa2SMiklos Szeredi err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode), 71233670fa2SMiklos Szeredi &name, &outarg, &inode); 71344003728SChristoph Hellwig if (err) { 71444003728SChristoph Hellwig if (err == -ENOENT) 71533670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 71644003728SChristoph Hellwig return ERR_PTR(err); 71733670fa2SMiklos Szeredi } 71844003728SChristoph Hellwig 71944003728SChristoph Hellwig parent = d_obtain_alias(inode); 720*c35eebe9SAl Viro if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) 72133670fa2SMiklos Szeredi fuse_invalidate_entry_cache(parent); 72233670fa2SMiklos Szeredi 72333670fa2SMiklos Szeredi return parent; 72433670fa2SMiklos Szeredi } 725dbd561d2SMiklos Szeredi 726dbd561d2SMiklos Szeredi static const struct export_operations fuse_export_operations = { 727dbd561d2SMiklos Szeredi .fh_to_dentry = fuse_fh_to_dentry, 728dbd561d2SMiklos Szeredi .fh_to_parent = fuse_fh_to_parent, 729dbd561d2SMiklos Szeredi .encode_fh = fuse_encode_fh, 73033670fa2SMiklos Szeredi .get_parent = fuse_get_parent, 731dbd561d2SMiklos Szeredi }; 732dbd561d2SMiklos Szeredi 733ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations fuse_super_operations = { 734d8a5ba45SMiklos Szeredi .alloc_inode = fuse_alloc_inode, 735d8a5ba45SMiklos Szeredi .destroy_inode = fuse_destroy_inode, 736b57922d9SAl Viro .evict_inode = fuse_evict_inode, 737ead5f0b5SMiklos Szeredi .drop_inode = generic_delete_inode, 73871421259SMiklos Szeredi .remount_fs = fuse_remount_fs, 739d8a5ba45SMiklos Szeredi .put_super = fuse_put_super, 74069a53bf2SMiklos Szeredi .umount_begin = fuse_umount_begin, 741e5e5558eSMiklos Szeredi .statfs = fuse_statfs, 742d8a5ba45SMiklos Szeredi .show_options = fuse_show_options, 743d8a5ba45SMiklos Szeredi }; 744d8a5ba45SMiklos Szeredi 745487ea5afSCsaba Henk static void sanitize_global_limit(unsigned *limit) 746487ea5afSCsaba Henk { 747487ea5afSCsaba Henk if (*limit == 0) 748487ea5afSCsaba Henk *limit = ((num_physpages << PAGE_SHIFT) >> 13) / 749487ea5afSCsaba Henk sizeof(struct fuse_req); 750487ea5afSCsaba Henk 751487ea5afSCsaba Henk if (*limit >= 1 << 16) 752487ea5afSCsaba Henk *limit = (1 << 16) - 1; 753487ea5afSCsaba Henk } 754487ea5afSCsaba Henk 755487ea5afSCsaba Henk static int set_global_limit(const char *val, struct kernel_param *kp) 756487ea5afSCsaba Henk { 757487ea5afSCsaba Henk int rv; 758487ea5afSCsaba Henk 759487ea5afSCsaba Henk rv = param_set_uint(val, kp); 760487ea5afSCsaba Henk if (rv) 761487ea5afSCsaba Henk return rv; 762487ea5afSCsaba Henk 763487ea5afSCsaba Henk sanitize_global_limit((unsigned *)kp->arg); 764487ea5afSCsaba Henk 765487ea5afSCsaba Henk return 0; 766487ea5afSCsaba Henk } 767487ea5afSCsaba Henk 768487ea5afSCsaba Henk static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) 769487ea5afSCsaba Henk { 770487ea5afSCsaba Henk int cap_sys_admin = capable(CAP_SYS_ADMIN); 771487ea5afSCsaba Henk 772487ea5afSCsaba Henk if (arg->minor < 13) 773487ea5afSCsaba Henk return; 774487ea5afSCsaba Henk 775487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 776487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 777487ea5afSCsaba Henk 778487ea5afSCsaba Henk if (arg->max_background) { 779487ea5afSCsaba Henk fc->max_background = arg->max_background; 780487ea5afSCsaba Henk 781487ea5afSCsaba Henk if (!cap_sys_admin && fc->max_background > max_user_bgreq) 782487ea5afSCsaba Henk fc->max_background = max_user_bgreq; 783487ea5afSCsaba Henk } 784487ea5afSCsaba Henk if (arg->congestion_threshold) { 785487ea5afSCsaba Henk fc->congestion_threshold = arg->congestion_threshold; 786487ea5afSCsaba Henk 787487ea5afSCsaba Henk if (!cap_sys_admin && 788487ea5afSCsaba Henk fc->congestion_threshold > max_user_congthresh) 789487ea5afSCsaba Henk fc->congestion_threshold = max_user_congthresh; 790487ea5afSCsaba Henk } 791487ea5afSCsaba Henk } 792487ea5afSCsaba Henk 7939b9a0469SMiklos Szeredi static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) 7949b9a0469SMiklos Szeredi { 7959b9a0469SMiklos Szeredi struct fuse_init_out *arg = &req->misc.init_out; 7969b9a0469SMiklos Szeredi 7979b9a0469SMiklos Szeredi if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) 7989b9a0469SMiklos Szeredi fc->conn_error = 1; 7999b9a0469SMiklos Szeredi else { 8009cd68455SMiklos Szeredi unsigned long ra_pages; 8019cd68455SMiklos Szeredi 802487ea5afSCsaba Henk process_init_limits(fc, arg); 803487ea5afSCsaba Henk 8049cd68455SMiklos Szeredi if (arg->minor >= 6) { 8059cd68455SMiklos Szeredi ra_pages = arg->max_readahead / PAGE_CACHE_SIZE; 8069cd68455SMiklos Szeredi if (arg->flags & FUSE_ASYNC_READ) 8079cd68455SMiklos Szeredi fc->async_read = 1; 80871421259SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 80971421259SMiklos Szeredi fc->no_lock = 1; 8106ff958edSMiklos Szeredi if (arg->flags & FUSE_ATOMIC_O_TRUNC) 8116ff958edSMiklos Szeredi fc->atomic_o_trunc = 1; 81233670fa2SMiklos Szeredi if (arg->minor >= 9) { 81333670fa2SMiklos Szeredi /* LOOKUP has dependency on proto version */ 81433670fa2SMiklos Szeredi if (arg->flags & FUSE_EXPORT_SUPPORT) 81533670fa2SMiklos Szeredi fc->export_support = 1; 81633670fa2SMiklos Szeredi } 81778bb6cb9SMiklos Szeredi if (arg->flags & FUSE_BIG_WRITES) 81878bb6cb9SMiklos Szeredi fc->big_writes = 1; 819e0a43ddcSMiklos Szeredi if (arg->flags & FUSE_DONT_MASK) 820e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 82171421259SMiklos Szeredi } else { 8229cd68455SMiklos Szeredi ra_pages = fc->max_read / PAGE_CACHE_SIZE; 82371421259SMiklos Szeredi fc->no_lock = 1; 82471421259SMiklos Szeredi } 8259cd68455SMiklos Szeredi 8269cd68455SMiklos Szeredi fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); 8279b9a0469SMiklos Szeredi fc->minor = arg->minor; 8289b9a0469SMiklos Szeredi fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 829f948d564SMiklos Szeredi fc->max_write = max_t(unsigned, 4096, fc->max_write); 8300ec7ca41SMiklos Szeredi fc->conn_init = 1; 8319b9a0469SMiklos Szeredi } 83208a53cdcSMiklos Szeredi fc->blocked = 0; 83308a53cdcSMiklos Szeredi wake_up_all(&fc->blocked_waitq); 8349b9a0469SMiklos Szeredi } 8359b9a0469SMiklos Szeredi 836ce1d5a49SMiklos Szeredi static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) 8379b9a0469SMiklos Szeredi { 8389b9a0469SMiklos Szeredi struct fuse_init_in *arg = &req->misc.init_in; 839095da6cbSMiklos Szeredi 8409b9a0469SMiklos Szeredi arg->major = FUSE_KERNEL_VERSION; 8419b9a0469SMiklos Szeredi arg->minor = FUSE_KERNEL_MINOR_VERSION; 8429cd68455SMiklos Szeredi arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; 84378bb6cb9SMiklos Szeredi arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | 844e0a43ddcSMiklos Szeredi FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK; 8459b9a0469SMiklos Szeredi req->in.h.opcode = FUSE_INIT; 8469b9a0469SMiklos Szeredi req->in.numargs = 1; 8479b9a0469SMiklos Szeredi req->in.args[0].size = sizeof(*arg); 8489b9a0469SMiklos Szeredi req->in.args[0].value = arg; 8499b9a0469SMiklos Szeredi req->out.numargs = 1; 8503ad2f3fbSDaniel Mack /* Variable length argument used for backward compatibility 8519b9a0469SMiklos Szeredi with interface version < 7.5. Rest of init_out is zeroed 8529b9a0469SMiklos Szeredi by do_get_request(), so a short reply is not a problem */ 8539b9a0469SMiklos Szeredi req->out.argvar = 1; 8549b9a0469SMiklos Szeredi req->out.args[0].size = sizeof(struct fuse_init_out); 8559b9a0469SMiklos Szeredi req->out.args[0].value = &req->misc.init_out; 8569b9a0469SMiklos Szeredi req->end = process_init_reply; 857b93f858aSTejun Heo fuse_request_send_background(fc, req); 8589b9a0469SMiklos Szeredi } 8599b9a0469SMiklos Szeredi 86043901aabSTejun Heo static void fuse_free_conn(struct fuse_conn *fc) 86143901aabSTejun Heo { 86243901aabSTejun Heo kfree(fc); 86343901aabSTejun Heo } 86443901aabSTejun Heo 865a325f9b9STejun Heo static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) 866a325f9b9STejun Heo { 867a325f9b9STejun Heo int err; 868a325f9b9STejun Heo 869d993831fSJens Axboe fc->bdi.name = "fuse"; 870a325f9b9STejun Heo fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; 871a325f9b9STejun Heo fc->bdi.unplug_io_fn = default_unplug_io_fn; 872a325f9b9STejun Heo /* fuse does it's own writeback accounting */ 873a325f9b9STejun Heo fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; 874a325f9b9STejun Heo 875a325f9b9STejun Heo err = bdi_init(&fc->bdi); 876a325f9b9STejun Heo if (err) 877a325f9b9STejun Heo return err; 878a325f9b9STejun Heo 879a325f9b9STejun Heo fc->bdi_initialized = 1; 880a325f9b9STejun Heo 881a325f9b9STejun Heo if (sb->s_bdev) { 882a325f9b9STejun Heo err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", 883a325f9b9STejun Heo MAJOR(fc->dev), MINOR(fc->dev)); 884a325f9b9STejun Heo } else { 885a325f9b9STejun Heo err = bdi_register_dev(&fc->bdi, fc->dev); 886a325f9b9STejun Heo } 887a325f9b9STejun Heo 888a325f9b9STejun Heo if (err) 889a325f9b9STejun Heo return err; 890a325f9b9STejun Heo 891a325f9b9STejun Heo /* 892a325f9b9STejun Heo * For a single fuse filesystem use max 1% of dirty + 893a325f9b9STejun Heo * writeback threshold. 894a325f9b9STejun Heo * 895a325f9b9STejun Heo * This gives about 1M of write buffer for memory maps on a 896a325f9b9STejun Heo * machine with 1G and 10% dirty_ratio, which should be more 897a325f9b9STejun Heo * than enough. 898a325f9b9STejun Heo * 899a325f9b9STejun Heo * Privileged users can raise it by writing to 900a325f9b9STejun Heo * 901a325f9b9STejun Heo * /sys/class/bdi/<bdi>/max_ratio 902a325f9b9STejun Heo */ 903a325f9b9STejun Heo bdi_set_max_ratio(&fc->bdi, 1); 904a325f9b9STejun Heo 905a325f9b9STejun Heo return 0; 906a325f9b9STejun Heo } 907a325f9b9STejun Heo 908d8a5ba45SMiklos Szeredi static int fuse_fill_super(struct super_block *sb, void *data, int silent) 909d8a5ba45SMiklos Szeredi { 910d8a5ba45SMiklos Szeredi struct fuse_conn *fc; 911d8a5ba45SMiklos Szeredi struct inode *root; 912d8a5ba45SMiklos Szeredi struct fuse_mount_data d; 913d8a5ba45SMiklos Szeredi struct file *file; 914f543f253SMiklos Szeredi struct dentry *root_dentry; 915ce1d5a49SMiklos Szeredi struct fuse_req *init_req; 916d8a5ba45SMiklos Szeredi int err; 917d8091614SMiklos Szeredi int is_bdev = sb->s_bdev != NULL; 918d8a5ba45SMiklos Szeredi 919c2b8f006SMiklos Szeredi err = -EINVAL; 92071421259SMiklos Szeredi if (sb->s_flags & MS_MANDLOCK) 921c2b8f006SMiklos Szeredi goto err; 92271421259SMiklos Szeredi 923d8091614SMiklos Szeredi if (!parse_fuse_opt((char *) data, &d, is_bdev)) 924c2b8f006SMiklos Szeredi goto err; 925d8a5ba45SMiklos Szeredi 926d8091614SMiklos Szeredi if (is_bdev) { 927875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 928c2b8f006SMiklos Szeredi err = -EINVAL; 929d8091614SMiklos Szeredi if (!sb_set_blocksize(sb, d.blksize)) 930c2b8f006SMiklos Szeredi goto err; 931875d95ecSMiklos Szeredi #endif 932d8091614SMiklos Szeredi } else { 933d8a5ba45SMiklos Szeredi sb->s_blocksize = PAGE_CACHE_SIZE; 934d8a5ba45SMiklos Szeredi sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 935d8091614SMiklos Szeredi } 936d8a5ba45SMiklos Szeredi sb->s_magic = FUSE_SUPER_MAGIC; 937d8a5ba45SMiklos Szeredi sb->s_op = &fuse_super_operations; 938d8a5ba45SMiklos Szeredi sb->s_maxbytes = MAX_LFS_FILESIZE; 939dbd561d2SMiklos Szeredi sb->s_export_op = &fuse_export_operations; 940d8a5ba45SMiklos Szeredi 941d8a5ba45SMiklos Szeredi file = fget(d.fd); 942c2b8f006SMiklos Szeredi err = -EINVAL; 943d8a5ba45SMiklos Szeredi if (!file) 944c2b8f006SMiklos Szeredi goto err; 945d8a5ba45SMiklos Szeredi 946c2b8f006SMiklos Szeredi if (file->f_op != &fuse_dev_operations) 947c2b8f006SMiklos Szeredi goto err_fput; 9480720b315SMiklos Szeredi 9490d179aa5STejun Heo fc = kmalloc(sizeof(*fc), GFP_KERNEL); 950c2b8f006SMiklos Szeredi err = -ENOMEM; 951c2b8f006SMiklos Szeredi if (!fc) 952c2b8f006SMiklos Szeredi goto err_fput; 953d8a5ba45SMiklos Szeredi 954a325f9b9STejun Heo fuse_conn_init(fc); 955a325f9b9STejun Heo 956a325f9b9STejun Heo fc->dev = sb->s_dev; 9573b463ae0SJohn Muir fc->sb = sb; 958a325f9b9STejun Heo err = fuse_bdi_init(fc, sb); 959a325f9b9STejun Heo if (err) 960a325f9b9STejun Heo goto err_put_conn; 9610d179aa5STejun Heo 96232a88aa1SJens Axboe sb->s_bdi = &fc->bdi; 96332a88aa1SJens Axboe 964e0a43ddcSMiklos Szeredi /* Handle umasking inside the fuse code */ 965e0a43ddcSMiklos Szeredi if (sb->s_flags & MS_POSIXACL) 966e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 967e0a43ddcSMiklos Szeredi sb->s_flags |= MS_POSIXACL; 968e0a43ddcSMiklos Szeredi 96943901aabSTejun Heo fc->release = fuse_free_conn; 9701e9a4ed9SMiklos Szeredi fc->flags = d.flags; 971d8a5ba45SMiklos Szeredi fc->user_id = d.user_id; 97287729a55SMiklos Szeredi fc->group_id = d.group_id; 973f948d564SMiklos Szeredi fc->max_read = max_t(unsigned, 4096, d.max_read); 974d8a5ba45SMiklos Szeredi 975f543f253SMiklos Szeredi /* Used by get_root_inode() */ 976f543f253SMiklos Szeredi sb->s_fs_info = fc; 977f543f253SMiklos Szeredi 978d8a5ba45SMiklos Szeredi err = -ENOMEM; 979b93f858aSTejun Heo root = fuse_get_root_inode(sb, d.rootmode); 980f543f253SMiklos Szeredi if (!root) 981c2b8f006SMiklos Szeredi goto err_put_conn; 982d8a5ba45SMiklos Szeredi 983f543f253SMiklos Szeredi root_dentry = d_alloc_root(root); 984f543f253SMiklos Szeredi if (!root_dentry) { 985d8a5ba45SMiklos Szeredi iput(root); 986c2b8f006SMiklos Szeredi goto err_put_conn; 987d8a5ba45SMiklos Szeredi } 988*c35eebe9SAl Viro /* only now - we want root dentry with NULL ->d_op */ 989*c35eebe9SAl Viro sb->s_d_op = &fuse_dentry_operations; 990f543f253SMiklos Szeredi 991ce1d5a49SMiklos Szeredi init_req = fuse_request_alloc(); 992ce1d5a49SMiklos Szeredi if (!init_req) 993ce1d5a49SMiklos Szeredi goto err_put_root; 994ce1d5a49SMiklos Szeredi 9950ec7ca41SMiklos Szeredi if (is_bdev) { 9960ec7ca41SMiklos Szeredi fc->destroy_req = fuse_request_alloc(); 9970ec7ca41SMiklos Szeredi if (!fc->destroy_req) 99817e18ab6SJulia Lawall goto err_free_init_req; 9990ec7ca41SMiklos Szeredi } 10000ec7ca41SMiklos Szeredi 1001bafa9654SMiklos Szeredi mutex_lock(&fuse_mutex); 10028aa09a50SMiklos Szeredi err = -EINVAL; 10038aa09a50SMiklos Szeredi if (file->private_data) 1004bafa9654SMiklos Szeredi goto err_unlock; 10058aa09a50SMiklos Szeredi 1006bafa9654SMiklos Szeredi err = fuse_ctl_add_conn(fc); 1007bafa9654SMiklos Szeredi if (err) 1008bafa9654SMiklos Szeredi goto err_unlock; 1009bafa9654SMiklos Szeredi 1010bafa9654SMiklos Szeredi list_add_tail(&fc->entry, &fuse_conn_list); 1011f543f253SMiklos Szeredi sb->s_root = root_dentry; 1012f543f253SMiklos Szeredi fc->connected = 1; 1013bafa9654SMiklos Szeredi file->private_data = fuse_conn_get(fc); 1014bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 10150720b315SMiklos Szeredi /* 10160720b315SMiklos Szeredi * atomic_dec_and_test() in fput() provides the necessary 10170720b315SMiklos Szeredi * memory barrier for file->private_data to be visible on all 10180720b315SMiklos Szeredi * CPUs after this 10190720b315SMiklos Szeredi */ 10200720b315SMiklos Szeredi fput(file); 1021f543f253SMiklos Szeredi 1022ce1d5a49SMiklos Szeredi fuse_send_init(fc, init_req); 1023f543f253SMiklos Szeredi 1024d8a5ba45SMiklos Szeredi return 0; 1025d8a5ba45SMiklos Szeredi 1026bafa9654SMiklos Szeredi err_unlock: 1027bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 102817e18ab6SJulia Lawall err_free_init_req: 1029ce1d5a49SMiklos Szeredi fuse_request_free(init_req); 1030f543f253SMiklos Szeredi err_put_root: 1031f543f253SMiklos Szeredi dput(root_dentry); 1032c2b8f006SMiklos Szeredi err_put_conn: 1033a325f9b9STejun Heo fuse_bdi_destroy(fc); 1034bafa9654SMiklos Szeredi fuse_conn_put(fc); 1035c2b8f006SMiklos Szeredi err_fput: 1036c2b8f006SMiklos Szeredi fput(file); 1037c2b8f006SMiklos Szeredi err: 1038d8a5ba45SMiklos Szeredi return err; 1039d8a5ba45SMiklos Szeredi } 1040d8a5ba45SMiklos Szeredi 10413c26ff6eSAl Viro static struct dentry *fuse_mount(struct file_system_type *fs_type, 1042d8a5ba45SMiklos Szeredi int flags, const char *dev_name, 10433c26ff6eSAl Viro void *raw_data) 1044d8a5ba45SMiklos Szeredi { 10453c26ff6eSAl Viro return mount_nodev(fs_type, flags, raw_data, fuse_fill_super); 1046d8a5ba45SMiklos Szeredi } 1047d8a5ba45SMiklos Szeredi 10483b463ae0SJohn Muir static void fuse_kill_sb_anon(struct super_block *sb) 10493b463ae0SJohn Muir { 10503b463ae0SJohn Muir struct fuse_conn *fc = get_fuse_conn_super(sb); 10513b463ae0SJohn Muir 10523b463ae0SJohn Muir if (fc) { 10533b463ae0SJohn Muir down_write(&fc->killsb); 10543b463ae0SJohn Muir fc->sb = NULL; 10553b463ae0SJohn Muir up_write(&fc->killsb); 10563b463ae0SJohn Muir } 10573b463ae0SJohn Muir 10583b463ae0SJohn Muir kill_anon_super(sb); 10593b463ae0SJohn Muir } 10603b463ae0SJohn Muir 1061875d95ecSMiklos Szeredi static struct file_system_type fuse_fs_type = { 1062875d95ecSMiklos Szeredi .owner = THIS_MODULE, 1063875d95ecSMiklos Szeredi .name = "fuse", 106479c0b2dfSMiklos Szeredi .fs_flags = FS_HAS_SUBTYPE, 10653c26ff6eSAl Viro .mount = fuse_mount, 10663b463ae0SJohn Muir .kill_sb = fuse_kill_sb_anon, 1067875d95ecSMiklos Szeredi }; 1068875d95ecSMiklos Szeredi 1069875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 1070152a0836SAl Viro static struct dentry *fuse_mount_blk(struct file_system_type *fs_type, 1071d6392f87SMiklos Szeredi int flags, const char *dev_name, 1072152a0836SAl Viro void *raw_data) 1073d6392f87SMiklos Szeredi { 1074152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, raw_data, fuse_fill_super); 1075d6392f87SMiklos Szeredi } 1076d6392f87SMiklos Szeredi 10773b463ae0SJohn Muir static void fuse_kill_sb_blk(struct super_block *sb) 10783b463ae0SJohn Muir { 10793b463ae0SJohn Muir struct fuse_conn *fc = get_fuse_conn_super(sb); 10803b463ae0SJohn Muir 10813b463ae0SJohn Muir if (fc) { 10823b463ae0SJohn Muir down_write(&fc->killsb); 10833b463ae0SJohn Muir fc->sb = NULL; 10843b463ae0SJohn Muir up_write(&fc->killsb); 10853b463ae0SJohn Muir } 10863b463ae0SJohn Muir 10873b463ae0SJohn Muir kill_block_super(sb); 10883b463ae0SJohn Muir } 10893b463ae0SJohn Muir 1090d6392f87SMiklos Szeredi static struct file_system_type fuseblk_fs_type = { 1091d6392f87SMiklos Szeredi .owner = THIS_MODULE, 1092d6392f87SMiklos Szeredi .name = "fuseblk", 1093152a0836SAl Viro .mount = fuse_mount_blk, 10943b463ae0SJohn Muir .kill_sb = fuse_kill_sb_blk, 1095edad01e2SAlexey Dobriyan .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, 1096d6392f87SMiklos Szeredi }; 1097d6392f87SMiklos Szeredi 1098875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1099875d95ecSMiklos Szeredi { 1100875d95ecSMiklos Szeredi return register_filesystem(&fuseblk_fs_type); 1101875d95ecSMiklos Szeredi } 1102875d95ecSMiklos Szeredi 1103875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1104875d95ecSMiklos Szeredi { 1105875d95ecSMiklos Szeredi unregister_filesystem(&fuseblk_fs_type); 1106875d95ecSMiklos Szeredi } 1107875d95ecSMiklos Szeredi #else 1108875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1109875d95ecSMiklos Szeredi { 1110875d95ecSMiklos Szeredi return 0; 1111875d95ecSMiklos Szeredi } 1112875d95ecSMiklos Szeredi 1113875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1114875d95ecSMiklos Szeredi { 1115875d95ecSMiklos Szeredi } 1116875d95ecSMiklos Szeredi #endif 1117875d95ecSMiklos Szeredi 111851cc5068SAlexey Dobriyan static void fuse_inode_init_once(void *foo) 1119d8a5ba45SMiklos Szeredi { 1120d8a5ba45SMiklos Szeredi struct inode *inode = foo; 1121d8a5ba45SMiklos Szeredi 1122d8a5ba45SMiklos Szeredi inode_init_once(inode); 1123d8a5ba45SMiklos Szeredi } 1124d8a5ba45SMiklos Szeredi 1125d8a5ba45SMiklos Szeredi static int __init fuse_fs_init(void) 1126d8a5ba45SMiklos Szeredi { 1127d8a5ba45SMiklos Szeredi int err; 1128d8a5ba45SMiklos Szeredi 1129d8a5ba45SMiklos Szeredi err = register_filesystem(&fuse_fs_type); 1130d8a5ba45SMiklos Szeredi if (err) 1131d6392f87SMiklos Szeredi goto out; 1132d6392f87SMiklos Szeredi 1133875d95ecSMiklos Szeredi err = register_fuseblk(); 1134d6392f87SMiklos Szeredi if (err) 1135d6392f87SMiklos Szeredi goto out_unreg; 1136d6392f87SMiklos Szeredi 1137d8a5ba45SMiklos Szeredi fuse_inode_cachep = kmem_cache_create("fuse_inode", 1138d8a5ba45SMiklos Szeredi sizeof(struct fuse_inode), 1139d8a5ba45SMiklos Szeredi 0, SLAB_HWCACHE_ALIGN, 114020c2df83SPaul Mundt fuse_inode_init_once); 1141d8a5ba45SMiklos Szeredi err = -ENOMEM; 1142d6392f87SMiklos Szeredi if (!fuse_inode_cachep) 1143d6392f87SMiklos Szeredi goto out_unreg2; 1144d8a5ba45SMiklos Szeredi 1145d6392f87SMiklos Szeredi return 0; 1146d6392f87SMiklos Szeredi 1147d6392f87SMiklos Szeredi out_unreg2: 1148875d95ecSMiklos Szeredi unregister_fuseblk(); 1149d6392f87SMiklos Szeredi out_unreg: 1150d6392f87SMiklos Szeredi unregister_filesystem(&fuse_fs_type); 1151d6392f87SMiklos Szeredi out: 1152d8a5ba45SMiklos Szeredi return err; 1153d8a5ba45SMiklos Szeredi } 1154d8a5ba45SMiklos Szeredi 1155d8a5ba45SMiklos Szeredi static void fuse_fs_cleanup(void) 1156d8a5ba45SMiklos Szeredi { 1157d8a5ba45SMiklos Szeredi unregister_filesystem(&fuse_fs_type); 1158875d95ecSMiklos Szeredi unregister_fuseblk(); 1159d8a5ba45SMiklos Szeredi kmem_cache_destroy(fuse_inode_cachep); 1160d8a5ba45SMiklos Szeredi } 1161d8a5ba45SMiklos Szeredi 11625c89e17eSGreg Kroah-Hartman static struct kobject *fuse_kobj; 11635c89e17eSGreg Kroah-Hartman static struct kobject *connections_kobj; 11645c89e17eSGreg Kroah-Hartman 1165f543f253SMiklos Szeredi static int fuse_sysfs_init(void) 1166f543f253SMiklos Szeredi { 1167f543f253SMiklos Szeredi int err; 1168f543f253SMiklos Szeredi 116900d26666SGreg Kroah-Hartman fuse_kobj = kobject_create_and_add("fuse", fs_kobj); 11705c89e17eSGreg Kroah-Hartman if (!fuse_kobj) { 11715c89e17eSGreg Kroah-Hartman err = -ENOMEM; 1172f543f253SMiklos Szeredi goto out_err; 11735c89e17eSGreg Kroah-Hartman } 1174f543f253SMiklos Szeredi 11755c89e17eSGreg Kroah-Hartman connections_kobj = kobject_create_and_add("connections", fuse_kobj); 11765c89e17eSGreg Kroah-Hartman if (!connections_kobj) { 11775c89e17eSGreg Kroah-Hartman err = -ENOMEM; 1178f543f253SMiklos Szeredi goto out_fuse_unregister; 11795c89e17eSGreg Kroah-Hartman } 1180f543f253SMiklos Szeredi 1181f543f253SMiklos Szeredi return 0; 1182f543f253SMiklos Szeredi 1183f543f253SMiklos Szeredi out_fuse_unregister: 1184197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1185f543f253SMiklos Szeredi out_err: 1186f543f253SMiklos Szeredi return err; 1187f543f253SMiklos Szeredi } 1188f543f253SMiklos Szeredi 1189f543f253SMiklos Szeredi static void fuse_sysfs_cleanup(void) 1190f543f253SMiklos Szeredi { 1191197b12d6SGreg Kroah-Hartman kobject_put(connections_kobj); 1192197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1193f543f253SMiklos Szeredi } 1194f543f253SMiklos Szeredi 1195d8a5ba45SMiklos Szeredi static int __init fuse_init(void) 1196d8a5ba45SMiklos Szeredi { 1197d8a5ba45SMiklos Szeredi int res; 1198d8a5ba45SMiklos Szeredi 11991729a16cSMiklos Szeredi printk(KERN_INFO "fuse init (API version %i.%i)\n", 1200d8a5ba45SMiklos Szeredi FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); 1201d8a5ba45SMiklos Szeredi 1202bafa9654SMiklos Szeredi INIT_LIST_HEAD(&fuse_conn_list); 1203d8a5ba45SMiklos Szeredi res = fuse_fs_init(); 1204d8a5ba45SMiklos Szeredi if (res) 1205d8a5ba45SMiklos Szeredi goto err; 1206d8a5ba45SMiklos Szeredi 1207334f485dSMiklos Szeredi res = fuse_dev_init(); 1208334f485dSMiklos Szeredi if (res) 1209334f485dSMiklos Szeredi goto err_fs_cleanup; 1210334f485dSMiklos Szeredi 1211f543f253SMiklos Szeredi res = fuse_sysfs_init(); 1212f543f253SMiklos Szeredi if (res) 1213f543f253SMiklos Szeredi goto err_dev_cleanup; 1214f543f253SMiklos Szeredi 1215bafa9654SMiklos Szeredi res = fuse_ctl_init(); 1216bafa9654SMiklos Szeredi if (res) 1217bafa9654SMiklos Szeredi goto err_sysfs_cleanup; 1218bafa9654SMiklos Szeredi 1219487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 1220487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 1221487ea5afSCsaba Henk 1222d8a5ba45SMiklos Szeredi return 0; 1223d8a5ba45SMiklos Szeredi 1224bafa9654SMiklos Szeredi err_sysfs_cleanup: 1225bafa9654SMiklos Szeredi fuse_sysfs_cleanup(); 1226f543f253SMiklos Szeredi err_dev_cleanup: 1227f543f253SMiklos Szeredi fuse_dev_cleanup(); 1228334f485dSMiklos Szeredi err_fs_cleanup: 1229334f485dSMiklos Szeredi fuse_fs_cleanup(); 1230d8a5ba45SMiklos Szeredi err: 1231d8a5ba45SMiklos Szeredi return res; 1232d8a5ba45SMiklos Szeredi } 1233d8a5ba45SMiklos Szeredi 1234d8a5ba45SMiklos Szeredi static void __exit fuse_exit(void) 1235d8a5ba45SMiklos Szeredi { 1236d8a5ba45SMiklos Szeredi printk(KERN_DEBUG "fuse exit\n"); 1237d8a5ba45SMiklos Szeredi 1238bafa9654SMiklos Szeredi fuse_ctl_cleanup(); 1239f543f253SMiklos Szeredi fuse_sysfs_cleanup(); 1240d8a5ba45SMiklos Szeredi fuse_fs_cleanup(); 1241334f485dSMiklos Szeredi fuse_dev_cleanup(); 1242d8a5ba45SMiklos Szeredi } 1243d8a5ba45SMiklos Szeredi 1244d8a5ba45SMiklos Szeredi module_init(fuse_init); 1245d8a5ba45SMiklos Szeredi module_exit(fuse_exit); 1246