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 67c30da2e9SDavid Howells struct fuse_fs_context { 68c30da2e9SDavid Howells const char *subtype; 69c30da2e9SDavid Howells bool is_bdev; 70d8a5ba45SMiklos Szeredi int fd; 71d8a5ba45SMiklos Szeredi unsigned rootmode; 72499dcf20SEric W. Biederman kuid_t user_id; 73499dcf20SEric W. Biederman kgid_t group_id; 745a533682SMiklos Szeredi unsigned fd_present:1; 755a533682SMiklos Szeredi unsigned rootmode_present:1; 765a533682SMiklos Szeredi unsigned user_id_present:1; 775a533682SMiklos Szeredi unsigned group_id_present:1; 7829433a29SMiklos Szeredi unsigned default_permissions:1; 7929433a29SMiklos Szeredi unsigned allow_other:1; 80db50b96cSMiklos Szeredi unsigned max_read; 81d8091614SMiklos Szeredi unsigned blksize; 82d8a5ba45SMiklos Szeredi }; 83d8a5ba45SMiklos Szeredi 84a2daff68SRandy Dunlap struct fuse_forget_link *fuse_alloc_forget(void) 8507e77dcaSMiklos Szeredi { 8607e77dcaSMiklos Szeredi return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); 8707e77dcaSMiklos Szeredi } 8807e77dcaSMiklos Szeredi 89d8a5ba45SMiklos Szeredi static struct inode *fuse_alloc_inode(struct super_block *sb) 90d8a5ba45SMiklos Szeredi { 91d8a5ba45SMiklos Szeredi struct fuse_inode *fi; 92d8a5ba45SMiklos Szeredi 939031a69cSzhangliguang fi = kmem_cache_alloc(fuse_inode_cachep, GFP_KERNEL); 949031a69cSzhangliguang if (!fi) 95d8a5ba45SMiklos Szeredi return NULL; 96d8a5ba45SMiklos Szeredi 970a0898cfSMiklos Szeredi fi->i_time = 0; 982f1e8196SMiklos Szeredi fi->inval_mask = 0; 99d8a5ba45SMiklos Szeredi fi->nodeid = 0; 1009e6268dbSMiklos Szeredi fi->nlookup = 0; 101fbee36b9SJohn Muir fi->attr_version = 0; 10245c72cd7SPavel Shilovsky fi->orig_ino = 0; 1034582a4abSFeng Shuo fi->state = 0; 1045c672ab3SMiklos Szeredi mutex_init(&fi->mutex); 105f15ecfefSKirill Tkhai spin_lock_init(&fi->lock); 10607e77dcaSMiklos Szeredi fi->forget = fuse_alloc_forget(); 10707e77dcaSMiklos Szeredi if (!fi->forget) { 1089031a69cSzhangliguang kmem_cache_free(fuse_inode_cachep, fi); 109e5e5558eSMiklos Szeredi return NULL; 110e5e5558eSMiklos Szeredi } 111d8a5ba45SMiklos Szeredi 1129031a69cSzhangliguang return &fi->inode; 113d8a5ba45SMiklos Szeredi } 114d8a5ba45SMiklos Szeredi 1159baf28bbSAl Viro static void fuse_free_inode(struct inode *inode) 116d8a5ba45SMiklos Szeredi { 117e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1189baf28bbSAl Viro 1195c672ab3SMiklos Szeredi mutex_destroy(&fi->mutex); 12007e77dcaSMiklos Szeredi kfree(fi->forget); 1219baf28bbSAl Viro kmem_cache_free(fuse_inode_cachep, fi); 122d8a5ba45SMiklos Szeredi } 123d8a5ba45SMiklos Szeredi 124b57922d9SAl Viro static void fuse_evict_inode(struct inode *inode) 125d8a5ba45SMiklos Szeredi { 1269baf28bbSAl Viro struct fuse_inode *fi = get_fuse_inode(inode); 1279baf28bbSAl Viro 12891b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data); 129dbd5768fSJan Kara clear_inode(inode); 1301751e8a6SLinus Torvalds if (inode->i_sb->s_flags & SB_ACTIVE) { 131e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 13207e77dcaSMiklos Szeredi fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup); 13307e77dcaSMiklos Szeredi fi->forget = NULL; 134e5e5558eSMiklos Szeredi } 1359baf28bbSAl Viro if (S_ISREG(inode->i_mode) && !is_bad_inode(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 14171421259SMiklos Szeredi static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) 14271421259SMiklos Szeredi { 14302b9984dSTheodore Ts'o sync_filesystem(sb); 1441751e8a6SLinus Torvalds if (*flags & SB_MANDLOCK) 14571421259SMiklos Szeredi return -EINVAL; 14671421259SMiklos Szeredi 14771421259SMiklos Szeredi return 0; 14871421259SMiklos Szeredi } 14971421259SMiklos Szeredi 15045c72cd7SPavel Shilovsky /* 15145c72cd7SPavel Shilovsky * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down 15245c72cd7SPavel Shilovsky * so that it will fit. 15345c72cd7SPavel Shilovsky */ 15445c72cd7SPavel Shilovsky static ino_t fuse_squash_ino(u64 ino64) 15545c72cd7SPavel Shilovsky { 15645c72cd7SPavel Shilovsky ino_t ino = (ino_t) ino64; 15745c72cd7SPavel Shilovsky if (sizeof(ino_t) < sizeof(u64)) 15845c72cd7SPavel Shilovsky ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8; 15945c72cd7SPavel Shilovsky return ino; 16045c72cd7SPavel Shilovsky } 16145c72cd7SPavel Shilovsky 1623be5a52bSMiklos Szeredi void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 1633be5a52bSMiklos Szeredi u64 attr_valid) 164d8a5ba45SMiklos Szeredi { 1659ffbb916SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 166ebc14c4dSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 167d8a5ba45SMiklos Szeredi 168f15ecfefSKirill Tkhai lockdep_assert_held(&fi->lock); 169f15ecfefSKirill Tkhai 1704510d86fSKirill Tkhai fi->attr_version = atomic64_inc_return(&fc->attr_version); 1711fb69e78SMiklos Szeredi fi->i_time = attr_valid; 1722f1e8196SMiklos Szeredi WRITE_ONCE(fi->inval_mask, 0); 1731fb69e78SMiklos Szeredi 17445c72cd7SPavel Shilovsky inode->i_ino = fuse_squash_ino(attr->ino); 175ebc14c4dSMiklos Szeredi inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 176bfe86848SMiklos Szeredi set_nlink(inode, attr->nlink); 1778cb08329SEric W. Biederman inode->i_uid = make_kuid(fc->user_ns, attr->uid); 1788cb08329SEric W. Biederman inode->i_gid = make_kgid(fc->user_ns, attr->gid); 179d8a5ba45SMiklos Szeredi inode->i_blocks = attr->blocks; 180d8a5ba45SMiklos Szeredi inode->i_atime.tv_sec = attr->atime; 181d8a5ba45SMiklos Szeredi inode->i_atime.tv_nsec = attr->atimensec; 182b0aa7606SMaxim Patlasov /* mtime from server may be stale due to local buffered write */ 183b0aa7606SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) { 184d8a5ba45SMiklos Szeredi inode->i_mtime.tv_sec = attr->mtime; 185d8a5ba45SMiklos Szeredi inode->i_mtime.tv_nsec = attr->mtimensec; 186d8a5ba45SMiklos Szeredi inode->i_ctime.tv_sec = attr->ctime; 187d8a5ba45SMiklos Szeredi inode->i_ctime.tv_nsec = attr->ctimensec; 18831f3267bSMaxim Patlasov } 189e00d2c2dSMiklos Szeredi 1900e9663eeSMiklos Szeredi if (attr->blksize != 0) 1910e9663eeSMiklos Szeredi inode->i_blkbits = ilog2(attr->blksize); 1920e9663eeSMiklos Szeredi else 1930e9663eeSMiklos Szeredi inode->i_blkbits = inode->i_sb->s_blocksize_bits; 1940e9663eeSMiklos Szeredi 195ebc14c4dSMiklos Szeredi /* 196ebc14c4dSMiklos Szeredi * Don't set the sticky bit in i_mode, unless we want the VFS 197ebc14c4dSMiklos Szeredi * to check permissions. This prevents failures due to the 198ebc14c4dSMiklos Szeredi * check in may_delete(). 199ebc14c4dSMiklos Szeredi */ 200ebc14c4dSMiklos Szeredi fi->orig_i_mode = inode->i_mode; 20129433a29SMiklos Szeredi if (!fc->default_permissions) 202ebc14c4dSMiklos Szeredi inode->i_mode &= ~S_ISVTX; 20345c72cd7SPavel Shilovsky 20445c72cd7SPavel Shilovsky fi->orig_ino = attr->ino; 2053be5a52bSMiklos Szeredi } 2063be5a52bSMiklos Szeredi 2073be5a52bSMiklos Szeredi void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, 2083be5a52bSMiklos Szeredi u64 attr_valid, u64 attr_version) 2093be5a52bSMiklos Szeredi { 2103be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 2113be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 2128373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 2133be5a52bSMiklos Szeredi loff_t oldsize; 214a64ba10fSArnd Bergmann struct timespec64 old_mtime; 2153be5a52bSMiklos Szeredi 216f15ecfefSKirill Tkhai spin_lock(&fi->lock); 21706a7c3c2SMaxim Patlasov if ((attr_version != 0 && fi->attr_version > attr_version) || 21806a7c3c2SMaxim Patlasov test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { 219f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 2203be5a52bSMiklos Szeredi return; 2213be5a52bSMiklos Szeredi } 2223be5a52bSMiklos Szeredi 223a64ba10fSArnd Bergmann old_mtime = inode->i_mtime; 2243be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, attr, attr_valid); 225ebc14c4dSMiklos Szeredi 226e00d2c2dSMiklos Szeredi oldsize = inode->i_size; 2278373200bSPavel Emelyanov /* 2288373200bSPavel Emelyanov * In case of writeback_cache enabled, the cached writes beyond EOF 2298373200bSPavel Emelyanov * extend local i_size without keeping userspace server in sync. So, 2308373200bSPavel Emelyanov * attr->size coming from server can be stale. We cannot trust it. 2318373200bSPavel Emelyanov */ 2328373200bSPavel Emelyanov if (!is_wb || !S_ISREG(inode->i_mode)) 233e00d2c2dSMiklos Szeredi i_size_write(inode, attr->size); 234f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 235e00d2c2dSMiklos Szeredi 2368373200bSPavel Emelyanov if (!is_wb && S_ISREG(inode->i_mode)) { 237eed2179eSBrian Foster bool inval = false; 238eed2179eSBrian Foster 239eed2179eSBrian Foster if (oldsize != attr->size) { 2407caef267SKirill A. Shutemov truncate_pagecache(inode, attr->size); 241ad2ba64dSKirill Smelkov if (!fc->explicit_inval_data) 242eed2179eSBrian Foster inval = true; 243eed2179eSBrian Foster } else if (fc->auto_inval_data) { 244a64ba10fSArnd Bergmann struct timespec64 new_mtime = { 245eed2179eSBrian Foster .tv_sec = attr->mtime, 246eed2179eSBrian Foster .tv_nsec = attr->mtimensec, 247eed2179eSBrian Foster }; 248eed2179eSBrian Foster 249eed2179eSBrian Foster /* 250eed2179eSBrian Foster * Auto inval mode also checks and invalidates if mtime 251eed2179eSBrian Foster * has changed. 252eed2179eSBrian Foster */ 253a64ba10fSArnd Bergmann if (!timespec64_equal(&old_mtime, &new_mtime)) 254eed2179eSBrian Foster inval = true; 255eed2179eSBrian Foster } 256eed2179eSBrian Foster 257eed2179eSBrian Foster if (inval) 258b1009979SMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 259e00d2c2dSMiklos Szeredi } 260d8a5ba45SMiklos Szeredi } 261d8a5ba45SMiklos Szeredi 262d8a5ba45SMiklos Szeredi static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) 263d8a5ba45SMiklos Szeredi { 264d8a5ba45SMiklos Szeredi inode->i_mode = attr->mode & S_IFMT; 2659ffbb916SMiklos Szeredi inode->i_size = attr->size; 266b0aa7606SMaxim Patlasov inode->i_mtime.tv_sec = attr->mtime; 267b0aa7606SMaxim Patlasov inode->i_mtime.tv_nsec = attr->mtimensec; 26831f3267bSMaxim Patlasov inode->i_ctime.tv_sec = attr->ctime; 26931f3267bSMaxim Patlasov inode->i_ctime.tv_nsec = attr->ctimensec; 270e5e5558eSMiklos Szeredi if (S_ISREG(inode->i_mode)) { 271e5e5558eSMiklos Szeredi fuse_init_common(inode); 272b6aeadedSMiklos Szeredi fuse_init_file_inode(inode); 273e5e5558eSMiklos Szeredi } else if (S_ISDIR(inode->i_mode)) 274e5e5558eSMiklos Szeredi fuse_init_dir(inode); 275e5e5558eSMiklos Szeredi else if (S_ISLNK(inode->i_mode)) 276e5e5558eSMiklos Szeredi fuse_init_symlink(inode); 277e5e5558eSMiklos Szeredi else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || 278e5e5558eSMiklos Szeredi S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 279e5e5558eSMiklos Szeredi fuse_init_common(inode); 280e5e5558eSMiklos Szeredi init_special_inode(inode, inode->i_mode, 281e5e5558eSMiklos Szeredi new_decode_dev(attr->rdev)); 28239ee059aSMiklos Szeredi } else 28339ee059aSMiklos Szeredi BUG(); 284d8a5ba45SMiklos Szeredi } 285d8a5ba45SMiklos Szeredi 2863b463ae0SJohn Muir int fuse_inode_eq(struct inode *inode, void *_nodeidp) 287d8a5ba45SMiklos Szeredi { 288b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 289d8a5ba45SMiklos Szeredi if (get_node_id(inode) == nodeid) 290d8a5ba45SMiklos Szeredi return 1; 291d8a5ba45SMiklos Szeredi else 292d8a5ba45SMiklos Szeredi return 0; 293d8a5ba45SMiklos Szeredi } 294d8a5ba45SMiklos Szeredi 295d8a5ba45SMiklos Szeredi static int fuse_inode_set(struct inode *inode, void *_nodeidp) 296d8a5ba45SMiklos Szeredi { 297b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 298d8a5ba45SMiklos Szeredi get_fuse_inode(inode)->nodeid = nodeid; 299d8a5ba45SMiklos Szeredi return 0; 300d8a5ba45SMiklos Szeredi } 301d8a5ba45SMiklos Szeredi 302b48badf0SMiklos Szeredi struct inode *fuse_iget(struct super_block *sb, u64 nodeid, 3031fb69e78SMiklos Szeredi int generation, struct fuse_attr *attr, 3041fb69e78SMiklos Szeredi u64 attr_valid, u64 attr_version) 305d8a5ba45SMiklos Szeredi { 306d8a5ba45SMiklos Szeredi struct inode *inode; 3079e6268dbSMiklos Szeredi struct fuse_inode *fi; 308d8a5ba45SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 309d8a5ba45SMiklos Szeredi 310d8a5ba45SMiklos Szeredi retry: 311d8a5ba45SMiklos Szeredi inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); 312d8a5ba45SMiklos Szeredi if (!inode) 313d8a5ba45SMiklos Szeredi return NULL; 314d8a5ba45SMiklos Szeredi 315d8a5ba45SMiklos Szeredi if ((inode->i_state & I_NEW)) { 316b0aa7606SMaxim Patlasov inode->i_flags |= S_NOATIME; 317d31433c8SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(attr->mode)) 318b0aa7606SMaxim Patlasov inode->i_flags |= S_NOCMTIME; 319d8a5ba45SMiklos Szeredi inode->i_generation = generation; 320d8a5ba45SMiklos Szeredi fuse_init_inode(inode, attr); 321d8a5ba45SMiklos Szeredi unlock_new_inode(inode); 322d8a5ba45SMiklos Szeredi } else if ((inode->i_mode ^ attr->mode) & S_IFMT) { 323d8a5ba45SMiklos Szeredi /* Inode has changed type, any I/O on the old should fail */ 324d8a5ba45SMiklos Szeredi make_bad_inode(inode); 325d8a5ba45SMiklos Szeredi iput(inode); 326d8a5ba45SMiklos Szeredi goto retry; 327d8a5ba45SMiklos Szeredi } 328d8a5ba45SMiklos Szeredi 3299e6268dbSMiklos Szeredi fi = get_fuse_inode(inode); 330c9d8f5f0SKirill Tkhai spin_lock(&fi->lock); 3319e6268dbSMiklos Szeredi fi->nlookup++; 332c9d8f5f0SKirill Tkhai spin_unlock(&fi->lock); 3331fb69e78SMiklos Szeredi fuse_change_attributes(inode, attr, attr_valid, attr_version); 3341fb69e78SMiklos Szeredi 335d8a5ba45SMiklos Szeredi return inode; 336d8a5ba45SMiklos Szeredi } 337d8a5ba45SMiklos Szeredi 3383b463ae0SJohn Muir int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, 3393b463ae0SJohn Muir loff_t offset, loff_t len) 3403b463ae0SJohn Muir { 3413b463ae0SJohn Muir struct inode *inode; 3423b463ae0SJohn Muir pgoff_t pg_start; 3433b463ae0SJohn Muir pgoff_t pg_end; 3443b463ae0SJohn Muir 3453b463ae0SJohn Muir inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid); 3463b463ae0SJohn Muir if (!inode) 3473b463ae0SJohn Muir return -ENOENT; 3483b463ae0SJohn Muir 3493b463ae0SJohn Muir fuse_invalidate_attr(inode); 35060bcc88aSSeth Forshee forget_all_cached_acls(inode); 3513b463ae0SJohn Muir if (offset >= 0) { 35209cbfeafSKirill A. Shutemov pg_start = offset >> PAGE_SHIFT; 3533b463ae0SJohn Muir if (len <= 0) 3543b463ae0SJohn Muir pg_end = -1; 3553b463ae0SJohn Muir else 35609cbfeafSKirill A. Shutemov pg_end = (offset + len - 1) >> PAGE_SHIFT; 3573b463ae0SJohn Muir invalidate_inode_pages2_range(inode->i_mapping, 3583b463ae0SJohn Muir pg_start, pg_end); 3593b463ae0SJohn Muir } 3603b463ae0SJohn Muir iput(inode); 3613b463ae0SJohn Muir return 0; 3623b463ae0SJohn Muir } 3633b463ae0SJohn Muir 36463576c13SMiklos Szeredi bool fuse_lock_inode(struct inode *inode) 3655c672ab3SMiklos Szeredi { 36663576c13SMiklos Szeredi bool locked = false; 36763576c13SMiklos Szeredi 36863576c13SMiklos Szeredi if (!get_fuse_conn(inode)->parallel_dirops) { 3695c672ab3SMiklos Szeredi mutex_lock(&get_fuse_inode(inode)->mutex); 37063576c13SMiklos Szeredi locked = true; 3715c672ab3SMiklos Szeredi } 3725c672ab3SMiklos Szeredi 37363576c13SMiklos Szeredi return locked; 37463576c13SMiklos Szeredi } 37563576c13SMiklos Szeredi 37663576c13SMiklos Szeredi void fuse_unlock_inode(struct inode *inode, bool locked) 3775c672ab3SMiklos Szeredi { 37863576c13SMiklos Szeredi if (locked) 3795c672ab3SMiklos Szeredi mutex_unlock(&get_fuse_inode(inode)->mutex); 3805c672ab3SMiklos Szeredi } 3815c672ab3SMiklos Szeredi 38242faad99SAl Viro static void fuse_umount_begin(struct super_block *sb) 38369a53bf2SMiklos Szeredi { 384eb98e3bdSMiklos Szeredi fuse_abort_conn(get_fuse_conn_super(sb)); 38569a53bf2SMiklos Szeredi } 38669a53bf2SMiklos Szeredi 3870ec7ca41SMiklos Szeredi static void fuse_send_destroy(struct fuse_conn *fc) 3880ec7ca41SMiklos Szeredi { 3890ec7ca41SMiklos Szeredi struct fuse_req *req = fc->destroy_req; 3900ec7ca41SMiklos Szeredi if (req && fc->conn_init) { 3910ec7ca41SMiklos Szeredi fc->destroy_req = NULL; 3920ec7ca41SMiklos Szeredi req->in.h.opcode = FUSE_DESTROY; 393825d6d33SMiklos Szeredi __set_bit(FR_FORCE, &req->flags); 394825d6d33SMiklos Szeredi __clear_bit(FR_BACKGROUND, &req->flags); 395b93f858aSTejun Heo fuse_request_send(fc, req); 3960ec7ca41SMiklos Szeredi fuse_put_request(fc, req); 3970ec7ca41SMiklos Szeredi } 3980ec7ca41SMiklos Szeredi } 3990ec7ca41SMiklos Szeredi 400a325f9b9STejun Heo static void fuse_put_super(struct super_block *sb) 401a325f9b9STejun Heo { 402a325f9b9STejun Heo struct fuse_conn *fc = get_fuse_conn_super(sb); 403a325f9b9STejun Heo 404bbd99797SMiklos Szeredi mutex_lock(&fuse_mutex); 405bbd99797SMiklos Szeredi list_del(&fc->entry); 406bbd99797SMiklos Szeredi fuse_ctl_remove_conn(fc); 407bbd99797SMiklos Szeredi mutex_unlock(&fuse_mutex); 408bbd99797SMiklos Szeredi 409bafa9654SMiklos Szeredi fuse_conn_put(fc); 410d8a5ba45SMiklos Szeredi } 411d8a5ba45SMiklos Szeredi 412e5e5558eSMiklos Szeredi static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 413e5e5558eSMiklos Szeredi { 414e5e5558eSMiklos Szeredi stbuf->f_type = FUSE_SUPER_MAGIC; 415e5e5558eSMiklos Szeredi stbuf->f_bsize = attr->bsize; 416de5f1202SMiklos Szeredi stbuf->f_frsize = attr->frsize; 417e5e5558eSMiklos Szeredi stbuf->f_blocks = attr->blocks; 418e5e5558eSMiklos Szeredi stbuf->f_bfree = attr->bfree; 419e5e5558eSMiklos Szeredi stbuf->f_bavail = attr->bavail; 420e5e5558eSMiklos Szeredi stbuf->f_files = attr->files; 421e5e5558eSMiklos Szeredi stbuf->f_ffree = attr->ffree; 422e5e5558eSMiklos Szeredi stbuf->f_namelen = attr->namelen; 423e5e5558eSMiklos Szeredi /* fsid is left zero */ 424e5e5558eSMiklos Szeredi } 425e5e5558eSMiklos Szeredi 426726c3342SDavid Howells static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) 427e5e5558eSMiklos Szeredi { 428726c3342SDavid Howells struct super_block *sb = dentry->d_sb; 429e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 4307078187aSMiklos Szeredi FUSE_ARGS(args); 431e5e5558eSMiklos Szeredi struct fuse_statfs_out outarg; 432e5e5558eSMiklos Szeredi int err; 433e5e5558eSMiklos Szeredi 434c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) { 435e57ac683SMiklos Szeredi buf->f_type = FUSE_SUPER_MAGIC; 436e57ac683SMiklos Szeredi return 0; 437e57ac683SMiklos Szeredi } 438e57ac683SMiklos Szeredi 439de5f1202SMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 4407078187aSMiklos Szeredi args.in.numargs = 0; 4417078187aSMiklos Szeredi args.in.h.opcode = FUSE_STATFS; 4422b0143b5SDavid Howells args.in.h.nodeid = get_node_id(d_inode(dentry)); 4437078187aSMiklos Szeredi args.out.numargs = 1; 44421f62174SMiklos Szeredi args.out.args[0].size = sizeof(outarg); 4457078187aSMiklos Szeredi args.out.args[0].value = &outarg; 4467078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 447e5e5558eSMiklos Szeredi if (!err) 448e5e5558eSMiklos Szeredi convert_fuse_statfs(buf, &outarg.st); 449e5e5558eSMiklos Szeredi return err; 450e5e5558eSMiklos Szeredi } 451e5e5558eSMiklos Szeredi 452d8a5ba45SMiklos Szeredi enum { 453c30da2e9SDavid Howells OPT_SOURCE, 454c30da2e9SDavid Howells OPT_SUBTYPE, 455d8a5ba45SMiklos Szeredi OPT_FD, 456d8a5ba45SMiklos Szeredi OPT_ROOTMODE, 457d8a5ba45SMiklos Szeredi OPT_USER_ID, 45887729a55SMiklos Szeredi OPT_GROUP_ID, 459d8a5ba45SMiklos Szeredi OPT_DEFAULT_PERMISSIONS, 460d8a5ba45SMiklos Szeredi OPT_ALLOW_OTHER, 461db50b96cSMiklos Szeredi OPT_MAX_READ, 462d8091614SMiklos Szeredi OPT_BLKSIZE, 463d8a5ba45SMiklos Szeredi OPT_ERR 464d8a5ba45SMiklos Szeredi }; 465d8a5ba45SMiklos Szeredi 466c30da2e9SDavid Howells static const struct fs_parameter_spec fuse_param_specs[] = { 467c30da2e9SDavid Howells fsparam_string ("source", OPT_SOURCE), 468c30da2e9SDavid Howells fsparam_u32 ("fd", OPT_FD), 469c30da2e9SDavid Howells fsparam_u32oct ("rootmode", OPT_ROOTMODE), 470c30da2e9SDavid Howells fsparam_u32 ("user_id", OPT_USER_ID), 471c30da2e9SDavid Howells fsparam_u32 ("group_id", OPT_GROUP_ID), 472c30da2e9SDavid Howells fsparam_flag ("default_permissions", OPT_DEFAULT_PERMISSIONS), 473c30da2e9SDavid Howells fsparam_flag ("allow_other", OPT_ALLOW_OTHER), 474c30da2e9SDavid Howells fsparam_u32 ("max_read", OPT_MAX_READ), 475c30da2e9SDavid Howells fsparam_u32 ("blksize", OPT_BLKSIZE), 476c7eb6869SDavid Howells fsparam_string ("subtype", OPT_SUBTYPE), 477c30da2e9SDavid Howells {} 478d8a5ba45SMiklos Szeredi }; 479d8a5ba45SMiklos Szeredi 480c30da2e9SDavid Howells static const struct fs_parameter_description fuse_fs_parameters = { 481c30da2e9SDavid Howells .name = "fuse", 482c30da2e9SDavid Howells .specs = fuse_param_specs, 483c30da2e9SDavid Howells }; 484c30da2e9SDavid Howells 485c30da2e9SDavid Howells static int fuse_parse_param(struct fs_context *fc, struct fs_parameter *param) 486233a01faSMiklos Szeredi { 487c30da2e9SDavid Howells struct fs_parse_result result; 488c30da2e9SDavid Howells struct fuse_fs_context *ctx = fc->fs_private; 489c30da2e9SDavid Howells int opt; 490233a01faSMiklos Szeredi 491c30da2e9SDavid Howells opt = fs_parse(fc, &fuse_fs_parameters, param, &result); 492c30da2e9SDavid Howells if (opt < 0) 493c30da2e9SDavid Howells return opt; 494d8a5ba45SMiklos Szeredi 495c30da2e9SDavid Howells switch (opt) { 496c30da2e9SDavid Howells case OPT_SOURCE: 497c30da2e9SDavid Howells if (fc->source) 498c30da2e9SDavid Howells return invalf(fc, "fuse: Multiple sources specified"); 499c30da2e9SDavid Howells fc->source = param->string; 500c30da2e9SDavid Howells param->string = NULL; 501c30da2e9SDavid Howells break; 502d8a5ba45SMiklos Szeredi 503c30da2e9SDavid Howells case OPT_SUBTYPE: 504c30da2e9SDavid Howells if (ctx->subtype) 505c30da2e9SDavid Howells return invalf(fc, "fuse: Multiple subtypes specified"); 506c30da2e9SDavid Howells ctx->subtype = param->string; 507c30da2e9SDavid Howells param->string = NULL; 508d8a5ba45SMiklos Szeredi return 0; 509c30da2e9SDavid Howells 510c30da2e9SDavid Howells case OPT_FD: 511c30da2e9SDavid Howells ctx->fd = result.uint_32; 512c30da2e9SDavid Howells ctx->fd_present = 1; 513d8a5ba45SMiklos Szeredi break; 514d8a5ba45SMiklos Szeredi 515d8a5ba45SMiklos Szeredi case OPT_ROOTMODE: 516c30da2e9SDavid Howells if (!fuse_valid_type(result.uint_32)) 517c30da2e9SDavid Howells return invalf(fc, "fuse: Invalid rootmode"); 518c30da2e9SDavid Howells ctx->rootmode = result.uint_32; 519c30da2e9SDavid Howells ctx->rootmode_present = 1; 520d8a5ba45SMiklos Szeredi break; 521d8a5ba45SMiklos Szeredi 522d8a5ba45SMiklos Szeredi case OPT_USER_ID: 523c30da2e9SDavid Howells ctx->user_id = make_kuid(fc->user_ns, result.uint_32); 524c30da2e9SDavid Howells if (!uid_valid(ctx->user_id)) 525c30da2e9SDavid Howells return invalf(fc, "fuse: Invalid user_id"); 526c30da2e9SDavid Howells ctx->user_id_present = 1; 527d8a5ba45SMiklos Szeredi break; 528d8a5ba45SMiklos Szeredi 52987729a55SMiklos Szeredi case OPT_GROUP_ID: 530c30da2e9SDavid Howells ctx->group_id = make_kgid(fc->user_ns, result.uint_32); 531c30da2e9SDavid Howells if (!gid_valid(ctx->group_id)) 532c30da2e9SDavid Howells return invalf(fc, "fuse: Invalid group_id"); 533c30da2e9SDavid Howells ctx->group_id_present = 1; 53487729a55SMiklos Szeredi break; 53587729a55SMiklos Szeredi 5361e9a4ed9SMiklos Szeredi case OPT_DEFAULT_PERMISSIONS: 537c30da2e9SDavid Howells ctx->default_permissions = 1; 5381e9a4ed9SMiklos Szeredi break; 5391e9a4ed9SMiklos Szeredi 5401e9a4ed9SMiklos Szeredi case OPT_ALLOW_OTHER: 541c30da2e9SDavid Howells ctx->allow_other = 1; 5421e9a4ed9SMiklos Szeredi break; 5431e9a4ed9SMiklos Szeredi 544db50b96cSMiklos Szeredi case OPT_MAX_READ: 545c30da2e9SDavid Howells ctx->max_read = result.uint_32; 546db50b96cSMiklos Szeredi break; 547db50b96cSMiklos Szeredi 548d8091614SMiklos Szeredi case OPT_BLKSIZE: 549c30da2e9SDavid Howells if (!ctx->is_bdev) 550c30da2e9SDavid Howells return invalf(fc, "fuse: blksize only supported for fuseblk"); 551c30da2e9SDavid Howells ctx->blksize = result.uint_32; 552d8091614SMiklos Szeredi break; 553d8091614SMiklos Szeredi 554d8a5ba45SMiklos Szeredi default: 555c30da2e9SDavid Howells return -EINVAL; 556d8a5ba45SMiklos Szeredi } 5575a533682SMiklos Szeredi 558d8a5ba45SMiklos Szeredi return 0; 559c30da2e9SDavid Howells } 560d8a5ba45SMiklos Szeredi 561c30da2e9SDavid Howells static void fuse_free_fc(struct fs_context *fc) 562c30da2e9SDavid Howells { 563c30da2e9SDavid Howells struct fuse_fs_context *ctx = fc->fs_private; 564c30da2e9SDavid Howells 565c30da2e9SDavid Howells if (ctx) { 566c30da2e9SDavid Howells kfree(ctx->subtype); 567c30da2e9SDavid Howells kfree(ctx); 568c30da2e9SDavid Howells } 569d8a5ba45SMiklos Szeredi } 570d8a5ba45SMiklos Szeredi 57134c80b1dSAl Viro static int fuse_show_options(struct seq_file *m, struct dentry *root) 572d8a5ba45SMiklos Szeredi { 57334c80b1dSAl Viro struct super_block *sb = root->d_sb; 57434c80b1dSAl Viro struct fuse_conn *fc = get_fuse_conn_super(sb); 575d8a5ba45SMiklos Szeredi 5768cb08329SEric W. Biederman seq_printf(m, ",user_id=%u", from_kuid_munged(fc->user_ns, fc->user_id)); 5778cb08329SEric W. Biederman seq_printf(m, ",group_id=%u", from_kgid_munged(fc->user_ns, fc->group_id)); 57829433a29SMiklos Szeredi if (fc->default_permissions) 5791e9a4ed9SMiklos Szeredi seq_puts(m, ",default_permissions"); 58029433a29SMiklos Szeredi if (fc->allow_other) 5811e9a4ed9SMiklos Szeredi seq_puts(m, ",allow_other"); 582db50b96cSMiklos Szeredi if (fc->max_read != ~0) 583db50b96cSMiklos Szeredi seq_printf(m, ",max_read=%u", fc->max_read); 58434c80b1dSAl Viro if (sb->s_bdev && sb->s_blocksize != FUSE_DEFAULT_BLKSIZE) 58534c80b1dSAl Viro seq_printf(m, ",blksize=%lu", sb->s_blocksize); 586d8a5ba45SMiklos Szeredi return 0; 587d8a5ba45SMiklos Szeredi } 588d8a5ba45SMiklos Szeredi 589f88996a9SMiklos Szeredi static void fuse_iqueue_init(struct fuse_iqueue *fiq) 590f88996a9SMiklos Szeredi { 591f88996a9SMiklos Szeredi memset(fiq, 0, sizeof(struct fuse_iqueue)); 592f88996a9SMiklos Szeredi init_waitqueue_head(&fiq->waitq); 593f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->pending); 594f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->interrupts); 595f88996a9SMiklos Szeredi fiq->forget_list_tail = &fiq->forget_list_head; 596e16714d8SMiklos Szeredi fiq->connected = 1; 597f88996a9SMiklos Szeredi } 598f88996a9SMiklos Szeredi 5993a2b5b9cSMiklos Szeredi static void fuse_pqueue_init(struct fuse_pqueue *fpq) 6003a2b5b9cSMiklos Szeredi { 601be2ff42cSKirill Tkhai unsigned int i; 602be2ff42cSKirill Tkhai 60345a91cb1SMiklos Szeredi spin_lock_init(&fpq->lock); 604be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) 605be2ff42cSKirill Tkhai INIT_LIST_HEAD(&fpq->processing[i]); 6063a2b5b9cSMiklos Szeredi INIT_LIST_HEAD(&fpq->io); 607e96edd94SMiklos Szeredi fpq->connected = 1; 6083a2b5b9cSMiklos Szeredi } 6093a2b5b9cSMiklos Szeredi 6108cb08329SEric W. Biederman void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns) 611d8a5ba45SMiklos Szeredi { 6120d179aa5STejun Heo memset(fc, 0, sizeof(*fc)); 613d7133114SMiklos Szeredi spin_lock_init(&fc->lock); 614ae2dffa3SKirill Tkhai spin_lock_init(&fc->bg_lock); 6153b463ae0SJohn Muir init_rwsem(&fc->killsb); 616095fc40aSElena Reshetova refcount_set(&fc->count, 1); 617c3696046SMiklos Szeredi atomic_set(&fc->dev_count, 1); 61808a53cdcSMiklos Szeredi init_waitqueue_head(&fc->blocked_waitq); 619de5e3decSMiklos Szeredi init_waitqueue_head(&fc->reserved_req_waitq); 620f88996a9SMiklos Szeredi fuse_iqueue_init(&fc->iq); 621d12def1bSMiklos Szeredi INIT_LIST_HEAD(&fc->bg_queue); 6220d179aa5STejun Heo INIT_LIST_HEAD(&fc->entry); 623cc080e9eSMiklos Szeredi INIT_LIST_HEAD(&fc->devices); 624095da6cbSMiklos Szeredi atomic_set(&fc->num_waiting, 0); 6257a6d3c8bSCsaba Henk fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; 6267a6d3c8bSCsaba Henk fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; 62775126f55SMiklos Szeredi atomic64_set(&fc->khctr, 0); 62895668a69STejun Heo fc->polled_files = RB_ROOT; 6290aada884SMaxim Patlasov fc->blocked = 0; 630796523fbSMaxim Patlasov fc->initialized = 0; 631e16714d8SMiklos Szeredi fc->connected = 1; 6324510d86fSKirill Tkhai atomic64_set(&fc->attr_version, 1); 6339c8ef561SMiklos Szeredi get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); 6340b6e9ea0SSeth Forshee fc->pid_ns = get_pid_ns(task_active_pid_ns(current)); 6358cb08329SEric W. Biederman fc->user_ns = get_user_ns(user_ns); 6368a3177dbSMiklos Szeredi fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; 637d8a5ba45SMiklos Szeredi } 6380d179aa5STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_init); 639d8a5ba45SMiklos Szeredi 640bafa9654SMiklos Szeredi void fuse_conn_put(struct fuse_conn *fc) 641bafa9654SMiklos Szeredi { 642095fc40aSElena Reshetova if (refcount_dec_and_test(&fc->count)) { 6430ec7ca41SMiklos Szeredi if (fc->destroy_req) 6440ec7ca41SMiklos Szeredi fuse_request_free(fc->destroy_req); 6450b6e9ea0SSeth Forshee put_pid_ns(fc->pid_ns); 6468cb08329SEric W. Biederman put_user_ns(fc->user_ns); 64743901aabSTejun Heo fc->release(fc); 648bafa9654SMiklos Szeredi } 649d2a85164SMiklos Szeredi } 65008cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_put); 651bafa9654SMiklos Szeredi 652bafa9654SMiklos Szeredi struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) 653bafa9654SMiklos Szeredi { 654095fc40aSElena Reshetova refcount_inc(&fc->count); 655bafa9654SMiklos Szeredi return fc; 656bafa9654SMiklos Szeredi } 65708cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_get); 658bafa9654SMiklos Szeredi 659b93f858aSTejun Heo static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) 660d8a5ba45SMiklos Szeredi { 661d8a5ba45SMiklos Szeredi struct fuse_attr attr; 662d8a5ba45SMiklos Szeredi memset(&attr, 0, sizeof(attr)); 663d8a5ba45SMiklos Szeredi 664d8a5ba45SMiklos Szeredi attr.mode = mode; 665d8a5ba45SMiklos Szeredi attr.ino = FUSE_ROOT_ID; 666074406faSMiklos Szeredi attr.nlink = 1; 6671fb69e78SMiklos Szeredi return fuse_iget(sb, 1, 0, &attr, 0, 0); 668d8a5ba45SMiklos Szeredi } 669d8a5ba45SMiklos Szeredi 6701729a16cSMiklos Szeredi struct fuse_inode_handle { 671dbd561d2SMiklos Szeredi u64 nodeid; 672dbd561d2SMiklos Szeredi u32 generation; 673dbd561d2SMiklos Szeredi }; 674dbd561d2SMiklos Szeredi 675dbd561d2SMiklos Szeredi static struct dentry *fuse_get_dentry(struct super_block *sb, 676dbd561d2SMiklos Szeredi struct fuse_inode_handle *handle) 677dbd561d2SMiklos Szeredi { 67833670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 679dbd561d2SMiklos Szeredi struct inode *inode; 680dbd561d2SMiklos Szeredi struct dentry *entry; 681dbd561d2SMiklos Szeredi int err = -ESTALE; 682dbd561d2SMiklos Szeredi 683dbd561d2SMiklos Szeredi if (handle->nodeid == 0) 684dbd561d2SMiklos Szeredi goto out_err; 685dbd561d2SMiklos Szeredi 686dbd561d2SMiklos Szeredi inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid); 68733670fa2SMiklos Szeredi if (!inode) { 68833670fa2SMiklos Szeredi struct fuse_entry_out outarg; 68913983d06SAl Viro const struct qstr name = QSTR_INIT(".", 1); 69033670fa2SMiklos Szeredi 69133670fa2SMiklos Szeredi if (!fc->export_support) 692dbd561d2SMiklos Szeredi goto out_err; 69333670fa2SMiklos Szeredi 69433670fa2SMiklos Szeredi err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg, 69533670fa2SMiklos Szeredi &inode); 69633670fa2SMiklos Szeredi if (err && err != -ENOENT) 69733670fa2SMiklos Szeredi goto out_err; 69833670fa2SMiklos Szeredi if (err || !inode) { 69933670fa2SMiklos Szeredi err = -ESTALE; 70033670fa2SMiklos Szeredi goto out_err; 70133670fa2SMiklos Szeredi } 70233670fa2SMiklos Szeredi err = -EIO; 70333670fa2SMiklos Szeredi if (get_node_id(inode) != handle->nodeid) 70433670fa2SMiklos Szeredi goto out_iput; 70533670fa2SMiklos Szeredi } 706dbd561d2SMiklos Szeredi err = -ESTALE; 707dbd561d2SMiklos Szeredi if (inode->i_generation != handle->generation) 708dbd561d2SMiklos Szeredi goto out_iput; 709dbd561d2SMiklos Szeredi 71044003728SChristoph Hellwig entry = d_obtain_alias(inode); 711c35eebe9SAl Viro if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) 712dbd561d2SMiklos Szeredi fuse_invalidate_entry_cache(entry); 713dbd561d2SMiklos Szeredi 714dbd561d2SMiklos Szeredi return entry; 715dbd561d2SMiklos Szeredi 716dbd561d2SMiklos Szeredi out_iput: 717dbd561d2SMiklos Szeredi iput(inode); 718dbd561d2SMiklos Szeredi out_err: 719dbd561d2SMiklos Szeredi return ERR_PTR(err); 720dbd561d2SMiklos Szeredi } 721dbd561d2SMiklos Szeredi 722b0b0382bSAl Viro static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len, 723b0b0382bSAl Viro struct inode *parent) 724dbd561d2SMiklos Szeredi { 725b0b0382bSAl Viro int len = parent ? 6 : 3; 726dbd561d2SMiklos Szeredi u64 nodeid; 727dbd561d2SMiklos Szeredi u32 generation; 728dbd561d2SMiklos Szeredi 7295fe0c237SAneesh Kumar K.V if (*max_len < len) { 7305fe0c237SAneesh Kumar K.V *max_len = len; 73194e07a75SNamjae Jeon return FILEID_INVALID; 7325fe0c237SAneesh Kumar K.V } 733dbd561d2SMiklos Szeredi 734dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(inode)->nodeid; 735dbd561d2SMiklos Szeredi generation = inode->i_generation; 736dbd561d2SMiklos Szeredi 737dbd561d2SMiklos Szeredi fh[0] = (u32)(nodeid >> 32); 738dbd561d2SMiklos Szeredi fh[1] = (u32)(nodeid & 0xffffffff); 739dbd561d2SMiklos Szeredi fh[2] = generation; 740dbd561d2SMiklos Szeredi 741b0b0382bSAl Viro if (parent) { 742dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(parent)->nodeid; 743dbd561d2SMiklos Szeredi generation = parent->i_generation; 744dbd561d2SMiklos Szeredi 745dbd561d2SMiklos Szeredi fh[3] = (u32)(nodeid >> 32); 746dbd561d2SMiklos Szeredi fh[4] = (u32)(nodeid & 0xffffffff); 747dbd561d2SMiklos Szeredi fh[5] = generation; 748dbd561d2SMiklos Szeredi } 749dbd561d2SMiklos Szeredi 750dbd561d2SMiklos Szeredi *max_len = len; 751b0b0382bSAl Viro return parent ? 0x82 : 0x81; 752dbd561d2SMiklos Szeredi } 753dbd561d2SMiklos Szeredi 754dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_dentry(struct super_block *sb, 755dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 756dbd561d2SMiklos Szeredi { 757dbd561d2SMiklos Szeredi struct fuse_inode_handle handle; 758dbd561d2SMiklos Szeredi 759dbd561d2SMiklos Szeredi if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3) 760dbd561d2SMiklos Szeredi return NULL; 761dbd561d2SMiklos Szeredi 762dbd561d2SMiklos Szeredi handle.nodeid = (u64) fid->raw[0] << 32; 763dbd561d2SMiklos Szeredi handle.nodeid |= (u64) fid->raw[1]; 764dbd561d2SMiklos Szeredi handle.generation = fid->raw[2]; 765dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &handle); 766dbd561d2SMiklos Szeredi } 767dbd561d2SMiklos Szeredi 768dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_parent(struct super_block *sb, 769dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 770dbd561d2SMiklos Szeredi { 771dbd561d2SMiklos Szeredi struct fuse_inode_handle parent; 772dbd561d2SMiklos Szeredi 773dbd561d2SMiklos Szeredi if (fh_type != 0x82 || fh_len < 6) 774dbd561d2SMiklos Szeredi return NULL; 775dbd561d2SMiklos Szeredi 776dbd561d2SMiklos Szeredi parent.nodeid = (u64) fid->raw[3] << 32; 777dbd561d2SMiklos Szeredi parent.nodeid |= (u64) fid->raw[4]; 778dbd561d2SMiklos Szeredi parent.generation = fid->raw[5]; 779dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &parent); 780dbd561d2SMiklos Szeredi } 781dbd561d2SMiklos Szeredi 78233670fa2SMiklos Szeredi static struct dentry *fuse_get_parent(struct dentry *child) 78333670fa2SMiklos Szeredi { 7842b0143b5SDavid Howells struct inode *child_inode = d_inode(child); 78533670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(child_inode); 78633670fa2SMiklos Szeredi struct inode *inode; 78733670fa2SMiklos Szeredi struct dentry *parent; 78833670fa2SMiklos Szeredi struct fuse_entry_out outarg; 78913983d06SAl Viro const struct qstr name = QSTR_INIT("..", 2); 79033670fa2SMiklos Szeredi int err; 79133670fa2SMiklos Szeredi 79233670fa2SMiklos Szeredi if (!fc->export_support) 79333670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 79433670fa2SMiklos Szeredi 79533670fa2SMiklos Szeredi err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode), 79633670fa2SMiklos Szeredi &name, &outarg, &inode); 79744003728SChristoph Hellwig if (err) { 79844003728SChristoph Hellwig if (err == -ENOENT) 79933670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 80044003728SChristoph Hellwig return ERR_PTR(err); 80133670fa2SMiklos Szeredi } 80244003728SChristoph Hellwig 80344003728SChristoph Hellwig parent = d_obtain_alias(inode); 804c35eebe9SAl Viro if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) 80533670fa2SMiklos Szeredi fuse_invalidate_entry_cache(parent); 80633670fa2SMiklos Szeredi 80733670fa2SMiklos Szeredi return parent; 80833670fa2SMiklos Szeredi } 809dbd561d2SMiklos Szeredi 810dbd561d2SMiklos Szeredi static const struct export_operations fuse_export_operations = { 811dbd561d2SMiklos Szeredi .fh_to_dentry = fuse_fh_to_dentry, 812dbd561d2SMiklos Szeredi .fh_to_parent = fuse_fh_to_parent, 813dbd561d2SMiklos Szeredi .encode_fh = fuse_encode_fh, 81433670fa2SMiklos Szeredi .get_parent = fuse_get_parent, 815dbd561d2SMiklos Szeredi }; 816dbd561d2SMiklos Szeredi 817ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations fuse_super_operations = { 818d8a5ba45SMiklos Szeredi .alloc_inode = fuse_alloc_inode, 8199baf28bbSAl Viro .free_inode = fuse_free_inode, 820b57922d9SAl Viro .evict_inode = fuse_evict_inode, 8211e18bda8SMiklos Szeredi .write_inode = fuse_write_inode, 822ead5f0b5SMiklos Szeredi .drop_inode = generic_delete_inode, 82371421259SMiklos Szeredi .remount_fs = fuse_remount_fs, 824d8a5ba45SMiklos Szeredi .put_super = fuse_put_super, 82569a53bf2SMiklos Szeredi .umount_begin = fuse_umount_begin, 826e5e5558eSMiklos Szeredi .statfs = fuse_statfs, 827d8a5ba45SMiklos Szeredi .show_options = fuse_show_options, 828d8a5ba45SMiklos Szeredi }; 829d8a5ba45SMiklos Szeredi 830487ea5afSCsaba Henk static void sanitize_global_limit(unsigned *limit) 831487ea5afSCsaba Henk { 832487ea5afSCsaba Henk if (*limit == 0) 833ca79b0c2SArun KS *limit = ((totalram_pages() << PAGE_SHIFT) >> 13) / 834487ea5afSCsaba Henk sizeof(struct fuse_req); 835487ea5afSCsaba Henk 836487ea5afSCsaba Henk if (*limit >= 1 << 16) 837487ea5afSCsaba Henk *limit = (1 << 16) - 1; 838487ea5afSCsaba Henk } 839487ea5afSCsaba Henk 840e4dca7b7SKees Cook static int set_global_limit(const char *val, const struct kernel_param *kp) 841487ea5afSCsaba Henk { 842487ea5afSCsaba Henk int rv; 843487ea5afSCsaba Henk 844487ea5afSCsaba Henk rv = param_set_uint(val, kp); 845487ea5afSCsaba Henk if (rv) 846487ea5afSCsaba Henk return rv; 847487ea5afSCsaba Henk 848487ea5afSCsaba Henk sanitize_global_limit((unsigned *)kp->arg); 849487ea5afSCsaba Henk 850487ea5afSCsaba Henk return 0; 851487ea5afSCsaba Henk } 852487ea5afSCsaba Henk 853487ea5afSCsaba Henk static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) 854487ea5afSCsaba Henk { 855487ea5afSCsaba Henk int cap_sys_admin = capable(CAP_SYS_ADMIN); 856487ea5afSCsaba Henk 857487ea5afSCsaba Henk if (arg->minor < 13) 858487ea5afSCsaba Henk return; 859487ea5afSCsaba Henk 860487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 861487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 862487ea5afSCsaba Henk 863ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 864487ea5afSCsaba Henk if (arg->max_background) { 865487ea5afSCsaba Henk fc->max_background = arg->max_background; 866487ea5afSCsaba Henk 867487ea5afSCsaba Henk if (!cap_sys_admin && fc->max_background > max_user_bgreq) 868487ea5afSCsaba Henk fc->max_background = max_user_bgreq; 869487ea5afSCsaba Henk } 870487ea5afSCsaba Henk if (arg->congestion_threshold) { 871487ea5afSCsaba Henk fc->congestion_threshold = arg->congestion_threshold; 872487ea5afSCsaba Henk 873487ea5afSCsaba Henk if (!cap_sys_admin && 874487ea5afSCsaba Henk fc->congestion_threshold > max_user_congthresh) 875487ea5afSCsaba Henk fc->congestion_threshold = max_user_congthresh; 876487ea5afSCsaba Henk } 877ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 878487ea5afSCsaba Henk } 879487ea5afSCsaba Henk 8809b9a0469SMiklos Szeredi static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) 8819b9a0469SMiklos Szeredi { 8829b9a0469SMiklos Szeredi struct fuse_init_out *arg = &req->misc.init_out; 8839b9a0469SMiklos Szeredi 8849b9a0469SMiklos Szeredi if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) 8859b9a0469SMiklos Szeredi fc->conn_error = 1; 8869b9a0469SMiklos Szeredi else { 8879cd68455SMiklos Szeredi unsigned long ra_pages; 8889cd68455SMiklos Szeredi 889487ea5afSCsaba Henk process_init_limits(fc, arg); 890487ea5afSCsaba Henk 8919cd68455SMiklos Szeredi if (arg->minor >= 6) { 89209cbfeafSKirill A. Shutemov ra_pages = arg->max_readahead / PAGE_SIZE; 8939cd68455SMiklos Szeredi if (arg->flags & FUSE_ASYNC_READ) 8949cd68455SMiklos Szeredi fc->async_read = 1; 89571421259SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 89671421259SMiklos Szeredi fc->no_lock = 1; 89737fb3a30SMiklos Szeredi if (arg->minor >= 17) { 89837fb3a30SMiklos Szeredi if (!(arg->flags & FUSE_FLOCK_LOCKS)) 89937fb3a30SMiklos Szeredi fc->no_flock = 1; 90024114504SMiklos Szeredi } else { 90124114504SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 90224114504SMiklos Szeredi fc->no_flock = 1; 90337fb3a30SMiklos Szeredi } 9046ff958edSMiklos Szeredi if (arg->flags & FUSE_ATOMIC_O_TRUNC) 9056ff958edSMiklos Szeredi fc->atomic_o_trunc = 1; 90633670fa2SMiklos Szeredi if (arg->minor >= 9) { 90733670fa2SMiklos Szeredi /* LOOKUP has dependency on proto version */ 90833670fa2SMiklos Szeredi if (arg->flags & FUSE_EXPORT_SUPPORT) 90933670fa2SMiklos Szeredi fc->export_support = 1; 91033670fa2SMiklos Szeredi } 91178bb6cb9SMiklos Szeredi if (arg->flags & FUSE_BIG_WRITES) 91278bb6cb9SMiklos Szeredi fc->big_writes = 1; 913e0a43ddcSMiklos Szeredi if (arg->flags & FUSE_DONT_MASK) 914e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 91572d0d248SBrian Foster if (arg->flags & FUSE_AUTO_INVAL_DATA) 91672d0d248SBrian Foster fc->auto_inval_data = 1; 917ad2ba64dSKirill Smelkov else if (arg->flags & FUSE_EXPLICIT_INVAL_DATA) 918ad2ba64dSKirill Smelkov fc->explicit_inval_data = 1; 91928420dadSMiklos Szeredi if (arg->flags & FUSE_DO_READDIRPLUS) { 9200b05b183SAnand V. Avati fc->do_readdirplus = 1; 921634734b6SEric Wong if (arg->flags & FUSE_READDIRPLUS_AUTO) 922634734b6SEric Wong fc->readdirplus_auto = 1; 92328420dadSMiklos Szeredi } 92460b9df7aSMiklos Szeredi if (arg->flags & FUSE_ASYNC_DIO) 92560b9df7aSMiklos Szeredi fc->async_dio = 1; 9264d99ff8fSPavel Emelyanov if (arg->flags & FUSE_WRITEBACK_CACHE) 9274d99ff8fSPavel Emelyanov fc->writeback_cache = 1; 9285c672ab3SMiklos Szeredi if (arg->flags & FUSE_PARALLEL_DIROPS) 9295c672ab3SMiklos Szeredi fc->parallel_dirops = 1; 9305e940c1dSMiklos Szeredi if (arg->flags & FUSE_HANDLE_KILLPRIV) 9315e940c1dSMiklos Szeredi fc->handle_killpriv = 1; 932e27c9d38SMiklos Szeredi if (arg->time_gran && arg->time_gran <= 1000000000) 933e27c9d38SMiklos Szeredi fc->sb->s_time_gran = arg->time_gran; 93460bcc88aSSeth Forshee if ((arg->flags & FUSE_POSIX_ACL)) { 93529433a29SMiklos Szeredi fc->default_permissions = 1; 93660bcc88aSSeth Forshee fc->posix_acl = 1; 93760bcc88aSSeth Forshee fc->sb->s_xattr = fuse_acl_xattr_handlers; 93860bcc88aSSeth Forshee } 9395571f1e6SDan Schatzberg if (arg->flags & FUSE_CACHE_SYMLINKS) 9405571f1e6SDan Schatzberg fc->cache_symlinks = 1; 9413b7008b2SSzymon Lukasz if (arg->flags & FUSE_ABORT_ERROR) 9423b7008b2SSzymon Lukasz fc->abort_err = 1; 9435da784ccSConstantine Shulyupin if (arg->flags & FUSE_MAX_PAGES) { 9445da784ccSConstantine Shulyupin fc->max_pages = 9455da784ccSConstantine Shulyupin min_t(unsigned int, FUSE_MAX_MAX_PAGES, 9465da784ccSConstantine Shulyupin max_t(unsigned int, arg->max_pages, 1)); 9475da784ccSConstantine Shulyupin } 94871421259SMiklos Szeredi } else { 94909cbfeafSKirill A. Shutemov ra_pages = fc->max_read / PAGE_SIZE; 95071421259SMiklos Szeredi fc->no_lock = 1; 95137fb3a30SMiklos Szeredi fc->no_flock = 1; 95271421259SMiklos Szeredi } 9539cd68455SMiklos Szeredi 9545f7f7543SJan Kara fc->sb->s_bdi->ra_pages = 9555f7f7543SJan Kara min(fc->sb->s_bdi->ra_pages, ra_pages); 9569b9a0469SMiklos Szeredi fc->minor = arg->minor; 9579b9a0469SMiklos Szeredi fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 958f948d564SMiklos Szeredi fc->max_write = max_t(unsigned, 4096, fc->max_write); 9590ec7ca41SMiklos Szeredi fc->conn_init = 1; 9609b9a0469SMiklos Szeredi } 9619759bd51SMiklos Szeredi fuse_set_initialized(fc); 96208a53cdcSMiklos Szeredi wake_up_all(&fc->blocked_waitq); 9639b9a0469SMiklos Szeredi } 9649b9a0469SMiklos Szeredi 965ce1d5a49SMiklos Szeredi static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) 9669b9a0469SMiklos Szeredi { 9679b9a0469SMiklos Szeredi struct fuse_init_in *arg = &req->misc.init_in; 968095da6cbSMiklos Szeredi 9699b9a0469SMiklos Szeredi arg->major = FUSE_KERNEL_VERSION; 9709b9a0469SMiklos Szeredi arg->minor = FUSE_KERNEL_MINOR_VERSION; 9715f7f7543SJan Kara arg->max_readahead = fc->sb->s_bdi->ra_pages * PAGE_SIZE; 97278bb6cb9SMiklos Szeredi arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | 97337fb3a30SMiklos Szeredi FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | 97469fe05c9SMiklos Szeredi FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | 9759446385fSWei Fang FUSE_FLOCK_LOCKS | FUSE_HAS_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | 9764d99ff8fSPavel Emelyanov FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | 9775c672ab3SMiklos Szeredi FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | 9783b7008b2SSzymon Lukasz FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | 979d9a9ea94SChad Austin FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS | 980ad2ba64dSKirill Smelkov FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA; 9819b9a0469SMiklos Szeredi req->in.h.opcode = FUSE_INIT; 9829b9a0469SMiklos Szeredi req->in.numargs = 1; 9839b9a0469SMiklos Szeredi req->in.args[0].size = sizeof(*arg); 9849b9a0469SMiklos Szeredi req->in.args[0].value = arg; 9859b9a0469SMiklos Szeredi req->out.numargs = 1; 9863ad2f3fbSDaniel Mack /* Variable length argument used for backward compatibility 9879b9a0469SMiklos Szeredi with interface version < 7.5. Rest of init_out is zeroed 9889b9a0469SMiklos Szeredi by do_get_request(), so a short reply is not a problem */ 9899b9a0469SMiklos Szeredi req->out.argvar = 1; 9909b9a0469SMiklos Szeredi req->out.args[0].size = sizeof(struct fuse_init_out); 9919b9a0469SMiklos Szeredi req->out.args[0].value = &req->misc.init_out; 9929b9a0469SMiklos Szeredi req->end = process_init_reply; 993b93f858aSTejun Heo fuse_request_send_background(fc, req); 9949b9a0469SMiklos Szeredi } 9959b9a0469SMiklos Szeredi 99643901aabSTejun Heo static void fuse_free_conn(struct fuse_conn *fc) 99743901aabSTejun Heo { 998cc080e9eSMiklos Szeredi WARN_ON(!list_empty(&fc->devices)); 999dd3e2c55SAl Viro kfree_rcu(fc, rcu); 100043901aabSTejun Heo } 100143901aabSTejun Heo 1002a325f9b9STejun Heo static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) 1003a325f9b9STejun Heo { 1004a325f9b9STejun Heo int err; 10055f7f7543SJan Kara char *suffix = ""; 1006a325f9b9STejun Heo 100769c8ebf8SJan Kara if (sb->s_bdev) { 10085f7f7543SJan Kara suffix = "-fuseblk"; 100969c8ebf8SJan Kara /* 101069c8ebf8SJan Kara * sb->s_bdi points to blkdev's bdi however we want to redirect 101169c8ebf8SJan Kara * it to our private bdi... 101269c8ebf8SJan Kara */ 101369c8ebf8SJan Kara bdi_put(sb->s_bdi); 101469c8ebf8SJan Kara sb->s_bdi = &noop_backing_dev_info; 101569c8ebf8SJan Kara } 10165f7f7543SJan Kara err = super_setup_bdi_name(sb, "%u:%u%s", MAJOR(fc->dev), 10175f7f7543SJan Kara MINOR(fc->dev), suffix); 1018a325f9b9STejun Heo if (err) 1019a325f9b9STejun Heo return err; 1020a325f9b9STejun Heo 1021b5420237SNikolay Borisov sb->s_bdi->ra_pages = VM_READAHEAD_PAGES; 10225f7f7543SJan Kara /* fuse does it's own writeback accounting */ 10235f7f7543SJan Kara sb->s_bdi->capabilities = BDI_CAP_NO_ACCT_WB | BDI_CAP_STRICTLIMIT; 10245f7f7543SJan Kara 1025a325f9b9STejun Heo /* 1026a325f9b9STejun Heo * For a single fuse filesystem use max 1% of dirty + 1027a325f9b9STejun Heo * writeback threshold. 1028a325f9b9STejun Heo * 1029a325f9b9STejun Heo * This gives about 1M of write buffer for memory maps on a 1030a325f9b9STejun Heo * machine with 1G and 10% dirty_ratio, which should be more 1031a325f9b9STejun Heo * than enough. 1032a325f9b9STejun Heo * 1033a325f9b9STejun Heo * Privileged users can raise it by writing to 1034a325f9b9STejun Heo * 1035a325f9b9STejun Heo * /sys/class/bdi/<bdi>/max_ratio 1036a325f9b9STejun Heo */ 10375f7f7543SJan Kara bdi_set_max_ratio(sb->s_bdi, 1); 1038a325f9b9STejun Heo 1039a325f9b9STejun Heo return 0; 1040a325f9b9STejun Heo } 1041a325f9b9STejun Heo 1042cc080e9eSMiklos Szeredi struct fuse_dev *fuse_dev_alloc(struct fuse_conn *fc) 1043cc080e9eSMiklos Szeredi { 1044cc080e9eSMiklos Szeredi struct fuse_dev *fud; 1045be2ff42cSKirill Tkhai struct list_head *pq; 1046cc080e9eSMiklos Szeredi 1047cc080e9eSMiklos Szeredi fud = kzalloc(sizeof(struct fuse_dev), GFP_KERNEL); 1048be2ff42cSKirill Tkhai if (!fud) 1049be2ff42cSKirill Tkhai return NULL; 1050be2ff42cSKirill Tkhai 1051be2ff42cSKirill Tkhai pq = kcalloc(FUSE_PQ_HASH_SIZE, sizeof(struct list_head), GFP_KERNEL); 1052be2ff42cSKirill Tkhai if (!pq) { 1053be2ff42cSKirill Tkhai kfree(fud); 1054be2ff42cSKirill Tkhai return NULL; 1055be2ff42cSKirill Tkhai } 1056be2ff42cSKirill Tkhai 1057be2ff42cSKirill Tkhai fud->pq.processing = pq; 1058cc080e9eSMiklos Szeredi fud->fc = fuse_conn_get(fc); 1059c3696046SMiklos Szeredi fuse_pqueue_init(&fud->pq); 1060cc080e9eSMiklos Szeredi 1061cc080e9eSMiklos Szeredi spin_lock(&fc->lock); 1062cc080e9eSMiklos Szeredi list_add_tail(&fud->entry, &fc->devices); 1063cc080e9eSMiklos Szeredi spin_unlock(&fc->lock); 1064cc080e9eSMiklos Szeredi 1065cc080e9eSMiklos Szeredi return fud; 1066cc080e9eSMiklos Szeredi } 1067cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_alloc); 1068cc080e9eSMiklos Szeredi 1069cc080e9eSMiklos Szeredi void fuse_dev_free(struct fuse_dev *fud) 1070cc080e9eSMiklos Szeredi { 1071cc080e9eSMiklos Szeredi struct fuse_conn *fc = fud->fc; 1072cc080e9eSMiklos Szeredi 1073cc080e9eSMiklos Szeredi if (fc) { 1074cc080e9eSMiklos Szeredi spin_lock(&fc->lock); 1075cc080e9eSMiklos Szeredi list_del(&fud->entry); 1076cc080e9eSMiklos Szeredi spin_unlock(&fc->lock); 1077cc080e9eSMiklos Szeredi 1078cc080e9eSMiklos Szeredi fuse_conn_put(fc); 1079cc080e9eSMiklos Szeredi } 1080d72f70daSTakeshi Misawa kfree(fud->pq.processing); 1081cc080e9eSMiklos Szeredi kfree(fud); 1082cc080e9eSMiklos Szeredi } 1083cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_free); 1084cc080e9eSMiklos Szeredi 1085c30da2e9SDavid Howells static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc) 1086d8a5ba45SMiklos Szeredi { 1087c30da2e9SDavid Howells struct fuse_fs_context *ctx = fsc->fs_private; 1088cc080e9eSMiklos Szeredi struct fuse_dev *fud; 1089d8a5ba45SMiklos Szeredi struct fuse_conn *fc; 1090d8a5ba45SMiklos Szeredi struct inode *root; 1091d8a5ba45SMiklos Szeredi struct file *file; 1092f543f253SMiklos Szeredi struct dentry *root_dentry; 1093ce1d5a49SMiklos Szeredi struct fuse_req *init_req; 1094d8a5ba45SMiklos Szeredi int err; 1095d8091614SMiklos Szeredi int is_bdev = sb->s_bdev != NULL; 1096d8a5ba45SMiklos Szeredi 1097c2b8f006SMiklos Szeredi err = -EINVAL; 10981751e8a6SLinus Torvalds if (sb->s_flags & SB_MANDLOCK) 1099c2b8f006SMiklos Szeredi goto err; 110071421259SMiklos Szeredi 11011751e8a6SLinus Torvalds sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION); 11029e1f1de0SAl Viro 1103d8091614SMiklos Szeredi if (is_bdev) { 1104875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 1105c2b8f006SMiklos Szeredi err = -EINVAL; 1106c30da2e9SDavid Howells if (!sb_set_blocksize(sb, ctx->blksize)) 1107c2b8f006SMiklos Szeredi goto err; 1108875d95ecSMiklos Szeredi #endif 1109d8091614SMiklos Szeredi } else { 111009cbfeafSKirill A. Shutemov sb->s_blocksize = PAGE_SIZE; 111109cbfeafSKirill A. Shutemov sb->s_blocksize_bits = PAGE_SHIFT; 1112d8091614SMiklos Szeredi } 1113c30da2e9SDavid Howells 1114c30da2e9SDavid Howells sb->s_subtype = ctx->subtype; 1115c30da2e9SDavid Howells ctx->subtype = NULL; 1116d8a5ba45SMiklos Szeredi sb->s_magic = FUSE_SUPER_MAGIC; 1117d8a5ba45SMiklos Szeredi sb->s_op = &fuse_super_operations; 1118703c7362SSeth Forshee sb->s_xattr = fuse_xattr_handlers; 1119d8a5ba45SMiklos Szeredi sb->s_maxbytes = MAX_LFS_FILESIZE; 11200a2da9b2SMiklos Szeredi sb->s_time_gran = 1; 1121dbd561d2SMiklos Szeredi sb->s_export_op = &fuse_export_operations; 11220834136aSMimi Zohar sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE; 11230834136aSMimi Zohar if (sb->s_user_ns != &init_user_ns) 11240834136aSMimi Zohar sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER; 1125d8a5ba45SMiklos Szeredi 1126c30da2e9SDavid Howells file = fget(ctx->fd); 1127c2b8f006SMiklos Szeredi err = -EINVAL; 1128d8a5ba45SMiklos Szeredi if (!file) 1129c2b8f006SMiklos Szeredi goto err; 1130d8a5ba45SMiklos Szeredi 11318cb08329SEric W. Biederman /* 11328cb08329SEric W. Biederman * Require mount to happen from the same user namespace which 11338cb08329SEric W. Biederman * opened /dev/fuse to prevent potential attacks. 11348cb08329SEric W. Biederman */ 11358cb08329SEric W. Biederman if (file->f_op != &fuse_dev_operations || 11368cb08329SEric W. Biederman file->f_cred->user_ns != sb->s_user_ns) 1137c2b8f006SMiklos Szeredi goto err_fput; 11380720b315SMiklos Szeredi 1139e45b2546SEric W. Biederman /* 1140e45b2546SEric W. Biederman * If we are not in the initial user namespace posix 1141e45b2546SEric W. Biederman * acls must be translated. 1142e45b2546SEric W. Biederman */ 1143e45b2546SEric W. Biederman if (sb->s_user_ns != &init_user_ns) 1144e45b2546SEric W. Biederman sb->s_xattr = fuse_no_acl_xattr_handlers; 1145e45b2546SEric W. Biederman 11460d179aa5STejun Heo fc = kmalloc(sizeof(*fc), GFP_KERNEL); 1147c2b8f006SMiklos Szeredi err = -ENOMEM; 1148c2b8f006SMiklos Szeredi if (!fc) 1149c2b8f006SMiklos Szeredi goto err_fput; 1150d8a5ba45SMiklos Szeredi 11518cb08329SEric W. Biederman fuse_conn_init(fc, sb->s_user_ns); 11520ad0b325SMiklos Szeredi fc->release = fuse_free_conn; 1153a325f9b9STejun Heo 1154cc080e9eSMiklos Szeredi fud = fuse_dev_alloc(fc); 1155cc080e9eSMiklos Szeredi if (!fud) 1156cc080e9eSMiklos Szeredi goto err_put_conn; 1157cc080e9eSMiklos Szeredi 1158a325f9b9STejun Heo fc->dev = sb->s_dev; 11593b463ae0SJohn Muir fc->sb = sb; 1160a325f9b9STejun Heo err = fuse_bdi_init(fc, sb); 1161a325f9b9STejun Heo if (err) 1162cc080e9eSMiklos Szeredi goto err_dev_free; 11630d179aa5STejun Heo 1164e0a43ddcSMiklos Szeredi /* Handle umasking inside the fuse code */ 11651751e8a6SLinus Torvalds if (sb->s_flags & SB_POSIXACL) 1166e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 11671751e8a6SLinus Torvalds sb->s_flags |= SB_POSIXACL; 1168e0a43ddcSMiklos Szeredi 1169c30da2e9SDavid Howells fc->default_permissions = ctx->default_permissions; 1170c30da2e9SDavid Howells fc->allow_other = ctx->allow_other; 1171c30da2e9SDavid Howells fc->user_id = ctx->user_id; 1172c30da2e9SDavid Howells fc->group_id = ctx->group_id; 1173c30da2e9SDavid Howells fc->max_read = max_t(unsigned, 4096, ctx->max_read); 1174d8a5ba45SMiklos Szeredi 1175f543f253SMiklos Szeredi /* Used by get_root_inode() */ 1176f543f253SMiklos Szeredi sb->s_fs_info = fc; 1177f543f253SMiklos Szeredi 1178d8a5ba45SMiklos Szeredi err = -ENOMEM; 1179c30da2e9SDavid Howells root = fuse_get_root_inode(sb, ctx->rootmode); 11800ce267ffSMiklos Szeredi sb->s_d_op = &fuse_root_dentry_operations; 118148fde701SAl Viro root_dentry = d_make_root(root); 118248fde701SAl Viro if (!root_dentry) 1183cc080e9eSMiklos Szeredi goto err_dev_free; 11840ce267ffSMiklos Szeredi /* Root dentry doesn't have .d_revalidate */ 1185c35eebe9SAl Viro sb->s_d_op = &fuse_dentry_operations; 1186f543f253SMiklos Szeredi 11874250c066SMaxim Patlasov init_req = fuse_request_alloc(0); 1188ce1d5a49SMiklos Szeredi if (!init_req) 1189ce1d5a49SMiklos Szeredi goto err_put_root; 1190825d6d33SMiklos Szeredi __set_bit(FR_BACKGROUND, &init_req->flags); 1191ce1d5a49SMiklos Szeredi 11920ec7ca41SMiklos Szeredi if (is_bdev) { 11934250c066SMaxim Patlasov fc->destroy_req = fuse_request_alloc(0); 11940ec7ca41SMiklos Szeredi if (!fc->destroy_req) 119517e18ab6SJulia Lawall goto err_free_init_req; 11960ec7ca41SMiklos Szeredi } 11970ec7ca41SMiklos Szeredi 1198bafa9654SMiklos Szeredi mutex_lock(&fuse_mutex); 11998aa09a50SMiklos Szeredi err = -EINVAL; 12008aa09a50SMiklos Szeredi if (file->private_data) 1201bafa9654SMiklos Szeredi goto err_unlock; 12028aa09a50SMiklos Szeredi 1203bafa9654SMiklos Szeredi err = fuse_ctl_add_conn(fc); 1204bafa9654SMiklos Szeredi if (err) 1205bafa9654SMiklos Szeredi goto err_unlock; 1206bafa9654SMiklos Szeredi 1207bafa9654SMiklos Szeredi list_add_tail(&fc->entry, &fuse_conn_list); 1208f543f253SMiklos Szeredi sb->s_root = root_dentry; 1209cc080e9eSMiklos Szeredi file->private_data = fud; 1210bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 12110720b315SMiklos Szeredi /* 12120720b315SMiklos Szeredi * atomic_dec_and_test() in fput() provides the necessary 12130720b315SMiklos Szeredi * memory barrier for file->private_data to be visible on all 12140720b315SMiklos Szeredi * CPUs after this 12150720b315SMiklos Szeredi */ 12160720b315SMiklos Szeredi fput(file); 1217f543f253SMiklos Szeredi 1218ce1d5a49SMiklos Szeredi fuse_send_init(fc, init_req); 1219f543f253SMiklos Szeredi 1220d8a5ba45SMiklos Szeredi return 0; 1221d8a5ba45SMiklos Szeredi 1222bafa9654SMiklos Szeredi err_unlock: 1223bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 122417e18ab6SJulia Lawall err_free_init_req: 1225ce1d5a49SMiklos Szeredi fuse_request_free(init_req); 1226f543f253SMiklos Szeredi err_put_root: 1227f543f253SMiklos Szeredi dput(root_dentry); 1228cc080e9eSMiklos Szeredi err_dev_free: 1229cc080e9eSMiklos Szeredi fuse_dev_free(fud); 1230c2b8f006SMiklos Szeredi err_put_conn: 1231bafa9654SMiklos Szeredi fuse_conn_put(fc); 1232543b8f86STetsuo Handa sb->s_fs_info = NULL; 1233c2b8f006SMiklos Szeredi err_fput: 1234c2b8f006SMiklos Szeredi fput(file); 1235c2b8f006SMiklos Szeredi err: 1236d8a5ba45SMiklos Szeredi return err; 1237d8a5ba45SMiklos Szeredi } 1238d8a5ba45SMiklos Szeredi 1239c30da2e9SDavid Howells static int fuse_get_tree(struct fs_context *fc) 1240d8a5ba45SMiklos Szeredi { 1241c30da2e9SDavid Howells struct fuse_fs_context *ctx = fc->fs_private; 1242c30da2e9SDavid Howells 1243c30da2e9SDavid Howells if (!ctx->fd_present || !ctx->rootmode_present || 1244c30da2e9SDavid Howells !ctx->user_id_present || !ctx->group_id_present) 1245c30da2e9SDavid Howells return -EINVAL; 1246c30da2e9SDavid Howells 1247c30da2e9SDavid Howells #ifdef CONFIG_BLOCK 1248c30da2e9SDavid Howells if (ctx->is_bdev) 1249c30da2e9SDavid Howells return get_tree_bdev(fc, fuse_fill_super); 1250c30da2e9SDavid Howells #endif 1251c30da2e9SDavid Howells 1252c30da2e9SDavid Howells return get_tree_nodev(fc, fuse_fill_super); 1253c30da2e9SDavid Howells } 1254c30da2e9SDavid Howells 1255c30da2e9SDavid Howells static const struct fs_context_operations fuse_context_ops = { 1256c30da2e9SDavid Howells .free = fuse_free_fc, 1257c30da2e9SDavid Howells .parse_param = fuse_parse_param, 1258c30da2e9SDavid Howells .get_tree = fuse_get_tree, 1259c30da2e9SDavid Howells }; 1260c30da2e9SDavid Howells 1261c30da2e9SDavid Howells /* 1262c30da2e9SDavid Howells * Set up the filesystem mount context. 1263c30da2e9SDavid Howells */ 1264c30da2e9SDavid Howells static int fuse_init_fs_context(struct fs_context *fc) 1265c30da2e9SDavid Howells { 1266c30da2e9SDavid Howells struct fuse_fs_context *ctx; 1267c30da2e9SDavid Howells 1268c30da2e9SDavid Howells ctx = kzalloc(sizeof(struct fuse_fs_context), GFP_KERNEL); 1269c30da2e9SDavid Howells if (!ctx) 1270c30da2e9SDavid Howells return -ENOMEM; 1271c30da2e9SDavid Howells 1272c30da2e9SDavid Howells ctx->max_read = ~0; 1273c30da2e9SDavid Howells ctx->blksize = FUSE_DEFAULT_BLKSIZE; 1274c30da2e9SDavid Howells 1275c30da2e9SDavid Howells #ifdef CONFIG_BLOCK 1276c30da2e9SDavid Howells if (fc->fs_type == &fuseblk_fs_type) 1277c30da2e9SDavid Howells ctx->is_bdev = true; 1278c30da2e9SDavid Howells #endif 1279c30da2e9SDavid Howells 1280c30da2e9SDavid Howells fc->fs_private = ctx; 1281c30da2e9SDavid Howells fc->ops = &fuse_context_ops; 1282c30da2e9SDavid Howells return 0; 1283d8a5ba45SMiklos Szeredi } 1284d8a5ba45SMiklos Szeredi 1285e8f3bd77SMiklos Szeredi static void fuse_sb_destroy(struct super_block *sb) 12863b463ae0SJohn Muir { 12873b463ae0SJohn Muir struct fuse_conn *fc = get_fuse_conn_super(sb); 12883b463ae0SJohn Muir 12893b463ae0SJohn Muir if (fc) { 1290e8f3bd77SMiklos Szeredi fuse_send_destroy(fc); 1291e8f3bd77SMiklos Szeredi 1292eb98e3bdSMiklos Szeredi fuse_abort_conn(fc); 1293e8f3bd77SMiklos Szeredi fuse_wait_aborted(fc); 1294e8f3bd77SMiklos Szeredi 12953b463ae0SJohn Muir down_write(&fc->killsb); 12963b463ae0SJohn Muir fc->sb = NULL; 12973b463ae0SJohn Muir up_write(&fc->killsb); 12983b463ae0SJohn Muir } 1299e8f3bd77SMiklos Szeredi } 13003b463ae0SJohn Muir 1301e8f3bd77SMiklos Szeredi static void fuse_kill_sb_anon(struct super_block *sb) 1302e8f3bd77SMiklos Szeredi { 1303e8f3bd77SMiklos Szeredi fuse_sb_destroy(sb); 13043b463ae0SJohn Muir kill_anon_super(sb); 13053b463ae0SJohn Muir } 13063b463ae0SJohn Muir 1307875d95ecSMiklos Szeredi static struct file_system_type fuse_fs_type = { 1308875d95ecSMiklos Szeredi .owner = THIS_MODULE, 1309875d95ecSMiklos Szeredi .name = "fuse", 13104ad769f3SEric W. Biederman .fs_flags = FS_HAS_SUBTYPE | FS_USERNS_MOUNT, 1311c30da2e9SDavid Howells .init_fs_context = fuse_init_fs_context, 1312c30da2e9SDavid Howells .parameters = &fuse_fs_parameters, 13133b463ae0SJohn Muir .kill_sb = fuse_kill_sb_anon, 1314875d95ecSMiklos Szeredi }; 13157f78e035SEric W. Biederman MODULE_ALIAS_FS("fuse"); 1316875d95ecSMiklos Szeredi 1317875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 13183b463ae0SJohn Muir static void fuse_kill_sb_blk(struct super_block *sb) 13193b463ae0SJohn Muir { 1320e8f3bd77SMiklos Szeredi fuse_sb_destroy(sb); 13213b463ae0SJohn Muir kill_block_super(sb); 13223b463ae0SJohn Muir } 13233b463ae0SJohn Muir 1324d6392f87SMiklos Szeredi static struct file_system_type fuseblk_fs_type = { 1325d6392f87SMiklos Szeredi .owner = THIS_MODULE, 1326d6392f87SMiklos Szeredi .name = "fuseblk", 1327c30da2e9SDavid Howells .init_fs_context = fuse_init_fs_context, 1328c30da2e9SDavid Howells .parameters = &fuse_fs_parameters, 13293b463ae0SJohn Muir .kill_sb = fuse_kill_sb_blk, 1330edad01e2SAlexey Dobriyan .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, 1331d6392f87SMiklos Szeredi }; 13327f78e035SEric W. Biederman MODULE_ALIAS_FS("fuseblk"); 1333d6392f87SMiklos Szeredi 1334875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1335875d95ecSMiklos Szeredi { 1336875d95ecSMiklos Szeredi return register_filesystem(&fuseblk_fs_type); 1337875d95ecSMiklos Szeredi } 1338875d95ecSMiklos Szeredi 1339875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1340875d95ecSMiklos Szeredi { 1341875d95ecSMiklos Szeredi unregister_filesystem(&fuseblk_fs_type); 1342875d95ecSMiklos Szeredi } 1343875d95ecSMiklos Szeredi #else 1344875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1345875d95ecSMiklos Szeredi { 1346875d95ecSMiklos Szeredi return 0; 1347875d95ecSMiklos Szeredi } 1348875d95ecSMiklos Szeredi 1349875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1350875d95ecSMiklos Szeredi { 1351875d95ecSMiklos Szeredi } 1352875d95ecSMiklos Szeredi #endif 1353875d95ecSMiklos Szeredi 135451cc5068SAlexey Dobriyan static void fuse_inode_init_once(void *foo) 1355d8a5ba45SMiklos Szeredi { 1356d8a5ba45SMiklos Szeredi struct inode *inode = foo; 1357d8a5ba45SMiklos Szeredi 1358d8a5ba45SMiklos Szeredi inode_init_once(inode); 1359d8a5ba45SMiklos Szeredi } 1360d8a5ba45SMiklos Szeredi 1361d8a5ba45SMiklos Szeredi static int __init fuse_fs_init(void) 1362d8a5ba45SMiklos Szeredi { 1363d8a5ba45SMiklos Szeredi int err; 1364d8a5ba45SMiklos Szeredi 1365d8a5ba45SMiklos Szeredi fuse_inode_cachep = kmem_cache_create("fuse_inode", 13665d097056SVladimir Davydov sizeof(struct fuse_inode), 0, 1367df206988SJohannes Weiner SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT|SLAB_RECLAIM_ACCOUNT, 136820c2df83SPaul Mundt fuse_inode_init_once); 1369d8a5ba45SMiklos Szeredi err = -ENOMEM; 1370d6392f87SMiklos Szeredi if (!fuse_inode_cachep) 1371988f0325SAl Viro goto out; 1372988f0325SAl Viro 1373988f0325SAl Viro err = register_fuseblk(); 1374988f0325SAl Viro if (err) 1375988f0325SAl Viro goto out2; 1376988f0325SAl Viro 1377988f0325SAl Viro err = register_filesystem(&fuse_fs_type); 1378988f0325SAl Viro if (err) 1379988f0325SAl Viro goto out3; 1380d8a5ba45SMiklos Szeredi 1381d6392f87SMiklos Szeredi return 0; 1382d6392f87SMiklos Szeredi 1383988f0325SAl Viro out3: 1384875d95ecSMiklos Szeredi unregister_fuseblk(); 1385988f0325SAl Viro out2: 1386988f0325SAl Viro kmem_cache_destroy(fuse_inode_cachep); 1387d6392f87SMiklos Szeredi out: 1388d8a5ba45SMiklos Szeredi return err; 1389d8a5ba45SMiklos Szeredi } 1390d8a5ba45SMiklos Szeredi 1391d8a5ba45SMiklos Szeredi static void fuse_fs_cleanup(void) 1392d8a5ba45SMiklos Szeredi { 1393d8a5ba45SMiklos Szeredi unregister_filesystem(&fuse_fs_type); 1394875d95ecSMiklos Szeredi unregister_fuseblk(); 13958c0a8537SKirill A. Shutemov 13968c0a8537SKirill A. Shutemov /* 13978c0a8537SKirill A. Shutemov * Make sure all delayed rcu free inodes are flushed before we 13988c0a8537SKirill A. Shutemov * destroy cache. 13998c0a8537SKirill A. Shutemov */ 14008c0a8537SKirill A. Shutemov rcu_barrier(); 1401d8a5ba45SMiklos Szeredi kmem_cache_destroy(fuse_inode_cachep); 1402d8a5ba45SMiklos Szeredi } 1403d8a5ba45SMiklos Szeredi 14045c89e17eSGreg Kroah-Hartman static struct kobject *fuse_kobj; 14055c89e17eSGreg Kroah-Hartman 1406f543f253SMiklos Szeredi static int fuse_sysfs_init(void) 1407f543f253SMiklos Szeredi { 1408f543f253SMiklos Szeredi int err; 1409f543f253SMiklos Szeredi 141000d26666SGreg Kroah-Hartman fuse_kobj = kobject_create_and_add("fuse", fs_kobj); 14115c89e17eSGreg Kroah-Hartman if (!fuse_kobj) { 14125c89e17eSGreg Kroah-Hartman err = -ENOMEM; 1413f543f253SMiklos Szeredi goto out_err; 14145c89e17eSGreg Kroah-Hartman } 1415f543f253SMiklos Szeredi 1416f9bb4882SEric W. Biederman err = sysfs_create_mount_point(fuse_kobj, "connections"); 1417f9bb4882SEric W. Biederman if (err) 1418f543f253SMiklos Szeredi goto out_fuse_unregister; 1419f543f253SMiklos Szeredi 1420f543f253SMiklos Szeredi return 0; 1421f543f253SMiklos Szeredi 1422f543f253SMiklos Szeredi out_fuse_unregister: 1423197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1424f543f253SMiklos Szeredi out_err: 1425f543f253SMiklos Szeredi return err; 1426f543f253SMiklos Szeredi } 1427f543f253SMiklos Szeredi 1428f543f253SMiklos Szeredi static void fuse_sysfs_cleanup(void) 1429f543f253SMiklos Szeredi { 1430f9bb4882SEric W. Biederman sysfs_remove_mount_point(fuse_kobj, "connections"); 1431197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1432f543f253SMiklos Szeredi } 1433f543f253SMiklos Szeredi 1434d8a5ba45SMiklos Szeredi static int __init fuse_init(void) 1435d8a5ba45SMiklos Szeredi { 1436d8a5ba45SMiklos Szeredi int res; 1437d8a5ba45SMiklos Szeredi 1438f2294482SKirill Smelkov pr_info("init (API version %i.%i)\n", 1439d8a5ba45SMiklos Szeredi FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); 1440d8a5ba45SMiklos Szeredi 1441bafa9654SMiklos Szeredi INIT_LIST_HEAD(&fuse_conn_list); 1442d8a5ba45SMiklos Szeredi res = fuse_fs_init(); 1443d8a5ba45SMiklos Szeredi if (res) 1444d8a5ba45SMiklos Szeredi goto err; 1445d8a5ba45SMiklos Szeredi 1446334f485dSMiklos Szeredi res = fuse_dev_init(); 1447334f485dSMiklos Szeredi if (res) 1448334f485dSMiklos Szeredi goto err_fs_cleanup; 1449334f485dSMiklos Szeredi 1450f543f253SMiklos Szeredi res = fuse_sysfs_init(); 1451f543f253SMiklos Szeredi if (res) 1452f543f253SMiklos Szeredi goto err_dev_cleanup; 1453f543f253SMiklos Szeredi 1454bafa9654SMiklos Szeredi res = fuse_ctl_init(); 1455bafa9654SMiklos Szeredi if (res) 1456bafa9654SMiklos Szeredi goto err_sysfs_cleanup; 1457bafa9654SMiklos Szeredi 1458487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 1459487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 1460487ea5afSCsaba Henk 1461d8a5ba45SMiklos Szeredi return 0; 1462d8a5ba45SMiklos Szeredi 1463bafa9654SMiklos Szeredi err_sysfs_cleanup: 1464bafa9654SMiklos Szeredi fuse_sysfs_cleanup(); 1465f543f253SMiklos Szeredi err_dev_cleanup: 1466f543f253SMiklos Szeredi fuse_dev_cleanup(); 1467334f485dSMiklos Szeredi err_fs_cleanup: 1468334f485dSMiklos Szeredi fuse_fs_cleanup(); 1469d8a5ba45SMiklos Szeredi err: 1470d8a5ba45SMiklos Szeredi return res; 1471d8a5ba45SMiklos Szeredi } 1472d8a5ba45SMiklos Szeredi 1473d8a5ba45SMiklos Szeredi static void __exit fuse_exit(void) 1474d8a5ba45SMiklos Szeredi { 1475f2294482SKirill Smelkov pr_debug("exit\n"); 1476d8a5ba45SMiklos Szeredi 1477bafa9654SMiklos Szeredi fuse_ctl_cleanup(); 1478f543f253SMiklos Szeredi fuse_sysfs_cleanup(); 1479d8a5ba45SMiklos Szeredi fuse_fs_cleanup(); 1480334f485dSMiklos Szeredi fuse_dev_cleanup(); 1481d8a5ba45SMiklos Szeredi } 1482d8a5ba45SMiklos Szeredi 1483d8a5ba45SMiklos Szeredi module_init(fuse_init); 1484d8a5ba45SMiklos Szeredi module_exit(fuse_exit); 1485