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> 2360bcc88aSSeth Forshee #include <linux/posix_acl.h> 240b6e9ea0SSeth Forshee #include <linux/pid_namespace.h> 25d8a5ba45SMiklos Szeredi 26d8a5ba45SMiklos Szeredi MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); 27d8a5ba45SMiklos Szeredi MODULE_DESCRIPTION("Filesystem in Userspace"); 28d8a5ba45SMiklos Szeredi MODULE_LICENSE("GPL"); 29d8a5ba45SMiklos Szeredi 30e18b890bSChristoph Lameter static struct kmem_cache *fuse_inode_cachep; 31bafa9654SMiklos Szeredi struct list_head fuse_conn_list; 32bafa9654SMiklos Szeredi DEFINE_MUTEX(fuse_mutex); 33d8a5ba45SMiklos Szeredi 34e4dca7b7SKees Cook static int set_global_limit(const char *val, const struct kernel_param *kp); 35487ea5afSCsaba Henk 3679a9d994SCsaba Henk unsigned max_user_bgreq; 37487ea5afSCsaba Henk module_param_call(max_user_bgreq, set_global_limit, param_get_uint, 38487ea5afSCsaba Henk &max_user_bgreq, 0644); 39487ea5afSCsaba Henk __MODULE_PARM_TYPE(max_user_bgreq, "uint"); 40487ea5afSCsaba Henk MODULE_PARM_DESC(max_user_bgreq, 41487ea5afSCsaba Henk "Global limit for the maximum number of backgrounded requests an " 42487ea5afSCsaba Henk "unprivileged user can set"); 43487ea5afSCsaba Henk 4479a9d994SCsaba Henk unsigned max_user_congthresh; 45487ea5afSCsaba Henk module_param_call(max_user_congthresh, set_global_limit, param_get_uint, 46487ea5afSCsaba Henk &max_user_congthresh, 0644); 47487ea5afSCsaba Henk __MODULE_PARM_TYPE(max_user_congthresh, "uint"); 48487ea5afSCsaba Henk MODULE_PARM_DESC(max_user_congthresh, 49487ea5afSCsaba Henk "Global limit for the maximum congestion threshold an " 50487ea5afSCsaba Henk "unprivileged user can set"); 51487ea5afSCsaba Henk 52d8a5ba45SMiklos Szeredi #define FUSE_SUPER_MAGIC 0x65735546 53d8a5ba45SMiklos Szeredi 54d1875dbaSMiklos Szeredi #define FUSE_DEFAULT_BLKSIZE 512 55d1875dbaSMiklos Szeredi 567a6d3c8bSCsaba Henk /** Maximum number of outstanding background requests */ 577a6d3c8bSCsaba Henk #define FUSE_DEFAULT_MAX_BACKGROUND 12 587a6d3c8bSCsaba Henk 597a6d3c8bSCsaba Henk /** Congestion starts at 75% of maximum */ 607a6d3c8bSCsaba Henk #define FUSE_DEFAULT_CONGESTION_THRESHOLD (FUSE_DEFAULT_MAX_BACKGROUND * 3 / 4) 617a6d3c8bSCsaba Henk 62d8a5ba45SMiklos Szeredi struct fuse_mount_data { 63d8a5ba45SMiklos Szeredi int fd; 64d8a5ba45SMiklos Szeredi unsigned rootmode; 65499dcf20SEric W. Biederman kuid_t user_id; 66499dcf20SEric W. Biederman kgid_t group_id; 675a533682SMiklos Szeredi unsigned fd_present:1; 685a533682SMiklos Szeredi unsigned rootmode_present:1; 695a533682SMiklos Szeredi unsigned user_id_present:1; 705a533682SMiklos Szeredi unsigned group_id_present:1; 7129433a29SMiklos Szeredi unsigned default_permissions:1; 7229433a29SMiklos Szeredi unsigned allow_other:1; 73db50b96cSMiklos Szeredi unsigned max_read; 74d8091614SMiklos Szeredi unsigned blksize; 75d8a5ba45SMiklos Szeredi }; 76d8a5ba45SMiklos Szeredi 77a2daff68SRandy Dunlap struct fuse_forget_link *fuse_alloc_forget(void) 7807e77dcaSMiklos Szeredi { 7907e77dcaSMiklos Szeredi return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); 8007e77dcaSMiklos Szeredi } 8107e77dcaSMiklos Szeredi 82d8a5ba45SMiklos Szeredi static struct inode *fuse_alloc_inode(struct super_block *sb) 83d8a5ba45SMiklos Szeredi { 84d8a5ba45SMiklos Szeredi struct inode *inode; 85d8a5ba45SMiklos Szeredi struct fuse_inode *fi; 86d8a5ba45SMiklos Szeredi 87e94b1766SChristoph Lameter inode = kmem_cache_alloc(fuse_inode_cachep, GFP_KERNEL); 88d8a5ba45SMiklos Szeredi if (!inode) 89d8a5ba45SMiklos Szeredi return NULL; 90d8a5ba45SMiklos Szeredi 91d8a5ba45SMiklos Szeredi fi = get_fuse_inode(inode); 920a0898cfSMiklos Szeredi fi->i_time = 0; 932f1e8196SMiklos Szeredi fi->inval_mask = 0; 94d8a5ba45SMiklos Szeredi fi->nodeid = 0; 959e6268dbSMiklos Szeredi fi->nlookup = 0; 96fbee36b9SJohn Muir fi->attr_version = 0; 9745c72cd7SPavel Shilovsky fi->orig_ino = 0; 984582a4abSFeng Shuo fi->state = 0; 995c672ab3SMiklos Szeredi mutex_init(&fi->mutex); 10007e77dcaSMiklos Szeredi fi->forget = fuse_alloc_forget(); 10107e77dcaSMiklos Szeredi if (!fi->forget) { 102e5e5558eSMiklos Szeredi kmem_cache_free(fuse_inode_cachep, inode); 103e5e5558eSMiklos Szeredi return NULL; 104e5e5558eSMiklos Szeredi } 105d8a5ba45SMiklos Szeredi 106d8a5ba45SMiklos Szeredi return inode; 107d8a5ba45SMiklos Szeredi } 108d8a5ba45SMiklos Szeredi 109fa0d7e3dSNick Piggin static void fuse_i_callback(struct rcu_head *head) 110fa0d7e3dSNick Piggin { 111fa0d7e3dSNick Piggin struct inode *inode = container_of(head, struct inode, i_rcu); 112fa0d7e3dSNick Piggin kmem_cache_free(fuse_inode_cachep, inode); 113fa0d7e3dSNick Piggin } 114fa0d7e3dSNick Piggin 115d8a5ba45SMiklos Szeredi static void fuse_destroy_inode(struct inode *inode) 116d8a5ba45SMiklos Szeredi { 117e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1184fc4bb79SMyungho Jung if (S_ISREG(inode->i_mode) && !is_bad_inode(inode)) { 119ab2257e9SMiklos Szeredi WARN_ON(!list_empty(&fi->write_files)); 120ab2257e9SMiklos Szeredi WARN_ON(!list_empty(&fi->queued_writes)); 121ab2257e9SMiklos Szeredi } 1225c672ab3SMiklos Szeredi mutex_destroy(&fi->mutex); 12307e77dcaSMiklos Szeredi kfree(fi->forget); 124fa0d7e3dSNick Piggin call_rcu(&inode->i_rcu, fuse_i_callback); 125d8a5ba45SMiklos Szeredi } 126d8a5ba45SMiklos Szeredi 127b57922d9SAl Viro static void fuse_evict_inode(struct inode *inode) 128d8a5ba45SMiklos Szeredi { 12991b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data); 130dbd5768fSJan Kara clear_inode(inode); 1311751e8a6SLinus Torvalds if (inode->i_sb->s_flags & SB_ACTIVE) { 132e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 133e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 13407e77dcaSMiklos Szeredi fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup); 13507e77dcaSMiklos Szeredi fi->forget = NULL; 136e5e5558eSMiklos Szeredi } 137d8a5ba45SMiklos Szeredi } 138d8a5ba45SMiklos Szeredi 13971421259SMiklos Szeredi static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) 14071421259SMiklos Szeredi { 14102b9984dSTheodore Ts'o sync_filesystem(sb); 1421751e8a6SLinus Torvalds if (*flags & SB_MANDLOCK) 14371421259SMiklos Szeredi return -EINVAL; 14471421259SMiklos Szeredi 14571421259SMiklos Szeredi return 0; 14671421259SMiklos Szeredi } 14771421259SMiklos Szeredi 14845c72cd7SPavel Shilovsky /* 14945c72cd7SPavel Shilovsky * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down 15045c72cd7SPavel Shilovsky * so that it will fit. 15145c72cd7SPavel Shilovsky */ 15245c72cd7SPavel Shilovsky static ino_t fuse_squash_ino(u64 ino64) 15345c72cd7SPavel Shilovsky { 15445c72cd7SPavel Shilovsky ino_t ino = (ino_t) ino64; 15545c72cd7SPavel Shilovsky if (sizeof(ino_t) < sizeof(u64)) 15645c72cd7SPavel Shilovsky ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8; 15745c72cd7SPavel Shilovsky return ino; 15845c72cd7SPavel Shilovsky } 15945c72cd7SPavel Shilovsky 1603be5a52bSMiklos Szeredi void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 1613be5a52bSMiklos Szeredi u64 attr_valid) 162d8a5ba45SMiklos Szeredi { 1639ffbb916SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 164ebc14c4dSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 165d8a5ba45SMiklos Szeredi 1661fb69e78SMiklos Szeredi fi->attr_version = ++fc->attr_version; 1671fb69e78SMiklos Szeredi fi->i_time = attr_valid; 1682f1e8196SMiklos Szeredi WRITE_ONCE(fi->inval_mask, 0); 1691fb69e78SMiklos Szeredi 17045c72cd7SPavel Shilovsky inode->i_ino = fuse_squash_ino(attr->ino); 171ebc14c4dSMiklos Szeredi inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 172bfe86848SMiklos Szeredi set_nlink(inode, attr->nlink); 1738cb08329SEric W. Biederman inode->i_uid = make_kuid(fc->user_ns, attr->uid); 1748cb08329SEric W. Biederman inode->i_gid = make_kgid(fc->user_ns, attr->gid); 175d8a5ba45SMiklos Szeredi inode->i_blocks = attr->blocks; 176d8a5ba45SMiklos Szeredi inode->i_atime.tv_sec = attr->atime; 177d8a5ba45SMiklos Szeredi inode->i_atime.tv_nsec = attr->atimensec; 178b0aa7606SMaxim Patlasov /* mtime from server may be stale due to local buffered write */ 179b0aa7606SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) { 180d8a5ba45SMiklos Szeredi inode->i_mtime.tv_sec = attr->mtime; 181d8a5ba45SMiklos Szeredi inode->i_mtime.tv_nsec = attr->mtimensec; 182d8a5ba45SMiklos Szeredi inode->i_ctime.tv_sec = attr->ctime; 183d8a5ba45SMiklos Szeredi inode->i_ctime.tv_nsec = attr->ctimensec; 18431f3267bSMaxim Patlasov } 185e00d2c2dSMiklos Szeredi 1860e9663eeSMiklos Szeredi if (attr->blksize != 0) 1870e9663eeSMiklos Szeredi inode->i_blkbits = ilog2(attr->blksize); 1880e9663eeSMiklos Szeredi else 1890e9663eeSMiklos Szeredi inode->i_blkbits = inode->i_sb->s_blocksize_bits; 1900e9663eeSMiklos Szeredi 191ebc14c4dSMiklos Szeredi /* 192ebc14c4dSMiklos Szeredi * Don't set the sticky bit in i_mode, unless we want the VFS 193ebc14c4dSMiklos Szeredi * to check permissions. This prevents failures due to the 194ebc14c4dSMiklos Szeredi * check in may_delete(). 195ebc14c4dSMiklos Szeredi */ 196ebc14c4dSMiklos Szeredi fi->orig_i_mode = inode->i_mode; 19729433a29SMiklos Szeredi if (!fc->default_permissions) 198ebc14c4dSMiklos Szeredi inode->i_mode &= ~S_ISVTX; 19945c72cd7SPavel Shilovsky 20045c72cd7SPavel Shilovsky fi->orig_ino = attr->ino; 2013be5a52bSMiklos Szeredi } 2023be5a52bSMiklos Szeredi 2033be5a52bSMiklos Szeredi void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, 2043be5a52bSMiklos Szeredi u64 attr_valid, u64 attr_version) 2053be5a52bSMiklos Szeredi { 2063be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 2073be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 2088373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 2093be5a52bSMiklos Szeredi loff_t oldsize; 210a64ba10fSArnd Bergmann struct timespec64 old_mtime; 2113be5a52bSMiklos Szeredi 2123be5a52bSMiklos Szeredi spin_lock(&fc->lock); 21306a7c3c2SMaxim Patlasov if ((attr_version != 0 && fi->attr_version > attr_version) || 21406a7c3c2SMaxim Patlasov test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { 2153be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 2163be5a52bSMiklos Szeredi return; 2173be5a52bSMiklos Szeredi } 2183be5a52bSMiklos Szeredi 219a64ba10fSArnd Bergmann old_mtime = inode->i_mtime; 2203be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, attr, attr_valid); 221ebc14c4dSMiklos Szeredi 222e00d2c2dSMiklos Szeredi oldsize = inode->i_size; 2238373200bSPavel Emelyanov /* 2248373200bSPavel Emelyanov * In case of writeback_cache enabled, the cached writes beyond EOF 2258373200bSPavel Emelyanov * extend local i_size without keeping userspace server in sync. So, 2268373200bSPavel Emelyanov * attr->size coming from server can be stale. We cannot trust it. 2278373200bSPavel Emelyanov */ 2288373200bSPavel Emelyanov if (!is_wb || !S_ISREG(inode->i_mode)) 229e00d2c2dSMiklos Szeredi i_size_write(inode, attr->size); 230e00d2c2dSMiklos Szeredi spin_unlock(&fc->lock); 231e00d2c2dSMiklos Szeredi 2328373200bSPavel Emelyanov if (!is_wb && S_ISREG(inode->i_mode)) { 233eed2179eSBrian Foster bool inval = false; 234eed2179eSBrian Foster 235eed2179eSBrian Foster if (oldsize != attr->size) { 2367caef267SKirill A. Shutemov truncate_pagecache(inode, attr->size); 237eed2179eSBrian Foster inval = true; 238eed2179eSBrian Foster } else if (fc->auto_inval_data) { 239a64ba10fSArnd Bergmann struct timespec64 new_mtime = { 240eed2179eSBrian Foster .tv_sec = attr->mtime, 241eed2179eSBrian Foster .tv_nsec = attr->mtimensec, 242eed2179eSBrian Foster }; 243eed2179eSBrian Foster 244eed2179eSBrian Foster /* 245eed2179eSBrian Foster * Auto inval mode also checks and invalidates if mtime 246eed2179eSBrian Foster * has changed. 247eed2179eSBrian Foster */ 248a64ba10fSArnd Bergmann if (!timespec64_equal(&old_mtime, &new_mtime)) 249eed2179eSBrian Foster inval = true; 250eed2179eSBrian Foster } 251eed2179eSBrian Foster 252eed2179eSBrian Foster if (inval) 253b1009979SMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 254e00d2c2dSMiklos Szeredi } 255d8a5ba45SMiklos Szeredi } 256d8a5ba45SMiklos Szeredi 257d8a5ba45SMiklos Szeredi static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) 258d8a5ba45SMiklos Szeredi { 259d8a5ba45SMiklos Szeredi inode->i_mode = attr->mode & S_IFMT; 2609ffbb916SMiklos Szeredi inode->i_size = attr->size; 261b0aa7606SMaxim Patlasov inode->i_mtime.tv_sec = attr->mtime; 262b0aa7606SMaxim Patlasov inode->i_mtime.tv_nsec = attr->mtimensec; 26331f3267bSMaxim Patlasov inode->i_ctime.tv_sec = attr->ctime; 26431f3267bSMaxim Patlasov inode->i_ctime.tv_nsec = attr->ctimensec; 265e5e5558eSMiklos Szeredi if (S_ISREG(inode->i_mode)) { 266e5e5558eSMiklos Szeredi fuse_init_common(inode); 267b6aeadedSMiklos Szeredi fuse_init_file_inode(inode); 268e5e5558eSMiklos Szeredi } else if (S_ISDIR(inode->i_mode)) 269e5e5558eSMiklos Szeredi fuse_init_dir(inode); 270e5e5558eSMiklos Szeredi else if (S_ISLNK(inode->i_mode)) 271e5e5558eSMiklos Szeredi fuse_init_symlink(inode); 272e5e5558eSMiklos Szeredi else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || 273e5e5558eSMiklos Szeredi S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 274e5e5558eSMiklos Szeredi fuse_init_common(inode); 275e5e5558eSMiklos Szeredi init_special_inode(inode, inode->i_mode, 276e5e5558eSMiklos Szeredi new_decode_dev(attr->rdev)); 27739ee059aSMiklos Szeredi } else 27839ee059aSMiklos Szeredi BUG(); 279d8a5ba45SMiklos Szeredi } 280d8a5ba45SMiklos Szeredi 2813b463ae0SJohn Muir int fuse_inode_eq(struct inode *inode, void *_nodeidp) 282d8a5ba45SMiklos Szeredi { 283b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 284d8a5ba45SMiklos Szeredi if (get_node_id(inode) == nodeid) 285d8a5ba45SMiklos Szeredi return 1; 286d8a5ba45SMiklos Szeredi else 287d8a5ba45SMiklos Szeredi return 0; 288d8a5ba45SMiklos Szeredi } 289d8a5ba45SMiklos Szeredi 290d8a5ba45SMiklos Szeredi static int fuse_inode_set(struct inode *inode, void *_nodeidp) 291d8a5ba45SMiklos Szeredi { 292b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 293d8a5ba45SMiklos Szeredi get_fuse_inode(inode)->nodeid = nodeid; 294d8a5ba45SMiklos Szeredi return 0; 295d8a5ba45SMiklos Szeredi } 296d8a5ba45SMiklos Szeredi 297b48badf0SMiklos Szeredi struct inode *fuse_iget(struct super_block *sb, u64 nodeid, 2981fb69e78SMiklos Szeredi int generation, struct fuse_attr *attr, 2991fb69e78SMiklos Szeredi u64 attr_valid, u64 attr_version) 300d8a5ba45SMiklos Szeredi { 301d8a5ba45SMiklos Szeredi struct inode *inode; 3029e6268dbSMiklos Szeredi struct fuse_inode *fi; 303d8a5ba45SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 304d8a5ba45SMiklos Szeredi 305d8a5ba45SMiklos Szeredi retry: 306d8a5ba45SMiklos Szeredi inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); 307d8a5ba45SMiklos Szeredi if (!inode) 308d8a5ba45SMiklos Szeredi return NULL; 309d8a5ba45SMiklos Szeredi 310d8a5ba45SMiklos Szeredi if ((inode->i_state & I_NEW)) { 311b0aa7606SMaxim Patlasov inode->i_flags |= S_NOATIME; 312d31433c8SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(attr->mode)) 313b0aa7606SMaxim Patlasov inode->i_flags |= S_NOCMTIME; 314d8a5ba45SMiklos Szeredi inode->i_generation = generation; 315d8a5ba45SMiklos Szeredi fuse_init_inode(inode, attr); 316d8a5ba45SMiklos Szeredi unlock_new_inode(inode); 317d8a5ba45SMiklos Szeredi } else if ((inode->i_mode ^ attr->mode) & S_IFMT) { 318d8a5ba45SMiklos Szeredi /* Inode has changed type, any I/O on the old should fail */ 319d8a5ba45SMiklos Szeredi make_bad_inode(inode); 320d8a5ba45SMiklos Szeredi iput(inode); 321d8a5ba45SMiklos Szeredi goto retry; 322d8a5ba45SMiklos Szeredi } 323d8a5ba45SMiklos Szeredi 3249e6268dbSMiklos Szeredi fi = get_fuse_inode(inode); 3258da5ff23SMiklos Szeredi spin_lock(&fc->lock); 3269e6268dbSMiklos Szeredi fi->nlookup++; 3278da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 3281fb69e78SMiklos Szeredi fuse_change_attributes(inode, attr, attr_valid, attr_version); 3291fb69e78SMiklos Szeredi 330d8a5ba45SMiklos Szeredi return inode; 331d8a5ba45SMiklos Szeredi } 332d8a5ba45SMiklos Szeredi 3333b463ae0SJohn Muir int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, 3343b463ae0SJohn Muir loff_t offset, loff_t len) 3353b463ae0SJohn Muir { 3363b463ae0SJohn Muir struct inode *inode; 3373b463ae0SJohn Muir pgoff_t pg_start; 3383b463ae0SJohn Muir pgoff_t pg_end; 3393b463ae0SJohn Muir 3403b463ae0SJohn Muir inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid); 3413b463ae0SJohn Muir if (!inode) 3423b463ae0SJohn Muir return -ENOENT; 3433b463ae0SJohn Muir 3443b463ae0SJohn Muir fuse_invalidate_attr(inode); 34560bcc88aSSeth Forshee forget_all_cached_acls(inode); 3463b463ae0SJohn Muir if (offset >= 0) { 34709cbfeafSKirill A. Shutemov pg_start = offset >> PAGE_SHIFT; 3483b463ae0SJohn Muir if (len <= 0) 3493b463ae0SJohn Muir pg_end = -1; 3503b463ae0SJohn Muir else 35109cbfeafSKirill A. Shutemov pg_end = (offset + len - 1) >> PAGE_SHIFT; 3523b463ae0SJohn Muir invalidate_inode_pages2_range(inode->i_mapping, 3533b463ae0SJohn Muir pg_start, pg_end); 3543b463ae0SJohn Muir } 3553b463ae0SJohn Muir iput(inode); 3563b463ae0SJohn Muir return 0; 3573b463ae0SJohn Muir } 3583b463ae0SJohn Muir 35963576c13SMiklos Szeredi bool fuse_lock_inode(struct inode *inode) 3605c672ab3SMiklos Szeredi { 36163576c13SMiklos Szeredi bool locked = false; 36263576c13SMiklos Szeredi 36363576c13SMiklos Szeredi if (!get_fuse_conn(inode)->parallel_dirops) { 3645c672ab3SMiklos Szeredi mutex_lock(&get_fuse_inode(inode)->mutex); 36563576c13SMiklos Szeredi locked = true; 3665c672ab3SMiklos Szeredi } 3675c672ab3SMiklos Szeredi 36863576c13SMiklos Szeredi return locked; 36963576c13SMiklos Szeredi } 37063576c13SMiklos Szeredi 37163576c13SMiklos Szeredi void fuse_unlock_inode(struct inode *inode, bool locked) 3725c672ab3SMiklos Szeredi { 37363576c13SMiklos Szeredi if (locked) 3745c672ab3SMiklos Szeredi mutex_unlock(&get_fuse_inode(inode)->mutex); 3755c672ab3SMiklos Szeredi } 3765c672ab3SMiklos Szeredi 37742faad99SAl Viro static void fuse_umount_begin(struct super_block *sb) 37869a53bf2SMiklos Szeredi { 3793b7008b2SSzymon Lukasz fuse_abort_conn(get_fuse_conn_super(sb), false); 38069a53bf2SMiklos Szeredi } 38169a53bf2SMiklos Szeredi 3820ec7ca41SMiklos Szeredi static void fuse_send_destroy(struct fuse_conn *fc) 3830ec7ca41SMiklos Szeredi { 3840ec7ca41SMiklos Szeredi struct fuse_req *req = fc->destroy_req; 3850ec7ca41SMiklos Szeredi if (req && fc->conn_init) { 3860ec7ca41SMiklos Szeredi fc->destroy_req = NULL; 3870ec7ca41SMiklos Szeredi req->in.h.opcode = FUSE_DESTROY; 388825d6d33SMiklos Szeredi __set_bit(FR_FORCE, &req->flags); 389825d6d33SMiklos Szeredi __clear_bit(FR_BACKGROUND, &req->flags); 390b93f858aSTejun Heo fuse_request_send(fc, req); 3910ec7ca41SMiklos Szeredi fuse_put_request(fc, req); 3920ec7ca41SMiklos Szeredi } 3930ec7ca41SMiklos Szeredi } 3940ec7ca41SMiklos Szeredi 395a325f9b9STejun Heo static void fuse_put_super(struct super_block *sb) 396a325f9b9STejun Heo { 397a325f9b9STejun Heo struct fuse_conn *fc = get_fuse_conn_super(sb); 398a325f9b9STejun Heo 399bbd99797SMiklos Szeredi mutex_lock(&fuse_mutex); 400bbd99797SMiklos Szeredi list_del(&fc->entry); 401bbd99797SMiklos Szeredi fuse_ctl_remove_conn(fc); 402bbd99797SMiklos Szeredi mutex_unlock(&fuse_mutex); 403bbd99797SMiklos Szeredi 404bafa9654SMiklos Szeredi fuse_conn_put(fc); 405d8a5ba45SMiklos Szeredi } 406d8a5ba45SMiklos Szeredi 407e5e5558eSMiklos Szeredi static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 408e5e5558eSMiklos Szeredi { 409e5e5558eSMiklos Szeredi stbuf->f_type = FUSE_SUPER_MAGIC; 410e5e5558eSMiklos Szeredi stbuf->f_bsize = attr->bsize; 411de5f1202SMiklos Szeredi stbuf->f_frsize = attr->frsize; 412e5e5558eSMiklos Szeredi stbuf->f_blocks = attr->blocks; 413e5e5558eSMiklos Szeredi stbuf->f_bfree = attr->bfree; 414e5e5558eSMiklos Szeredi stbuf->f_bavail = attr->bavail; 415e5e5558eSMiklos Szeredi stbuf->f_files = attr->files; 416e5e5558eSMiklos Szeredi stbuf->f_ffree = attr->ffree; 417e5e5558eSMiklos Szeredi stbuf->f_namelen = attr->namelen; 418e5e5558eSMiklos Szeredi /* fsid is left zero */ 419e5e5558eSMiklos Szeredi } 420e5e5558eSMiklos Szeredi 421726c3342SDavid Howells static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) 422e5e5558eSMiklos Szeredi { 423726c3342SDavid Howells struct super_block *sb = dentry->d_sb; 424e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 4257078187aSMiklos Szeredi FUSE_ARGS(args); 426e5e5558eSMiklos Szeredi struct fuse_statfs_out outarg; 427e5e5558eSMiklos Szeredi int err; 428e5e5558eSMiklos Szeredi 429c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) { 430e57ac683SMiklos Szeredi buf->f_type = FUSE_SUPER_MAGIC; 431e57ac683SMiklos Szeredi return 0; 432e57ac683SMiklos Szeredi } 433e57ac683SMiklos Szeredi 434de5f1202SMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 4357078187aSMiklos Szeredi args.in.numargs = 0; 4367078187aSMiklos Szeredi args.in.h.opcode = FUSE_STATFS; 4372b0143b5SDavid Howells args.in.h.nodeid = get_node_id(d_inode(dentry)); 4387078187aSMiklos Szeredi args.out.numargs = 1; 43921f62174SMiklos Szeredi args.out.args[0].size = sizeof(outarg); 4407078187aSMiklos Szeredi args.out.args[0].value = &outarg; 4417078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 442e5e5558eSMiklos Szeredi if (!err) 443e5e5558eSMiklos Szeredi convert_fuse_statfs(buf, &outarg.st); 444e5e5558eSMiklos Szeredi return err; 445e5e5558eSMiklos Szeredi } 446e5e5558eSMiklos Szeredi 447d8a5ba45SMiklos Szeredi enum { 448d8a5ba45SMiklos Szeredi OPT_FD, 449d8a5ba45SMiklos Szeredi OPT_ROOTMODE, 450d8a5ba45SMiklos Szeredi OPT_USER_ID, 45187729a55SMiklos Szeredi OPT_GROUP_ID, 452d8a5ba45SMiklos Szeredi OPT_DEFAULT_PERMISSIONS, 453d8a5ba45SMiklos Szeredi OPT_ALLOW_OTHER, 454db50b96cSMiklos Szeredi OPT_MAX_READ, 455d8091614SMiklos Szeredi OPT_BLKSIZE, 456d8a5ba45SMiklos Szeredi OPT_ERR 457d8a5ba45SMiklos Szeredi }; 458d8a5ba45SMiklos Szeredi 459a447c093SSteven Whitehouse static const match_table_t tokens = { 460d8a5ba45SMiklos Szeredi {OPT_FD, "fd=%u"}, 461d8a5ba45SMiklos Szeredi {OPT_ROOTMODE, "rootmode=%o"}, 462d8a5ba45SMiklos Szeredi {OPT_USER_ID, "user_id=%u"}, 46387729a55SMiklos Szeredi {OPT_GROUP_ID, "group_id=%u"}, 464d8a5ba45SMiklos Szeredi {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, 465d8a5ba45SMiklos Szeredi {OPT_ALLOW_OTHER, "allow_other"}, 466db50b96cSMiklos Szeredi {OPT_MAX_READ, "max_read=%u"}, 467d8091614SMiklos Szeredi {OPT_BLKSIZE, "blksize=%u"}, 468d8a5ba45SMiklos Szeredi {OPT_ERR, NULL} 469d8a5ba45SMiklos Szeredi }; 470d8a5ba45SMiklos Szeredi 471233a01faSMiklos Szeredi static int fuse_match_uint(substring_t *s, unsigned int *res) 472233a01faSMiklos Szeredi { 473233a01faSMiklos Szeredi int err = -ENOMEM; 474233a01faSMiklos Szeredi char *buf = match_strdup(s); 475233a01faSMiklos Szeredi if (buf) { 476233a01faSMiklos Szeredi err = kstrtouint(buf, 10, res); 477233a01faSMiklos Szeredi kfree(buf); 478233a01faSMiklos Szeredi } 479233a01faSMiklos Szeredi return err; 480233a01faSMiklos Szeredi } 481233a01faSMiklos Szeredi 4828cb08329SEric W. Biederman static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev, 4838cb08329SEric W. Biederman struct user_namespace *user_ns) 484d8a5ba45SMiklos Szeredi { 485d8a5ba45SMiklos Szeredi char *p; 486d8a5ba45SMiklos Szeredi memset(d, 0, sizeof(struct fuse_mount_data)); 487db50b96cSMiklos Szeredi d->max_read = ~0; 488d1875dbaSMiklos Szeredi d->blksize = FUSE_DEFAULT_BLKSIZE; 489d8a5ba45SMiklos Szeredi 490d8a5ba45SMiklos Szeredi while ((p = strsep(&opt, ",")) != NULL) { 491d8a5ba45SMiklos Szeredi int token; 492d8a5ba45SMiklos Szeredi int value; 493233a01faSMiklos Szeredi unsigned uv; 494d8a5ba45SMiklos Szeredi substring_t args[MAX_OPT_ARGS]; 495d8a5ba45SMiklos Szeredi if (!*p) 496d8a5ba45SMiklos Szeredi continue; 497d8a5ba45SMiklos Szeredi 498d8a5ba45SMiklos Szeredi token = match_token(p, tokens, args); 499d8a5ba45SMiklos Szeredi switch (token) { 500d8a5ba45SMiklos Szeredi case OPT_FD: 501d8a5ba45SMiklos Szeredi if (match_int(&args[0], &value)) 502d8a5ba45SMiklos Szeredi return 0; 503d8a5ba45SMiklos Szeredi d->fd = value; 5045a533682SMiklos Szeredi d->fd_present = 1; 505d8a5ba45SMiklos Szeredi break; 506d8a5ba45SMiklos Szeredi 507d8a5ba45SMiklos Szeredi case OPT_ROOTMODE: 508d8a5ba45SMiklos Szeredi if (match_octal(&args[0], &value)) 509d8a5ba45SMiklos Szeredi return 0; 510a5bfffacSTimo Savola if (!fuse_valid_type(value)) 511a5bfffacSTimo Savola return 0; 512d8a5ba45SMiklos Szeredi d->rootmode = value; 5135a533682SMiklos Szeredi d->rootmode_present = 1; 514d8a5ba45SMiklos Szeredi break; 515d8a5ba45SMiklos Szeredi 516d8a5ba45SMiklos Szeredi case OPT_USER_ID: 517233a01faSMiklos Szeredi if (fuse_match_uint(&args[0], &uv)) 518d8a5ba45SMiklos Szeredi return 0; 5198cb08329SEric W. Biederman d->user_id = make_kuid(user_ns, uv); 520499dcf20SEric W. Biederman if (!uid_valid(d->user_id)) 521499dcf20SEric W. Biederman return 0; 5225a533682SMiklos Szeredi d->user_id_present = 1; 523d8a5ba45SMiklos Szeredi break; 524d8a5ba45SMiklos Szeredi 52587729a55SMiklos Szeredi case OPT_GROUP_ID: 526233a01faSMiklos Szeredi if (fuse_match_uint(&args[0], &uv)) 52787729a55SMiklos Szeredi return 0; 5288cb08329SEric W. Biederman d->group_id = make_kgid(user_ns, uv); 529499dcf20SEric W. Biederman if (!gid_valid(d->group_id)) 530499dcf20SEric W. Biederman return 0; 5315a533682SMiklos Szeredi d->group_id_present = 1; 53287729a55SMiklos Szeredi break; 53387729a55SMiklos Szeredi 5341e9a4ed9SMiklos Szeredi case OPT_DEFAULT_PERMISSIONS: 53529433a29SMiklos Szeredi d->default_permissions = 1; 5361e9a4ed9SMiklos Szeredi break; 5371e9a4ed9SMiklos Szeredi 5381e9a4ed9SMiklos Szeredi case OPT_ALLOW_OTHER: 53929433a29SMiklos Szeredi d->allow_other = 1; 5401e9a4ed9SMiklos Szeredi break; 5411e9a4ed9SMiklos Szeredi 542db50b96cSMiklos Szeredi case OPT_MAX_READ: 543db50b96cSMiklos Szeredi if (match_int(&args[0], &value)) 544db50b96cSMiklos Szeredi return 0; 545db50b96cSMiklos Szeredi d->max_read = value; 546db50b96cSMiklos Szeredi break; 547db50b96cSMiklos Szeredi 548d8091614SMiklos Szeredi case OPT_BLKSIZE: 549d8091614SMiklos Szeredi if (!is_bdev || match_int(&args[0], &value)) 550d8091614SMiklos Szeredi return 0; 551d8091614SMiklos Szeredi d->blksize = value; 552d8091614SMiklos Szeredi break; 553d8091614SMiklos Szeredi 554d8a5ba45SMiklos Szeredi default: 555d8a5ba45SMiklos Szeredi return 0; 556d8a5ba45SMiklos Szeredi } 557d8a5ba45SMiklos Szeredi } 5585a533682SMiklos Szeredi 5595a533682SMiklos Szeredi if (!d->fd_present || !d->rootmode_present || 5605a533682SMiklos Szeredi !d->user_id_present || !d->group_id_present) 561d8a5ba45SMiklos Szeredi return 0; 562d8a5ba45SMiklos Szeredi 563d8a5ba45SMiklos Szeredi return 1; 564d8a5ba45SMiklos Szeredi } 565d8a5ba45SMiklos Szeredi 56634c80b1dSAl Viro static int fuse_show_options(struct seq_file *m, struct dentry *root) 567d8a5ba45SMiklos Szeredi { 56834c80b1dSAl Viro struct super_block *sb = root->d_sb; 56934c80b1dSAl Viro struct fuse_conn *fc = get_fuse_conn_super(sb); 570d8a5ba45SMiklos Szeredi 5718cb08329SEric W. Biederman seq_printf(m, ",user_id=%u", from_kuid_munged(fc->user_ns, fc->user_id)); 5728cb08329SEric W. Biederman seq_printf(m, ",group_id=%u", from_kgid_munged(fc->user_ns, fc->group_id)); 57329433a29SMiklos Szeredi if (fc->default_permissions) 5741e9a4ed9SMiklos Szeredi seq_puts(m, ",default_permissions"); 57529433a29SMiklos Szeredi if (fc->allow_other) 5761e9a4ed9SMiklos Szeredi seq_puts(m, ",allow_other"); 577db50b96cSMiklos Szeredi if (fc->max_read != ~0) 578db50b96cSMiklos Szeredi seq_printf(m, ",max_read=%u", fc->max_read); 57934c80b1dSAl Viro if (sb->s_bdev && sb->s_blocksize != FUSE_DEFAULT_BLKSIZE) 58034c80b1dSAl Viro seq_printf(m, ",blksize=%lu", sb->s_blocksize); 581d8a5ba45SMiklos Szeredi return 0; 582d8a5ba45SMiklos Szeredi } 583d8a5ba45SMiklos Szeredi 584f88996a9SMiklos Szeredi static void fuse_iqueue_init(struct fuse_iqueue *fiq) 585f88996a9SMiklos Szeredi { 586f88996a9SMiklos Szeredi memset(fiq, 0, sizeof(struct fuse_iqueue)); 587f88996a9SMiklos Szeredi init_waitqueue_head(&fiq->waitq); 588f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->pending); 589f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->interrupts); 590f88996a9SMiklos Szeredi fiq->forget_list_tail = &fiq->forget_list_head; 591e16714d8SMiklos Szeredi fiq->connected = 1; 592f88996a9SMiklos Szeredi } 593f88996a9SMiklos Szeredi 5943a2b5b9cSMiklos Szeredi static void fuse_pqueue_init(struct fuse_pqueue *fpq) 5953a2b5b9cSMiklos Szeredi { 596be2ff42cSKirill Tkhai unsigned int i; 597be2ff42cSKirill Tkhai 59845a91cb1SMiklos Szeredi spin_lock_init(&fpq->lock); 599be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) 600be2ff42cSKirill Tkhai INIT_LIST_HEAD(&fpq->processing[i]); 6013a2b5b9cSMiklos Szeredi INIT_LIST_HEAD(&fpq->io); 602e96edd94SMiklos Szeredi fpq->connected = 1; 6033a2b5b9cSMiklos Szeredi } 6043a2b5b9cSMiklos Szeredi 6058cb08329SEric W. Biederman void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns) 606d8a5ba45SMiklos Szeredi { 6070d179aa5STejun Heo memset(fc, 0, sizeof(*fc)); 608d7133114SMiklos Szeredi spin_lock_init(&fc->lock); 609ae2dffa3SKirill Tkhai spin_lock_init(&fc->bg_lock); 6103b463ae0SJohn Muir init_rwsem(&fc->killsb); 611095fc40aSElena Reshetova refcount_set(&fc->count, 1); 612c3696046SMiklos Szeredi atomic_set(&fc->dev_count, 1); 61308a53cdcSMiklos Szeredi init_waitqueue_head(&fc->blocked_waitq); 614de5e3decSMiklos Szeredi init_waitqueue_head(&fc->reserved_req_waitq); 615f88996a9SMiklos Szeredi fuse_iqueue_init(&fc->iq); 616d12def1bSMiklos Szeredi INIT_LIST_HEAD(&fc->bg_queue); 6170d179aa5STejun Heo INIT_LIST_HEAD(&fc->entry); 618cc080e9eSMiklos Szeredi INIT_LIST_HEAD(&fc->devices); 619095da6cbSMiklos Szeredi atomic_set(&fc->num_waiting, 0); 6207a6d3c8bSCsaba Henk fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; 6217a6d3c8bSCsaba Henk fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; 622acf99433STejun Heo fc->khctr = 0; 62395668a69STejun Heo fc->polled_files = RB_ROOT; 6240aada884SMaxim Patlasov fc->blocked = 0; 625796523fbSMaxim Patlasov fc->initialized = 0; 626e16714d8SMiklos Szeredi fc->connected = 1; 6271fb69e78SMiklos Szeredi fc->attr_version = 1; 6289c8ef561SMiklos Szeredi get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); 6290b6e9ea0SSeth Forshee fc->pid_ns = get_pid_ns(task_active_pid_ns(current)); 6308cb08329SEric W. Biederman fc->user_ns = get_user_ns(user_ns); 631d8a5ba45SMiklos Szeredi } 6320d179aa5STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_init); 633d8a5ba45SMiklos Szeredi 634bafa9654SMiklos Szeredi void fuse_conn_put(struct fuse_conn *fc) 635bafa9654SMiklos Szeredi { 636095fc40aSElena Reshetova if (refcount_dec_and_test(&fc->count)) { 6370ec7ca41SMiklos Szeredi if (fc->destroy_req) 6380ec7ca41SMiklos Szeredi fuse_request_free(fc->destroy_req); 6390b6e9ea0SSeth Forshee put_pid_ns(fc->pid_ns); 6408cb08329SEric W. Biederman put_user_ns(fc->user_ns); 64143901aabSTejun Heo fc->release(fc); 642bafa9654SMiklos Szeredi } 643d2a85164SMiklos Szeredi } 64408cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_put); 645bafa9654SMiklos Szeredi 646bafa9654SMiklos Szeredi struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) 647bafa9654SMiklos Szeredi { 648095fc40aSElena Reshetova refcount_inc(&fc->count); 649bafa9654SMiklos Szeredi return fc; 650bafa9654SMiklos Szeredi } 65108cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_get); 652bafa9654SMiklos Szeredi 653b93f858aSTejun Heo static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) 654d8a5ba45SMiklos Szeredi { 655d8a5ba45SMiklos Szeredi struct fuse_attr attr; 656d8a5ba45SMiklos Szeredi memset(&attr, 0, sizeof(attr)); 657d8a5ba45SMiklos Szeredi 658d8a5ba45SMiklos Szeredi attr.mode = mode; 659d8a5ba45SMiklos Szeredi attr.ino = FUSE_ROOT_ID; 660074406faSMiklos Szeredi attr.nlink = 1; 6611fb69e78SMiklos Szeredi return fuse_iget(sb, 1, 0, &attr, 0, 0); 662d8a5ba45SMiklos Szeredi } 663d8a5ba45SMiklos Szeredi 6641729a16cSMiklos Szeredi struct fuse_inode_handle { 665dbd561d2SMiklos Szeredi u64 nodeid; 666dbd561d2SMiklos Szeredi u32 generation; 667dbd561d2SMiklos Szeredi }; 668dbd561d2SMiklos Szeredi 669dbd561d2SMiklos Szeredi static struct dentry *fuse_get_dentry(struct super_block *sb, 670dbd561d2SMiklos Szeredi struct fuse_inode_handle *handle) 671dbd561d2SMiklos Szeredi { 67233670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 673dbd561d2SMiklos Szeredi struct inode *inode; 674dbd561d2SMiklos Szeredi struct dentry *entry; 675dbd561d2SMiklos Szeredi int err = -ESTALE; 676dbd561d2SMiklos Szeredi 677dbd561d2SMiklos Szeredi if (handle->nodeid == 0) 678dbd561d2SMiklos Szeredi goto out_err; 679dbd561d2SMiklos Szeredi 680dbd561d2SMiklos Szeredi inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid); 68133670fa2SMiklos Szeredi if (!inode) { 68233670fa2SMiklos Szeredi struct fuse_entry_out outarg; 68313983d06SAl Viro const struct qstr name = QSTR_INIT(".", 1); 68433670fa2SMiklos Szeredi 68533670fa2SMiklos Szeredi if (!fc->export_support) 686dbd561d2SMiklos Szeredi goto out_err; 68733670fa2SMiklos Szeredi 68833670fa2SMiklos Szeredi err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg, 68933670fa2SMiklos Szeredi &inode); 69033670fa2SMiklos Szeredi if (err && err != -ENOENT) 69133670fa2SMiklos Szeredi goto out_err; 69233670fa2SMiklos Szeredi if (err || !inode) { 69333670fa2SMiklos Szeredi err = -ESTALE; 69433670fa2SMiklos Szeredi goto out_err; 69533670fa2SMiklos Szeredi } 69633670fa2SMiklos Szeredi err = -EIO; 69733670fa2SMiklos Szeredi if (get_node_id(inode) != handle->nodeid) 69833670fa2SMiklos Szeredi goto out_iput; 69933670fa2SMiklos Szeredi } 700dbd561d2SMiklos Szeredi err = -ESTALE; 701dbd561d2SMiklos Szeredi if (inode->i_generation != handle->generation) 702dbd561d2SMiklos Szeredi goto out_iput; 703dbd561d2SMiklos Szeredi 70444003728SChristoph Hellwig entry = d_obtain_alias(inode); 705c35eebe9SAl Viro if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) 706dbd561d2SMiklos Szeredi fuse_invalidate_entry_cache(entry); 707dbd561d2SMiklos Szeredi 708dbd561d2SMiklos Szeredi return entry; 709dbd561d2SMiklos Szeredi 710dbd561d2SMiklos Szeredi out_iput: 711dbd561d2SMiklos Szeredi iput(inode); 712dbd561d2SMiklos Szeredi out_err: 713dbd561d2SMiklos Szeredi return ERR_PTR(err); 714dbd561d2SMiklos Szeredi } 715dbd561d2SMiklos Szeredi 716b0b0382bSAl Viro static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len, 717b0b0382bSAl Viro struct inode *parent) 718dbd561d2SMiklos Szeredi { 719b0b0382bSAl Viro int len = parent ? 6 : 3; 720dbd561d2SMiklos Szeredi u64 nodeid; 721dbd561d2SMiklos Szeredi u32 generation; 722dbd561d2SMiklos Szeredi 7235fe0c237SAneesh Kumar K.V if (*max_len < len) { 7245fe0c237SAneesh Kumar K.V *max_len = len; 72594e07a75SNamjae Jeon return FILEID_INVALID; 7265fe0c237SAneesh Kumar K.V } 727dbd561d2SMiklos Szeredi 728dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(inode)->nodeid; 729dbd561d2SMiklos Szeredi generation = inode->i_generation; 730dbd561d2SMiklos Szeredi 731dbd561d2SMiklos Szeredi fh[0] = (u32)(nodeid >> 32); 732dbd561d2SMiklos Szeredi fh[1] = (u32)(nodeid & 0xffffffff); 733dbd561d2SMiklos Szeredi fh[2] = generation; 734dbd561d2SMiklos Szeredi 735b0b0382bSAl Viro if (parent) { 736dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(parent)->nodeid; 737dbd561d2SMiklos Szeredi generation = parent->i_generation; 738dbd561d2SMiklos Szeredi 739dbd561d2SMiklos Szeredi fh[3] = (u32)(nodeid >> 32); 740dbd561d2SMiklos Szeredi fh[4] = (u32)(nodeid & 0xffffffff); 741dbd561d2SMiklos Szeredi fh[5] = generation; 742dbd561d2SMiklos Szeredi } 743dbd561d2SMiklos Szeredi 744dbd561d2SMiklos Szeredi *max_len = len; 745b0b0382bSAl Viro return parent ? 0x82 : 0x81; 746dbd561d2SMiklos Szeredi } 747dbd561d2SMiklos Szeredi 748dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_dentry(struct super_block *sb, 749dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 750dbd561d2SMiklos Szeredi { 751dbd561d2SMiklos Szeredi struct fuse_inode_handle handle; 752dbd561d2SMiklos Szeredi 753dbd561d2SMiklos Szeredi if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3) 754dbd561d2SMiklos Szeredi return NULL; 755dbd561d2SMiklos Szeredi 756dbd561d2SMiklos Szeredi handle.nodeid = (u64) fid->raw[0] << 32; 757dbd561d2SMiklos Szeredi handle.nodeid |= (u64) fid->raw[1]; 758dbd561d2SMiklos Szeredi handle.generation = fid->raw[2]; 759dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &handle); 760dbd561d2SMiklos Szeredi } 761dbd561d2SMiklos Szeredi 762dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_parent(struct super_block *sb, 763dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 764dbd561d2SMiklos Szeredi { 765dbd561d2SMiklos Szeredi struct fuse_inode_handle parent; 766dbd561d2SMiklos Szeredi 767dbd561d2SMiklos Szeredi if (fh_type != 0x82 || fh_len < 6) 768dbd561d2SMiklos Szeredi return NULL; 769dbd561d2SMiklos Szeredi 770dbd561d2SMiklos Szeredi parent.nodeid = (u64) fid->raw[3] << 32; 771dbd561d2SMiklos Szeredi parent.nodeid |= (u64) fid->raw[4]; 772dbd561d2SMiklos Szeredi parent.generation = fid->raw[5]; 773dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &parent); 774dbd561d2SMiklos Szeredi } 775dbd561d2SMiklos Szeredi 77633670fa2SMiklos Szeredi static struct dentry *fuse_get_parent(struct dentry *child) 77733670fa2SMiklos Szeredi { 7782b0143b5SDavid Howells struct inode *child_inode = d_inode(child); 77933670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(child_inode); 78033670fa2SMiklos Szeredi struct inode *inode; 78133670fa2SMiklos Szeredi struct dentry *parent; 78233670fa2SMiklos Szeredi struct fuse_entry_out outarg; 78313983d06SAl Viro const struct qstr name = QSTR_INIT("..", 2); 78433670fa2SMiklos Szeredi int err; 78533670fa2SMiklos Szeredi 78633670fa2SMiklos Szeredi if (!fc->export_support) 78733670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 78833670fa2SMiklos Szeredi 78933670fa2SMiklos Szeredi err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode), 79033670fa2SMiklos Szeredi &name, &outarg, &inode); 79144003728SChristoph Hellwig if (err) { 79244003728SChristoph Hellwig if (err == -ENOENT) 79333670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 79444003728SChristoph Hellwig return ERR_PTR(err); 79533670fa2SMiklos Szeredi } 79644003728SChristoph Hellwig 79744003728SChristoph Hellwig parent = d_obtain_alias(inode); 798c35eebe9SAl Viro if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) 79933670fa2SMiklos Szeredi fuse_invalidate_entry_cache(parent); 80033670fa2SMiklos Szeredi 80133670fa2SMiklos Szeredi return parent; 80233670fa2SMiklos Szeredi } 803dbd561d2SMiklos Szeredi 804dbd561d2SMiklos Szeredi static const struct export_operations fuse_export_operations = { 805dbd561d2SMiklos Szeredi .fh_to_dentry = fuse_fh_to_dentry, 806dbd561d2SMiklos Szeredi .fh_to_parent = fuse_fh_to_parent, 807dbd561d2SMiklos Szeredi .encode_fh = fuse_encode_fh, 80833670fa2SMiklos Szeredi .get_parent = fuse_get_parent, 809dbd561d2SMiklos Szeredi }; 810dbd561d2SMiklos Szeredi 811ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations fuse_super_operations = { 812d8a5ba45SMiklos Szeredi .alloc_inode = fuse_alloc_inode, 813d8a5ba45SMiklos Szeredi .destroy_inode = fuse_destroy_inode, 814b57922d9SAl Viro .evict_inode = fuse_evict_inode, 8151e18bda8SMiklos Szeredi .write_inode = fuse_write_inode, 816ead5f0b5SMiklos Szeredi .drop_inode = generic_delete_inode, 81771421259SMiklos Szeredi .remount_fs = fuse_remount_fs, 818d8a5ba45SMiklos Szeredi .put_super = fuse_put_super, 81969a53bf2SMiklos Szeredi .umount_begin = fuse_umount_begin, 820e5e5558eSMiklos Szeredi .statfs = fuse_statfs, 821d8a5ba45SMiklos Szeredi .show_options = fuse_show_options, 822d8a5ba45SMiklos Szeredi }; 823d8a5ba45SMiklos Szeredi 824487ea5afSCsaba Henk static void sanitize_global_limit(unsigned *limit) 825487ea5afSCsaba Henk { 826487ea5afSCsaba Henk if (*limit == 0) 8270ed5fd13SJiang Liu *limit = ((totalram_pages << PAGE_SHIFT) >> 13) / 828487ea5afSCsaba Henk sizeof(struct fuse_req); 829487ea5afSCsaba Henk 830487ea5afSCsaba Henk if (*limit >= 1 << 16) 831487ea5afSCsaba Henk *limit = (1 << 16) - 1; 832487ea5afSCsaba Henk } 833487ea5afSCsaba Henk 834e4dca7b7SKees Cook static int set_global_limit(const char *val, const struct kernel_param *kp) 835487ea5afSCsaba Henk { 836487ea5afSCsaba Henk int rv; 837487ea5afSCsaba Henk 838487ea5afSCsaba Henk rv = param_set_uint(val, kp); 839487ea5afSCsaba Henk if (rv) 840487ea5afSCsaba Henk return rv; 841487ea5afSCsaba Henk 842487ea5afSCsaba Henk sanitize_global_limit((unsigned *)kp->arg); 843487ea5afSCsaba Henk 844487ea5afSCsaba Henk return 0; 845487ea5afSCsaba Henk } 846487ea5afSCsaba Henk 847487ea5afSCsaba Henk static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) 848487ea5afSCsaba Henk { 849487ea5afSCsaba Henk int cap_sys_admin = capable(CAP_SYS_ADMIN); 850487ea5afSCsaba Henk 851487ea5afSCsaba Henk if (arg->minor < 13) 852487ea5afSCsaba Henk return; 853487ea5afSCsaba Henk 854487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 855487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 856487ea5afSCsaba Henk 857ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 858487ea5afSCsaba Henk if (arg->max_background) { 859487ea5afSCsaba Henk fc->max_background = arg->max_background; 860487ea5afSCsaba Henk 861487ea5afSCsaba Henk if (!cap_sys_admin && fc->max_background > max_user_bgreq) 862487ea5afSCsaba Henk fc->max_background = max_user_bgreq; 863487ea5afSCsaba Henk } 864487ea5afSCsaba Henk if (arg->congestion_threshold) { 865487ea5afSCsaba Henk fc->congestion_threshold = arg->congestion_threshold; 866487ea5afSCsaba Henk 867487ea5afSCsaba Henk if (!cap_sys_admin && 868487ea5afSCsaba Henk fc->congestion_threshold > max_user_congthresh) 869487ea5afSCsaba Henk fc->congestion_threshold = max_user_congthresh; 870487ea5afSCsaba Henk } 871ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 872487ea5afSCsaba Henk } 873487ea5afSCsaba Henk 8749b9a0469SMiklos Szeredi static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) 8759b9a0469SMiklos Szeredi { 8769b9a0469SMiklos Szeredi struct fuse_init_out *arg = &req->misc.init_out; 8779b9a0469SMiklos Szeredi 8789b9a0469SMiklos Szeredi if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) 8799b9a0469SMiklos Szeredi fc->conn_error = 1; 8809b9a0469SMiklos Szeredi else { 8819cd68455SMiklos Szeredi unsigned long ra_pages; 8829cd68455SMiklos Szeredi 883487ea5afSCsaba Henk process_init_limits(fc, arg); 884487ea5afSCsaba Henk 8859cd68455SMiklos Szeredi if (arg->minor >= 6) { 88609cbfeafSKirill A. Shutemov ra_pages = arg->max_readahead / PAGE_SIZE; 8879cd68455SMiklos Szeredi if (arg->flags & FUSE_ASYNC_READ) 8889cd68455SMiklos Szeredi fc->async_read = 1; 88971421259SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 89071421259SMiklos Szeredi fc->no_lock = 1; 89137fb3a30SMiklos Szeredi if (arg->minor >= 17) { 89237fb3a30SMiklos Szeredi if (!(arg->flags & FUSE_FLOCK_LOCKS)) 89337fb3a30SMiklos Szeredi fc->no_flock = 1; 89424114504SMiklos Szeredi } else { 89524114504SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 89624114504SMiklos Szeredi fc->no_flock = 1; 89737fb3a30SMiklos Szeredi } 8986ff958edSMiklos Szeredi if (arg->flags & FUSE_ATOMIC_O_TRUNC) 8996ff958edSMiklos Szeredi fc->atomic_o_trunc = 1; 90033670fa2SMiklos Szeredi if (arg->minor >= 9) { 90133670fa2SMiklos Szeredi /* LOOKUP has dependency on proto version */ 90233670fa2SMiklos Szeredi if (arg->flags & FUSE_EXPORT_SUPPORT) 90333670fa2SMiklos Szeredi fc->export_support = 1; 90433670fa2SMiklos Szeredi } 90578bb6cb9SMiklos Szeredi if (arg->flags & FUSE_BIG_WRITES) 90678bb6cb9SMiklos Szeredi fc->big_writes = 1; 907e0a43ddcSMiklos Szeredi if (arg->flags & FUSE_DONT_MASK) 908e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 90972d0d248SBrian Foster if (arg->flags & FUSE_AUTO_INVAL_DATA) 91072d0d248SBrian Foster fc->auto_inval_data = 1; 91128420dadSMiklos Szeredi if (arg->flags & FUSE_DO_READDIRPLUS) { 9120b05b183SAnand V. Avati fc->do_readdirplus = 1; 913634734b6SEric Wong if (arg->flags & FUSE_READDIRPLUS_AUTO) 914634734b6SEric Wong fc->readdirplus_auto = 1; 91528420dadSMiklos Szeredi } 91660b9df7aSMiklos Szeredi if (arg->flags & FUSE_ASYNC_DIO) 91760b9df7aSMiklos Szeredi fc->async_dio = 1; 9184d99ff8fSPavel Emelyanov if (arg->flags & FUSE_WRITEBACK_CACHE) 9194d99ff8fSPavel Emelyanov fc->writeback_cache = 1; 9205c672ab3SMiklos Szeredi if (arg->flags & FUSE_PARALLEL_DIROPS) 9215c672ab3SMiklos Szeredi fc->parallel_dirops = 1; 9225e940c1dSMiklos Szeredi if (arg->flags & FUSE_HANDLE_KILLPRIV) 9235e940c1dSMiklos Szeredi fc->handle_killpriv = 1; 924e27c9d38SMiklos Szeredi if (arg->time_gran && arg->time_gran <= 1000000000) 925e27c9d38SMiklos Szeredi fc->sb->s_time_gran = arg->time_gran; 92660bcc88aSSeth Forshee if ((arg->flags & FUSE_POSIX_ACL)) { 92729433a29SMiklos Szeredi fc->default_permissions = 1; 92860bcc88aSSeth Forshee fc->posix_acl = 1; 92960bcc88aSSeth Forshee fc->sb->s_xattr = fuse_acl_xattr_handlers; 93060bcc88aSSeth Forshee } 9315571f1e6SDan Schatzberg if (arg->flags & FUSE_CACHE_SYMLINKS) 9325571f1e6SDan Schatzberg fc->cache_symlinks = 1; 9333b7008b2SSzymon Lukasz if (arg->flags & FUSE_ABORT_ERROR) 9343b7008b2SSzymon Lukasz fc->abort_err = 1; 9355da784ccSConstantine Shulyupin if (arg->flags & FUSE_MAX_PAGES) { 9365da784ccSConstantine Shulyupin fc->max_pages = 9375da784ccSConstantine Shulyupin min_t(unsigned int, FUSE_MAX_MAX_PAGES, 9385da784ccSConstantine Shulyupin max_t(unsigned int, arg->max_pages, 1)); 9395da784ccSConstantine Shulyupin } 94071421259SMiklos Szeredi } else { 94109cbfeafSKirill A. Shutemov ra_pages = fc->max_read / PAGE_SIZE; 94271421259SMiklos Szeredi fc->no_lock = 1; 94337fb3a30SMiklos Szeredi fc->no_flock = 1; 94471421259SMiklos Szeredi } 9459cd68455SMiklos Szeredi 9465f7f7543SJan Kara fc->sb->s_bdi->ra_pages = 9475f7f7543SJan Kara min(fc->sb->s_bdi->ra_pages, ra_pages); 9489b9a0469SMiklos Szeredi fc->minor = arg->minor; 9499b9a0469SMiklos Szeredi fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 950f948d564SMiklos Szeredi fc->max_write = max_t(unsigned, 4096, fc->max_write); 9510ec7ca41SMiklos Szeredi fc->conn_init = 1; 9529b9a0469SMiklos Szeredi } 9539759bd51SMiklos Szeredi fuse_set_initialized(fc); 95408a53cdcSMiklos Szeredi wake_up_all(&fc->blocked_waitq); 9559b9a0469SMiklos Szeredi } 9569b9a0469SMiklos Szeredi 957ce1d5a49SMiklos Szeredi static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) 9589b9a0469SMiklos Szeredi { 9599b9a0469SMiklos Szeredi struct fuse_init_in *arg = &req->misc.init_in; 960095da6cbSMiklos Szeredi 9619b9a0469SMiklos Szeredi arg->major = FUSE_KERNEL_VERSION; 9629b9a0469SMiklos Szeredi arg->minor = FUSE_KERNEL_MINOR_VERSION; 9635f7f7543SJan Kara arg->max_readahead = fc->sb->s_bdi->ra_pages * PAGE_SIZE; 96478bb6cb9SMiklos Szeredi arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | 96537fb3a30SMiklos Szeredi FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | 96669fe05c9SMiklos Szeredi FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | 9679446385fSWei Fang FUSE_FLOCK_LOCKS | FUSE_HAS_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | 9684d99ff8fSPavel Emelyanov FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | 9695c672ab3SMiklos Szeredi FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | 9703b7008b2SSzymon Lukasz FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | 9715571f1e6SDan Schatzberg FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS; 9729b9a0469SMiklos Szeredi req->in.h.opcode = FUSE_INIT; 9739b9a0469SMiklos Szeredi req->in.numargs = 1; 9749b9a0469SMiklos Szeredi req->in.args[0].size = sizeof(*arg); 9759b9a0469SMiklos Szeredi req->in.args[0].value = arg; 9769b9a0469SMiklos Szeredi req->out.numargs = 1; 9773ad2f3fbSDaniel Mack /* Variable length argument used for backward compatibility 9789b9a0469SMiklos Szeredi with interface version < 7.5. Rest of init_out is zeroed 9799b9a0469SMiklos Szeredi by do_get_request(), so a short reply is not a problem */ 9809b9a0469SMiklos Szeredi req->out.argvar = 1; 9819b9a0469SMiklos Szeredi req->out.args[0].size = sizeof(struct fuse_init_out); 9829b9a0469SMiklos Szeredi req->out.args[0].value = &req->misc.init_out; 9839b9a0469SMiklos Szeredi req->end = process_init_reply; 984b93f858aSTejun Heo fuse_request_send_background(fc, req); 9859b9a0469SMiklos Szeredi } 9869b9a0469SMiklos Szeredi 98743901aabSTejun Heo static void fuse_free_conn(struct fuse_conn *fc) 98843901aabSTejun Heo { 989cc080e9eSMiklos Szeredi WARN_ON(!list_empty(&fc->devices)); 990dd3e2c55SAl Viro kfree_rcu(fc, rcu); 99143901aabSTejun Heo } 99243901aabSTejun Heo 993a325f9b9STejun Heo static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) 994a325f9b9STejun Heo { 995a325f9b9STejun Heo int err; 9965f7f7543SJan Kara char *suffix = ""; 997a325f9b9STejun Heo 99869c8ebf8SJan Kara if (sb->s_bdev) { 9995f7f7543SJan Kara suffix = "-fuseblk"; 100069c8ebf8SJan Kara /* 100169c8ebf8SJan Kara * sb->s_bdi points to blkdev's bdi however we want to redirect 100269c8ebf8SJan Kara * it to our private bdi... 100369c8ebf8SJan Kara */ 100469c8ebf8SJan Kara bdi_put(sb->s_bdi); 100569c8ebf8SJan Kara sb->s_bdi = &noop_backing_dev_info; 100669c8ebf8SJan Kara } 10075f7f7543SJan Kara err = super_setup_bdi_name(sb, "%u:%u%s", MAJOR(fc->dev), 10085f7f7543SJan Kara MINOR(fc->dev), suffix); 1009a325f9b9STejun Heo if (err) 1010a325f9b9STejun Heo return err; 1011a325f9b9STejun Heo 10125f7f7543SJan Kara sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_SIZE; 10135f7f7543SJan Kara /* fuse does it's own writeback accounting */ 10145f7f7543SJan Kara sb->s_bdi->capabilities = BDI_CAP_NO_ACCT_WB | BDI_CAP_STRICTLIMIT; 10155f7f7543SJan Kara 1016a325f9b9STejun Heo /* 1017a325f9b9STejun Heo * For a single fuse filesystem use max 1% of dirty + 1018a325f9b9STejun Heo * writeback threshold. 1019a325f9b9STejun Heo * 1020a325f9b9STejun Heo * This gives about 1M of write buffer for memory maps on a 1021a325f9b9STejun Heo * machine with 1G and 10% dirty_ratio, which should be more 1022a325f9b9STejun Heo * than enough. 1023a325f9b9STejun Heo * 1024a325f9b9STejun Heo * Privileged users can raise it by writing to 1025a325f9b9STejun Heo * 1026a325f9b9STejun Heo * /sys/class/bdi/<bdi>/max_ratio 1027a325f9b9STejun Heo */ 10285f7f7543SJan Kara bdi_set_max_ratio(sb->s_bdi, 1); 1029a325f9b9STejun Heo 1030a325f9b9STejun Heo return 0; 1031a325f9b9STejun Heo } 1032a325f9b9STejun Heo 1033cc080e9eSMiklos Szeredi struct fuse_dev *fuse_dev_alloc(struct fuse_conn *fc) 1034cc080e9eSMiklos Szeredi { 1035cc080e9eSMiklos Szeredi struct fuse_dev *fud; 1036be2ff42cSKirill Tkhai struct list_head *pq; 1037cc080e9eSMiklos Szeredi 1038cc080e9eSMiklos Szeredi fud = kzalloc(sizeof(struct fuse_dev), GFP_KERNEL); 1039be2ff42cSKirill Tkhai if (!fud) 1040be2ff42cSKirill Tkhai return NULL; 1041be2ff42cSKirill Tkhai 1042be2ff42cSKirill Tkhai pq = kcalloc(FUSE_PQ_HASH_SIZE, sizeof(struct list_head), GFP_KERNEL); 1043be2ff42cSKirill Tkhai if (!pq) { 1044be2ff42cSKirill Tkhai kfree(fud); 1045be2ff42cSKirill Tkhai return NULL; 1046be2ff42cSKirill Tkhai } 1047be2ff42cSKirill Tkhai 1048be2ff42cSKirill Tkhai fud->pq.processing = pq; 1049cc080e9eSMiklos Szeredi fud->fc = fuse_conn_get(fc); 1050c3696046SMiklos Szeredi fuse_pqueue_init(&fud->pq); 1051cc080e9eSMiklos Szeredi 1052cc080e9eSMiklos Szeredi spin_lock(&fc->lock); 1053cc080e9eSMiklos Szeredi list_add_tail(&fud->entry, &fc->devices); 1054cc080e9eSMiklos Szeredi spin_unlock(&fc->lock); 1055cc080e9eSMiklos Szeredi 1056cc080e9eSMiklos Szeredi return fud; 1057cc080e9eSMiklos Szeredi } 1058cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_alloc); 1059cc080e9eSMiklos Szeredi 1060cc080e9eSMiklos Szeredi void fuse_dev_free(struct fuse_dev *fud) 1061cc080e9eSMiklos Szeredi { 1062cc080e9eSMiklos Szeredi struct fuse_conn *fc = fud->fc; 1063cc080e9eSMiklos Szeredi 1064cc080e9eSMiklos Szeredi if (fc) { 1065cc080e9eSMiklos Szeredi spin_lock(&fc->lock); 1066cc080e9eSMiklos Szeredi list_del(&fud->entry); 1067cc080e9eSMiklos Szeredi spin_unlock(&fc->lock); 1068cc080e9eSMiklos Szeredi 1069cc080e9eSMiklos Szeredi fuse_conn_put(fc); 1070cc080e9eSMiklos Szeredi } 1071d72f70daSTakeshi Misawa kfree(fud->pq.processing); 1072cc080e9eSMiklos Szeredi kfree(fud); 1073cc080e9eSMiklos Szeredi } 1074cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_free); 1075cc080e9eSMiklos Szeredi 1076d8a5ba45SMiklos Szeredi static int fuse_fill_super(struct super_block *sb, void *data, int silent) 1077d8a5ba45SMiklos Szeredi { 1078cc080e9eSMiklos Szeredi struct fuse_dev *fud; 1079d8a5ba45SMiklos Szeredi struct fuse_conn *fc; 1080d8a5ba45SMiklos Szeredi struct inode *root; 1081d8a5ba45SMiklos Szeredi struct fuse_mount_data d; 1082d8a5ba45SMiklos Szeredi struct file *file; 1083f543f253SMiklos Szeredi struct dentry *root_dentry; 1084ce1d5a49SMiklos Szeredi struct fuse_req *init_req; 1085d8a5ba45SMiklos Szeredi int err; 1086d8091614SMiklos Szeredi int is_bdev = sb->s_bdev != NULL; 1087d8a5ba45SMiklos Szeredi 1088c2b8f006SMiklos Szeredi err = -EINVAL; 10891751e8a6SLinus Torvalds if (sb->s_flags & SB_MANDLOCK) 1090c2b8f006SMiklos Szeredi goto err; 109171421259SMiklos Szeredi 10921751e8a6SLinus Torvalds sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION); 10939e1f1de0SAl Viro 10948cb08329SEric W. Biederman if (!parse_fuse_opt(data, &d, is_bdev, sb->s_user_ns)) 1095c2b8f006SMiklos Szeredi goto err; 1096d8a5ba45SMiklos Szeredi 1097d8091614SMiklos Szeredi if (is_bdev) { 1098875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 1099c2b8f006SMiklos Szeredi err = -EINVAL; 1100d8091614SMiklos Szeredi if (!sb_set_blocksize(sb, d.blksize)) 1101c2b8f006SMiklos Szeredi goto err; 1102875d95ecSMiklos Szeredi #endif 1103d8091614SMiklos Szeredi } else { 110409cbfeafSKirill A. Shutemov sb->s_blocksize = PAGE_SIZE; 110509cbfeafSKirill A. Shutemov sb->s_blocksize_bits = PAGE_SHIFT; 1106d8091614SMiklos Szeredi } 1107d8a5ba45SMiklos Szeredi sb->s_magic = FUSE_SUPER_MAGIC; 1108d8a5ba45SMiklos Szeredi sb->s_op = &fuse_super_operations; 1109703c7362SSeth Forshee sb->s_xattr = fuse_xattr_handlers; 1110d8a5ba45SMiklos Szeredi sb->s_maxbytes = MAX_LFS_FILESIZE; 11110a2da9b2SMiklos Szeredi sb->s_time_gran = 1; 1112dbd561d2SMiklos Szeredi sb->s_export_op = &fuse_export_operations; 11130834136aSMimi Zohar sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE; 11140834136aSMimi Zohar if (sb->s_user_ns != &init_user_ns) 11150834136aSMimi Zohar sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER; 1116d8a5ba45SMiklos Szeredi 1117d8a5ba45SMiklos Szeredi file = fget(d.fd); 1118c2b8f006SMiklos Szeredi err = -EINVAL; 1119d8a5ba45SMiklos Szeredi if (!file) 1120c2b8f006SMiklos Szeredi goto err; 1121d8a5ba45SMiklos Szeredi 11228cb08329SEric W. Biederman /* 11238cb08329SEric W. Biederman * Require mount to happen from the same user namespace which 11248cb08329SEric W. Biederman * opened /dev/fuse to prevent potential attacks. 11258cb08329SEric W. Biederman */ 11268cb08329SEric W. Biederman if (file->f_op != &fuse_dev_operations || 11278cb08329SEric W. Biederman file->f_cred->user_ns != sb->s_user_ns) 1128c2b8f006SMiklos Szeredi goto err_fput; 11290720b315SMiklos Szeredi 1130e45b2546SEric W. Biederman /* 1131e45b2546SEric W. Biederman * If we are not in the initial user namespace posix 1132e45b2546SEric W. Biederman * acls must be translated. 1133e45b2546SEric W. Biederman */ 1134e45b2546SEric W. Biederman if (sb->s_user_ns != &init_user_ns) 1135e45b2546SEric W. Biederman sb->s_xattr = fuse_no_acl_xattr_handlers; 1136e45b2546SEric W. Biederman 11370d179aa5STejun Heo fc = kmalloc(sizeof(*fc), GFP_KERNEL); 1138c2b8f006SMiklos Szeredi err = -ENOMEM; 1139c2b8f006SMiklos Szeredi if (!fc) 1140c2b8f006SMiklos Szeredi goto err_fput; 1141d8a5ba45SMiklos Szeredi 11428cb08329SEric W. Biederman fuse_conn_init(fc, sb->s_user_ns); 11430ad0b325SMiklos Szeredi fc->release = fuse_free_conn; 1144a325f9b9STejun Heo 1145cc080e9eSMiklos Szeredi fud = fuse_dev_alloc(fc); 1146cc080e9eSMiklos Szeredi if (!fud) 1147cc080e9eSMiklos Szeredi goto err_put_conn; 1148cc080e9eSMiklos Szeredi 1149a325f9b9STejun Heo fc->dev = sb->s_dev; 11503b463ae0SJohn Muir fc->sb = sb; 1151a325f9b9STejun Heo err = fuse_bdi_init(fc, sb); 1152a325f9b9STejun Heo if (err) 1153cc080e9eSMiklos Szeredi goto err_dev_free; 11540d179aa5STejun Heo 1155e0a43ddcSMiklos Szeredi /* Handle umasking inside the fuse code */ 11561751e8a6SLinus Torvalds if (sb->s_flags & SB_POSIXACL) 1157e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 11581751e8a6SLinus Torvalds sb->s_flags |= SB_POSIXACL; 1159e0a43ddcSMiklos Szeredi 116029433a29SMiklos Szeredi fc->default_permissions = d.default_permissions; 116129433a29SMiklos Szeredi fc->allow_other = d.allow_other; 1162d8a5ba45SMiklos Szeredi fc->user_id = d.user_id; 116387729a55SMiklos Szeredi fc->group_id = d.group_id; 1164f948d564SMiklos Szeredi fc->max_read = max_t(unsigned, 4096, d.max_read); 11655da784ccSConstantine Shulyupin fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; 1166d8a5ba45SMiklos Szeredi 1167f543f253SMiklos Szeredi /* Used by get_root_inode() */ 1168f543f253SMiklos Szeredi sb->s_fs_info = fc; 1169f543f253SMiklos Szeredi 1170d8a5ba45SMiklos Szeredi err = -ENOMEM; 1171b93f858aSTejun Heo root = fuse_get_root_inode(sb, d.rootmode); 11720ce267ffSMiklos Szeredi sb->s_d_op = &fuse_root_dentry_operations; 117348fde701SAl Viro root_dentry = d_make_root(root); 117448fde701SAl Viro if (!root_dentry) 1175cc080e9eSMiklos Szeredi goto err_dev_free; 11760ce267ffSMiklos Szeredi /* Root dentry doesn't have .d_revalidate */ 1177c35eebe9SAl Viro sb->s_d_op = &fuse_dentry_operations; 1178f543f253SMiklos Szeredi 11794250c066SMaxim Patlasov init_req = fuse_request_alloc(0); 1180ce1d5a49SMiklos Szeredi if (!init_req) 1181ce1d5a49SMiklos Szeredi goto err_put_root; 1182825d6d33SMiklos Szeredi __set_bit(FR_BACKGROUND, &init_req->flags); 1183ce1d5a49SMiklos Szeredi 11840ec7ca41SMiklos Szeredi if (is_bdev) { 11854250c066SMaxim Patlasov fc->destroy_req = fuse_request_alloc(0); 11860ec7ca41SMiklos Szeredi if (!fc->destroy_req) 118717e18ab6SJulia Lawall goto err_free_init_req; 11880ec7ca41SMiklos Szeredi } 11890ec7ca41SMiklos Szeredi 1190bafa9654SMiklos Szeredi mutex_lock(&fuse_mutex); 11918aa09a50SMiklos Szeredi err = -EINVAL; 11928aa09a50SMiklos Szeredi if (file->private_data) 1193bafa9654SMiklos Szeredi goto err_unlock; 11948aa09a50SMiklos Szeredi 1195bafa9654SMiklos Szeredi err = fuse_ctl_add_conn(fc); 1196bafa9654SMiklos Szeredi if (err) 1197bafa9654SMiklos Szeredi goto err_unlock; 1198bafa9654SMiklos Szeredi 1199bafa9654SMiklos Szeredi list_add_tail(&fc->entry, &fuse_conn_list); 1200f543f253SMiklos Szeredi sb->s_root = root_dentry; 1201cc080e9eSMiklos Szeredi file->private_data = fud; 1202bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 12030720b315SMiklos Szeredi /* 12040720b315SMiklos Szeredi * atomic_dec_and_test() in fput() provides the necessary 12050720b315SMiklos Szeredi * memory barrier for file->private_data to be visible on all 12060720b315SMiklos Szeredi * CPUs after this 12070720b315SMiklos Szeredi */ 12080720b315SMiklos Szeredi fput(file); 1209f543f253SMiklos Szeredi 1210ce1d5a49SMiklos Szeredi fuse_send_init(fc, init_req); 1211f543f253SMiklos Szeredi 1212d8a5ba45SMiklos Szeredi return 0; 1213d8a5ba45SMiklos Szeredi 1214bafa9654SMiklos Szeredi err_unlock: 1215bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 121617e18ab6SJulia Lawall err_free_init_req: 1217ce1d5a49SMiklos Szeredi fuse_request_free(init_req); 1218f543f253SMiklos Szeredi err_put_root: 1219f543f253SMiklos Szeredi dput(root_dentry); 1220cc080e9eSMiklos Szeredi err_dev_free: 1221cc080e9eSMiklos Szeredi fuse_dev_free(fud); 1222c2b8f006SMiklos Szeredi err_put_conn: 1223bafa9654SMiklos Szeredi fuse_conn_put(fc); 1224543b8f86STetsuo Handa sb->s_fs_info = NULL; 1225c2b8f006SMiklos Szeredi err_fput: 1226c2b8f006SMiklos Szeredi fput(file); 1227c2b8f006SMiklos Szeredi err: 1228d8a5ba45SMiklos Szeredi return err; 1229d8a5ba45SMiklos Szeredi } 1230d8a5ba45SMiklos Szeredi 12313c26ff6eSAl Viro static struct dentry *fuse_mount(struct file_system_type *fs_type, 1232d8a5ba45SMiklos Szeredi int flags, const char *dev_name, 12333c26ff6eSAl Viro void *raw_data) 1234d8a5ba45SMiklos Szeredi { 12353c26ff6eSAl Viro return mount_nodev(fs_type, flags, raw_data, fuse_fill_super); 1236d8a5ba45SMiklos Szeredi } 1237d8a5ba45SMiklos Szeredi 1238e8f3bd77SMiklos Szeredi static void fuse_sb_destroy(struct super_block *sb) 12393b463ae0SJohn Muir { 12403b463ae0SJohn Muir struct fuse_conn *fc = get_fuse_conn_super(sb); 12413b463ae0SJohn Muir 12423b463ae0SJohn Muir if (fc) { 1243e8f3bd77SMiklos Szeredi fuse_send_destroy(fc); 1244e8f3bd77SMiklos Szeredi 1245e8f3bd77SMiklos Szeredi fuse_abort_conn(fc, false); 1246e8f3bd77SMiklos Szeredi fuse_wait_aborted(fc); 1247e8f3bd77SMiklos Szeredi 12483b463ae0SJohn Muir down_write(&fc->killsb); 12493b463ae0SJohn Muir fc->sb = NULL; 12503b463ae0SJohn Muir up_write(&fc->killsb); 12513b463ae0SJohn Muir } 1252e8f3bd77SMiklos Szeredi } 12533b463ae0SJohn Muir 1254e8f3bd77SMiklos Szeredi static void fuse_kill_sb_anon(struct super_block *sb) 1255e8f3bd77SMiklos Szeredi { 1256e8f3bd77SMiklos Szeredi fuse_sb_destroy(sb); 12573b463ae0SJohn Muir kill_anon_super(sb); 12583b463ae0SJohn Muir } 12593b463ae0SJohn Muir 1260875d95ecSMiklos Szeredi static struct file_system_type fuse_fs_type = { 1261875d95ecSMiklos Szeredi .owner = THIS_MODULE, 1262875d95ecSMiklos Szeredi .name = "fuse", 12634ad769f3SEric W. Biederman .fs_flags = FS_HAS_SUBTYPE | FS_USERNS_MOUNT, 12643c26ff6eSAl Viro .mount = fuse_mount, 12653b463ae0SJohn Muir .kill_sb = fuse_kill_sb_anon, 1266875d95ecSMiklos Szeredi }; 12677f78e035SEric W. Biederman MODULE_ALIAS_FS("fuse"); 1268875d95ecSMiklos Szeredi 1269875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 1270152a0836SAl Viro static struct dentry *fuse_mount_blk(struct file_system_type *fs_type, 1271d6392f87SMiklos Szeredi int flags, const char *dev_name, 1272152a0836SAl Viro void *raw_data) 1273d6392f87SMiklos Szeredi { 1274152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, raw_data, fuse_fill_super); 1275d6392f87SMiklos Szeredi } 1276d6392f87SMiklos Szeredi 12773b463ae0SJohn Muir static void fuse_kill_sb_blk(struct super_block *sb) 12783b463ae0SJohn Muir { 1279e8f3bd77SMiklos Szeredi fuse_sb_destroy(sb); 12803b463ae0SJohn Muir kill_block_super(sb); 12813b463ae0SJohn Muir } 12823b463ae0SJohn Muir 1283d6392f87SMiklos Szeredi static struct file_system_type fuseblk_fs_type = { 1284d6392f87SMiklos Szeredi .owner = THIS_MODULE, 1285d6392f87SMiklos Szeredi .name = "fuseblk", 1286152a0836SAl Viro .mount = fuse_mount_blk, 12873b463ae0SJohn Muir .kill_sb = fuse_kill_sb_blk, 1288edad01e2SAlexey Dobriyan .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, 1289d6392f87SMiklos Szeredi }; 12907f78e035SEric W. Biederman MODULE_ALIAS_FS("fuseblk"); 1291d6392f87SMiklos Szeredi 1292875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1293875d95ecSMiklos Szeredi { 1294875d95ecSMiklos Szeredi return register_filesystem(&fuseblk_fs_type); 1295875d95ecSMiklos Szeredi } 1296875d95ecSMiklos Szeredi 1297875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1298875d95ecSMiklos Szeredi { 1299875d95ecSMiklos Szeredi unregister_filesystem(&fuseblk_fs_type); 1300875d95ecSMiklos Szeredi } 1301875d95ecSMiklos Szeredi #else 1302875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1303875d95ecSMiklos Szeredi { 1304875d95ecSMiklos Szeredi return 0; 1305875d95ecSMiklos Szeredi } 1306875d95ecSMiklos Szeredi 1307875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1308875d95ecSMiklos Szeredi { 1309875d95ecSMiklos Szeredi } 1310875d95ecSMiklos Szeredi #endif 1311875d95ecSMiklos Szeredi 131251cc5068SAlexey Dobriyan static void fuse_inode_init_once(void *foo) 1313d8a5ba45SMiklos Szeredi { 1314d8a5ba45SMiklos Szeredi struct inode *inode = foo; 1315d8a5ba45SMiklos Szeredi 1316d8a5ba45SMiklos Szeredi inode_init_once(inode); 1317d8a5ba45SMiklos Szeredi } 1318d8a5ba45SMiklos Szeredi 1319d8a5ba45SMiklos Szeredi static int __init fuse_fs_init(void) 1320d8a5ba45SMiklos Szeredi { 1321d8a5ba45SMiklos Szeredi int err; 1322d8a5ba45SMiklos Szeredi 1323d8a5ba45SMiklos Szeredi fuse_inode_cachep = kmem_cache_create("fuse_inode", 13245d097056SVladimir Davydov sizeof(struct fuse_inode), 0, 1325df206988SJohannes Weiner SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT|SLAB_RECLAIM_ACCOUNT, 132620c2df83SPaul Mundt fuse_inode_init_once); 1327d8a5ba45SMiklos Szeredi err = -ENOMEM; 1328d6392f87SMiklos Szeredi if (!fuse_inode_cachep) 1329988f0325SAl Viro goto out; 1330988f0325SAl Viro 1331988f0325SAl Viro err = register_fuseblk(); 1332988f0325SAl Viro if (err) 1333988f0325SAl Viro goto out2; 1334988f0325SAl Viro 1335988f0325SAl Viro err = register_filesystem(&fuse_fs_type); 1336988f0325SAl Viro if (err) 1337988f0325SAl Viro goto out3; 1338d8a5ba45SMiklos Szeredi 1339d6392f87SMiklos Szeredi return 0; 1340d6392f87SMiklos Szeredi 1341988f0325SAl Viro out3: 1342875d95ecSMiklos Szeredi unregister_fuseblk(); 1343988f0325SAl Viro out2: 1344988f0325SAl Viro kmem_cache_destroy(fuse_inode_cachep); 1345d6392f87SMiklos Szeredi out: 1346d8a5ba45SMiklos Szeredi return err; 1347d8a5ba45SMiklos Szeredi } 1348d8a5ba45SMiklos Szeredi 1349d8a5ba45SMiklos Szeredi static void fuse_fs_cleanup(void) 1350d8a5ba45SMiklos Szeredi { 1351d8a5ba45SMiklos Szeredi unregister_filesystem(&fuse_fs_type); 1352875d95ecSMiklos Szeredi unregister_fuseblk(); 13538c0a8537SKirill A. Shutemov 13548c0a8537SKirill A. Shutemov /* 13558c0a8537SKirill A. Shutemov * Make sure all delayed rcu free inodes are flushed before we 13568c0a8537SKirill A. Shutemov * destroy cache. 13578c0a8537SKirill A. Shutemov */ 13588c0a8537SKirill A. Shutemov rcu_barrier(); 1359d8a5ba45SMiklos Szeredi kmem_cache_destroy(fuse_inode_cachep); 1360d8a5ba45SMiklos Szeredi } 1361d8a5ba45SMiklos Szeredi 13625c89e17eSGreg Kroah-Hartman static struct kobject *fuse_kobj; 13635c89e17eSGreg Kroah-Hartman 1364f543f253SMiklos Szeredi static int fuse_sysfs_init(void) 1365f543f253SMiklos Szeredi { 1366f543f253SMiklos Szeredi int err; 1367f543f253SMiklos Szeredi 136800d26666SGreg Kroah-Hartman fuse_kobj = kobject_create_and_add("fuse", fs_kobj); 13695c89e17eSGreg Kroah-Hartman if (!fuse_kobj) { 13705c89e17eSGreg Kroah-Hartman err = -ENOMEM; 1371f543f253SMiklos Szeredi goto out_err; 13725c89e17eSGreg Kroah-Hartman } 1373f543f253SMiklos Szeredi 1374f9bb4882SEric W. Biederman err = sysfs_create_mount_point(fuse_kobj, "connections"); 1375f9bb4882SEric W. Biederman if (err) 1376f543f253SMiklos Szeredi goto out_fuse_unregister; 1377f543f253SMiklos Szeredi 1378f543f253SMiklos Szeredi return 0; 1379f543f253SMiklos Szeredi 1380f543f253SMiklos Szeredi out_fuse_unregister: 1381197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1382f543f253SMiklos Szeredi out_err: 1383f543f253SMiklos Szeredi return err; 1384f543f253SMiklos Szeredi } 1385f543f253SMiklos Szeredi 1386f543f253SMiklos Szeredi static void fuse_sysfs_cleanup(void) 1387f543f253SMiklos Szeredi { 1388f9bb4882SEric W. Biederman sysfs_remove_mount_point(fuse_kobj, "connections"); 1389197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1390f543f253SMiklos Szeredi } 1391f543f253SMiklos Szeredi 1392d8a5ba45SMiklos Szeredi static int __init fuse_init(void) 1393d8a5ba45SMiklos Szeredi { 1394d8a5ba45SMiklos Szeredi int res; 1395d8a5ba45SMiklos Szeredi 13961729a16cSMiklos Szeredi printk(KERN_INFO "fuse init (API version %i.%i)\n", 1397d8a5ba45SMiklos Szeredi FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); 1398d8a5ba45SMiklos Szeredi 1399bafa9654SMiklos Szeredi INIT_LIST_HEAD(&fuse_conn_list); 1400d8a5ba45SMiklos Szeredi res = fuse_fs_init(); 1401d8a5ba45SMiklos Szeredi if (res) 1402d8a5ba45SMiklos Szeredi goto err; 1403d8a5ba45SMiklos Szeredi 1404334f485dSMiklos Szeredi res = fuse_dev_init(); 1405334f485dSMiklos Szeredi if (res) 1406334f485dSMiklos Szeredi goto err_fs_cleanup; 1407334f485dSMiklos Szeredi 1408f543f253SMiklos Szeredi res = fuse_sysfs_init(); 1409f543f253SMiklos Szeredi if (res) 1410f543f253SMiklos Szeredi goto err_dev_cleanup; 1411f543f253SMiklos Szeredi 1412bafa9654SMiklos Szeredi res = fuse_ctl_init(); 1413bafa9654SMiklos Szeredi if (res) 1414bafa9654SMiklos Szeredi goto err_sysfs_cleanup; 1415bafa9654SMiklos Szeredi 1416487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 1417487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 1418487ea5afSCsaba Henk 1419d8a5ba45SMiklos Szeredi return 0; 1420d8a5ba45SMiklos Szeredi 1421bafa9654SMiklos Szeredi err_sysfs_cleanup: 1422bafa9654SMiklos Szeredi fuse_sysfs_cleanup(); 1423f543f253SMiklos Szeredi err_dev_cleanup: 1424f543f253SMiklos Szeredi fuse_dev_cleanup(); 1425334f485dSMiklos Szeredi err_fs_cleanup: 1426334f485dSMiklos Szeredi fuse_fs_cleanup(); 1427d8a5ba45SMiklos Szeredi err: 1428d8a5ba45SMiklos Szeredi return res; 1429d8a5ba45SMiklos Szeredi } 1430d8a5ba45SMiklos Szeredi 1431d8a5ba45SMiklos Szeredi static void __exit fuse_exit(void) 1432d8a5ba45SMiklos Szeredi { 1433d8a5ba45SMiklos Szeredi printk(KERN_DEBUG "fuse exit\n"); 1434d8a5ba45SMiklos Szeredi 1435bafa9654SMiklos Szeredi fuse_ctl_cleanup(); 1436f543f253SMiklos Szeredi fuse_sysfs_cleanup(); 1437d8a5ba45SMiklos Szeredi fuse_fs_cleanup(); 1438334f485dSMiklos Szeredi fuse_dev_cleanup(); 1439d8a5ba45SMiklos Szeredi } 1440d8a5ba45SMiklos Szeredi 1441d8a5ba45SMiklos Szeredi module_init(fuse_init); 1442d8a5ba45SMiklos Szeredi module_exit(fuse_exit); 1443