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> 18c30da2e9SDavid Howells #include <linux/fs_context.h> 19c30da2e9SDavid Howells #include <linux/fs_parser.h> 20d8a5ba45SMiklos Szeredi #include <linux/statfs.h> 219c8ef561SMiklos Szeredi #include <linux/random.h> 22e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 23dbd561d2SMiklos Szeredi #include <linux/exportfs.h> 2460bcc88aSSeth Forshee #include <linux/posix_acl.h> 250b6e9ea0SSeth Forshee #include <linux/pid_namespace.h> 26d8a5ba45SMiklos Szeredi 27d8a5ba45SMiklos Szeredi MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); 28d8a5ba45SMiklos Szeredi MODULE_DESCRIPTION("Filesystem in Userspace"); 29d8a5ba45SMiklos Szeredi MODULE_LICENSE("GPL"); 30d8a5ba45SMiklos Szeredi 31e18b890bSChristoph Lameter static struct kmem_cache *fuse_inode_cachep; 32bafa9654SMiklos Szeredi struct list_head fuse_conn_list; 33bafa9654SMiklos Szeredi DEFINE_MUTEX(fuse_mutex); 34d8a5ba45SMiklos Szeredi 35e4dca7b7SKees Cook static int set_global_limit(const char *val, const struct kernel_param *kp); 36487ea5afSCsaba Henk 3779a9d994SCsaba Henk unsigned max_user_bgreq; 38487ea5afSCsaba Henk module_param_call(max_user_bgreq, set_global_limit, param_get_uint, 39487ea5afSCsaba Henk &max_user_bgreq, 0644); 40487ea5afSCsaba Henk __MODULE_PARM_TYPE(max_user_bgreq, "uint"); 41487ea5afSCsaba Henk MODULE_PARM_DESC(max_user_bgreq, 42487ea5afSCsaba Henk "Global limit for the maximum number of backgrounded requests an " 43487ea5afSCsaba Henk "unprivileged user can set"); 44487ea5afSCsaba Henk 4579a9d994SCsaba Henk unsigned max_user_congthresh; 46487ea5afSCsaba Henk module_param_call(max_user_congthresh, set_global_limit, param_get_uint, 47487ea5afSCsaba Henk &max_user_congthresh, 0644); 48487ea5afSCsaba Henk __MODULE_PARM_TYPE(max_user_congthresh, "uint"); 49487ea5afSCsaba Henk MODULE_PARM_DESC(max_user_congthresh, 50487ea5afSCsaba Henk "Global limit for the maximum congestion threshold an " 51487ea5afSCsaba Henk "unprivileged user can set"); 52487ea5afSCsaba Henk 53d8a5ba45SMiklos Szeredi #define FUSE_SUPER_MAGIC 0x65735546 54d8a5ba45SMiklos Szeredi 55d1875dbaSMiklos Szeredi #define FUSE_DEFAULT_BLKSIZE 512 56d1875dbaSMiklos Szeredi 577a6d3c8bSCsaba Henk /** Maximum number of outstanding background requests */ 587a6d3c8bSCsaba Henk #define FUSE_DEFAULT_MAX_BACKGROUND 12 597a6d3c8bSCsaba Henk 607a6d3c8bSCsaba Henk /** Congestion starts at 75% of maximum */ 617a6d3c8bSCsaba Henk #define FUSE_DEFAULT_CONGESTION_THRESHOLD (FUSE_DEFAULT_MAX_BACKGROUND * 3 / 4) 627a6d3c8bSCsaba Henk 63c30da2e9SDavid Howells #ifdef CONFIG_BLOCK 64c30da2e9SDavid Howells static struct file_system_type fuseblk_fs_type; 65c30da2e9SDavid Howells #endif 66c30da2e9SDavid Howells 67a2daff68SRandy Dunlap struct fuse_forget_link *fuse_alloc_forget(void) 6807e77dcaSMiklos Szeredi { 69dc69e98cSKhazhismel Kumykov return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL_ACCOUNT); 7007e77dcaSMiklos Szeredi } 7107e77dcaSMiklos Szeredi 72d8a5ba45SMiklos Szeredi static struct inode *fuse_alloc_inode(struct super_block *sb) 73d8a5ba45SMiklos Szeredi { 74d8a5ba45SMiklos Szeredi struct fuse_inode *fi; 75d8a5ba45SMiklos Szeredi 769031a69cSzhangliguang fi = kmem_cache_alloc(fuse_inode_cachep, GFP_KERNEL); 779031a69cSzhangliguang if (!fi) 78d8a5ba45SMiklos Szeredi return NULL; 79d8a5ba45SMiklos Szeredi 800a0898cfSMiklos Szeredi fi->i_time = 0; 812f1e8196SMiklos Szeredi fi->inval_mask = 0; 82d8a5ba45SMiklos Szeredi fi->nodeid = 0; 839e6268dbSMiklos Szeredi fi->nlookup = 0; 84fbee36b9SJohn Muir fi->attr_version = 0; 8545c72cd7SPavel Shilovsky fi->orig_ino = 0; 864582a4abSFeng Shuo fi->state = 0; 875c672ab3SMiklos Szeredi mutex_init(&fi->mutex); 886ae330caSVivek Goyal init_rwsem(&fi->i_mmap_sem); 89f15ecfefSKirill Tkhai spin_lock_init(&fi->lock); 9007e77dcaSMiklos Szeredi fi->forget = fuse_alloc_forget(); 91c2d0ad00SVivek Goyal if (!fi->forget) 92c2d0ad00SVivek Goyal goto out_free; 93c2d0ad00SVivek Goyal 94c2d0ad00SVivek Goyal if (IS_ENABLED(CONFIG_FUSE_DAX) && !fuse_dax_inode_alloc(sb, fi)) 95c2d0ad00SVivek Goyal goto out_free_forget; 96d8a5ba45SMiklos Szeredi 979031a69cSzhangliguang return &fi->inode; 98c2d0ad00SVivek Goyal 99c2d0ad00SVivek Goyal out_free_forget: 100c2d0ad00SVivek Goyal kfree(fi->forget); 101c2d0ad00SVivek Goyal out_free: 102c2d0ad00SVivek Goyal kmem_cache_free(fuse_inode_cachep, fi); 103c2d0ad00SVivek Goyal return NULL; 104d8a5ba45SMiklos Szeredi } 105d8a5ba45SMiklos Szeredi 1069baf28bbSAl Viro static void fuse_free_inode(struct inode *inode) 107d8a5ba45SMiklos Szeredi { 108e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1099baf28bbSAl Viro 1105c672ab3SMiklos Szeredi mutex_destroy(&fi->mutex); 11107e77dcaSMiklos Szeredi kfree(fi->forget); 112c2d0ad00SVivek Goyal #ifdef CONFIG_FUSE_DAX 113c2d0ad00SVivek Goyal kfree(fi->dax); 114c2d0ad00SVivek Goyal #endif 1159baf28bbSAl Viro kmem_cache_free(fuse_inode_cachep, fi); 116d8a5ba45SMiklos Szeredi } 117d8a5ba45SMiklos Szeredi 118b57922d9SAl Viro static void fuse_evict_inode(struct inode *inode) 119d8a5ba45SMiklos Szeredi { 1209baf28bbSAl Viro struct fuse_inode *fi = get_fuse_inode(inode); 1219baf28bbSAl Viro 12291b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data); 123dbd5768fSJan Kara clear_inode(inode); 1241751e8a6SLinus Torvalds if (inode->i_sb->s_flags & SB_ACTIVE) { 125e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 126c2d0ad00SVivek Goyal 127c2d0ad00SVivek Goyal if (FUSE_IS_DAX(inode)) 128c2d0ad00SVivek Goyal fuse_dax_inode_cleanup(inode); 1291866d779SMax Reitz if (fi->nlookup) { 1301866d779SMax Reitz fuse_queue_forget(fc, fi->forget, fi->nodeid, 1311866d779SMax Reitz fi->nlookup); 13207e77dcaSMiklos Szeredi fi->forget = NULL; 133e5e5558eSMiklos Szeredi } 1341866d779SMax Reitz } 1355d069dbeSMiklos Szeredi if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) { 1369baf28bbSAl Viro WARN_ON(!list_empty(&fi->write_files)); 1379baf28bbSAl Viro WARN_ON(!list_empty(&fi->queued_writes)); 1389baf28bbSAl Viro } 139d8a5ba45SMiklos Szeredi } 140d8a5ba45SMiklos Szeredi 14184c21507SMiklos Szeredi static int fuse_reconfigure(struct fs_context *fsc) 14271421259SMiklos Szeredi { 14384c21507SMiklos Szeredi struct super_block *sb = fsc->root->d_sb; 1440189a2d3SMiklos Szeredi 14502b9984dSTheodore Ts'o sync_filesystem(sb); 14684c21507SMiklos Szeredi if (fsc->sb_flags & SB_MANDLOCK) 14771421259SMiklos Szeredi return -EINVAL; 14871421259SMiklos Szeredi 14971421259SMiklos Szeredi return 0; 15071421259SMiklos Szeredi } 15171421259SMiklos Szeredi 15245c72cd7SPavel Shilovsky /* 15345c72cd7SPavel Shilovsky * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down 15445c72cd7SPavel Shilovsky * so that it will fit. 15545c72cd7SPavel Shilovsky */ 15645c72cd7SPavel Shilovsky static ino_t fuse_squash_ino(u64 ino64) 15745c72cd7SPavel Shilovsky { 15845c72cd7SPavel Shilovsky ino_t ino = (ino_t) ino64; 15945c72cd7SPavel Shilovsky if (sizeof(ino_t) < sizeof(u64)) 16045c72cd7SPavel Shilovsky ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8; 16145c72cd7SPavel Shilovsky return ino; 16245c72cd7SPavel Shilovsky } 16345c72cd7SPavel Shilovsky 1643be5a52bSMiklos Szeredi void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 1653be5a52bSMiklos Szeredi u64 attr_valid) 166d8a5ba45SMiklos Szeredi { 1679ffbb916SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 168ebc14c4dSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 169d8a5ba45SMiklos Szeredi 170f15ecfefSKirill Tkhai lockdep_assert_held(&fi->lock); 171f15ecfefSKirill Tkhai 1724510d86fSKirill Tkhai fi->attr_version = atomic64_inc_return(&fc->attr_version); 1731fb69e78SMiklos Szeredi fi->i_time = attr_valid; 1742f1e8196SMiklos Szeredi WRITE_ONCE(fi->inval_mask, 0); 1751fb69e78SMiklos Szeredi 17645c72cd7SPavel Shilovsky inode->i_ino = fuse_squash_ino(attr->ino); 177ebc14c4dSMiklos Szeredi inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 178bfe86848SMiklos Szeredi set_nlink(inode, attr->nlink); 1798cb08329SEric W. Biederman inode->i_uid = make_kuid(fc->user_ns, attr->uid); 1808cb08329SEric W. Biederman inode->i_gid = make_kgid(fc->user_ns, attr->gid); 181d8a5ba45SMiklos Szeredi inode->i_blocks = attr->blocks; 182d8a5ba45SMiklos Szeredi inode->i_atime.tv_sec = attr->atime; 183d8a5ba45SMiklos Szeredi inode->i_atime.tv_nsec = attr->atimensec; 184b0aa7606SMaxim Patlasov /* mtime from server may be stale due to local buffered write */ 185b0aa7606SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) { 186d8a5ba45SMiklos Szeredi inode->i_mtime.tv_sec = attr->mtime; 187d8a5ba45SMiklos Szeredi inode->i_mtime.tv_nsec = attr->mtimensec; 188d8a5ba45SMiklos Szeredi inode->i_ctime.tv_sec = attr->ctime; 189d8a5ba45SMiklos Szeredi inode->i_ctime.tv_nsec = attr->ctimensec; 19031f3267bSMaxim Patlasov } 191e00d2c2dSMiklos Szeredi 1920e9663eeSMiklos Szeredi if (attr->blksize != 0) 1930e9663eeSMiklos Szeredi inode->i_blkbits = ilog2(attr->blksize); 1940e9663eeSMiklos Szeredi else 1950e9663eeSMiklos Szeredi inode->i_blkbits = inode->i_sb->s_blocksize_bits; 1960e9663eeSMiklos Szeredi 197ebc14c4dSMiklos Szeredi /* 198ebc14c4dSMiklos Szeredi * Don't set the sticky bit in i_mode, unless we want the VFS 199ebc14c4dSMiklos Szeredi * to check permissions. This prevents failures due to the 200ebc14c4dSMiklos Szeredi * check in may_delete(). 201ebc14c4dSMiklos Szeredi */ 202ebc14c4dSMiklos Szeredi fi->orig_i_mode = inode->i_mode; 20329433a29SMiklos Szeredi if (!fc->default_permissions) 204ebc14c4dSMiklos Szeredi inode->i_mode &= ~S_ISVTX; 20545c72cd7SPavel Shilovsky 20645c72cd7SPavel Shilovsky fi->orig_ino = attr->ino; 2079d769e6aSVivek Goyal 2089d769e6aSVivek Goyal /* 2099d769e6aSVivek Goyal * We are refreshing inode data and it is possible that another 2109d769e6aSVivek Goyal * client set suid/sgid or security.capability xattr. So clear 2119d769e6aSVivek Goyal * S_NOSEC. Ideally, we could have cleared it only if suid/sgid 2129d769e6aSVivek Goyal * was set or if security.capability xattr was set. But we don't 2139d769e6aSVivek Goyal * know if security.capability has been set or not. So clear it 2149d769e6aSVivek Goyal * anyway. Its less efficient but should be safe. 2159d769e6aSVivek Goyal */ 2169d769e6aSVivek Goyal inode->i_flags &= ~S_NOSEC; 2173be5a52bSMiklos Szeredi } 2183be5a52bSMiklos Szeredi 2193be5a52bSMiklos Szeredi void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, 2203be5a52bSMiklos Szeredi u64 attr_valid, u64 attr_version) 2213be5a52bSMiklos Szeredi { 2223be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 2233be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 2248373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 2253be5a52bSMiklos Szeredi loff_t oldsize; 226a64ba10fSArnd Bergmann struct timespec64 old_mtime; 2273be5a52bSMiklos Szeredi 228f15ecfefSKirill Tkhai spin_lock(&fi->lock); 22906a7c3c2SMaxim Patlasov if ((attr_version != 0 && fi->attr_version > attr_version) || 23006a7c3c2SMaxim Patlasov test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { 231f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 2323be5a52bSMiklos Szeredi return; 2333be5a52bSMiklos Szeredi } 2343be5a52bSMiklos Szeredi 235a64ba10fSArnd Bergmann old_mtime = inode->i_mtime; 2363be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, attr, attr_valid); 237ebc14c4dSMiklos Szeredi 238e00d2c2dSMiklos Szeredi oldsize = inode->i_size; 2398373200bSPavel Emelyanov /* 2408373200bSPavel Emelyanov * In case of writeback_cache enabled, the cached writes beyond EOF 2418373200bSPavel Emelyanov * extend local i_size without keeping userspace server in sync. So, 2428373200bSPavel Emelyanov * attr->size coming from server can be stale. We cannot trust it. 2438373200bSPavel Emelyanov */ 2448373200bSPavel Emelyanov if (!is_wb || !S_ISREG(inode->i_mode)) 245e00d2c2dSMiklos Szeredi i_size_write(inode, attr->size); 246f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 247e00d2c2dSMiklos Szeredi 2488373200bSPavel Emelyanov if (!is_wb && S_ISREG(inode->i_mode)) { 249eed2179eSBrian Foster bool inval = false; 250eed2179eSBrian Foster 251eed2179eSBrian Foster if (oldsize != attr->size) { 2527caef267SKirill A. Shutemov truncate_pagecache(inode, attr->size); 253ad2ba64dSKirill Smelkov if (!fc->explicit_inval_data) 254eed2179eSBrian Foster inval = true; 255eed2179eSBrian Foster } else if (fc->auto_inval_data) { 256a64ba10fSArnd Bergmann struct timespec64 new_mtime = { 257eed2179eSBrian Foster .tv_sec = attr->mtime, 258eed2179eSBrian Foster .tv_nsec = attr->mtimensec, 259eed2179eSBrian Foster }; 260eed2179eSBrian Foster 261eed2179eSBrian Foster /* 262eed2179eSBrian Foster * Auto inval mode also checks and invalidates if mtime 263eed2179eSBrian Foster * has changed. 264eed2179eSBrian Foster */ 265a64ba10fSArnd Bergmann if (!timespec64_equal(&old_mtime, &new_mtime)) 266eed2179eSBrian Foster inval = true; 267eed2179eSBrian Foster } 268eed2179eSBrian Foster 269eed2179eSBrian Foster if (inval) 270b1009979SMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 271e00d2c2dSMiklos Szeredi } 272d8a5ba45SMiklos Szeredi } 273d8a5ba45SMiklos Szeredi 274d8a5ba45SMiklos Szeredi static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) 275d8a5ba45SMiklos Szeredi { 276d8a5ba45SMiklos Szeredi inode->i_mode = attr->mode & S_IFMT; 2779ffbb916SMiklos Szeredi inode->i_size = attr->size; 278b0aa7606SMaxim Patlasov inode->i_mtime.tv_sec = attr->mtime; 279b0aa7606SMaxim Patlasov inode->i_mtime.tv_nsec = attr->mtimensec; 28031f3267bSMaxim Patlasov inode->i_ctime.tv_sec = attr->ctime; 28131f3267bSMaxim Patlasov inode->i_ctime.tv_nsec = attr->ctimensec; 282e5e5558eSMiklos Szeredi if (S_ISREG(inode->i_mode)) { 283e5e5558eSMiklos Szeredi fuse_init_common(inode); 284b6aeadedSMiklos Szeredi fuse_init_file_inode(inode); 285e5e5558eSMiklos Szeredi } else if (S_ISDIR(inode->i_mode)) 286e5e5558eSMiklos Szeredi fuse_init_dir(inode); 287e5e5558eSMiklos Szeredi else if (S_ISLNK(inode->i_mode)) 288e5e5558eSMiklos Szeredi fuse_init_symlink(inode); 289e5e5558eSMiklos Szeredi else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || 290e5e5558eSMiklos Szeredi S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 291e5e5558eSMiklos Szeredi fuse_init_common(inode); 292e5e5558eSMiklos Szeredi init_special_inode(inode, inode->i_mode, 293e5e5558eSMiklos Szeredi new_decode_dev(attr->rdev)); 29439ee059aSMiklos Szeredi } else 29539ee059aSMiklos Szeredi BUG(); 296d8a5ba45SMiklos Szeredi } 297d8a5ba45SMiklos Szeredi 298fcee216bSMax Reitz static int fuse_inode_eq(struct inode *inode, void *_nodeidp) 299d8a5ba45SMiklos Szeredi { 300b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 301d8a5ba45SMiklos Szeredi if (get_node_id(inode) == nodeid) 302d8a5ba45SMiklos Szeredi return 1; 303d8a5ba45SMiklos Szeredi else 304d8a5ba45SMiklos Szeredi return 0; 305d8a5ba45SMiklos Szeredi } 306d8a5ba45SMiklos Szeredi 307d8a5ba45SMiklos Szeredi static int fuse_inode_set(struct inode *inode, void *_nodeidp) 308d8a5ba45SMiklos Szeredi { 309b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 310d8a5ba45SMiklos Szeredi get_fuse_inode(inode)->nodeid = nodeid; 311d8a5ba45SMiklos Szeredi return 0; 312d8a5ba45SMiklos Szeredi } 313d8a5ba45SMiklos Szeredi 314b48badf0SMiklos Szeredi struct inode *fuse_iget(struct super_block *sb, u64 nodeid, 3151fb69e78SMiklos Szeredi int generation, struct fuse_attr *attr, 3161fb69e78SMiklos Szeredi u64 attr_valid, u64 attr_version) 317d8a5ba45SMiklos Szeredi { 318d8a5ba45SMiklos Szeredi struct inode *inode; 3199e6268dbSMiklos Szeredi struct fuse_inode *fi; 320d8a5ba45SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 321d8a5ba45SMiklos Szeredi 322bf109c64SMax Reitz /* 323bf109c64SMax Reitz * Auto mount points get their node id from the submount root, which is 324bf109c64SMax Reitz * not a unique identifier within this filesystem. 325bf109c64SMax Reitz * 326bf109c64SMax Reitz * To avoid conflicts, do not place submount points into the inode hash 327bf109c64SMax Reitz * table. 328bf109c64SMax Reitz */ 329bf109c64SMax Reitz if (fc->auto_submounts && (attr->flags & FUSE_ATTR_SUBMOUNT) && 330bf109c64SMax Reitz S_ISDIR(attr->mode)) { 331bf109c64SMax Reitz inode = new_inode(sb); 332bf109c64SMax Reitz if (!inode) 333bf109c64SMax Reitz return NULL; 334bf109c64SMax Reitz 335bf109c64SMax Reitz fuse_init_inode(inode, attr); 336bf109c64SMax Reitz get_fuse_inode(inode)->nodeid = nodeid; 337bf109c64SMax Reitz inode->i_flags |= S_AUTOMOUNT; 338bf109c64SMax Reitz goto done; 339bf109c64SMax Reitz } 340bf109c64SMax Reitz 341d8a5ba45SMiklos Szeredi retry: 342d8a5ba45SMiklos Szeredi inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); 343d8a5ba45SMiklos Szeredi if (!inode) 344d8a5ba45SMiklos Szeredi return NULL; 345d8a5ba45SMiklos Szeredi 346d8a5ba45SMiklos Szeredi if ((inode->i_state & I_NEW)) { 347b0aa7606SMaxim Patlasov inode->i_flags |= S_NOATIME; 348d31433c8SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(attr->mode)) 349b0aa7606SMaxim Patlasov inode->i_flags |= S_NOCMTIME; 350d8a5ba45SMiklos Szeredi inode->i_generation = generation; 351d8a5ba45SMiklos Szeredi fuse_init_inode(inode, attr); 352d8a5ba45SMiklos Szeredi unlock_new_inode(inode); 35315db1683SAmir Goldstein } else if (fuse_stale_inode(inode, generation, attr)) { 35415db1683SAmir Goldstein /* nodeid was reused, any I/O on the old inode should fail */ 3555d069dbeSMiklos Szeredi fuse_make_bad(inode); 356d8a5ba45SMiklos Szeredi iput(inode); 357d8a5ba45SMiklos Szeredi goto retry; 358d8a5ba45SMiklos Szeredi } 359bf109c64SMax Reitz done: 3609e6268dbSMiklos Szeredi fi = get_fuse_inode(inode); 361c9d8f5f0SKirill Tkhai spin_lock(&fi->lock); 3629e6268dbSMiklos Szeredi fi->nlookup++; 363c9d8f5f0SKirill Tkhai spin_unlock(&fi->lock); 3641fb69e78SMiklos Szeredi fuse_change_attributes(inode, attr, attr_valid, attr_version); 3651fb69e78SMiklos Szeredi 366d8a5ba45SMiklos Szeredi return inode; 367d8a5ba45SMiklos Szeredi } 368d8a5ba45SMiklos Szeredi 369fcee216bSMax Reitz struct inode *fuse_ilookup(struct fuse_conn *fc, u64 nodeid, 370fcee216bSMax Reitz struct fuse_mount **fm) 371fcee216bSMax Reitz { 372fcee216bSMax Reitz struct fuse_mount *fm_iter; 373fcee216bSMax Reitz struct inode *inode; 374fcee216bSMax Reitz 375fcee216bSMax Reitz WARN_ON(!rwsem_is_locked(&fc->killsb)); 376fcee216bSMax Reitz list_for_each_entry(fm_iter, &fc->mounts, fc_entry) { 377fcee216bSMax Reitz if (!fm_iter->sb) 378fcee216bSMax Reitz continue; 379fcee216bSMax Reitz 380fcee216bSMax Reitz inode = ilookup5(fm_iter->sb, nodeid, fuse_inode_eq, &nodeid); 381fcee216bSMax Reitz if (inode) { 382fcee216bSMax Reitz if (fm) 383fcee216bSMax Reitz *fm = fm_iter; 384fcee216bSMax Reitz return inode; 385fcee216bSMax Reitz } 386fcee216bSMax Reitz } 387fcee216bSMax Reitz 388fcee216bSMax Reitz return NULL; 389fcee216bSMax Reitz } 390fcee216bSMax Reitz 391fcee216bSMax Reitz int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid, 3923b463ae0SJohn Muir loff_t offset, loff_t len) 3933b463ae0SJohn Muir { 3945ddd9cedSMiklos Szeredi struct fuse_inode *fi; 3953b463ae0SJohn Muir struct inode *inode; 3963b463ae0SJohn Muir pgoff_t pg_start; 3973b463ae0SJohn Muir pgoff_t pg_end; 3983b463ae0SJohn Muir 399fcee216bSMax Reitz inode = fuse_ilookup(fc, nodeid, NULL); 4003b463ae0SJohn Muir if (!inode) 4013b463ae0SJohn Muir return -ENOENT; 4023b463ae0SJohn Muir 4035ddd9cedSMiklos Szeredi fi = get_fuse_inode(inode); 4045ddd9cedSMiklos Szeredi spin_lock(&fi->lock); 4055ddd9cedSMiklos Szeredi fi->attr_version = atomic64_inc_return(&fc->attr_version); 4065ddd9cedSMiklos Szeredi spin_unlock(&fi->lock); 4075ddd9cedSMiklos Szeredi 4083b463ae0SJohn Muir fuse_invalidate_attr(inode); 40960bcc88aSSeth Forshee forget_all_cached_acls(inode); 4103b463ae0SJohn Muir if (offset >= 0) { 41109cbfeafSKirill A. Shutemov pg_start = offset >> PAGE_SHIFT; 4123b463ae0SJohn Muir if (len <= 0) 4133b463ae0SJohn Muir pg_end = -1; 4143b463ae0SJohn Muir else 41509cbfeafSKirill A. Shutemov pg_end = (offset + len - 1) >> PAGE_SHIFT; 4163b463ae0SJohn Muir invalidate_inode_pages2_range(inode->i_mapping, 4173b463ae0SJohn Muir pg_start, pg_end); 4183b463ae0SJohn Muir } 4193b463ae0SJohn Muir iput(inode); 4203b463ae0SJohn Muir return 0; 4213b463ae0SJohn Muir } 4223b463ae0SJohn Muir 42363576c13SMiklos Szeredi bool fuse_lock_inode(struct inode *inode) 4245c672ab3SMiklos Szeredi { 42563576c13SMiklos Szeredi bool locked = false; 42663576c13SMiklos Szeredi 42763576c13SMiklos Szeredi if (!get_fuse_conn(inode)->parallel_dirops) { 4285c672ab3SMiklos Szeredi mutex_lock(&get_fuse_inode(inode)->mutex); 42963576c13SMiklos Szeredi locked = true; 4305c672ab3SMiklos Szeredi } 4315c672ab3SMiklos Szeredi 43263576c13SMiklos Szeredi return locked; 43363576c13SMiklos Szeredi } 43463576c13SMiklos Szeredi 43563576c13SMiklos Szeredi void fuse_unlock_inode(struct inode *inode, bool locked) 4365c672ab3SMiklos Szeredi { 43763576c13SMiklos Szeredi if (locked) 4385c672ab3SMiklos Szeredi mutex_unlock(&get_fuse_inode(inode)->mutex); 4395c672ab3SMiklos Szeredi } 4405c672ab3SMiklos Szeredi 44142faad99SAl Viro static void fuse_umount_begin(struct super_block *sb) 44269a53bf2SMiklos Szeredi { 44315c8e72eSVivek Goyal struct fuse_conn *fc = get_fuse_conn_super(sb); 44415c8e72eSVivek Goyal 44515c8e72eSVivek Goyal if (!fc->no_force_umount) 44615c8e72eSVivek Goyal fuse_abort_conn(fc); 44769a53bf2SMiklos Szeredi } 44869a53bf2SMiklos Szeredi 449fcee216bSMax Reitz static void fuse_send_destroy(struct fuse_mount *fm) 4500ec7ca41SMiklos Szeredi { 451fcee216bSMax Reitz if (fm->fc->conn_init) { 4521ccd1ea2SMiklos Szeredi FUSE_ARGS(args); 4531ccd1ea2SMiklos Szeredi 4541ccd1ea2SMiklos Szeredi args.opcode = FUSE_DESTROY; 4551ccd1ea2SMiklos Szeredi args.force = true; 4561ccd1ea2SMiklos Szeredi args.nocreds = true; 457fcee216bSMax Reitz fuse_simple_request(fm, &args); 4580ec7ca41SMiklos Szeredi } 4590ec7ca41SMiklos Szeredi } 4600ec7ca41SMiklos Szeredi 461a325f9b9STejun Heo static void fuse_put_super(struct super_block *sb) 462a325f9b9STejun Heo { 463fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount_super(sb); 464a325f9b9STejun Heo 465514b5e3fSMiklos Szeredi fuse_conn_put(fm->fc); 466514b5e3fSMiklos Szeredi kfree(fm); 467d8a5ba45SMiklos Szeredi } 468d8a5ba45SMiklos Szeredi 469e5e5558eSMiklos Szeredi static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 470e5e5558eSMiklos Szeredi { 471e5e5558eSMiklos Szeredi stbuf->f_type = FUSE_SUPER_MAGIC; 472e5e5558eSMiklos Szeredi stbuf->f_bsize = attr->bsize; 473de5f1202SMiklos Szeredi stbuf->f_frsize = attr->frsize; 474e5e5558eSMiklos Szeredi stbuf->f_blocks = attr->blocks; 475e5e5558eSMiklos Szeredi stbuf->f_bfree = attr->bfree; 476e5e5558eSMiklos Szeredi stbuf->f_bavail = attr->bavail; 477e5e5558eSMiklos Szeredi stbuf->f_files = attr->files; 478e5e5558eSMiklos Szeredi stbuf->f_ffree = attr->ffree; 479e5e5558eSMiklos Szeredi stbuf->f_namelen = attr->namelen; 480e5e5558eSMiklos Szeredi /* fsid is left zero */ 481e5e5558eSMiklos Szeredi } 482e5e5558eSMiklos Szeredi 483726c3342SDavid Howells static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) 484e5e5558eSMiklos Szeredi { 485726c3342SDavid Howells struct super_block *sb = dentry->d_sb; 486fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount_super(sb); 4877078187aSMiklos Szeredi FUSE_ARGS(args); 488e5e5558eSMiklos Szeredi struct fuse_statfs_out outarg; 489e5e5558eSMiklos Szeredi int err; 490e5e5558eSMiklos Szeredi 491fcee216bSMax Reitz if (!fuse_allow_current_process(fm->fc)) { 492e57ac683SMiklos Szeredi buf->f_type = FUSE_SUPER_MAGIC; 493e57ac683SMiklos Szeredi return 0; 494e57ac683SMiklos Szeredi } 495e57ac683SMiklos Szeredi 496de5f1202SMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 497d5b48543SMiklos Szeredi args.in_numargs = 0; 498d5b48543SMiklos Szeredi args.opcode = FUSE_STATFS; 499d5b48543SMiklos Szeredi args.nodeid = get_node_id(d_inode(dentry)); 500d5b48543SMiklos Szeredi args.out_numargs = 1; 501d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outarg); 502d5b48543SMiklos Szeredi args.out_args[0].value = &outarg; 503fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 504e5e5558eSMiklos Szeredi if (!err) 505e5e5558eSMiklos Szeredi convert_fuse_statfs(buf, &outarg.st); 506e5e5558eSMiklos Szeredi return err; 507e5e5558eSMiklos Szeredi } 508e5e5558eSMiklos Szeredi 5092d82ab25SGreg Kurz static int fuse_sync_fs(struct super_block *sb, int wait) 5102d82ab25SGreg Kurz { 5112d82ab25SGreg Kurz struct fuse_mount *fm = get_fuse_mount_super(sb); 5122d82ab25SGreg Kurz struct fuse_conn *fc = fm->fc; 5132d82ab25SGreg Kurz struct fuse_syncfs_in inarg; 5142d82ab25SGreg Kurz FUSE_ARGS(args); 5152d82ab25SGreg Kurz int err; 5162d82ab25SGreg Kurz 5172d82ab25SGreg Kurz /* 5182d82ab25SGreg Kurz * Userspace cannot handle the wait == 0 case. Avoid a 5192d82ab25SGreg Kurz * gratuitous roundtrip. 5202d82ab25SGreg Kurz */ 5212d82ab25SGreg Kurz if (!wait) 5222d82ab25SGreg Kurz return 0; 5232d82ab25SGreg Kurz 5242d82ab25SGreg Kurz /* The filesystem is being unmounted. Nothing to do. */ 5252d82ab25SGreg Kurz if (!sb->s_root) 5262d82ab25SGreg Kurz return 0; 5272d82ab25SGreg Kurz 5282d82ab25SGreg Kurz if (!fc->sync_fs) 5292d82ab25SGreg Kurz return 0; 5302d82ab25SGreg Kurz 5312d82ab25SGreg Kurz memset(&inarg, 0, sizeof(inarg)); 5322d82ab25SGreg Kurz args.in_numargs = 1; 5332d82ab25SGreg Kurz args.in_args[0].size = sizeof(inarg); 5342d82ab25SGreg Kurz args.in_args[0].value = &inarg; 5352d82ab25SGreg Kurz args.opcode = FUSE_SYNCFS; 5362d82ab25SGreg Kurz args.nodeid = get_node_id(sb->s_root->d_inode); 5372d82ab25SGreg Kurz args.out_numargs = 0; 5382d82ab25SGreg Kurz 5392d82ab25SGreg Kurz err = fuse_simple_request(fm, &args); 5402d82ab25SGreg Kurz if (err == -ENOSYS) { 5412d82ab25SGreg Kurz fc->sync_fs = 0; 5422d82ab25SGreg Kurz err = 0; 5432d82ab25SGreg Kurz } 5442d82ab25SGreg Kurz 5452d82ab25SGreg Kurz return err; 5462d82ab25SGreg Kurz } 5472d82ab25SGreg Kurz 548d8a5ba45SMiklos Szeredi enum { 549c30da2e9SDavid Howells OPT_SOURCE, 550c30da2e9SDavid Howells OPT_SUBTYPE, 551d8a5ba45SMiklos Szeredi OPT_FD, 552d8a5ba45SMiklos Szeredi OPT_ROOTMODE, 553d8a5ba45SMiklos Szeredi OPT_USER_ID, 55487729a55SMiklos Szeredi OPT_GROUP_ID, 555d8a5ba45SMiklos Szeredi OPT_DEFAULT_PERMISSIONS, 556d8a5ba45SMiklos Szeredi OPT_ALLOW_OTHER, 557db50b96cSMiklos Szeredi OPT_MAX_READ, 558d8091614SMiklos Szeredi OPT_BLKSIZE, 559d8a5ba45SMiklos Szeredi OPT_ERR 560d8a5ba45SMiklos Szeredi }; 561d8a5ba45SMiklos Szeredi 562d7167b14SAl Viro static const struct fs_parameter_spec fuse_fs_parameters[] = { 563c30da2e9SDavid Howells fsparam_string ("source", OPT_SOURCE), 564c30da2e9SDavid Howells fsparam_u32 ("fd", OPT_FD), 565c30da2e9SDavid Howells fsparam_u32oct ("rootmode", OPT_ROOTMODE), 566c30da2e9SDavid Howells fsparam_u32 ("user_id", OPT_USER_ID), 567c30da2e9SDavid Howells fsparam_u32 ("group_id", OPT_GROUP_ID), 568c30da2e9SDavid Howells fsparam_flag ("default_permissions", OPT_DEFAULT_PERMISSIONS), 569c30da2e9SDavid Howells fsparam_flag ("allow_other", OPT_ALLOW_OTHER), 570c30da2e9SDavid Howells fsparam_u32 ("max_read", OPT_MAX_READ), 571c30da2e9SDavid Howells fsparam_u32 ("blksize", OPT_BLKSIZE), 572c7eb6869SDavid Howells fsparam_string ("subtype", OPT_SUBTYPE), 573c30da2e9SDavid Howells {} 574d8a5ba45SMiklos Szeredi }; 575d8a5ba45SMiklos Szeredi 57684c21507SMiklos Szeredi static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param) 577233a01faSMiklos Szeredi { 578c30da2e9SDavid Howells struct fs_parse_result result; 57984c21507SMiklos Szeredi struct fuse_fs_context *ctx = fsc->fs_private; 580c30da2e9SDavid Howells int opt; 581233a01faSMiklos Szeredi 58284c21507SMiklos Szeredi if (fsc->purpose == FS_CONTEXT_FOR_RECONFIGURE) { 583e8b20a47SMiklos Szeredi /* 584e8b20a47SMiklos Szeredi * Ignore options coming from mount(MS_REMOUNT) for backward 585e8b20a47SMiklos Szeredi * compatibility. 586e8b20a47SMiklos Szeredi */ 58784c21507SMiklos Szeredi if (fsc->oldapi) 588e8b20a47SMiklos Szeredi return 0; 589e8b20a47SMiklos Szeredi 59084c21507SMiklos Szeredi return invalfc(fsc, "No changes allowed in reconfigure"); 591b330966fSMiklos Szeredi } 592b330966fSMiklos Szeredi 59384c21507SMiklos Szeredi opt = fs_parse(fsc, fuse_fs_parameters, param, &result); 594c30da2e9SDavid Howells if (opt < 0) 595c30da2e9SDavid Howells return opt; 596d8a5ba45SMiklos Szeredi 597c30da2e9SDavid Howells switch (opt) { 598c30da2e9SDavid Howells case OPT_SOURCE: 59984c21507SMiklos Szeredi if (fsc->source) 60084c21507SMiklos Szeredi return invalfc(fsc, "Multiple sources specified"); 60184c21507SMiklos Szeredi fsc->source = param->string; 602c30da2e9SDavid Howells param->string = NULL; 603c30da2e9SDavid Howells break; 604d8a5ba45SMiklos Szeredi 605c30da2e9SDavid Howells case OPT_SUBTYPE: 606c30da2e9SDavid Howells if (ctx->subtype) 60784c21507SMiklos Szeredi return invalfc(fsc, "Multiple subtypes specified"); 608c30da2e9SDavid Howells ctx->subtype = param->string; 609c30da2e9SDavid Howells param->string = NULL; 610d8a5ba45SMiklos Szeredi return 0; 611c30da2e9SDavid Howells 612c30da2e9SDavid Howells case OPT_FD: 613c30da2e9SDavid Howells ctx->fd = result.uint_32; 614cabdb4faSzhengbin ctx->fd_present = true; 615d8a5ba45SMiklos Szeredi break; 616d8a5ba45SMiklos Szeredi 617d8a5ba45SMiklos Szeredi case OPT_ROOTMODE: 618c30da2e9SDavid Howells if (!fuse_valid_type(result.uint_32)) 61984c21507SMiklos Szeredi return invalfc(fsc, "Invalid rootmode"); 620c30da2e9SDavid Howells ctx->rootmode = result.uint_32; 621cabdb4faSzhengbin ctx->rootmode_present = true; 622d8a5ba45SMiklos Szeredi break; 623d8a5ba45SMiklos Szeredi 624d8a5ba45SMiklos Szeredi case OPT_USER_ID: 62584c21507SMiklos Szeredi ctx->user_id = make_kuid(fsc->user_ns, result.uint_32); 626c30da2e9SDavid Howells if (!uid_valid(ctx->user_id)) 62784c21507SMiklos Szeredi return invalfc(fsc, "Invalid user_id"); 628cabdb4faSzhengbin ctx->user_id_present = true; 629d8a5ba45SMiklos Szeredi break; 630d8a5ba45SMiklos Szeredi 63187729a55SMiklos Szeredi case OPT_GROUP_ID: 63284c21507SMiklos Szeredi ctx->group_id = make_kgid(fsc->user_ns, result.uint_32); 633c30da2e9SDavid Howells if (!gid_valid(ctx->group_id)) 63484c21507SMiklos Szeredi return invalfc(fsc, "Invalid group_id"); 635cabdb4faSzhengbin ctx->group_id_present = true; 63687729a55SMiklos Szeredi break; 63787729a55SMiklos Szeredi 6381e9a4ed9SMiklos Szeredi case OPT_DEFAULT_PERMISSIONS: 639cabdb4faSzhengbin ctx->default_permissions = true; 6401e9a4ed9SMiklos Szeredi break; 6411e9a4ed9SMiklos Szeredi 6421e9a4ed9SMiklos Szeredi case OPT_ALLOW_OTHER: 643cabdb4faSzhengbin ctx->allow_other = true; 6441e9a4ed9SMiklos Szeredi break; 6451e9a4ed9SMiklos Szeredi 646db50b96cSMiklos Szeredi case OPT_MAX_READ: 647c30da2e9SDavid Howells ctx->max_read = result.uint_32; 648db50b96cSMiklos Szeredi break; 649db50b96cSMiklos Szeredi 650d8091614SMiklos Szeredi case OPT_BLKSIZE: 651c30da2e9SDavid Howells if (!ctx->is_bdev) 65284c21507SMiklos Szeredi return invalfc(fsc, "blksize only supported for fuseblk"); 653c30da2e9SDavid Howells ctx->blksize = result.uint_32; 654d8091614SMiklos Szeredi break; 655d8091614SMiklos Szeredi 656d8a5ba45SMiklos Szeredi default: 657c30da2e9SDavid Howells return -EINVAL; 658d8a5ba45SMiklos Szeredi } 6595a533682SMiklos Szeredi 660d8a5ba45SMiklos Szeredi return 0; 661c30da2e9SDavid Howells } 662d8a5ba45SMiklos Szeredi 66384c21507SMiklos Szeredi static void fuse_free_fsc(struct fs_context *fsc) 664c30da2e9SDavid Howells { 66584c21507SMiklos Szeredi struct fuse_fs_context *ctx = fsc->fs_private; 666c30da2e9SDavid Howells 667c30da2e9SDavid Howells if (ctx) { 668c30da2e9SDavid Howells kfree(ctx->subtype); 669c30da2e9SDavid Howells kfree(ctx); 670c30da2e9SDavid Howells } 671d8a5ba45SMiklos Szeredi } 672d8a5ba45SMiklos Szeredi 67334c80b1dSAl Viro static int fuse_show_options(struct seq_file *m, struct dentry *root) 674d8a5ba45SMiklos Szeredi { 67534c80b1dSAl Viro struct super_block *sb = root->d_sb; 67634c80b1dSAl Viro struct fuse_conn *fc = get_fuse_conn_super(sb); 677d8a5ba45SMiklos Szeredi 678f4fd4ae3SVivek Goyal if (fc->legacy_opts_show) { 679f4fd4ae3SVivek Goyal seq_printf(m, ",user_id=%u", 680f4fd4ae3SVivek Goyal from_kuid_munged(fc->user_ns, fc->user_id)); 681f4fd4ae3SVivek Goyal seq_printf(m, ",group_id=%u", 682f4fd4ae3SVivek Goyal from_kgid_munged(fc->user_ns, fc->group_id)); 68329433a29SMiklos Szeredi if (fc->default_permissions) 6841e9a4ed9SMiklos Szeredi seq_puts(m, ",default_permissions"); 68529433a29SMiklos Szeredi if (fc->allow_other) 6861e9a4ed9SMiklos Szeredi seq_puts(m, ",allow_other"); 687db50b96cSMiklos Szeredi if (fc->max_read != ~0) 688db50b96cSMiklos Szeredi seq_printf(m, ",max_read=%u", fc->max_read); 68934c80b1dSAl Viro if (sb->s_bdev && sb->s_blocksize != FUSE_DEFAULT_BLKSIZE) 69034c80b1dSAl Viro seq_printf(m, ",blksize=%lu", sb->s_blocksize); 691f4fd4ae3SVivek Goyal } 6921dd53957SVivek Goyal #ifdef CONFIG_FUSE_DAX 6931dd53957SVivek Goyal if (fc->dax) 6941dd53957SVivek Goyal seq_puts(m, ",dax"); 6951dd53957SVivek Goyal #endif 6961dd53957SVivek Goyal 697d8a5ba45SMiklos Szeredi return 0; 698d8a5ba45SMiklos Szeredi } 699d8a5ba45SMiklos Szeredi 700ae3aad77SStefan Hajnoczi static void fuse_iqueue_init(struct fuse_iqueue *fiq, 701ae3aad77SStefan Hajnoczi const struct fuse_iqueue_ops *ops, 702ae3aad77SStefan Hajnoczi void *priv) 703f88996a9SMiklos Szeredi { 704f88996a9SMiklos Szeredi memset(fiq, 0, sizeof(struct fuse_iqueue)); 70576e43c8cSEric Biggers spin_lock_init(&fiq->lock); 706f88996a9SMiklos Szeredi init_waitqueue_head(&fiq->waitq); 707f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->pending); 708f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->interrupts); 709f88996a9SMiklos Szeredi fiq->forget_list_tail = &fiq->forget_list_head; 710e16714d8SMiklos Szeredi fiq->connected = 1; 711ae3aad77SStefan Hajnoczi fiq->ops = ops; 712ae3aad77SStefan Hajnoczi fiq->priv = priv; 713f88996a9SMiklos Szeredi } 714f88996a9SMiklos Szeredi 7153a2b5b9cSMiklos Szeredi static void fuse_pqueue_init(struct fuse_pqueue *fpq) 7163a2b5b9cSMiklos Szeredi { 717be2ff42cSKirill Tkhai unsigned int i; 718be2ff42cSKirill Tkhai 71945a91cb1SMiklos Szeredi spin_lock_init(&fpq->lock); 720be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) 721be2ff42cSKirill Tkhai INIT_LIST_HEAD(&fpq->processing[i]); 7223a2b5b9cSMiklos Szeredi INIT_LIST_HEAD(&fpq->io); 723e96edd94SMiklos Szeredi fpq->connected = 1; 7243a2b5b9cSMiklos Szeredi } 7253a2b5b9cSMiklos Szeredi 726fcee216bSMax Reitz void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, 727fcee216bSMax Reitz struct user_namespace *user_ns, 728ae3aad77SStefan Hajnoczi const struct fuse_iqueue_ops *fiq_ops, void *fiq_priv) 729d8a5ba45SMiklos Szeredi { 7300d179aa5STejun Heo memset(fc, 0, sizeof(*fc)); 731d7133114SMiklos Szeredi spin_lock_init(&fc->lock); 732ae2dffa3SKirill Tkhai spin_lock_init(&fc->bg_lock); 7333b463ae0SJohn Muir init_rwsem(&fc->killsb); 734095fc40aSElena Reshetova refcount_set(&fc->count, 1); 735c3696046SMiklos Szeredi atomic_set(&fc->dev_count, 1); 73608a53cdcSMiklos Szeredi init_waitqueue_head(&fc->blocked_waitq); 737ae3aad77SStefan Hajnoczi fuse_iqueue_init(&fc->iq, fiq_ops, fiq_priv); 738d12def1bSMiklos Szeredi INIT_LIST_HEAD(&fc->bg_queue); 7390d179aa5STejun Heo INIT_LIST_HEAD(&fc->entry); 740cc080e9eSMiklos Szeredi INIT_LIST_HEAD(&fc->devices); 741095da6cbSMiklos Szeredi atomic_set(&fc->num_waiting, 0); 7427a6d3c8bSCsaba Henk fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; 7437a6d3c8bSCsaba Henk fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; 74475126f55SMiklos Szeredi atomic64_set(&fc->khctr, 0); 74595668a69STejun Heo fc->polled_files = RB_ROOT; 7460aada884SMaxim Patlasov fc->blocked = 0; 747796523fbSMaxim Patlasov fc->initialized = 0; 748e16714d8SMiklos Szeredi fc->connected = 1; 7494510d86fSKirill Tkhai atomic64_set(&fc->attr_version, 1); 7509c8ef561SMiklos Szeredi get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); 7510b6e9ea0SSeth Forshee fc->pid_ns = get_pid_ns(task_active_pid_ns(current)); 7528cb08329SEric W. Biederman fc->user_ns = get_user_ns(user_ns); 7538a3177dbSMiklos Szeredi fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; 754a7f0d7aaSConnor Kuehl fc->max_pages_limit = FUSE_MAX_MAX_PAGES; 755fcee216bSMax Reitz 756fcee216bSMax Reitz INIT_LIST_HEAD(&fc->mounts); 757fcee216bSMax Reitz list_add(&fm->fc_entry, &fc->mounts); 758fcee216bSMax Reitz fm->fc = fc; 759d8a5ba45SMiklos Szeredi } 7600d179aa5STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_init); 761d8a5ba45SMiklos Szeredi 762bafa9654SMiklos Szeredi void fuse_conn_put(struct fuse_conn *fc) 763bafa9654SMiklos Szeredi { 764095fc40aSElena Reshetova if (refcount_dec_and_test(&fc->count)) { 765a62a8ef9SStefan Hajnoczi struct fuse_iqueue *fiq = &fc->iq; 766a62a8ef9SStefan Hajnoczi 7671dd53957SVivek Goyal if (IS_ENABLED(CONFIG_FUSE_DAX)) 7681dd53957SVivek Goyal fuse_dax_conn_free(fc); 769a62a8ef9SStefan Hajnoczi if (fiq->ops->release) 770a62a8ef9SStefan Hajnoczi fiq->ops->release(fiq); 7710b6e9ea0SSeth Forshee put_pid_ns(fc->pid_ns); 7728cb08329SEric W. Biederman put_user_ns(fc->user_ns); 77343901aabSTejun Heo fc->release(fc); 774bafa9654SMiklos Szeredi } 775d2a85164SMiklos Szeredi } 77608cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_put); 777bafa9654SMiklos Szeredi 778bafa9654SMiklos Szeredi struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) 779bafa9654SMiklos Szeredi { 780095fc40aSElena Reshetova refcount_inc(&fc->count); 781bafa9654SMiklos Szeredi return fc; 782bafa9654SMiklos Szeredi } 78308cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_get); 784bafa9654SMiklos Szeredi 785b93f858aSTejun Heo static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) 786d8a5ba45SMiklos Szeredi { 787d8a5ba45SMiklos Szeredi struct fuse_attr attr; 788d8a5ba45SMiklos Szeredi memset(&attr, 0, sizeof(attr)); 789d8a5ba45SMiklos Szeredi 790d8a5ba45SMiklos Szeredi attr.mode = mode; 791d8a5ba45SMiklos Szeredi attr.ino = FUSE_ROOT_ID; 792074406faSMiklos Szeredi attr.nlink = 1; 7931fb69e78SMiklos Szeredi return fuse_iget(sb, 1, 0, &attr, 0, 0); 794d8a5ba45SMiklos Szeredi } 795d8a5ba45SMiklos Szeredi 7961729a16cSMiklos Szeredi struct fuse_inode_handle { 797dbd561d2SMiklos Szeredi u64 nodeid; 798dbd561d2SMiklos Szeredi u32 generation; 799dbd561d2SMiklos Szeredi }; 800dbd561d2SMiklos Szeredi 801dbd561d2SMiklos Szeredi static struct dentry *fuse_get_dentry(struct super_block *sb, 802dbd561d2SMiklos Szeredi struct fuse_inode_handle *handle) 803dbd561d2SMiklos Szeredi { 80433670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 805dbd561d2SMiklos Szeredi struct inode *inode; 806dbd561d2SMiklos Szeredi struct dentry *entry; 807dbd561d2SMiklos Szeredi int err = -ESTALE; 808dbd561d2SMiklos Szeredi 809dbd561d2SMiklos Szeredi if (handle->nodeid == 0) 810dbd561d2SMiklos Szeredi goto out_err; 811dbd561d2SMiklos Szeredi 812dbd561d2SMiklos Szeredi inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid); 81333670fa2SMiklos Szeredi if (!inode) { 81433670fa2SMiklos Szeredi struct fuse_entry_out outarg; 81513983d06SAl Viro const struct qstr name = QSTR_INIT(".", 1); 81633670fa2SMiklos Szeredi 81733670fa2SMiklos Szeredi if (!fc->export_support) 818dbd561d2SMiklos Szeredi goto out_err; 81933670fa2SMiklos Szeredi 82033670fa2SMiklos Szeredi err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg, 82133670fa2SMiklos Szeredi &inode); 82233670fa2SMiklos Szeredi if (err && err != -ENOENT) 82333670fa2SMiklos Szeredi goto out_err; 82433670fa2SMiklos Szeredi if (err || !inode) { 82533670fa2SMiklos Szeredi err = -ESTALE; 82633670fa2SMiklos Szeredi goto out_err; 82733670fa2SMiklos Szeredi } 82833670fa2SMiklos Szeredi err = -EIO; 82933670fa2SMiklos Szeredi if (get_node_id(inode) != handle->nodeid) 83033670fa2SMiklos Szeredi goto out_iput; 83133670fa2SMiklos Szeredi } 832dbd561d2SMiklos Szeredi err = -ESTALE; 833dbd561d2SMiklos Szeredi if (inode->i_generation != handle->generation) 834dbd561d2SMiklos Szeredi goto out_iput; 835dbd561d2SMiklos Szeredi 83644003728SChristoph Hellwig entry = d_obtain_alias(inode); 837c35eebe9SAl Viro if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) 838dbd561d2SMiklos Szeredi fuse_invalidate_entry_cache(entry); 839dbd561d2SMiklos Szeredi 840dbd561d2SMiklos Szeredi return entry; 841dbd561d2SMiklos Szeredi 842dbd561d2SMiklos Szeredi out_iput: 843dbd561d2SMiklos Szeredi iput(inode); 844dbd561d2SMiklos Szeredi out_err: 845dbd561d2SMiklos Szeredi return ERR_PTR(err); 846dbd561d2SMiklos Szeredi } 847dbd561d2SMiklos Szeredi 848b0b0382bSAl Viro static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len, 849b0b0382bSAl Viro struct inode *parent) 850dbd561d2SMiklos Szeredi { 851b0b0382bSAl Viro int len = parent ? 6 : 3; 852dbd561d2SMiklos Szeredi u64 nodeid; 853dbd561d2SMiklos Szeredi u32 generation; 854dbd561d2SMiklos Szeredi 8555fe0c237SAneesh Kumar K.V if (*max_len < len) { 8565fe0c237SAneesh Kumar K.V *max_len = len; 85794e07a75SNamjae Jeon return FILEID_INVALID; 8585fe0c237SAneesh Kumar K.V } 859dbd561d2SMiklos Szeredi 860dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(inode)->nodeid; 861dbd561d2SMiklos Szeredi generation = inode->i_generation; 862dbd561d2SMiklos Szeredi 863dbd561d2SMiklos Szeredi fh[0] = (u32)(nodeid >> 32); 864dbd561d2SMiklos Szeredi fh[1] = (u32)(nodeid & 0xffffffff); 865dbd561d2SMiklos Szeredi fh[2] = generation; 866dbd561d2SMiklos Szeredi 867b0b0382bSAl Viro if (parent) { 868dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(parent)->nodeid; 869dbd561d2SMiklos Szeredi generation = parent->i_generation; 870dbd561d2SMiklos Szeredi 871dbd561d2SMiklos Szeredi fh[3] = (u32)(nodeid >> 32); 872dbd561d2SMiklos Szeredi fh[4] = (u32)(nodeid & 0xffffffff); 873dbd561d2SMiklos Szeredi fh[5] = generation; 874dbd561d2SMiklos Szeredi } 875dbd561d2SMiklos Szeredi 876dbd561d2SMiklos Szeredi *max_len = len; 877b0b0382bSAl Viro return parent ? 0x82 : 0x81; 878dbd561d2SMiklos Szeredi } 879dbd561d2SMiklos Szeredi 880dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_dentry(struct super_block *sb, 881dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 882dbd561d2SMiklos Szeredi { 883dbd561d2SMiklos Szeredi struct fuse_inode_handle handle; 884dbd561d2SMiklos Szeredi 885dbd561d2SMiklos Szeredi if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3) 886dbd561d2SMiklos Szeredi return NULL; 887dbd561d2SMiklos Szeredi 888dbd561d2SMiklos Szeredi handle.nodeid = (u64) fid->raw[0] << 32; 889dbd561d2SMiklos Szeredi handle.nodeid |= (u64) fid->raw[1]; 890dbd561d2SMiklos Szeredi handle.generation = fid->raw[2]; 891dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &handle); 892dbd561d2SMiklos Szeredi } 893dbd561d2SMiklos Szeredi 894dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_parent(struct super_block *sb, 895dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 896dbd561d2SMiklos Szeredi { 897dbd561d2SMiklos Szeredi struct fuse_inode_handle parent; 898dbd561d2SMiklos Szeredi 899dbd561d2SMiklos Szeredi if (fh_type != 0x82 || fh_len < 6) 900dbd561d2SMiklos Szeredi return NULL; 901dbd561d2SMiklos Szeredi 902dbd561d2SMiklos Szeredi parent.nodeid = (u64) fid->raw[3] << 32; 903dbd561d2SMiklos Szeredi parent.nodeid |= (u64) fid->raw[4]; 904dbd561d2SMiklos Szeredi parent.generation = fid->raw[5]; 905dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &parent); 906dbd561d2SMiklos Szeredi } 907dbd561d2SMiklos Szeredi 90833670fa2SMiklos Szeredi static struct dentry *fuse_get_parent(struct dentry *child) 90933670fa2SMiklos Szeredi { 9102b0143b5SDavid Howells struct inode *child_inode = d_inode(child); 91133670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(child_inode); 91233670fa2SMiklos Szeredi struct inode *inode; 91333670fa2SMiklos Szeredi struct dentry *parent; 91433670fa2SMiklos Szeredi struct fuse_entry_out outarg; 91533670fa2SMiklos Szeredi int err; 91633670fa2SMiklos Szeredi 91733670fa2SMiklos Szeredi if (!fc->export_support) 91833670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 91933670fa2SMiklos Szeredi 92033670fa2SMiklos Szeredi err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode), 92180e5d1ffSAl Viro &dotdot_name, &outarg, &inode); 92244003728SChristoph Hellwig if (err) { 92344003728SChristoph Hellwig if (err == -ENOENT) 92433670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 92544003728SChristoph Hellwig return ERR_PTR(err); 92633670fa2SMiklos Szeredi } 92744003728SChristoph Hellwig 92844003728SChristoph Hellwig parent = d_obtain_alias(inode); 929c35eebe9SAl Viro if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) 93033670fa2SMiklos Szeredi fuse_invalidate_entry_cache(parent); 93133670fa2SMiklos Szeredi 93233670fa2SMiklos Szeredi return parent; 93333670fa2SMiklos Szeredi } 934dbd561d2SMiklos Szeredi 935dbd561d2SMiklos Szeredi static const struct export_operations fuse_export_operations = { 936dbd561d2SMiklos Szeredi .fh_to_dentry = fuse_fh_to_dentry, 937dbd561d2SMiklos Szeredi .fh_to_parent = fuse_fh_to_parent, 938dbd561d2SMiklos Szeredi .encode_fh = fuse_encode_fh, 93933670fa2SMiklos Szeredi .get_parent = fuse_get_parent, 940dbd561d2SMiklos Szeredi }; 941dbd561d2SMiklos Szeredi 942ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations fuse_super_operations = { 943d8a5ba45SMiklos Szeredi .alloc_inode = fuse_alloc_inode, 9449baf28bbSAl Viro .free_inode = fuse_free_inode, 945b57922d9SAl Viro .evict_inode = fuse_evict_inode, 9461e18bda8SMiklos Szeredi .write_inode = fuse_write_inode, 947ead5f0b5SMiklos Szeredi .drop_inode = generic_delete_inode, 948d8a5ba45SMiklos Szeredi .put_super = fuse_put_super, 94969a53bf2SMiklos Szeredi .umount_begin = fuse_umount_begin, 950e5e5558eSMiklos Szeredi .statfs = fuse_statfs, 9512d82ab25SGreg Kurz .sync_fs = fuse_sync_fs, 952d8a5ba45SMiklos Szeredi .show_options = fuse_show_options, 953d8a5ba45SMiklos Szeredi }; 954d8a5ba45SMiklos Szeredi 955487ea5afSCsaba Henk static void sanitize_global_limit(unsigned *limit) 956487ea5afSCsaba Henk { 957f22f812dSMiklos Szeredi /* 958f22f812dSMiklos Szeredi * The default maximum number of async requests is calculated to consume 959f22f812dSMiklos Szeredi * 1/2^13 of the total memory, assuming 392 bytes per request. 960f22f812dSMiklos Szeredi */ 961487ea5afSCsaba Henk if (*limit == 0) 962f22f812dSMiklos Szeredi *limit = ((totalram_pages() << PAGE_SHIFT) >> 13) / 392; 963487ea5afSCsaba Henk 964487ea5afSCsaba Henk if (*limit >= 1 << 16) 965487ea5afSCsaba Henk *limit = (1 << 16) - 1; 966487ea5afSCsaba Henk } 967487ea5afSCsaba Henk 968e4dca7b7SKees Cook static int set_global_limit(const char *val, const struct kernel_param *kp) 969487ea5afSCsaba Henk { 970487ea5afSCsaba Henk int rv; 971487ea5afSCsaba Henk 972487ea5afSCsaba Henk rv = param_set_uint(val, kp); 973487ea5afSCsaba Henk if (rv) 974487ea5afSCsaba Henk return rv; 975487ea5afSCsaba Henk 976487ea5afSCsaba Henk sanitize_global_limit((unsigned *)kp->arg); 977487ea5afSCsaba Henk 978487ea5afSCsaba Henk return 0; 979487ea5afSCsaba Henk } 980487ea5afSCsaba Henk 981487ea5afSCsaba Henk static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) 982487ea5afSCsaba Henk { 983487ea5afSCsaba Henk int cap_sys_admin = capable(CAP_SYS_ADMIN); 984487ea5afSCsaba Henk 985487ea5afSCsaba Henk if (arg->minor < 13) 986487ea5afSCsaba Henk return; 987487ea5afSCsaba Henk 988487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 989487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 990487ea5afSCsaba Henk 991ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 992487ea5afSCsaba Henk if (arg->max_background) { 993487ea5afSCsaba Henk fc->max_background = arg->max_background; 994487ea5afSCsaba Henk 995487ea5afSCsaba Henk if (!cap_sys_admin && fc->max_background > max_user_bgreq) 996487ea5afSCsaba Henk fc->max_background = max_user_bgreq; 997487ea5afSCsaba Henk } 998487ea5afSCsaba Henk if (arg->congestion_threshold) { 999487ea5afSCsaba Henk fc->congestion_threshold = arg->congestion_threshold; 1000487ea5afSCsaba Henk 1001487ea5afSCsaba Henk if (!cap_sys_admin && 1002487ea5afSCsaba Henk fc->congestion_threshold > max_user_congthresh) 1003487ea5afSCsaba Henk fc->congestion_threshold = max_user_congthresh; 1004487ea5afSCsaba Henk } 1005ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 1006487ea5afSCsaba Henk } 1007487ea5afSCsaba Henk 1008615047efSMiklos Szeredi struct fuse_init_args { 1009615047efSMiklos Szeredi struct fuse_args args; 1010615047efSMiklos Szeredi struct fuse_init_in in; 1011615047efSMiklos Szeredi struct fuse_init_out out; 1012615047efSMiklos Szeredi }; 10139b9a0469SMiklos Szeredi 1014fcee216bSMax Reitz static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args, 1015615047efSMiklos Szeredi int error) 1016615047efSMiklos Szeredi { 1017fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 1018615047efSMiklos Szeredi struct fuse_init_args *ia = container_of(args, typeof(*ia), args); 1019615047efSMiklos Szeredi struct fuse_init_out *arg = &ia->out; 1020fd1a1dc6SStefan Hajnoczi bool ok = true; 1021615047efSMiklos Szeredi 1022615047efSMiklos Szeredi if (error || arg->major != FUSE_KERNEL_VERSION) 1023fd1a1dc6SStefan Hajnoczi ok = false; 10249b9a0469SMiklos Szeredi else { 10259cd68455SMiklos Szeredi unsigned long ra_pages; 10269cd68455SMiklos Szeredi 1027487ea5afSCsaba Henk process_init_limits(fc, arg); 1028487ea5afSCsaba Henk 10299cd68455SMiklos Szeredi if (arg->minor >= 6) { 103009cbfeafSKirill A. Shutemov ra_pages = arg->max_readahead / PAGE_SIZE; 10319cd68455SMiklos Szeredi if (arg->flags & FUSE_ASYNC_READ) 10329cd68455SMiklos Szeredi fc->async_read = 1; 103371421259SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 103471421259SMiklos Szeredi fc->no_lock = 1; 103537fb3a30SMiklos Szeredi if (arg->minor >= 17) { 103637fb3a30SMiklos Szeredi if (!(arg->flags & FUSE_FLOCK_LOCKS)) 103737fb3a30SMiklos Szeredi fc->no_flock = 1; 103824114504SMiklos Szeredi } else { 103924114504SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 104024114504SMiklos Szeredi fc->no_flock = 1; 104137fb3a30SMiklos Szeredi } 10426ff958edSMiklos Szeredi if (arg->flags & FUSE_ATOMIC_O_TRUNC) 10436ff958edSMiklos Szeredi fc->atomic_o_trunc = 1; 104433670fa2SMiklos Szeredi if (arg->minor >= 9) { 104533670fa2SMiklos Szeredi /* LOOKUP has dependency on proto version */ 104633670fa2SMiklos Szeredi if (arg->flags & FUSE_EXPORT_SUPPORT) 104733670fa2SMiklos Szeredi fc->export_support = 1; 104833670fa2SMiklos Szeredi } 104978bb6cb9SMiklos Szeredi if (arg->flags & FUSE_BIG_WRITES) 105078bb6cb9SMiklos Szeredi fc->big_writes = 1; 1051e0a43ddcSMiklos Szeredi if (arg->flags & FUSE_DONT_MASK) 1052e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 105372d0d248SBrian Foster if (arg->flags & FUSE_AUTO_INVAL_DATA) 105472d0d248SBrian Foster fc->auto_inval_data = 1; 1055ad2ba64dSKirill Smelkov else if (arg->flags & FUSE_EXPLICIT_INVAL_DATA) 1056ad2ba64dSKirill Smelkov fc->explicit_inval_data = 1; 105728420dadSMiklos Szeredi if (arg->flags & FUSE_DO_READDIRPLUS) { 10580b05b183SAnand V. Avati fc->do_readdirplus = 1; 1059634734b6SEric Wong if (arg->flags & FUSE_READDIRPLUS_AUTO) 1060634734b6SEric Wong fc->readdirplus_auto = 1; 106128420dadSMiklos Szeredi } 106260b9df7aSMiklos Szeredi if (arg->flags & FUSE_ASYNC_DIO) 106360b9df7aSMiklos Szeredi fc->async_dio = 1; 10644d99ff8fSPavel Emelyanov if (arg->flags & FUSE_WRITEBACK_CACHE) 10654d99ff8fSPavel Emelyanov fc->writeback_cache = 1; 10665c672ab3SMiklos Szeredi if (arg->flags & FUSE_PARALLEL_DIROPS) 10675c672ab3SMiklos Szeredi fc->parallel_dirops = 1; 10685e940c1dSMiklos Szeredi if (arg->flags & FUSE_HANDLE_KILLPRIV) 10695e940c1dSMiklos Szeredi fc->handle_killpriv = 1; 1070e27c9d38SMiklos Szeredi if (arg->time_gran && arg->time_gran <= 1000000000) 1071fcee216bSMax Reitz fm->sb->s_time_gran = arg->time_gran; 107260bcc88aSSeth Forshee if ((arg->flags & FUSE_POSIX_ACL)) { 107329433a29SMiklos Szeredi fc->default_permissions = 1; 107460bcc88aSSeth Forshee fc->posix_acl = 1; 1075fcee216bSMax Reitz fm->sb->s_xattr = fuse_acl_xattr_handlers; 107660bcc88aSSeth Forshee } 10775571f1e6SDan Schatzberg if (arg->flags & FUSE_CACHE_SYMLINKS) 10785571f1e6SDan Schatzberg fc->cache_symlinks = 1; 10793b7008b2SSzymon Lukasz if (arg->flags & FUSE_ABORT_ERROR) 10803b7008b2SSzymon Lukasz fc->abort_err = 1; 10815da784ccSConstantine Shulyupin if (arg->flags & FUSE_MAX_PAGES) { 10825da784ccSConstantine Shulyupin fc->max_pages = 1083a7f0d7aaSConnor Kuehl min_t(unsigned int, fc->max_pages_limit, 10845da784ccSConstantine Shulyupin max_t(unsigned int, arg->max_pages, 1)); 10855da784ccSConstantine Shulyupin } 1086fd1a1dc6SStefan Hajnoczi if (IS_ENABLED(CONFIG_FUSE_DAX) && 1087fd1a1dc6SStefan Hajnoczi arg->flags & FUSE_MAP_ALIGNMENT && 1088fd1a1dc6SStefan Hajnoczi !fuse_dax_check_alignment(fc, arg->map_alignment)) { 1089fd1a1dc6SStefan Hajnoczi ok = false; 1090fd1a1dc6SStefan Hajnoczi } 10919d769e6aSVivek Goyal if (arg->flags & FUSE_HANDLE_KILLPRIV_V2) { 109263f9909fSVivek Goyal fc->handle_killpriv_v2 = 1; 10939d769e6aSVivek Goyal fm->sb->s_flags |= SB_NOSEC; 10949d769e6aSVivek Goyal } 109552a4c95fSVivek Goyal if (arg->flags & FUSE_SETXATTR_EXT) 109652a4c95fSVivek Goyal fc->setxattr_ext = 1; 109771421259SMiklos Szeredi } else { 109809cbfeafSKirill A. Shutemov ra_pages = fc->max_read / PAGE_SIZE; 109971421259SMiklos Szeredi fc->no_lock = 1; 110037fb3a30SMiklos Szeredi fc->no_flock = 1; 110171421259SMiklos Szeredi } 11029cd68455SMiklos Szeredi 1103fcee216bSMax Reitz fm->sb->s_bdi->ra_pages = 1104fcee216bSMax Reitz min(fm->sb->s_bdi->ra_pages, ra_pages); 11059b9a0469SMiklos Szeredi fc->minor = arg->minor; 11069b9a0469SMiklos Szeredi fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 1107f948d564SMiklos Szeredi fc->max_write = max_t(unsigned, 4096, fc->max_write); 11080ec7ca41SMiklos Szeredi fc->conn_init = 1; 11099b9a0469SMiklos Szeredi } 1110615047efSMiklos Szeredi kfree(ia); 1111615047efSMiklos Szeredi 1112fd1a1dc6SStefan Hajnoczi if (!ok) { 1113fd1a1dc6SStefan Hajnoczi fc->conn_init = 0; 1114fd1a1dc6SStefan Hajnoczi fc->conn_error = 1; 1115fd1a1dc6SStefan Hajnoczi } 1116fd1a1dc6SStefan Hajnoczi 11179759bd51SMiklos Szeredi fuse_set_initialized(fc); 111808a53cdcSMiklos Szeredi wake_up_all(&fc->blocked_waitq); 11199b9a0469SMiklos Szeredi } 11209b9a0469SMiklos Szeredi 1121fcee216bSMax Reitz void fuse_send_init(struct fuse_mount *fm) 11229b9a0469SMiklos Szeredi { 1123615047efSMiklos Szeredi struct fuse_init_args *ia; 1124095da6cbSMiklos Szeredi 1125615047efSMiklos Szeredi ia = kzalloc(sizeof(*ia), GFP_KERNEL | __GFP_NOFAIL); 1126615047efSMiklos Szeredi 1127615047efSMiklos Szeredi ia->in.major = FUSE_KERNEL_VERSION; 1128615047efSMiklos Szeredi ia->in.minor = FUSE_KERNEL_MINOR_VERSION; 1129fcee216bSMax Reitz ia->in.max_readahead = fm->sb->s_bdi->ra_pages * PAGE_SIZE; 1130615047efSMiklos Szeredi ia->in.flags |= 1131615047efSMiklos Szeredi FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | 113237fb3a30SMiklos Szeredi FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | 113369fe05c9SMiklos Szeredi FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | 11349446385fSWei Fang FUSE_FLOCK_LOCKS | FUSE_HAS_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | 11354d99ff8fSPavel Emelyanov FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | 11365c672ab3SMiklos Szeredi FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | 11373b7008b2SSzymon Lukasz FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | 1138d9a9ea94SChad Austin FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS | 113963f9909fSVivek Goyal FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA | 114052a4c95fSVivek Goyal FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT; 1141fd1a1dc6SStefan Hajnoczi #ifdef CONFIG_FUSE_DAX 1142fcee216bSMax Reitz if (fm->fc->dax) 1143fd1a1dc6SStefan Hajnoczi ia->in.flags |= FUSE_MAP_ALIGNMENT; 1144fd1a1dc6SStefan Hajnoczi #endif 1145bf109c64SMax Reitz if (fm->fc->auto_submounts) 1146bf109c64SMax Reitz ia->in.flags |= FUSE_SUBMOUNTS; 1147bf109c64SMax Reitz 1148615047efSMiklos Szeredi ia->args.opcode = FUSE_INIT; 1149615047efSMiklos Szeredi ia->args.in_numargs = 1; 1150615047efSMiklos Szeredi ia->args.in_args[0].size = sizeof(ia->in); 1151615047efSMiklos Szeredi ia->args.in_args[0].value = &ia->in; 1152615047efSMiklos Szeredi ia->args.out_numargs = 1; 11533ad2f3fbSDaniel Mack /* Variable length argument used for backward compatibility 11549b9a0469SMiklos Szeredi with interface version < 7.5. Rest of init_out is zeroed 11559b9a0469SMiklos Szeredi by do_get_request(), so a short reply is not a problem */ 1156cabdb4faSzhengbin ia->args.out_argvar = true; 1157615047efSMiklos Szeredi ia->args.out_args[0].size = sizeof(ia->out); 1158615047efSMiklos Szeredi ia->args.out_args[0].value = &ia->out; 1159615047efSMiklos Szeredi ia->args.force = true; 1160615047efSMiklos Szeredi ia->args.nocreds = true; 1161615047efSMiklos Szeredi ia->args.end = process_init_reply; 1162615047efSMiklos Szeredi 1163fcee216bSMax Reitz if (fuse_simple_background(fm, &ia->args, GFP_KERNEL) != 0) 1164fcee216bSMax Reitz process_init_reply(fm, &ia->args, -ENOTCONN); 11659b9a0469SMiklos Szeredi } 116695a84cdbSVivek Goyal EXPORT_SYMBOL_GPL(fuse_send_init); 11679b9a0469SMiklos Szeredi 1168783863d6SMiklos Szeredi void fuse_free_conn(struct fuse_conn *fc) 116943901aabSTejun Heo { 1170cc080e9eSMiklos Szeredi WARN_ON(!list_empty(&fc->devices)); 1171dd3e2c55SAl Viro kfree_rcu(fc, rcu); 117243901aabSTejun Heo } 1173783863d6SMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_free_conn); 117443901aabSTejun Heo 1175a325f9b9STejun Heo static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) 1176a325f9b9STejun Heo { 1177a325f9b9STejun Heo int err; 11785f7f7543SJan Kara char *suffix = ""; 1179a325f9b9STejun Heo 118069c8ebf8SJan Kara if (sb->s_bdev) { 11815f7f7543SJan Kara suffix = "-fuseblk"; 118269c8ebf8SJan Kara /* 118369c8ebf8SJan Kara * sb->s_bdi points to blkdev's bdi however we want to redirect 118469c8ebf8SJan Kara * it to our private bdi... 118569c8ebf8SJan Kara */ 118669c8ebf8SJan Kara bdi_put(sb->s_bdi); 118769c8ebf8SJan Kara sb->s_bdi = &noop_backing_dev_info; 118869c8ebf8SJan Kara } 11895f7f7543SJan Kara err = super_setup_bdi_name(sb, "%u:%u%s", MAJOR(fc->dev), 11905f7f7543SJan Kara MINOR(fc->dev), suffix); 1191a325f9b9STejun Heo if (err) 1192a325f9b9STejun Heo return err; 1193a325f9b9STejun Heo 11945f7f7543SJan Kara /* fuse does it's own writeback accounting */ 1195823423efSChristoph Hellwig sb->s_bdi->capabilities &= ~BDI_CAP_WRITEBACK_ACCT; 1196823423efSChristoph Hellwig sb->s_bdi->capabilities |= BDI_CAP_STRICTLIMIT; 11975f7f7543SJan Kara 1198a325f9b9STejun Heo /* 1199a325f9b9STejun Heo * For a single fuse filesystem use max 1% of dirty + 1200a325f9b9STejun Heo * writeback threshold. 1201a325f9b9STejun Heo * 1202a325f9b9STejun Heo * This gives about 1M of write buffer for memory maps on a 1203a325f9b9STejun Heo * machine with 1G and 10% dirty_ratio, which should be more 1204a325f9b9STejun Heo * than enough. 1205a325f9b9STejun Heo * 1206a325f9b9STejun Heo * Privileged users can raise it by writing to 1207a325f9b9STejun Heo * 1208a325f9b9STejun Heo * /sys/class/bdi/<bdi>/max_ratio 1209a325f9b9STejun Heo */ 12105f7f7543SJan Kara bdi_set_max_ratio(sb->s_bdi, 1); 1211a325f9b9STejun Heo 1212a325f9b9STejun Heo return 0; 1213a325f9b9STejun Heo } 1214a325f9b9STejun Heo 12150cd1eb9aSVivek Goyal struct fuse_dev *fuse_dev_alloc(void) 1216cc080e9eSMiklos Szeredi { 1217cc080e9eSMiklos Szeredi struct fuse_dev *fud; 1218be2ff42cSKirill Tkhai struct list_head *pq; 1219cc080e9eSMiklos Szeredi 1220cc080e9eSMiklos Szeredi fud = kzalloc(sizeof(struct fuse_dev), GFP_KERNEL); 1221be2ff42cSKirill Tkhai if (!fud) 1222be2ff42cSKirill Tkhai return NULL; 1223be2ff42cSKirill Tkhai 1224be2ff42cSKirill Tkhai pq = kcalloc(FUSE_PQ_HASH_SIZE, sizeof(struct list_head), GFP_KERNEL); 1225be2ff42cSKirill Tkhai if (!pq) { 1226be2ff42cSKirill Tkhai kfree(fud); 1227be2ff42cSKirill Tkhai return NULL; 1228be2ff42cSKirill Tkhai } 1229be2ff42cSKirill Tkhai 1230be2ff42cSKirill Tkhai fud->pq.processing = pq; 1231c3696046SMiklos Szeredi fuse_pqueue_init(&fud->pq); 1232cc080e9eSMiklos Szeredi 1233cc080e9eSMiklos Szeredi return fud; 1234cc080e9eSMiklos Szeredi } 1235cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_alloc); 1236cc080e9eSMiklos Szeredi 12370cd1eb9aSVivek Goyal void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc) 12380cd1eb9aSVivek Goyal { 12390cd1eb9aSVivek Goyal fud->fc = fuse_conn_get(fc); 12400cd1eb9aSVivek Goyal spin_lock(&fc->lock); 12410cd1eb9aSVivek Goyal list_add_tail(&fud->entry, &fc->devices); 12420cd1eb9aSVivek Goyal spin_unlock(&fc->lock); 12430cd1eb9aSVivek Goyal } 12440cd1eb9aSVivek Goyal EXPORT_SYMBOL_GPL(fuse_dev_install); 12450cd1eb9aSVivek Goyal 12460cd1eb9aSVivek Goyal struct fuse_dev *fuse_dev_alloc_install(struct fuse_conn *fc) 12470cd1eb9aSVivek Goyal { 12480cd1eb9aSVivek Goyal struct fuse_dev *fud; 12490cd1eb9aSVivek Goyal 12500cd1eb9aSVivek Goyal fud = fuse_dev_alloc(); 12510cd1eb9aSVivek Goyal if (!fud) 12520cd1eb9aSVivek Goyal return NULL; 12530cd1eb9aSVivek Goyal 12540cd1eb9aSVivek Goyal fuse_dev_install(fud, fc); 12550cd1eb9aSVivek Goyal return fud; 12560cd1eb9aSVivek Goyal } 12570cd1eb9aSVivek Goyal EXPORT_SYMBOL_GPL(fuse_dev_alloc_install); 12580cd1eb9aSVivek Goyal 1259cc080e9eSMiklos Szeredi void fuse_dev_free(struct fuse_dev *fud) 1260cc080e9eSMiklos Szeredi { 1261cc080e9eSMiklos Szeredi struct fuse_conn *fc = fud->fc; 1262cc080e9eSMiklos Szeredi 1263cc080e9eSMiklos Szeredi if (fc) { 1264cc080e9eSMiklos Szeredi spin_lock(&fc->lock); 1265cc080e9eSMiklos Szeredi list_del(&fud->entry); 1266cc080e9eSMiklos Szeredi spin_unlock(&fc->lock); 1267cc080e9eSMiklos Szeredi 1268cc080e9eSMiklos Szeredi fuse_conn_put(fc); 1269cc080e9eSMiklos Szeredi } 1270d72f70daSTakeshi Misawa kfree(fud->pq.processing); 1271cc080e9eSMiklos Szeredi kfree(fud); 1272cc080e9eSMiklos Szeredi } 1273cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_free); 1274cc080e9eSMiklos Szeredi 12751866d779SMax Reitz static void fuse_fill_attr_from_inode(struct fuse_attr *attr, 12761866d779SMax Reitz const struct fuse_inode *fi) 12771866d779SMax Reitz { 12781866d779SMax Reitz *attr = (struct fuse_attr){ 12791866d779SMax Reitz .ino = fi->inode.i_ino, 12801866d779SMax Reitz .size = fi->inode.i_size, 12811866d779SMax Reitz .blocks = fi->inode.i_blocks, 12821866d779SMax Reitz .atime = fi->inode.i_atime.tv_sec, 12831866d779SMax Reitz .mtime = fi->inode.i_mtime.tv_sec, 12841866d779SMax Reitz .ctime = fi->inode.i_ctime.tv_sec, 12851866d779SMax Reitz .atimensec = fi->inode.i_atime.tv_nsec, 12861866d779SMax Reitz .mtimensec = fi->inode.i_mtime.tv_nsec, 12871866d779SMax Reitz .ctimensec = fi->inode.i_ctime.tv_nsec, 12881866d779SMax Reitz .mode = fi->inode.i_mode, 12891866d779SMax Reitz .nlink = fi->inode.i_nlink, 12901866d779SMax Reitz .uid = fi->inode.i_uid.val, 12911866d779SMax Reitz .gid = fi->inode.i_gid.val, 12921866d779SMax Reitz .rdev = fi->inode.i_rdev, 12931866d779SMax Reitz .blksize = 1u << fi->inode.i_blkbits, 12941866d779SMax Reitz }; 12951866d779SMax Reitz } 12961866d779SMax Reitz 12971866d779SMax Reitz static void fuse_sb_defaults(struct super_block *sb) 12981866d779SMax Reitz { 12991866d779SMax Reitz sb->s_magic = FUSE_SUPER_MAGIC; 13001866d779SMax Reitz sb->s_op = &fuse_super_operations; 13011866d779SMax Reitz sb->s_xattr = fuse_xattr_handlers; 13021866d779SMax Reitz sb->s_maxbytes = MAX_LFS_FILESIZE; 13031866d779SMax Reitz sb->s_time_gran = 1; 13041866d779SMax Reitz sb->s_export_op = &fuse_export_operations; 13051866d779SMax Reitz sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE; 13061866d779SMax Reitz if (sb->s_user_ns != &init_user_ns) 13071866d779SMax Reitz sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER; 13081866d779SMax Reitz sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION); 13091866d779SMax Reitz 13101866d779SMax Reitz /* 13111866d779SMax Reitz * If we are not in the initial user namespace posix 13121866d779SMax Reitz * acls must be translated. 13131866d779SMax Reitz */ 13141866d779SMax Reitz if (sb->s_user_ns != &init_user_ns) 13151866d779SMax Reitz sb->s_xattr = fuse_no_acl_xattr_handlers; 13161866d779SMax Reitz } 13171866d779SMax Reitz 13181b539917SGreg Kurz static int fuse_fill_super_submount(struct super_block *sb, 13191866d779SMax Reitz struct fuse_inode *parent_fi) 13201866d779SMax Reitz { 13211866d779SMax Reitz struct fuse_mount *fm = get_fuse_mount_super(sb); 13221866d779SMax Reitz struct super_block *parent_sb = parent_fi->inode.i_sb; 13231866d779SMax Reitz struct fuse_attr root_attr; 13241866d779SMax Reitz struct inode *root; 13251866d779SMax Reitz 13261866d779SMax Reitz fuse_sb_defaults(sb); 13271866d779SMax Reitz fm->sb = sb; 13281866d779SMax Reitz 13291866d779SMax Reitz WARN_ON(sb->s_bdi != &noop_backing_dev_info); 13301866d779SMax Reitz sb->s_bdi = bdi_get(parent_sb->s_bdi); 13311866d779SMax Reitz 13321866d779SMax Reitz sb->s_xattr = parent_sb->s_xattr; 13331866d779SMax Reitz sb->s_time_gran = parent_sb->s_time_gran; 13341866d779SMax Reitz sb->s_blocksize = parent_sb->s_blocksize; 13351866d779SMax Reitz sb->s_blocksize_bits = parent_sb->s_blocksize_bits; 13361866d779SMax Reitz sb->s_subtype = kstrdup(parent_sb->s_subtype, GFP_KERNEL); 13371866d779SMax Reitz if (parent_sb->s_subtype && !sb->s_subtype) 13381866d779SMax Reitz return -ENOMEM; 13391866d779SMax Reitz 13401866d779SMax Reitz fuse_fill_attr_from_inode(&root_attr, parent_fi); 13411866d779SMax Reitz root = fuse_iget(sb, parent_fi->nodeid, 0, &root_attr, 0, 0); 13421866d779SMax Reitz /* 13431866d779SMax Reitz * This inode is just a duplicate, so it is not looked up and 13441866d779SMax Reitz * its nlookup should not be incremented. fuse_iget() does 13451866d779SMax Reitz * that, though, so undo it here. 13461866d779SMax Reitz */ 13471866d779SMax Reitz get_fuse_inode(root)->nlookup--; 13481866d779SMax Reitz sb->s_d_op = &fuse_dentry_operations; 13491866d779SMax Reitz sb->s_root = d_make_root(root); 13501866d779SMax Reitz if (!sb->s_root) 13511866d779SMax Reitz return -ENOMEM; 13521866d779SMax Reitz 13531866d779SMax Reitz return 0; 13541866d779SMax Reitz } 13551866d779SMax Reitz 1356266eb3f2SGreg Kurz /* Filesystem context private data holds the FUSE inode of the mount point */ 1357fe0a7bd8SGreg Kurz static int fuse_get_tree_submount(struct fs_context *fsc) 1358fe0a7bd8SGreg Kurz { 1359266eb3f2SGreg Kurz struct fuse_mount *fm; 1360266eb3f2SGreg Kurz struct fuse_inode *mp_fi = fsc->fs_private; 1361266eb3f2SGreg Kurz struct fuse_conn *fc = get_fuse_conn(&mp_fi->inode); 1362266eb3f2SGreg Kurz struct super_block *sb; 1363266eb3f2SGreg Kurz int err; 1364266eb3f2SGreg Kurz 1365266eb3f2SGreg Kurz fm = kzalloc(sizeof(struct fuse_mount), GFP_KERNEL); 1366266eb3f2SGreg Kurz if (!fm) 1367266eb3f2SGreg Kurz return -ENOMEM; 1368266eb3f2SGreg Kurz 1369266eb3f2SGreg Kurz fsc->s_fs_info = fm; 1370266eb3f2SGreg Kurz sb = sget_fc(fsc, NULL, set_anon_super_fc); 1371266eb3f2SGreg Kurz if (IS_ERR(sb)) { 1372266eb3f2SGreg Kurz kfree(fm); 1373266eb3f2SGreg Kurz return PTR_ERR(sb); 1374266eb3f2SGreg Kurz } 1375266eb3f2SGreg Kurz fm->fc = fuse_conn_get(fc); 1376266eb3f2SGreg Kurz 1377266eb3f2SGreg Kurz /* Initialize superblock, making @mp_fi its root */ 1378266eb3f2SGreg Kurz err = fuse_fill_super_submount(sb, mp_fi); 1379266eb3f2SGreg Kurz if (err) { 1380266eb3f2SGreg Kurz fuse_conn_put(fc); 1381266eb3f2SGreg Kurz kfree(fm); 1382266eb3f2SGreg Kurz sb->s_fs_info = NULL; 1383266eb3f2SGreg Kurz deactivate_locked_super(sb); 1384266eb3f2SGreg Kurz return err; 1385266eb3f2SGreg Kurz } 1386266eb3f2SGreg Kurz 1387266eb3f2SGreg Kurz down_write(&fc->killsb); 1388266eb3f2SGreg Kurz list_add_tail(&fm->fc_entry, &fc->mounts); 1389266eb3f2SGreg Kurz up_write(&fc->killsb); 1390266eb3f2SGreg Kurz 1391266eb3f2SGreg Kurz sb->s_flags |= SB_ACTIVE; 1392266eb3f2SGreg Kurz fsc->root = dget(sb->s_root); 1393266eb3f2SGreg Kurz 1394fe0a7bd8SGreg Kurz return 0; 1395fe0a7bd8SGreg Kurz } 1396fe0a7bd8SGreg Kurz 1397fe0a7bd8SGreg Kurz static const struct fs_context_operations fuse_context_submount_ops = { 1398fe0a7bd8SGreg Kurz .get_tree = fuse_get_tree_submount, 1399fe0a7bd8SGreg Kurz }; 1400fe0a7bd8SGreg Kurz 1401fe0a7bd8SGreg Kurz int fuse_init_fs_context_submount(struct fs_context *fsc) 1402fe0a7bd8SGreg Kurz { 1403fe0a7bd8SGreg Kurz fsc->ops = &fuse_context_submount_ops; 1404fe0a7bd8SGreg Kurz return 0; 1405fe0a7bd8SGreg Kurz } 1406fe0a7bd8SGreg Kurz EXPORT_SYMBOL_GPL(fuse_init_fs_context_submount); 1407fe0a7bd8SGreg Kurz 14080cc2656cSStefan Hajnoczi int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx) 1409d8a5ba45SMiklos Szeredi { 14107fd3abfaSVivek Goyal struct fuse_dev *fud = NULL; 1411fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount_super(sb); 1412fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 1413d8a5ba45SMiklos Szeredi struct inode *root; 1414f543f253SMiklos Szeredi struct dentry *root_dentry; 1415d8a5ba45SMiklos Szeredi int err; 1416d8a5ba45SMiklos Szeredi 1417c2b8f006SMiklos Szeredi err = -EINVAL; 14181751e8a6SLinus Torvalds if (sb->s_flags & SB_MANDLOCK) 1419c2b8f006SMiklos Szeredi goto err; 142071421259SMiklos Szeredi 14211866d779SMax Reitz fuse_sb_defaults(sb); 14229e1f1de0SAl Viro 14230cc2656cSStefan Hajnoczi if (ctx->is_bdev) { 1424875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 1425c2b8f006SMiklos Szeredi err = -EINVAL; 1426c30da2e9SDavid Howells if (!sb_set_blocksize(sb, ctx->blksize)) 1427c2b8f006SMiklos Szeredi goto err; 1428875d95ecSMiklos Szeredi #endif 1429d8091614SMiklos Szeredi } else { 143009cbfeafSKirill A. Shutemov sb->s_blocksize = PAGE_SIZE; 143109cbfeafSKirill A. Shutemov sb->s_blocksize_bits = PAGE_SHIFT; 1432d8091614SMiklos Szeredi } 1433c30da2e9SDavid Howells 1434c30da2e9SDavid Howells sb->s_subtype = ctx->subtype; 1435c30da2e9SDavid Howells ctx->subtype = NULL; 14361dd53957SVivek Goyal if (IS_ENABLED(CONFIG_FUSE_DAX)) { 14371dd53957SVivek Goyal err = fuse_dax_conn_alloc(fc, ctx->dax_dev); 14381dd53957SVivek Goyal if (err) 14391dd53957SVivek Goyal goto err; 14401dd53957SVivek Goyal } 1441e45b2546SEric W. Biederman 14427fd3abfaSVivek Goyal if (ctx->fudptr) { 14437fd3abfaSVivek Goyal err = -ENOMEM; 14440cd1eb9aSVivek Goyal fud = fuse_dev_alloc_install(fc); 1445cc080e9eSMiklos Szeredi if (!fud) 14461dd53957SVivek Goyal goto err_free_dax; 14477fd3abfaSVivek Goyal } 1448cc080e9eSMiklos Szeredi 1449a325f9b9STejun Heo fc->dev = sb->s_dev; 1450fcee216bSMax Reitz fm->sb = sb; 1451a325f9b9STejun Heo err = fuse_bdi_init(fc, sb); 1452a325f9b9STejun Heo if (err) 1453cc080e9eSMiklos Szeredi goto err_dev_free; 14540d179aa5STejun Heo 1455e0a43ddcSMiklos Szeredi /* Handle umasking inside the fuse code */ 14561751e8a6SLinus Torvalds if (sb->s_flags & SB_POSIXACL) 1457e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 14581751e8a6SLinus Torvalds sb->s_flags |= SB_POSIXACL; 1459e0a43ddcSMiklos Szeredi 1460c30da2e9SDavid Howells fc->default_permissions = ctx->default_permissions; 1461c30da2e9SDavid Howells fc->allow_other = ctx->allow_other; 1462c30da2e9SDavid Howells fc->user_id = ctx->user_id; 1463c30da2e9SDavid Howells fc->group_id = ctx->group_id; 1464f4fd4ae3SVivek Goyal fc->legacy_opts_show = ctx->legacy_opts_show; 14651866d779SMax Reitz fc->max_read = max_t(unsigned int, 4096, ctx->max_read); 1466783863d6SMiklos Szeredi fc->destroy = ctx->destroy; 146715c8e72eSVivek Goyal fc->no_control = ctx->no_control; 146815c8e72eSVivek Goyal fc->no_force_umount = ctx->no_force_umount; 1469f543f253SMiklos Szeredi 1470d8a5ba45SMiklos Szeredi err = -ENOMEM; 1471c30da2e9SDavid Howells root = fuse_get_root_inode(sb, ctx->rootmode); 14720ce267ffSMiklos Szeredi sb->s_d_op = &fuse_root_dentry_operations; 147348fde701SAl Viro root_dentry = d_make_root(root); 147448fde701SAl Viro if (!root_dentry) 1475cc080e9eSMiklos Szeredi goto err_dev_free; 14760ce267ffSMiklos Szeredi /* Root dentry doesn't have .d_revalidate */ 1477c35eebe9SAl Viro sb->s_d_op = &fuse_dentry_operations; 1478f543f253SMiklos Szeredi 1479bafa9654SMiklos Szeredi mutex_lock(&fuse_mutex); 14808aa09a50SMiklos Szeredi err = -EINVAL; 14817fd3abfaSVivek Goyal if (ctx->fudptr && *ctx->fudptr) 1482bafa9654SMiklos Szeredi goto err_unlock; 14838aa09a50SMiklos Szeredi 1484bafa9654SMiklos Szeredi err = fuse_ctl_add_conn(fc); 1485bafa9654SMiklos Szeredi if (err) 1486bafa9654SMiklos Szeredi goto err_unlock; 1487bafa9654SMiklos Szeredi 1488bafa9654SMiklos Szeredi list_add_tail(&fc->entry, &fuse_conn_list); 1489f543f253SMiklos Szeredi sb->s_root = root_dentry; 14907fd3abfaSVivek Goyal if (ctx->fudptr) 14910cc2656cSStefan Hajnoczi *ctx->fudptr = fud; 1492bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 1493d8a5ba45SMiklos Szeredi return 0; 1494d8a5ba45SMiklos Szeredi 1495bafa9654SMiklos Szeredi err_unlock: 1496bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 1497f543f253SMiklos Szeredi dput(root_dentry); 1498cc080e9eSMiklos Szeredi err_dev_free: 14997fd3abfaSVivek Goyal if (fud) 1500cc080e9eSMiklos Szeredi fuse_dev_free(fud); 15011dd53957SVivek Goyal err_free_dax: 15021dd53957SVivek Goyal if (IS_ENABLED(CONFIG_FUSE_DAX)) 15031dd53957SVivek Goyal fuse_dax_conn_free(fc); 15040cc2656cSStefan Hajnoczi err: 15050cc2656cSStefan Hajnoczi return err; 15060cc2656cSStefan Hajnoczi } 15070cc2656cSStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_fill_super_common); 15080cc2656cSStefan Hajnoczi 15090cc2656cSStefan Hajnoczi static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc) 15100cc2656cSStefan Hajnoczi { 15110cc2656cSStefan Hajnoczi struct fuse_fs_context *ctx = fsc->fs_private; 15120cc2656cSStefan Hajnoczi int err; 15130cc2656cSStefan Hajnoczi struct fuse_conn *fc; 1514fcee216bSMax Reitz struct fuse_mount *fm; 15150cc2656cSStefan Hajnoczi 1516*62dd1fc8SMiklos Szeredi if (!ctx->file || !ctx->rootmode_present || 1517badc7414SMiklos Szeredi !ctx->user_id_present || !ctx->group_id_present) 1518badc7414SMiklos Szeredi return -EINVAL; 1519badc7414SMiklos Szeredi 15200cc2656cSStefan Hajnoczi /* 15210cc2656cSStefan Hajnoczi * Require mount to happen from the same user namespace which 15220cc2656cSStefan Hajnoczi * opened /dev/fuse to prevent potential attacks. 15230cc2656cSStefan Hajnoczi */ 1524*62dd1fc8SMiklos Szeredi err = -EINVAL; 1525*62dd1fc8SMiklos Szeredi if ((ctx->file->f_op != &fuse_dev_operations) || 1526*62dd1fc8SMiklos Szeredi (ctx->file->f_cred->user_ns != sb->s_user_ns)) 1527*62dd1fc8SMiklos Szeredi goto err; 1528*62dd1fc8SMiklos Szeredi ctx->fudptr = &ctx->file->private_data; 15290cc2656cSStefan Hajnoczi 15300cc2656cSStefan Hajnoczi fc = kmalloc(sizeof(*fc), GFP_KERNEL); 15310cc2656cSStefan Hajnoczi err = -ENOMEM; 15320cc2656cSStefan Hajnoczi if (!fc) 1533*62dd1fc8SMiklos Szeredi goto err; 15340cc2656cSStefan Hajnoczi 1535fcee216bSMax Reitz fm = kzalloc(sizeof(*fm), GFP_KERNEL); 1536fcee216bSMax Reitz if (!fm) { 1537fcee216bSMax Reitz kfree(fc); 1538*62dd1fc8SMiklos Szeredi goto err; 1539fcee216bSMax Reitz } 1540fcee216bSMax Reitz 1541fcee216bSMax Reitz fuse_conn_init(fc, fm, sb->s_user_ns, &fuse_dev_fiq_ops, NULL); 15420cc2656cSStefan Hajnoczi fc->release = fuse_free_conn; 1543fcee216bSMax Reitz 1544fcee216bSMax Reitz sb->s_fs_info = fm; 15450cc2656cSStefan Hajnoczi 15460cc2656cSStefan Hajnoczi err = fuse_fill_super_common(sb, ctx); 15470cc2656cSStefan Hajnoczi if (err) 15480cc2656cSStefan Hajnoczi goto err_put_conn; 1549*62dd1fc8SMiklos Szeredi /* file->private_data shall be visible on all CPUs after this */ 1550*62dd1fc8SMiklos Szeredi smp_mb(); 1551fcee216bSMax Reitz fuse_send_init(get_fuse_mount_super(sb)); 15520cc2656cSStefan Hajnoczi return 0; 15530cc2656cSStefan Hajnoczi 1554c2b8f006SMiklos Szeredi err_put_conn: 1555514b5e3fSMiklos Szeredi fuse_conn_put(fc); 1556514b5e3fSMiklos Szeredi kfree(fm); 1557543b8f86STetsuo Handa sb->s_fs_info = NULL; 1558c2b8f006SMiklos Szeredi err: 1559d8a5ba45SMiklos Szeredi return err; 1560d8a5ba45SMiklos Szeredi } 1561d8a5ba45SMiklos Szeredi 156284c21507SMiklos Szeredi static int fuse_get_tree(struct fs_context *fsc) 1563d8a5ba45SMiklos Szeredi { 156484c21507SMiklos Szeredi struct fuse_fs_context *ctx = fsc->fs_private; 1565*62dd1fc8SMiklos Szeredi int err; 1566*62dd1fc8SMiklos Szeredi 1567*62dd1fc8SMiklos Szeredi if (ctx->fd_present) 1568*62dd1fc8SMiklos Szeredi ctx->file = fget(ctx->fd); 1569c30da2e9SDavid Howells 1570badc7414SMiklos Szeredi if (IS_ENABLED(CONFIG_BLOCK) && ctx->is_bdev) { 1571*62dd1fc8SMiklos Szeredi err = get_tree_bdev(fsc, fuse_fill_super); 1572*62dd1fc8SMiklos Szeredi goto out_fput; 1573badc7414SMiklos Szeredi } 1574c30da2e9SDavid Howells 1575*62dd1fc8SMiklos Szeredi err = get_tree_nodev(fsc, fuse_fill_super); 1576*62dd1fc8SMiklos Szeredi out_fput: 1577*62dd1fc8SMiklos Szeredi if (ctx->file) 1578*62dd1fc8SMiklos Szeredi fput(ctx->file); 1579*62dd1fc8SMiklos Szeredi return err; 1580c30da2e9SDavid Howells } 1581c30da2e9SDavid Howells 1582c30da2e9SDavid Howells static const struct fs_context_operations fuse_context_ops = { 158384c21507SMiklos Szeredi .free = fuse_free_fsc, 1584c30da2e9SDavid Howells .parse_param = fuse_parse_param, 15850189a2d3SMiklos Szeredi .reconfigure = fuse_reconfigure, 1586c30da2e9SDavid Howells .get_tree = fuse_get_tree, 1587c30da2e9SDavid Howells }; 1588c30da2e9SDavid Howells 1589c30da2e9SDavid Howells /* 1590c30da2e9SDavid Howells * Set up the filesystem mount context. 1591c30da2e9SDavid Howells */ 159284c21507SMiklos Szeredi static int fuse_init_fs_context(struct fs_context *fsc) 1593c30da2e9SDavid Howells { 1594c30da2e9SDavid Howells struct fuse_fs_context *ctx; 1595c30da2e9SDavid Howells 1596c30da2e9SDavid Howells ctx = kzalloc(sizeof(struct fuse_fs_context), GFP_KERNEL); 1597c30da2e9SDavid Howells if (!ctx) 1598c30da2e9SDavid Howells return -ENOMEM; 1599c30da2e9SDavid Howells 1600c30da2e9SDavid Howells ctx->max_read = ~0; 1601c30da2e9SDavid Howells ctx->blksize = FUSE_DEFAULT_BLKSIZE; 1602f4fd4ae3SVivek Goyal ctx->legacy_opts_show = true; 1603c30da2e9SDavid Howells 1604c30da2e9SDavid Howells #ifdef CONFIG_BLOCK 160584c21507SMiklos Szeredi if (fsc->fs_type == &fuseblk_fs_type) { 1606c30da2e9SDavid Howells ctx->is_bdev = true; 1607783863d6SMiklos Szeredi ctx->destroy = true; 1608783863d6SMiklos Szeredi } 1609c30da2e9SDavid Howells #endif 1610c30da2e9SDavid Howells 161184c21507SMiklos Szeredi fsc->fs_private = ctx; 161284c21507SMiklos Szeredi fsc->ops = &fuse_context_ops; 1613c30da2e9SDavid Howells return 0; 1614d8a5ba45SMiklos Szeredi } 1615d8a5ba45SMiklos Szeredi 1616fcee216bSMax Reitz bool fuse_mount_remove(struct fuse_mount *fm) 16173b463ae0SJohn Muir { 1618fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 1619fcee216bSMax Reitz bool last = false; 16203b463ae0SJohn Muir 1621fcee216bSMax Reitz down_write(&fc->killsb); 1622fcee216bSMax Reitz list_del_init(&fm->fc_entry); 1623fcee216bSMax Reitz if (list_empty(&fc->mounts)) 1624fcee216bSMax Reitz last = true; 1625fcee216bSMax Reitz up_write(&fc->killsb); 1626fcee216bSMax Reitz 1627fcee216bSMax Reitz return last; 1628fcee216bSMax Reitz } 1629fcee216bSMax Reitz EXPORT_SYMBOL_GPL(fuse_mount_remove); 1630fcee216bSMax Reitz 1631fcee216bSMax Reitz void fuse_conn_destroy(struct fuse_mount *fm) 1632fcee216bSMax Reitz { 1633fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 1634fcee216bSMax Reitz 16351ccd1ea2SMiklos Szeredi if (fc->destroy) 1636fcee216bSMax Reitz fuse_send_destroy(fm); 1637e8f3bd77SMiklos Szeredi 1638eb98e3bdSMiklos Szeredi fuse_abort_conn(fc); 1639e8f3bd77SMiklos Szeredi fuse_wait_aborted(fc); 1640e8f3bd77SMiklos Szeredi 1641413daa1aSMiklos Szeredi if (!list_empty(&fc->entry)) { 1642413daa1aSMiklos Szeredi mutex_lock(&fuse_mutex); 1643413daa1aSMiklos Szeredi list_del(&fc->entry); 1644413daa1aSMiklos Szeredi fuse_ctl_remove_conn(fc); 1645413daa1aSMiklos Szeredi mutex_unlock(&fuse_mutex); 16463b463ae0SJohn Muir } 1647e8f3bd77SMiklos Szeredi } 1648fcee216bSMax Reitz EXPORT_SYMBOL_GPL(fuse_conn_destroy); 16493b463ae0SJohn Muir 16506a68d1e1SMiklos Szeredi static void fuse_sb_destroy(struct super_block *sb) 1651e8f3bd77SMiklos Szeredi { 1652fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount_super(sb); 1653fcee216bSMax Reitz bool last; 1654fcee216bSMax Reitz 1655fcee216bSMax Reitz if (fm) { 1656fcee216bSMax Reitz last = fuse_mount_remove(fm); 1657fcee216bSMax Reitz if (last) 1658fcee216bSMax Reitz fuse_conn_destroy(fm); 1659fcee216bSMax Reitz } 16606a68d1e1SMiklos Szeredi } 16616a68d1e1SMiklos Szeredi 16626a68d1e1SMiklos Szeredi static void fuse_kill_sb_anon(struct super_block *sb) 16636a68d1e1SMiklos Szeredi { 16646a68d1e1SMiklos Szeredi fuse_sb_destroy(sb); 16653b463ae0SJohn Muir kill_anon_super(sb); 16663b463ae0SJohn Muir } 16673b463ae0SJohn Muir 1668875d95ecSMiklos Szeredi static struct file_system_type fuse_fs_type = { 1669875d95ecSMiklos Szeredi .owner = THIS_MODULE, 1670875d95ecSMiklos Szeredi .name = "fuse", 16714ad769f3SEric W. Biederman .fs_flags = FS_HAS_SUBTYPE | FS_USERNS_MOUNT, 1672c30da2e9SDavid Howells .init_fs_context = fuse_init_fs_context, 1673d7167b14SAl Viro .parameters = fuse_fs_parameters, 16743b463ae0SJohn Muir .kill_sb = fuse_kill_sb_anon, 1675875d95ecSMiklos Szeredi }; 16767f78e035SEric W. Biederman MODULE_ALIAS_FS("fuse"); 1677875d95ecSMiklos Szeredi 1678875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 16793b463ae0SJohn Muir static void fuse_kill_sb_blk(struct super_block *sb) 16803b463ae0SJohn Muir { 16816a68d1e1SMiklos Szeredi fuse_sb_destroy(sb); 16823b463ae0SJohn Muir kill_block_super(sb); 16833b463ae0SJohn Muir } 16843b463ae0SJohn Muir 1685d6392f87SMiklos Szeredi static struct file_system_type fuseblk_fs_type = { 1686d6392f87SMiklos Szeredi .owner = THIS_MODULE, 1687d6392f87SMiklos Szeredi .name = "fuseblk", 1688c30da2e9SDavid Howells .init_fs_context = fuse_init_fs_context, 1689d7167b14SAl Viro .parameters = fuse_fs_parameters, 16903b463ae0SJohn Muir .kill_sb = fuse_kill_sb_blk, 1691edad01e2SAlexey Dobriyan .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, 1692d6392f87SMiklos Szeredi }; 16937f78e035SEric W. Biederman MODULE_ALIAS_FS("fuseblk"); 1694d6392f87SMiklos Szeredi 1695875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1696875d95ecSMiklos Szeredi { 1697875d95ecSMiklos Szeredi return register_filesystem(&fuseblk_fs_type); 1698875d95ecSMiklos Szeredi } 1699875d95ecSMiklos Szeredi 1700875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1701875d95ecSMiklos Szeredi { 1702875d95ecSMiklos Szeredi unregister_filesystem(&fuseblk_fs_type); 1703875d95ecSMiklos Szeredi } 1704875d95ecSMiklos Szeredi #else 1705875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1706875d95ecSMiklos Szeredi { 1707875d95ecSMiklos Szeredi return 0; 1708875d95ecSMiklos Szeredi } 1709875d95ecSMiklos Szeredi 1710875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1711875d95ecSMiklos Szeredi { 1712875d95ecSMiklos Szeredi } 1713875d95ecSMiklos Szeredi #endif 1714875d95ecSMiklos Szeredi 171551cc5068SAlexey Dobriyan static void fuse_inode_init_once(void *foo) 1716d8a5ba45SMiklos Szeredi { 1717d8a5ba45SMiklos Szeredi struct inode *inode = foo; 1718d8a5ba45SMiklos Szeredi 1719d8a5ba45SMiklos Szeredi inode_init_once(inode); 1720d8a5ba45SMiklos Szeredi } 1721d8a5ba45SMiklos Szeredi 1722d8a5ba45SMiklos Szeredi static int __init fuse_fs_init(void) 1723d8a5ba45SMiklos Szeredi { 1724d8a5ba45SMiklos Szeredi int err; 1725d8a5ba45SMiklos Szeredi 1726d8a5ba45SMiklos Szeredi fuse_inode_cachep = kmem_cache_create("fuse_inode", 17275d097056SVladimir Davydov sizeof(struct fuse_inode), 0, 1728df206988SJohannes Weiner SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT|SLAB_RECLAIM_ACCOUNT, 172920c2df83SPaul Mundt fuse_inode_init_once); 1730d8a5ba45SMiklos Szeredi err = -ENOMEM; 1731d6392f87SMiklos Szeredi if (!fuse_inode_cachep) 1732988f0325SAl Viro goto out; 1733988f0325SAl Viro 1734988f0325SAl Viro err = register_fuseblk(); 1735988f0325SAl Viro if (err) 1736988f0325SAl Viro goto out2; 1737988f0325SAl Viro 1738988f0325SAl Viro err = register_filesystem(&fuse_fs_type); 1739988f0325SAl Viro if (err) 1740988f0325SAl Viro goto out3; 1741d8a5ba45SMiklos Szeredi 1742d6392f87SMiklos Szeredi return 0; 1743d6392f87SMiklos Szeredi 1744988f0325SAl Viro out3: 1745875d95ecSMiklos Szeredi unregister_fuseblk(); 1746988f0325SAl Viro out2: 1747988f0325SAl Viro kmem_cache_destroy(fuse_inode_cachep); 1748d6392f87SMiklos Szeredi out: 1749d8a5ba45SMiklos Szeredi return err; 1750d8a5ba45SMiklos Szeredi } 1751d8a5ba45SMiklos Szeredi 1752d8a5ba45SMiklos Szeredi static void fuse_fs_cleanup(void) 1753d8a5ba45SMiklos Szeredi { 1754d8a5ba45SMiklos Szeredi unregister_filesystem(&fuse_fs_type); 1755875d95ecSMiklos Szeredi unregister_fuseblk(); 17568c0a8537SKirill A. Shutemov 17578c0a8537SKirill A. Shutemov /* 17588c0a8537SKirill A. Shutemov * Make sure all delayed rcu free inodes are flushed before we 17598c0a8537SKirill A. Shutemov * destroy cache. 17608c0a8537SKirill A. Shutemov */ 17618c0a8537SKirill A. Shutemov rcu_barrier(); 1762d8a5ba45SMiklos Szeredi kmem_cache_destroy(fuse_inode_cachep); 1763d8a5ba45SMiklos Szeredi } 1764d8a5ba45SMiklos Szeredi 17655c89e17eSGreg Kroah-Hartman static struct kobject *fuse_kobj; 17665c89e17eSGreg Kroah-Hartman 1767f543f253SMiklos Szeredi static int fuse_sysfs_init(void) 1768f543f253SMiklos Szeredi { 1769f543f253SMiklos Szeredi int err; 1770f543f253SMiklos Szeredi 177100d26666SGreg Kroah-Hartman fuse_kobj = kobject_create_and_add("fuse", fs_kobj); 17725c89e17eSGreg Kroah-Hartman if (!fuse_kobj) { 17735c89e17eSGreg Kroah-Hartman err = -ENOMEM; 1774f543f253SMiklos Szeredi goto out_err; 17755c89e17eSGreg Kroah-Hartman } 1776f543f253SMiklos Szeredi 1777f9bb4882SEric W. Biederman err = sysfs_create_mount_point(fuse_kobj, "connections"); 1778f9bb4882SEric W. Biederman if (err) 1779f543f253SMiklos Szeredi goto out_fuse_unregister; 1780f543f253SMiklos Szeredi 1781f543f253SMiklos Szeredi return 0; 1782f543f253SMiklos Szeredi 1783f543f253SMiklos Szeredi out_fuse_unregister: 1784197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1785f543f253SMiklos Szeredi out_err: 1786f543f253SMiklos Szeredi return err; 1787f543f253SMiklos Szeredi } 1788f543f253SMiklos Szeredi 1789f543f253SMiklos Szeredi static void fuse_sysfs_cleanup(void) 1790f543f253SMiklos Szeredi { 1791f9bb4882SEric W. Biederman sysfs_remove_mount_point(fuse_kobj, "connections"); 1792197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1793f543f253SMiklos Szeredi } 1794f543f253SMiklos Szeredi 1795d8a5ba45SMiklos Szeredi static int __init fuse_init(void) 1796d8a5ba45SMiklos Szeredi { 1797d8a5ba45SMiklos Szeredi int res; 1798d8a5ba45SMiklos Szeredi 1799f2294482SKirill Smelkov pr_info("init (API version %i.%i)\n", 1800d8a5ba45SMiklos Szeredi FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); 1801d8a5ba45SMiklos Szeredi 1802bafa9654SMiklos Szeredi INIT_LIST_HEAD(&fuse_conn_list); 1803d8a5ba45SMiklos Szeredi res = fuse_fs_init(); 1804d8a5ba45SMiklos Szeredi if (res) 1805d8a5ba45SMiklos Szeredi goto err; 1806d8a5ba45SMiklos Szeredi 1807334f485dSMiklos Szeredi res = fuse_dev_init(); 1808334f485dSMiklos Szeredi if (res) 1809334f485dSMiklos Szeredi goto err_fs_cleanup; 1810334f485dSMiklos Szeredi 1811f543f253SMiklos Szeredi res = fuse_sysfs_init(); 1812f543f253SMiklos Szeredi if (res) 1813f543f253SMiklos Szeredi goto err_dev_cleanup; 1814f543f253SMiklos Szeredi 1815bafa9654SMiklos Szeredi res = fuse_ctl_init(); 1816bafa9654SMiklos Szeredi if (res) 1817bafa9654SMiklos Szeredi goto err_sysfs_cleanup; 1818bafa9654SMiklos Szeredi 1819487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 1820487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 1821487ea5afSCsaba Henk 1822d8a5ba45SMiklos Szeredi return 0; 1823d8a5ba45SMiklos Szeredi 1824bafa9654SMiklos Szeredi err_sysfs_cleanup: 1825bafa9654SMiklos Szeredi fuse_sysfs_cleanup(); 1826f543f253SMiklos Szeredi err_dev_cleanup: 1827f543f253SMiklos Szeredi fuse_dev_cleanup(); 1828334f485dSMiklos Szeredi err_fs_cleanup: 1829334f485dSMiklos Szeredi fuse_fs_cleanup(); 1830d8a5ba45SMiklos Szeredi err: 1831d8a5ba45SMiklos Szeredi return res; 1832d8a5ba45SMiklos Szeredi } 1833d8a5ba45SMiklos Szeredi 1834d8a5ba45SMiklos Szeredi static void __exit fuse_exit(void) 1835d8a5ba45SMiklos Szeredi { 1836f2294482SKirill Smelkov pr_debug("exit\n"); 1837d8a5ba45SMiklos Szeredi 1838bafa9654SMiklos Szeredi fuse_ctl_cleanup(); 1839f543f253SMiklos Szeredi fuse_sysfs_cleanup(); 1840d8a5ba45SMiklos Szeredi fuse_fs_cleanup(); 1841334f485dSMiklos Szeredi fuse_dev_cleanup(); 1842d8a5ba45SMiklos Szeredi } 1843d8a5ba45SMiklos Szeredi 1844d8a5ba45SMiklos Szeredi module_init(fuse_init); 1845d8a5ba45SMiklos Szeredi module_exit(fuse_exit); 1846