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); 88f15ecfefSKirill Tkhai spin_lock_init(&fi->lock); 8907e77dcaSMiklos Szeredi fi->forget = fuse_alloc_forget(); 9007e77dcaSMiklos Szeredi if (!fi->forget) { 919031a69cSzhangliguang kmem_cache_free(fuse_inode_cachep, fi); 92e5e5558eSMiklos Szeredi return NULL; 93e5e5558eSMiklos Szeredi } 94d8a5ba45SMiklos Szeredi 959031a69cSzhangliguang return &fi->inode; 96d8a5ba45SMiklos Szeredi } 97d8a5ba45SMiklos Szeredi 989baf28bbSAl Viro static void fuse_free_inode(struct inode *inode) 99d8a5ba45SMiklos Szeredi { 100e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1019baf28bbSAl Viro 1025c672ab3SMiklos Szeredi mutex_destroy(&fi->mutex); 10307e77dcaSMiklos Szeredi kfree(fi->forget); 1049baf28bbSAl Viro kmem_cache_free(fuse_inode_cachep, fi); 105d8a5ba45SMiklos Szeredi } 106d8a5ba45SMiklos Szeredi 107b57922d9SAl Viro static void fuse_evict_inode(struct inode *inode) 108d8a5ba45SMiklos Szeredi { 1099baf28bbSAl Viro struct fuse_inode *fi = get_fuse_inode(inode); 1109baf28bbSAl Viro 11191b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data); 112dbd5768fSJan Kara clear_inode(inode); 1131751e8a6SLinus Torvalds if (inode->i_sb->s_flags & SB_ACTIVE) { 114e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 11507e77dcaSMiklos Szeredi fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup); 11607e77dcaSMiklos Szeredi fi->forget = NULL; 117e5e5558eSMiklos Szeredi } 1189baf28bbSAl Viro if (S_ISREG(inode->i_mode) && !is_bad_inode(inode)) { 1199baf28bbSAl Viro WARN_ON(!list_empty(&fi->write_files)); 1209baf28bbSAl Viro WARN_ON(!list_empty(&fi->queued_writes)); 1219baf28bbSAl Viro } 122d8a5ba45SMiklos Szeredi } 123d8a5ba45SMiklos Szeredi 1240189a2d3SMiklos Szeredi static int fuse_reconfigure(struct fs_context *fc) 12571421259SMiklos Szeredi { 1260189a2d3SMiklos Szeredi struct super_block *sb = fc->root->d_sb; 1270189a2d3SMiklos Szeredi 12802b9984dSTheodore Ts'o sync_filesystem(sb); 1290189a2d3SMiklos Szeredi if (fc->sb_flags & SB_MANDLOCK) 13071421259SMiklos Szeredi return -EINVAL; 13171421259SMiklos Szeredi 13271421259SMiklos Szeredi return 0; 13371421259SMiklos Szeredi } 13471421259SMiklos Szeredi 13545c72cd7SPavel Shilovsky /* 13645c72cd7SPavel Shilovsky * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down 13745c72cd7SPavel Shilovsky * so that it will fit. 13845c72cd7SPavel Shilovsky */ 13945c72cd7SPavel Shilovsky static ino_t fuse_squash_ino(u64 ino64) 14045c72cd7SPavel Shilovsky { 14145c72cd7SPavel Shilovsky ino_t ino = (ino_t) ino64; 14245c72cd7SPavel Shilovsky if (sizeof(ino_t) < sizeof(u64)) 14345c72cd7SPavel Shilovsky ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8; 14445c72cd7SPavel Shilovsky return ino; 14545c72cd7SPavel Shilovsky } 14645c72cd7SPavel Shilovsky 1473be5a52bSMiklos Szeredi void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 1483be5a52bSMiklos Szeredi u64 attr_valid) 149d8a5ba45SMiklos Szeredi { 1509ffbb916SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 151ebc14c4dSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 152d8a5ba45SMiklos Szeredi 153f15ecfefSKirill Tkhai lockdep_assert_held(&fi->lock); 154f15ecfefSKirill Tkhai 1554510d86fSKirill Tkhai fi->attr_version = atomic64_inc_return(&fc->attr_version); 1561fb69e78SMiklos Szeredi fi->i_time = attr_valid; 1572f1e8196SMiklos Szeredi WRITE_ONCE(fi->inval_mask, 0); 1581fb69e78SMiklos Szeredi 15945c72cd7SPavel Shilovsky inode->i_ino = fuse_squash_ino(attr->ino); 160ebc14c4dSMiklos Szeredi inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 161bfe86848SMiklos Szeredi set_nlink(inode, attr->nlink); 1628cb08329SEric W. Biederman inode->i_uid = make_kuid(fc->user_ns, attr->uid); 1638cb08329SEric W. Biederman inode->i_gid = make_kgid(fc->user_ns, attr->gid); 164d8a5ba45SMiklos Szeredi inode->i_blocks = attr->blocks; 165d8a5ba45SMiklos Szeredi inode->i_atime.tv_sec = attr->atime; 166d8a5ba45SMiklos Szeredi inode->i_atime.tv_nsec = attr->atimensec; 167b0aa7606SMaxim Patlasov /* mtime from server may be stale due to local buffered write */ 168b0aa7606SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) { 169d8a5ba45SMiklos Szeredi inode->i_mtime.tv_sec = attr->mtime; 170d8a5ba45SMiklos Szeredi inode->i_mtime.tv_nsec = attr->mtimensec; 171d8a5ba45SMiklos Szeredi inode->i_ctime.tv_sec = attr->ctime; 172d8a5ba45SMiklos Szeredi inode->i_ctime.tv_nsec = attr->ctimensec; 17331f3267bSMaxim Patlasov } 174e00d2c2dSMiklos Szeredi 1750e9663eeSMiklos Szeredi if (attr->blksize != 0) 1760e9663eeSMiklos Szeredi inode->i_blkbits = ilog2(attr->blksize); 1770e9663eeSMiklos Szeredi else 1780e9663eeSMiklos Szeredi inode->i_blkbits = inode->i_sb->s_blocksize_bits; 1790e9663eeSMiklos Szeredi 180ebc14c4dSMiklos Szeredi /* 181ebc14c4dSMiklos Szeredi * Don't set the sticky bit in i_mode, unless we want the VFS 182ebc14c4dSMiklos Szeredi * to check permissions. This prevents failures due to the 183ebc14c4dSMiklos Szeredi * check in may_delete(). 184ebc14c4dSMiklos Szeredi */ 185ebc14c4dSMiklos Szeredi fi->orig_i_mode = inode->i_mode; 18629433a29SMiklos Szeredi if (!fc->default_permissions) 187ebc14c4dSMiklos Szeredi inode->i_mode &= ~S_ISVTX; 18845c72cd7SPavel Shilovsky 18945c72cd7SPavel Shilovsky fi->orig_ino = attr->ino; 1903be5a52bSMiklos Szeredi } 1913be5a52bSMiklos Szeredi 1923be5a52bSMiklos Szeredi void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, 1933be5a52bSMiklos Szeredi u64 attr_valid, u64 attr_version) 1943be5a52bSMiklos Szeredi { 1953be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1963be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1978373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 1983be5a52bSMiklos Szeredi loff_t oldsize; 199a64ba10fSArnd Bergmann struct timespec64 old_mtime; 2003be5a52bSMiklos Szeredi 201f15ecfefSKirill Tkhai spin_lock(&fi->lock); 20206a7c3c2SMaxim Patlasov if ((attr_version != 0 && fi->attr_version > attr_version) || 20306a7c3c2SMaxim Patlasov test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { 204f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 2053be5a52bSMiklos Szeredi return; 2063be5a52bSMiklos Szeredi } 2073be5a52bSMiklos Szeredi 208a64ba10fSArnd Bergmann old_mtime = inode->i_mtime; 2093be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, attr, attr_valid); 210ebc14c4dSMiklos Szeredi 211e00d2c2dSMiklos Szeredi oldsize = inode->i_size; 2128373200bSPavel Emelyanov /* 2138373200bSPavel Emelyanov * In case of writeback_cache enabled, the cached writes beyond EOF 2148373200bSPavel Emelyanov * extend local i_size without keeping userspace server in sync. So, 2158373200bSPavel Emelyanov * attr->size coming from server can be stale. We cannot trust it. 2168373200bSPavel Emelyanov */ 2178373200bSPavel Emelyanov if (!is_wb || !S_ISREG(inode->i_mode)) 218e00d2c2dSMiklos Szeredi i_size_write(inode, attr->size); 219f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 220e00d2c2dSMiklos Szeredi 2218373200bSPavel Emelyanov if (!is_wb && S_ISREG(inode->i_mode)) { 222eed2179eSBrian Foster bool inval = false; 223eed2179eSBrian Foster 224eed2179eSBrian Foster if (oldsize != attr->size) { 2257caef267SKirill A. Shutemov truncate_pagecache(inode, attr->size); 226ad2ba64dSKirill Smelkov if (!fc->explicit_inval_data) 227eed2179eSBrian Foster inval = true; 228eed2179eSBrian Foster } else if (fc->auto_inval_data) { 229a64ba10fSArnd Bergmann struct timespec64 new_mtime = { 230eed2179eSBrian Foster .tv_sec = attr->mtime, 231eed2179eSBrian Foster .tv_nsec = attr->mtimensec, 232eed2179eSBrian Foster }; 233eed2179eSBrian Foster 234eed2179eSBrian Foster /* 235eed2179eSBrian Foster * Auto inval mode also checks and invalidates if mtime 236eed2179eSBrian Foster * has changed. 237eed2179eSBrian Foster */ 238a64ba10fSArnd Bergmann if (!timespec64_equal(&old_mtime, &new_mtime)) 239eed2179eSBrian Foster inval = true; 240eed2179eSBrian Foster } 241eed2179eSBrian Foster 242eed2179eSBrian Foster if (inval) 243b1009979SMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 244e00d2c2dSMiklos Szeredi } 245d8a5ba45SMiklos Szeredi } 246d8a5ba45SMiklos Szeredi 247d8a5ba45SMiklos Szeredi static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) 248d8a5ba45SMiklos Szeredi { 249d8a5ba45SMiklos Szeredi inode->i_mode = attr->mode & S_IFMT; 2509ffbb916SMiklos Szeredi inode->i_size = attr->size; 251b0aa7606SMaxim Patlasov inode->i_mtime.tv_sec = attr->mtime; 252b0aa7606SMaxim Patlasov inode->i_mtime.tv_nsec = attr->mtimensec; 25331f3267bSMaxim Patlasov inode->i_ctime.tv_sec = attr->ctime; 25431f3267bSMaxim Patlasov inode->i_ctime.tv_nsec = attr->ctimensec; 255e5e5558eSMiklos Szeredi if (S_ISREG(inode->i_mode)) { 256e5e5558eSMiklos Szeredi fuse_init_common(inode); 257b6aeadedSMiklos Szeredi fuse_init_file_inode(inode); 258e5e5558eSMiklos Szeredi } else if (S_ISDIR(inode->i_mode)) 259e5e5558eSMiklos Szeredi fuse_init_dir(inode); 260e5e5558eSMiklos Szeredi else if (S_ISLNK(inode->i_mode)) 261e5e5558eSMiklos Szeredi fuse_init_symlink(inode); 262e5e5558eSMiklos Szeredi else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || 263e5e5558eSMiklos Szeredi S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 264e5e5558eSMiklos Szeredi fuse_init_common(inode); 265e5e5558eSMiklos Szeredi init_special_inode(inode, inode->i_mode, 266e5e5558eSMiklos Szeredi new_decode_dev(attr->rdev)); 26739ee059aSMiklos Szeredi } else 26839ee059aSMiklos Szeredi BUG(); 269d8a5ba45SMiklos Szeredi } 270d8a5ba45SMiklos Szeredi 2713b463ae0SJohn Muir int fuse_inode_eq(struct inode *inode, void *_nodeidp) 272d8a5ba45SMiklos Szeredi { 273b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 274d8a5ba45SMiklos Szeredi if (get_node_id(inode) == nodeid) 275d8a5ba45SMiklos Szeredi return 1; 276d8a5ba45SMiklos Szeredi else 277d8a5ba45SMiklos Szeredi return 0; 278d8a5ba45SMiklos Szeredi } 279d8a5ba45SMiklos Szeredi 280d8a5ba45SMiklos Szeredi static int fuse_inode_set(struct inode *inode, void *_nodeidp) 281d8a5ba45SMiklos Szeredi { 282b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 283d8a5ba45SMiklos Szeredi get_fuse_inode(inode)->nodeid = nodeid; 284d8a5ba45SMiklos Szeredi return 0; 285d8a5ba45SMiklos Szeredi } 286d8a5ba45SMiklos Szeredi 287b48badf0SMiklos Szeredi struct inode *fuse_iget(struct super_block *sb, u64 nodeid, 2881fb69e78SMiklos Szeredi int generation, struct fuse_attr *attr, 2891fb69e78SMiklos Szeredi u64 attr_valid, u64 attr_version) 290d8a5ba45SMiklos Szeredi { 291d8a5ba45SMiklos Szeredi struct inode *inode; 2929e6268dbSMiklos Szeredi struct fuse_inode *fi; 293d8a5ba45SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 294d8a5ba45SMiklos Szeredi 295d8a5ba45SMiklos Szeredi retry: 296d8a5ba45SMiklos Szeredi inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); 297d8a5ba45SMiklos Szeredi if (!inode) 298d8a5ba45SMiklos Szeredi return NULL; 299d8a5ba45SMiklos Szeredi 300d8a5ba45SMiklos Szeredi if ((inode->i_state & I_NEW)) { 301b0aa7606SMaxim Patlasov inode->i_flags |= S_NOATIME; 302d31433c8SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(attr->mode)) 303b0aa7606SMaxim Patlasov inode->i_flags |= S_NOCMTIME; 304d8a5ba45SMiklos Szeredi inode->i_generation = generation; 305d8a5ba45SMiklos Szeredi fuse_init_inode(inode, attr); 306d8a5ba45SMiklos Szeredi unlock_new_inode(inode); 307d8a5ba45SMiklos Szeredi } else if ((inode->i_mode ^ attr->mode) & S_IFMT) { 308d8a5ba45SMiklos Szeredi /* Inode has changed type, any I/O on the old should fail */ 309d8a5ba45SMiklos Szeredi make_bad_inode(inode); 310d8a5ba45SMiklos Szeredi iput(inode); 311d8a5ba45SMiklos Szeredi goto retry; 312d8a5ba45SMiklos Szeredi } 313d8a5ba45SMiklos Szeredi 3149e6268dbSMiklos Szeredi fi = get_fuse_inode(inode); 315c9d8f5f0SKirill Tkhai spin_lock(&fi->lock); 3169e6268dbSMiklos Szeredi fi->nlookup++; 317c9d8f5f0SKirill Tkhai spin_unlock(&fi->lock); 3181fb69e78SMiklos Szeredi fuse_change_attributes(inode, attr, attr_valid, attr_version); 3191fb69e78SMiklos Szeredi 320d8a5ba45SMiklos Szeredi return inode; 321d8a5ba45SMiklos Szeredi } 322d8a5ba45SMiklos Szeredi 3233b463ae0SJohn Muir int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, 3243b463ae0SJohn Muir loff_t offset, loff_t len) 3253b463ae0SJohn Muir { 3265ddd9cedSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 3275ddd9cedSMiklos Szeredi struct fuse_inode *fi; 3283b463ae0SJohn Muir struct inode *inode; 3293b463ae0SJohn Muir pgoff_t pg_start; 3303b463ae0SJohn Muir pgoff_t pg_end; 3313b463ae0SJohn Muir 3323b463ae0SJohn Muir inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid); 3333b463ae0SJohn Muir if (!inode) 3343b463ae0SJohn Muir return -ENOENT; 3353b463ae0SJohn Muir 3365ddd9cedSMiklos Szeredi fi = get_fuse_inode(inode); 3375ddd9cedSMiklos Szeredi spin_lock(&fi->lock); 3385ddd9cedSMiklos Szeredi fi->attr_version = atomic64_inc_return(&fc->attr_version); 3395ddd9cedSMiklos Szeredi spin_unlock(&fi->lock); 3405ddd9cedSMiklos Szeredi 3413b463ae0SJohn Muir fuse_invalidate_attr(inode); 34260bcc88aSSeth Forshee forget_all_cached_acls(inode); 3433b463ae0SJohn Muir if (offset >= 0) { 34409cbfeafSKirill A. Shutemov pg_start = offset >> PAGE_SHIFT; 3453b463ae0SJohn Muir if (len <= 0) 3463b463ae0SJohn Muir pg_end = -1; 3473b463ae0SJohn Muir else 34809cbfeafSKirill A. Shutemov pg_end = (offset + len - 1) >> PAGE_SHIFT; 3493b463ae0SJohn Muir invalidate_inode_pages2_range(inode->i_mapping, 3503b463ae0SJohn Muir pg_start, pg_end); 3513b463ae0SJohn Muir } 3523b463ae0SJohn Muir iput(inode); 3533b463ae0SJohn Muir return 0; 3543b463ae0SJohn Muir } 3553b463ae0SJohn Muir 35663576c13SMiklos Szeredi bool fuse_lock_inode(struct inode *inode) 3575c672ab3SMiklos Szeredi { 35863576c13SMiklos Szeredi bool locked = false; 35963576c13SMiklos Szeredi 36063576c13SMiklos Szeredi if (!get_fuse_conn(inode)->parallel_dirops) { 3615c672ab3SMiklos Szeredi mutex_lock(&get_fuse_inode(inode)->mutex); 36263576c13SMiklos Szeredi locked = true; 3635c672ab3SMiklos Szeredi } 3645c672ab3SMiklos Szeredi 36563576c13SMiklos Szeredi return locked; 36663576c13SMiklos Szeredi } 36763576c13SMiklos Szeredi 36863576c13SMiklos Szeredi void fuse_unlock_inode(struct inode *inode, bool locked) 3695c672ab3SMiklos Szeredi { 37063576c13SMiklos Szeredi if (locked) 3715c672ab3SMiklos Szeredi mutex_unlock(&get_fuse_inode(inode)->mutex); 3725c672ab3SMiklos Szeredi } 3735c672ab3SMiklos Szeredi 37442faad99SAl Viro static void fuse_umount_begin(struct super_block *sb) 37569a53bf2SMiklos Szeredi { 37615c8e72eSVivek Goyal struct fuse_conn *fc = get_fuse_conn_super(sb); 37715c8e72eSVivek Goyal 37815c8e72eSVivek Goyal if (!fc->no_force_umount) 37915c8e72eSVivek Goyal fuse_abort_conn(fc); 38069a53bf2SMiklos Szeredi } 38169a53bf2SMiklos Szeredi 3820ec7ca41SMiklos Szeredi static void fuse_send_destroy(struct fuse_conn *fc) 3830ec7ca41SMiklos Szeredi { 3841ccd1ea2SMiklos Szeredi if (fc->conn_init) { 3851ccd1ea2SMiklos Szeredi FUSE_ARGS(args); 3861ccd1ea2SMiklos Szeredi 3871ccd1ea2SMiklos Szeredi args.opcode = FUSE_DESTROY; 3881ccd1ea2SMiklos Szeredi args.force = true; 3891ccd1ea2SMiklos Szeredi args.nocreds = true; 3901ccd1ea2SMiklos Szeredi fuse_simple_request(fc, &args); 3910ec7ca41SMiklos Szeredi } 3920ec7ca41SMiklos Szeredi } 3930ec7ca41SMiklos Szeredi 394a325f9b9STejun Heo static void fuse_put_super(struct super_block *sb) 395a325f9b9STejun Heo { 396a325f9b9STejun Heo struct fuse_conn *fc = get_fuse_conn_super(sb); 397a325f9b9STejun Heo 398bbd99797SMiklos Szeredi mutex_lock(&fuse_mutex); 399bbd99797SMiklos Szeredi list_del(&fc->entry); 400bbd99797SMiklos Szeredi fuse_ctl_remove_conn(fc); 401bbd99797SMiklos Szeredi mutex_unlock(&fuse_mutex); 402bbd99797SMiklos Szeredi 403bafa9654SMiklos Szeredi fuse_conn_put(fc); 404d8a5ba45SMiklos Szeredi } 405d8a5ba45SMiklos Szeredi 406e5e5558eSMiklos Szeredi static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 407e5e5558eSMiklos Szeredi { 408e5e5558eSMiklos Szeredi stbuf->f_type = FUSE_SUPER_MAGIC; 409e5e5558eSMiklos Szeredi stbuf->f_bsize = attr->bsize; 410de5f1202SMiklos Szeredi stbuf->f_frsize = attr->frsize; 411e5e5558eSMiklos Szeredi stbuf->f_blocks = attr->blocks; 412e5e5558eSMiklos Szeredi stbuf->f_bfree = attr->bfree; 413e5e5558eSMiklos Szeredi stbuf->f_bavail = attr->bavail; 414e5e5558eSMiklos Szeredi stbuf->f_files = attr->files; 415e5e5558eSMiklos Szeredi stbuf->f_ffree = attr->ffree; 416e5e5558eSMiklos Szeredi stbuf->f_namelen = attr->namelen; 417e5e5558eSMiklos Szeredi /* fsid is left zero */ 418e5e5558eSMiklos Szeredi } 419e5e5558eSMiklos Szeredi 420726c3342SDavid Howells static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) 421e5e5558eSMiklos Szeredi { 422726c3342SDavid Howells struct super_block *sb = dentry->d_sb; 423e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 4247078187aSMiklos Szeredi FUSE_ARGS(args); 425e5e5558eSMiklos Szeredi struct fuse_statfs_out outarg; 426e5e5558eSMiklos Szeredi int err; 427e5e5558eSMiklos Szeredi 428c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) { 429e57ac683SMiklos Szeredi buf->f_type = FUSE_SUPER_MAGIC; 430e57ac683SMiklos Szeredi return 0; 431e57ac683SMiklos Szeredi } 432e57ac683SMiklos Szeredi 433de5f1202SMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 434d5b48543SMiklos Szeredi args.in_numargs = 0; 435d5b48543SMiklos Szeredi args.opcode = FUSE_STATFS; 436d5b48543SMiklos Szeredi args.nodeid = get_node_id(d_inode(dentry)); 437d5b48543SMiklos Szeredi args.out_numargs = 1; 438d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outarg); 439d5b48543SMiklos Szeredi args.out_args[0].value = &outarg; 4407078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 441e5e5558eSMiklos Szeredi if (!err) 442e5e5558eSMiklos Szeredi convert_fuse_statfs(buf, &outarg.st); 443e5e5558eSMiklos Szeredi return err; 444e5e5558eSMiklos Szeredi } 445e5e5558eSMiklos Szeredi 446d8a5ba45SMiklos Szeredi enum { 447c30da2e9SDavid Howells OPT_SOURCE, 448c30da2e9SDavid Howells OPT_SUBTYPE, 449d8a5ba45SMiklos Szeredi OPT_FD, 450d8a5ba45SMiklos Szeredi OPT_ROOTMODE, 451d8a5ba45SMiklos Szeredi OPT_USER_ID, 45287729a55SMiklos Szeredi OPT_GROUP_ID, 453d8a5ba45SMiklos Szeredi OPT_DEFAULT_PERMISSIONS, 454d8a5ba45SMiklos Szeredi OPT_ALLOW_OTHER, 455db50b96cSMiklos Szeredi OPT_MAX_READ, 456d8091614SMiklos Szeredi OPT_BLKSIZE, 457d8a5ba45SMiklos Szeredi OPT_ERR 458d8a5ba45SMiklos Szeredi }; 459d8a5ba45SMiklos Szeredi 460d7167b14SAl Viro static const struct fs_parameter_spec fuse_fs_parameters[] = { 461c30da2e9SDavid Howells fsparam_string ("source", OPT_SOURCE), 462c30da2e9SDavid Howells fsparam_u32 ("fd", OPT_FD), 463c30da2e9SDavid Howells fsparam_u32oct ("rootmode", OPT_ROOTMODE), 464c30da2e9SDavid Howells fsparam_u32 ("user_id", OPT_USER_ID), 465c30da2e9SDavid Howells fsparam_u32 ("group_id", OPT_GROUP_ID), 466c30da2e9SDavid Howells fsparam_flag ("default_permissions", OPT_DEFAULT_PERMISSIONS), 467c30da2e9SDavid Howells fsparam_flag ("allow_other", OPT_ALLOW_OTHER), 468c30da2e9SDavid Howells fsparam_u32 ("max_read", OPT_MAX_READ), 469c30da2e9SDavid Howells fsparam_u32 ("blksize", OPT_BLKSIZE), 470c7eb6869SDavid Howells fsparam_string ("subtype", OPT_SUBTYPE), 471c30da2e9SDavid Howells {} 472d8a5ba45SMiklos Szeredi }; 473d8a5ba45SMiklos Szeredi 474c30da2e9SDavid Howells static int fuse_parse_param(struct fs_context *fc, struct fs_parameter *param) 475233a01faSMiklos Szeredi { 476c30da2e9SDavid Howells struct fs_parse_result result; 477c30da2e9SDavid Howells struct fuse_fs_context *ctx = fc->fs_private; 478c30da2e9SDavid Howells int opt; 479233a01faSMiklos Szeredi 480b330966fSMiklos Szeredi if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) { 481e8b20a47SMiklos Szeredi /* 482e8b20a47SMiklos Szeredi * Ignore options coming from mount(MS_REMOUNT) for backward 483e8b20a47SMiklos Szeredi * compatibility. 484e8b20a47SMiklos Szeredi */ 485b330966fSMiklos Szeredi if (fc->oldapi) 486e8b20a47SMiklos Szeredi return 0; 487e8b20a47SMiklos Szeredi 488b330966fSMiklos Szeredi return invalfc(fc, "No changes allowed in reconfigure"); 489b330966fSMiklos Szeredi } 490b330966fSMiklos Szeredi 491d7167b14SAl Viro 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) 4982e28c49eSAl Viro return invalfc(fc, "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) 5052e28c49eSAl Viro return invalfc(fc, "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; 512cabdb4faSzhengbin ctx->fd_present = true; 513d8a5ba45SMiklos Szeredi break; 514d8a5ba45SMiklos Szeredi 515d8a5ba45SMiklos Szeredi case OPT_ROOTMODE: 516c30da2e9SDavid Howells if (!fuse_valid_type(result.uint_32)) 5172e28c49eSAl Viro return invalfc(fc, "Invalid rootmode"); 518c30da2e9SDavid Howells ctx->rootmode = result.uint_32; 519cabdb4faSzhengbin ctx->rootmode_present = true; 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)) 5252e28c49eSAl Viro return invalfc(fc, "Invalid user_id"); 526cabdb4faSzhengbin ctx->user_id_present = true; 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)) 5322e28c49eSAl Viro return invalfc(fc, "Invalid group_id"); 533cabdb4faSzhengbin ctx->group_id_present = true; 53487729a55SMiklos Szeredi break; 53587729a55SMiklos Szeredi 5361e9a4ed9SMiklos Szeredi case OPT_DEFAULT_PERMISSIONS: 537cabdb4faSzhengbin ctx->default_permissions = true; 5381e9a4ed9SMiklos Szeredi break; 5391e9a4ed9SMiklos Szeredi 5401e9a4ed9SMiklos Szeredi case OPT_ALLOW_OTHER: 541cabdb4faSzhengbin ctx->allow_other = true; 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) 5502e28c49eSAl Viro return invalfc(fc, "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 576f4fd4ae3SVivek Goyal if (fc->legacy_opts_show) { 577f4fd4ae3SVivek Goyal seq_printf(m, ",user_id=%u", 578f4fd4ae3SVivek Goyal from_kuid_munged(fc->user_ns, fc->user_id)); 579f4fd4ae3SVivek Goyal seq_printf(m, ",group_id=%u", 580f4fd4ae3SVivek Goyal from_kgid_munged(fc->user_ns, fc->group_id)); 58129433a29SMiklos Szeredi if (fc->default_permissions) 5821e9a4ed9SMiklos Szeredi seq_puts(m, ",default_permissions"); 58329433a29SMiklos Szeredi if (fc->allow_other) 5841e9a4ed9SMiklos Szeredi seq_puts(m, ",allow_other"); 585db50b96cSMiklos Szeredi if (fc->max_read != ~0) 586db50b96cSMiklos Szeredi seq_printf(m, ",max_read=%u", fc->max_read); 58734c80b1dSAl Viro if (sb->s_bdev && sb->s_blocksize != FUSE_DEFAULT_BLKSIZE) 58834c80b1dSAl Viro seq_printf(m, ",blksize=%lu", sb->s_blocksize); 589f4fd4ae3SVivek Goyal } 5901dd53957SVivek Goyal #ifdef CONFIG_FUSE_DAX 5911dd53957SVivek Goyal if (fc->dax) 5921dd53957SVivek Goyal seq_puts(m, ",dax"); 5931dd53957SVivek Goyal #endif 5941dd53957SVivek Goyal 595d8a5ba45SMiklos Szeredi return 0; 596d8a5ba45SMiklos Szeredi } 597d8a5ba45SMiklos Szeredi 598ae3aad77SStefan Hajnoczi static void fuse_iqueue_init(struct fuse_iqueue *fiq, 599ae3aad77SStefan Hajnoczi const struct fuse_iqueue_ops *ops, 600ae3aad77SStefan Hajnoczi void *priv) 601f88996a9SMiklos Szeredi { 602f88996a9SMiklos Szeredi memset(fiq, 0, sizeof(struct fuse_iqueue)); 60376e43c8cSEric Biggers spin_lock_init(&fiq->lock); 604f88996a9SMiklos Szeredi init_waitqueue_head(&fiq->waitq); 605f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->pending); 606f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->interrupts); 607f88996a9SMiklos Szeredi fiq->forget_list_tail = &fiq->forget_list_head; 608e16714d8SMiklos Szeredi fiq->connected = 1; 609ae3aad77SStefan Hajnoczi fiq->ops = ops; 610ae3aad77SStefan Hajnoczi fiq->priv = priv; 611f88996a9SMiklos Szeredi } 612f88996a9SMiklos Szeredi 6133a2b5b9cSMiklos Szeredi static void fuse_pqueue_init(struct fuse_pqueue *fpq) 6143a2b5b9cSMiklos Szeredi { 615be2ff42cSKirill Tkhai unsigned int i; 616be2ff42cSKirill Tkhai 61745a91cb1SMiklos Szeredi spin_lock_init(&fpq->lock); 618be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) 619be2ff42cSKirill Tkhai INIT_LIST_HEAD(&fpq->processing[i]); 6203a2b5b9cSMiklos Szeredi INIT_LIST_HEAD(&fpq->io); 621e96edd94SMiklos Szeredi fpq->connected = 1; 6223a2b5b9cSMiklos Szeredi } 6233a2b5b9cSMiklos Szeredi 624ae3aad77SStefan Hajnoczi void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns, 625ae3aad77SStefan Hajnoczi const struct fuse_iqueue_ops *fiq_ops, void *fiq_priv) 626d8a5ba45SMiklos Szeredi { 6270d179aa5STejun Heo memset(fc, 0, sizeof(*fc)); 628d7133114SMiklos Szeredi spin_lock_init(&fc->lock); 629ae2dffa3SKirill Tkhai spin_lock_init(&fc->bg_lock); 6303b463ae0SJohn Muir init_rwsem(&fc->killsb); 631095fc40aSElena Reshetova refcount_set(&fc->count, 1); 632c3696046SMiklos Szeredi atomic_set(&fc->dev_count, 1); 63308a53cdcSMiklos Szeredi init_waitqueue_head(&fc->blocked_waitq); 634ae3aad77SStefan Hajnoczi fuse_iqueue_init(&fc->iq, fiq_ops, fiq_priv); 635d12def1bSMiklos Szeredi INIT_LIST_HEAD(&fc->bg_queue); 6360d179aa5STejun Heo INIT_LIST_HEAD(&fc->entry); 637cc080e9eSMiklos Szeredi INIT_LIST_HEAD(&fc->devices); 638095da6cbSMiklos Szeredi atomic_set(&fc->num_waiting, 0); 6397a6d3c8bSCsaba Henk fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; 6407a6d3c8bSCsaba Henk fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; 64175126f55SMiklos Szeredi atomic64_set(&fc->khctr, 0); 64295668a69STejun Heo fc->polled_files = RB_ROOT; 6430aada884SMaxim Patlasov fc->blocked = 0; 644796523fbSMaxim Patlasov fc->initialized = 0; 645e16714d8SMiklos Szeredi fc->connected = 1; 6464510d86fSKirill Tkhai atomic64_set(&fc->attr_version, 1); 6479c8ef561SMiklos Szeredi get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); 6480b6e9ea0SSeth Forshee fc->pid_ns = get_pid_ns(task_active_pid_ns(current)); 6498cb08329SEric W. Biederman fc->user_ns = get_user_ns(user_ns); 6508a3177dbSMiklos Szeredi fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; 651d8a5ba45SMiklos Szeredi } 6520d179aa5STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_init); 653d8a5ba45SMiklos Szeredi 654bafa9654SMiklos Szeredi void fuse_conn_put(struct fuse_conn *fc) 655bafa9654SMiklos Szeredi { 656095fc40aSElena Reshetova if (refcount_dec_and_test(&fc->count)) { 657a62a8ef9SStefan Hajnoczi struct fuse_iqueue *fiq = &fc->iq; 658a62a8ef9SStefan Hajnoczi 6591dd53957SVivek Goyal if (IS_ENABLED(CONFIG_FUSE_DAX)) 6601dd53957SVivek Goyal fuse_dax_conn_free(fc); 661a62a8ef9SStefan Hajnoczi if (fiq->ops->release) 662a62a8ef9SStefan Hajnoczi fiq->ops->release(fiq); 6630b6e9ea0SSeth Forshee put_pid_ns(fc->pid_ns); 6648cb08329SEric W. Biederman put_user_ns(fc->user_ns); 66543901aabSTejun Heo fc->release(fc); 666bafa9654SMiklos Szeredi } 667d2a85164SMiklos Szeredi } 66808cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_put); 669bafa9654SMiklos Szeredi 670bafa9654SMiklos Szeredi struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) 671bafa9654SMiklos Szeredi { 672095fc40aSElena Reshetova refcount_inc(&fc->count); 673bafa9654SMiklos Szeredi return fc; 674bafa9654SMiklos Szeredi } 67508cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_get); 676bafa9654SMiklos Szeredi 677b93f858aSTejun Heo static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) 678d8a5ba45SMiklos Szeredi { 679d8a5ba45SMiklos Szeredi struct fuse_attr attr; 680d8a5ba45SMiklos Szeredi memset(&attr, 0, sizeof(attr)); 681d8a5ba45SMiklos Szeredi 682d8a5ba45SMiklos Szeredi attr.mode = mode; 683d8a5ba45SMiklos Szeredi attr.ino = FUSE_ROOT_ID; 684074406faSMiklos Szeredi attr.nlink = 1; 6851fb69e78SMiklos Szeredi return fuse_iget(sb, 1, 0, &attr, 0, 0); 686d8a5ba45SMiklos Szeredi } 687d8a5ba45SMiklos Szeredi 6881729a16cSMiklos Szeredi struct fuse_inode_handle { 689dbd561d2SMiklos Szeredi u64 nodeid; 690dbd561d2SMiklos Szeredi u32 generation; 691dbd561d2SMiklos Szeredi }; 692dbd561d2SMiklos Szeredi 693dbd561d2SMiklos Szeredi static struct dentry *fuse_get_dentry(struct super_block *sb, 694dbd561d2SMiklos Szeredi struct fuse_inode_handle *handle) 695dbd561d2SMiklos Szeredi { 69633670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 697dbd561d2SMiklos Szeredi struct inode *inode; 698dbd561d2SMiklos Szeredi struct dentry *entry; 699dbd561d2SMiklos Szeredi int err = -ESTALE; 700dbd561d2SMiklos Szeredi 701dbd561d2SMiklos Szeredi if (handle->nodeid == 0) 702dbd561d2SMiklos Szeredi goto out_err; 703dbd561d2SMiklos Szeredi 704dbd561d2SMiklos Szeredi inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid); 70533670fa2SMiklos Szeredi if (!inode) { 70633670fa2SMiklos Szeredi struct fuse_entry_out outarg; 70713983d06SAl Viro const struct qstr name = QSTR_INIT(".", 1); 70833670fa2SMiklos Szeredi 70933670fa2SMiklos Szeredi if (!fc->export_support) 710dbd561d2SMiklos Szeredi goto out_err; 71133670fa2SMiklos Szeredi 71233670fa2SMiklos Szeredi err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg, 71333670fa2SMiklos Szeredi &inode); 71433670fa2SMiklos Szeredi if (err && err != -ENOENT) 71533670fa2SMiklos Szeredi goto out_err; 71633670fa2SMiklos Szeredi if (err || !inode) { 71733670fa2SMiklos Szeredi err = -ESTALE; 71833670fa2SMiklos Szeredi goto out_err; 71933670fa2SMiklos Szeredi } 72033670fa2SMiklos Szeredi err = -EIO; 72133670fa2SMiklos Szeredi if (get_node_id(inode) != handle->nodeid) 72233670fa2SMiklos Szeredi goto out_iput; 72333670fa2SMiklos Szeredi } 724dbd561d2SMiklos Szeredi err = -ESTALE; 725dbd561d2SMiklos Szeredi if (inode->i_generation != handle->generation) 726dbd561d2SMiklos Szeredi goto out_iput; 727dbd561d2SMiklos Szeredi 72844003728SChristoph Hellwig entry = d_obtain_alias(inode); 729c35eebe9SAl Viro if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) 730dbd561d2SMiklos Szeredi fuse_invalidate_entry_cache(entry); 731dbd561d2SMiklos Szeredi 732dbd561d2SMiklos Szeredi return entry; 733dbd561d2SMiklos Szeredi 734dbd561d2SMiklos Szeredi out_iput: 735dbd561d2SMiklos Szeredi iput(inode); 736dbd561d2SMiklos Szeredi out_err: 737dbd561d2SMiklos Szeredi return ERR_PTR(err); 738dbd561d2SMiklos Szeredi } 739dbd561d2SMiklos Szeredi 740b0b0382bSAl Viro static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len, 741b0b0382bSAl Viro struct inode *parent) 742dbd561d2SMiklos Szeredi { 743b0b0382bSAl Viro int len = parent ? 6 : 3; 744dbd561d2SMiklos Szeredi u64 nodeid; 745dbd561d2SMiklos Szeredi u32 generation; 746dbd561d2SMiklos Szeredi 7475fe0c237SAneesh Kumar K.V if (*max_len < len) { 7485fe0c237SAneesh Kumar K.V *max_len = len; 74994e07a75SNamjae Jeon return FILEID_INVALID; 7505fe0c237SAneesh Kumar K.V } 751dbd561d2SMiklos Szeredi 752dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(inode)->nodeid; 753dbd561d2SMiklos Szeredi generation = inode->i_generation; 754dbd561d2SMiklos Szeredi 755dbd561d2SMiklos Szeredi fh[0] = (u32)(nodeid >> 32); 756dbd561d2SMiklos Szeredi fh[1] = (u32)(nodeid & 0xffffffff); 757dbd561d2SMiklos Szeredi fh[2] = generation; 758dbd561d2SMiklos Szeredi 759b0b0382bSAl Viro if (parent) { 760dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(parent)->nodeid; 761dbd561d2SMiklos Szeredi generation = parent->i_generation; 762dbd561d2SMiklos Szeredi 763dbd561d2SMiklos Szeredi fh[3] = (u32)(nodeid >> 32); 764dbd561d2SMiklos Szeredi fh[4] = (u32)(nodeid & 0xffffffff); 765dbd561d2SMiklos Szeredi fh[5] = generation; 766dbd561d2SMiklos Szeredi } 767dbd561d2SMiklos Szeredi 768dbd561d2SMiklos Szeredi *max_len = len; 769b0b0382bSAl Viro return parent ? 0x82 : 0x81; 770dbd561d2SMiklos Szeredi } 771dbd561d2SMiklos Szeredi 772dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_dentry(struct super_block *sb, 773dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 774dbd561d2SMiklos Szeredi { 775dbd561d2SMiklos Szeredi struct fuse_inode_handle handle; 776dbd561d2SMiklos Szeredi 777dbd561d2SMiklos Szeredi if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3) 778dbd561d2SMiklos Szeredi return NULL; 779dbd561d2SMiklos Szeredi 780dbd561d2SMiklos Szeredi handle.nodeid = (u64) fid->raw[0] << 32; 781dbd561d2SMiklos Szeredi handle.nodeid |= (u64) fid->raw[1]; 782dbd561d2SMiklos Szeredi handle.generation = fid->raw[2]; 783dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &handle); 784dbd561d2SMiklos Szeredi } 785dbd561d2SMiklos Szeredi 786dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_parent(struct super_block *sb, 787dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 788dbd561d2SMiklos Szeredi { 789dbd561d2SMiklos Szeredi struct fuse_inode_handle parent; 790dbd561d2SMiklos Szeredi 791dbd561d2SMiklos Szeredi if (fh_type != 0x82 || fh_len < 6) 792dbd561d2SMiklos Szeredi return NULL; 793dbd561d2SMiklos Szeredi 794dbd561d2SMiklos Szeredi parent.nodeid = (u64) fid->raw[3] << 32; 795dbd561d2SMiklos Szeredi parent.nodeid |= (u64) fid->raw[4]; 796dbd561d2SMiklos Szeredi parent.generation = fid->raw[5]; 797dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &parent); 798dbd561d2SMiklos Szeredi } 799dbd561d2SMiklos Szeredi 80033670fa2SMiklos Szeredi static struct dentry *fuse_get_parent(struct dentry *child) 80133670fa2SMiklos Szeredi { 8022b0143b5SDavid Howells struct inode *child_inode = d_inode(child); 80333670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(child_inode); 80433670fa2SMiklos Szeredi struct inode *inode; 80533670fa2SMiklos Szeredi struct dentry *parent; 80633670fa2SMiklos Szeredi struct fuse_entry_out outarg; 80713983d06SAl Viro const struct qstr name = QSTR_INIT("..", 2); 80833670fa2SMiklos Szeredi int err; 80933670fa2SMiklos Szeredi 81033670fa2SMiklos Szeredi if (!fc->export_support) 81133670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 81233670fa2SMiklos Szeredi 81333670fa2SMiklos Szeredi err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode), 81433670fa2SMiklos Szeredi &name, &outarg, &inode); 81544003728SChristoph Hellwig if (err) { 81644003728SChristoph Hellwig if (err == -ENOENT) 81733670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 81844003728SChristoph Hellwig return ERR_PTR(err); 81933670fa2SMiklos Szeredi } 82044003728SChristoph Hellwig 82144003728SChristoph Hellwig parent = d_obtain_alias(inode); 822c35eebe9SAl Viro if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) 82333670fa2SMiklos Szeredi fuse_invalidate_entry_cache(parent); 82433670fa2SMiklos Szeredi 82533670fa2SMiklos Szeredi return parent; 82633670fa2SMiklos Szeredi } 827dbd561d2SMiklos Szeredi 828dbd561d2SMiklos Szeredi static const struct export_operations fuse_export_operations = { 829dbd561d2SMiklos Szeredi .fh_to_dentry = fuse_fh_to_dentry, 830dbd561d2SMiklos Szeredi .fh_to_parent = fuse_fh_to_parent, 831dbd561d2SMiklos Szeredi .encode_fh = fuse_encode_fh, 83233670fa2SMiklos Szeredi .get_parent = fuse_get_parent, 833dbd561d2SMiklos Szeredi }; 834dbd561d2SMiklos Szeredi 835ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations fuse_super_operations = { 836d8a5ba45SMiklos Szeredi .alloc_inode = fuse_alloc_inode, 8379baf28bbSAl Viro .free_inode = fuse_free_inode, 838b57922d9SAl Viro .evict_inode = fuse_evict_inode, 8391e18bda8SMiklos Szeredi .write_inode = fuse_write_inode, 840ead5f0b5SMiklos Szeredi .drop_inode = generic_delete_inode, 841d8a5ba45SMiklos Szeredi .put_super = fuse_put_super, 84269a53bf2SMiklos Szeredi .umount_begin = fuse_umount_begin, 843e5e5558eSMiklos Szeredi .statfs = fuse_statfs, 844d8a5ba45SMiklos Szeredi .show_options = fuse_show_options, 845d8a5ba45SMiklos Szeredi }; 846d8a5ba45SMiklos Szeredi 847487ea5afSCsaba Henk static void sanitize_global_limit(unsigned *limit) 848487ea5afSCsaba Henk { 849f22f812dSMiklos Szeredi /* 850f22f812dSMiklos Szeredi * The default maximum number of async requests is calculated to consume 851f22f812dSMiklos Szeredi * 1/2^13 of the total memory, assuming 392 bytes per request. 852f22f812dSMiklos Szeredi */ 853487ea5afSCsaba Henk if (*limit == 0) 854f22f812dSMiklos Szeredi *limit = ((totalram_pages() << PAGE_SHIFT) >> 13) / 392; 855487ea5afSCsaba Henk 856487ea5afSCsaba Henk if (*limit >= 1 << 16) 857487ea5afSCsaba Henk *limit = (1 << 16) - 1; 858487ea5afSCsaba Henk } 859487ea5afSCsaba Henk 860e4dca7b7SKees Cook static int set_global_limit(const char *val, const struct kernel_param *kp) 861487ea5afSCsaba Henk { 862487ea5afSCsaba Henk int rv; 863487ea5afSCsaba Henk 864487ea5afSCsaba Henk rv = param_set_uint(val, kp); 865487ea5afSCsaba Henk if (rv) 866487ea5afSCsaba Henk return rv; 867487ea5afSCsaba Henk 868487ea5afSCsaba Henk sanitize_global_limit((unsigned *)kp->arg); 869487ea5afSCsaba Henk 870487ea5afSCsaba Henk return 0; 871487ea5afSCsaba Henk } 872487ea5afSCsaba Henk 873487ea5afSCsaba Henk static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) 874487ea5afSCsaba Henk { 875487ea5afSCsaba Henk int cap_sys_admin = capable(CAP_SYS_ADMIN); 876487ea5afSCsaba Henk 877487ea5afSCsaba Henk if (arg->minor < 13) 878487ea5afSCsaba Henk return; 879487ea5afSCsaba Henk 880487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 881487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 882487ea5afSCsaba Henk 883ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 884487ea5afSCsaba Henk if (arg->max_background) { 885487ea5afSCsaba Henk fc->max_background = arg->max_background; 886487ea5afSCsaba Henk 887487ea5afSCsaba Henk if (!cap_sys_admin && fc->max_background > max_user_bgreq) 888487ea5afSCsaba Henk fc->max_background = max_user_bgreq; 889487ea5afSCsaba Henk } 890487ea5afSCsaba Henk if (arg->congestion_threshold) { 891487ea5afSCsaba Henk fc->congestion_threshold = arg->congestion_threshold; 892487ea5afSCsaba Henk 893487ea5afSCsaba Henk if (!cap_sys_admin && 894487ea5afSCsaba Henk fc->congestion_threshold > max_user_congthresh) 895487ea5afSCsaba Henk fc->congestion_threshold = max_user_congthresh; 896487ea5afSCsaba Henk } 897ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 898487ea5afSCsaba Henk } 899487ea5afSCsaba Henk 900615047efSMiklos Szeredi struct fuse_init_args { 901615047efSMiklos Szeredi struct fuse_args args; 902615047efSMiklos Szeredi struct fuse_init_in in; 903615047efSMiklos Szeredi struct fuse_init_out out; 904615047efSMiklos Szeredi }; 9059b9a0469SMiklos Szeredi 906615047efSMiklos Szeredi static void process_init_reply(struct fuse_conn *fc, struct fuse_args *args, 907615047efSMiklos Szeredi int error) 908615047efSMiklos Szeredi { 909615047efSMiklos Szeredi struct fuse_init_args *ia = container_of(args, typeof(*ia), args); 910615047efSMiklos Szeredi struct fuse_init_out *arg = &ia->out; 911615047efSMiklos Szeredi 912615047efSMiklos Szeredi if (error || arg->major != FUSE_KERNEL_VERSION) 9139b9a0469SMiklos Szeredi fc->conn_error = 1; 9149b9a0469SMiklos Szeredi else { 9159cd68455SMiklos Szeredi unsigned long ra_pages; 9169cd68455SMiklos Szeredi 917487ea5afSCsaba Henk process_init_limits(fc, arg); 918487ea5afSCsaba Henk 9199cd68455SMiklos Szeredi if (arg->minor >= 6) { 92009cbfeafSKirill A. Shutemov ra_pages = arg->max_readahead / PAGE_SIZE; 9219cd68455SMiklos Szeredi if (arg->flags & FUSE_ASYNC_READ) 9229cd68455SMiklos Szeredi fc->async_read = 1; 92371421259SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 92471421259SMiklos Szeredi fc->no_lock = 1; 92537fb3a30SMiklos Szeredi if (arg->minor >= 17) { 92637fb3a30SMiklos Szeredi if (!(arg->flags & FUSE_FLOCK_LOCKS)) 92737fb3a30SMiklos Szeredi fc->no_flock = 1; 92824114504SMiklos Szeredi } else { 92924114504SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 93024114504SMiklos Szeredi fc->no_flock = 1; 93137fb3a30SMiklos Szeredi } 9326ff958edSMiklos Szeredi if (arg->flags & FUSE_ATOMIC_O_TRUNC) 9336ff958edSMiklos Szeredi fc->atomic_o_trunc = 1; 93433670fa2SMiklos Szeredi if (arg->minor >= 9) { 93533670fa2SMiklos Szeredi /* LOOKUP has dependency on proto version */ 93633670fa2SMiklos Szeredi if (arg->flags & FUSE_EXPORT_SUPPORT) 93733670fa2SMiklos Szeredi fc->export_support = 1; 93833670fa2SMiklos Szeredi } 93978bb6cb9SMiklos Szeredi if (arg->flags & FUSE_BIG_WRITES) 94078bb6cb9SMiklos Szeredi fc->big_writes = 1; 941e0a43ddcSMiklos Szeredi if (arg->flags & FUSE_DONT_MASK) 942e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 94372d0d248SBrian Foster if (arg->flags & FUSE_AUTO_INVAL_DATA) 94472d0d248SBrian Foster fc->auto_inval_data = 1; 945ad2ba64dSKirill Smelkov else if (arg->flags & FUSE_EXPLICIT_INVAL_DATA) 946ad2ba64dSKirill Smelkov fc->explicit_inval_data = 1; 94728420dadSMiklos Szeredi if (arg->flags & FUSE_DO_READDIRPLUS) { 9480b05b183SAnand V. Avati fc->do_readdirplus = 1; 949634734b6SEric Wong if (arg->flags & FUSE_READDIRPLUS_AUTO) 950634734b6SEric Wong fc->readdirplus_auto = 1; 95128420dadSMiklos Szeredi } 95260b9df7aSMiklos Szeredi if (arg->flags & FUSE_ASYNC_DIO) 95360b9df7aSMiklos Szeredi fc->async_dio = 1; 9544d99ff8fSPavel Emelyanov if (arg->flags & FUSE_WRITEBACK_CACHE) 9554d99ff8fSPavel Emelyanov fc->writeback_cache = 1; 9565c672ab3SMiklos Szeredi if (arg->flags & FUSE_PARALLEL_DIROPS) 9575c672ab3SMiklos Szeredi fc->parallel_dirops = 1; 9585e940c1dSMiklos Szeredi if (arg->flags & FUSE_HANDLE_KILLPRIV) 9595e940c1dSMiklos Szeredi fc->handle_killpriv = 1; 960e27c9d38SMiklos Szeredi if (arg->time_gran && arg->time_gran <= 1000000000) 961e27c9d38SMiklos Szeredi fc->sb->s_time_gran = arg->time_gran; 96260bcc88aSSeth Forshee if ((arg->flags & FUSE_POSIX_ACL)) { 96329433a29SMiklos Szeredi fc->default_permissions = 1; 96460bcc88aSSeth Forshee fc->posix_acl = 1; 96560bcc88aSSeth Forshee fc->sb->s_xattr = fuse_acl_xattr_handlers; 96660bcc88aSSeth Forshee } 9675571f1e6SDan Schatzberg if (arg->flags & FUSE_CACHE_SYMLINKS) 9685571f1e6SDan Schatzberg fc->cache_symlinks = 1; 9693b7008b2SSzymon Lukasz if (arg->flags & FUSE_ABORT_ERROR) 9703b7008b2SSzymon Lukasz fc->abort_err = 1; 9715da784ccSConstantine Shulyupin if (arg->flags & FUSE_MAX_PAGES) { 9725da784ccSConstantine Shulyupin fc->max_pages = 9735da784ccSConstantine Shulyupin min_t(unsigned int, FUSE_MAX_MAX_PAGES, 9745da784ccSConstantine Shulyupin max_t(unsigned int, arg->max_pages, 1)); 9755da784ccSConstantine Shulyupin } 97671421259SMiklos Szeredi } else { 97709cbfeafSKirill A. Shutemov ra_pages = fc->max_read / PAGE_SIZE; 97871421259SMiklos Szeredi fc->no_lock = 1; 97937fb3a30SMiklos Szeredi fc->no_flock = 1; 98071421259SMiklos Szeredi } 9819cd68455SMiklos Szeredi 9825f7f7543SJan Kara fc->sb->s_bdi->ra_pages = 9835f7f7543SJan Kara min(fc->sb->s_bdi->ra_pages, ra_pages); 9849b9a0469SMiklos Szeredi fc->minor = arg->minor; 9859b9a0469SMiklos Szeredi fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 986f948d564SMiklos Szeredi fc->max_write = max_t(unsigned, 4096, fc->max_write); 9870ec7ca41SMiklos Szeredi fc->conn_init = 1; 9889b9a0469SMiklos Szeredi } 989615047efSMiklos Szeredi kfree(ia); 990615047efSMiklos Szeredi 9919759bd51SMiklos Szeredi fuse_set_initialized(fc); 99208a53cdcSMiklos Szeredi wake_up_all(&fc->blocked_waitq); 9939b9a0469SMiklos Szeredi } 9949b9a0469SMiklos Szeredi 99595a84cdbSVivek Goyal void fuse_send_init(struct fuse_conn *fc) 9969b9a0469SMiklos Szeredi { 997615047efSMiklos Szeredi struct fuse_init_args *ia; 998095da6cbSMiklos Szeredi 999615047efSMiklos Szeredi ia = kzalloc(sizeof(*ia), GFP_KERNEL | __GFP_NOFAIL); 1000615047efSMiklos Szeredi 1001615047efSMiklos Szeredi ia->in.major = FUSE_KERNEL_VERSION; 1002615047efSMiklos Szeredi ia->in.minor = FUSE_KERNEL_MINOR_VERSION; 1003615047efSMiklos Szeredi ia->in.max_readahead = fc->sb->s_bdi->ra_pages * PAGE_SIZE; 1004615047efSMiklos Szeredi ia->in.flags |= 1005615047efSMiklos Szeredi FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | 100637fb3a30SMiklos Szeredi FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | 100769fe05c9SMiklos Szeredi FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | 10089446385fSWei Fang FUSE_FLOCK_LOCKS | FUSE_HAS_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | 10094d99ff8fSPavel Emelyanov FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | 10105c672ab3SMiklos Szeredi FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | 10113b7008b2SSzymon Lukasz FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | 1012d9a9ea94SChad Austin FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS | 1013ad2ba64dSKirill Smelkov FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA; 1014615047efSMiklos Szeredi ia->args.opcode = FUSE_INIT; 1015615047efSMiklos Szeredi ia->args.in_numargs = 1; 1016615047efSMiklos Szeredi ia->args.in_args[0].size = sizeof(ia->in); 1017615047efSMiklos Szeredi ia->args.in_args[0].value = &ia->in; 1018615047efSMiklos Szeredi ia->args.out_numargs = 1; 10193ad2f3fbSDaniel Mack /* Variable length argument used for backward compatibility 10209b9a0469SMiklos Szeredi with interface version < 7.5. Rest of init_out is zeroed 10219b9a0469SMiklos Szeredi by do_get_request(), so a short reply is not a problem */ 1022cabdb4faSzhengbin ia->args.out_argvar = true; 1023615047efSMiklos Szeredi ia->args.out_args[0].size = sizeof(ia->out); 1024615047efSMiklos Szeredi ia->args.out_args[0].value = &ia->out; 1025615047efSMiklos Szeredi ia->args.force = true; 1026615047efSMiklos Szeredi ia->args.nocreds = true; 1027615047efSMiklos Szeredi ia->args.end = process_init_reply; 1028615047efSMiklos Szeredi 1029615047efSMiklos Szeredi if (fuse_simple_background(fc, &ia->args, GFP_KERNEL) != 0) 1030615047efSMiklos Szeredi process_init_reply(fc, &ia->args, -ENOTCONN); 10319b9a0469SMiklos Szeredi } 103295a84cdbSVivek Goyal EXPORT_SYMBOL_GPL(fuse_send_init); 10339b9a0469SMiklos Szeredi 1034783863d6SMiklos Szeredi void fuse_free_conn(struct fuse_conn *fc) 103543901aabSTejun Heo { 1036cc080e9eSMiklos Szeredi WARN_ON(!list_empty(&fc->devices)); 1037dd3e2c55SAl Viro kfree_rcu(fc, rcu); 103843901aabSTejun Heo } 1039783863d6SMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_free_conn); 104043901aabSTejun Heo 1041a325f9b9STejun Heo static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) 1042a325f9b9STejun Heo { 1043a325f9b9STejun Heo int err; 10445f7f7543SJan Kara char *suffix = ""; 1045a325f9b9STejun Heo 104669c8ebf8SJan Kara if (sb->s_bdev) { 10475f7f7543SJan Kara suffix = "-fuseblk"; 104869c8ebf8SJan Kara /* 104969c8ebf8SJan Kara * sb->s_bdi points to blkdev's bdi however we want to redirect 105069c8ebf8SJan Kara * it to our private bdi... 105169c8ebf8SJan Kara */ 105269c8ebf8SJan Kara bdi_put(sb->s_bdi); 105369c8ebf8SJan Kara sb->s_bdi = &noop_backing_dev_info; 105469c8ebf8SJan Kara } 10555f7f7543SJan Kara err = super_setup_bdi_name(sb, "%u:%u%s", MAJOR(fc->dev), 10565f7f7543SJan Kara MINOR(fc->dev), suffix); 1057a325f9b9STejun Heo if (err) 1058a325f9b9STejun Heo return err; 1059a325f9b9STejun Heo 1060b5420237SNikolay Borisov sb->s_bdi->ra_pages = VM_READAHEAD_PAGES; 10615f7f7543SJan Kara /* fuse does it's own writeback accounting */ 10625f7f7543SJan Kara sb->s_bdi->capabilities = BDI_CAP_NO_ACCT_WB | BDI_CAP_STRICTLIMIT; 10635f7f7543SJan Kara 1064a325f9b9STejun Heo /* 1065a325f9b9STejun Heo * For a single fuse filesystem use max 1% of dirty + 1066a325f9b9STejun Heo * writeback threshold. 1067a325f9b9STejun Heo * 1068a325f9b9STejun Heo * This gives about 1M of write buffer for memory maps on a 1069a325f9b9STejun Heo * machine with 1G and 10% dirty_ratio, which should be more 1070a325f9b9STejun Heo * than enough. 1071a325f9b9STejun Heo * 1072a325f9b9STejun Heo * Privileged users can raise it by writing to 1073a325f9b9STejun Heo * 1074a325f9b9STejun Heo * /sys/class/bdi/<bdi>/max_ratio 1075a325f9b9STejun Heo */ 10765f7f7543SJan Kara bdi_set_max_ratio(sb->s_bdi, 1); 1077a325f9b9STejun Heo 1078a325f9b9STejun Heo return 0; 1079a325f9b9STejun Heo } 1080a325f9b9STejun Heo 10810cd1eb9aSVivek Goyal struct fuse_dev *fuse_dev_alloc(void) 1082cc080e9eSMiklos Szeredi { 1083cc080e9eSMiklos Szeredi struct fuse_dev *fud; 1084be2ff42cSKirill Tkhai struct list_head *pq; 1085cc080e9eSMiklos Szeredi 1086cc080e9eSMiklos Szeredi fud = kzalloc(sizeof(struct fuse_dev), GFP_KERNEL); 1087be2ff42cSKirill Tkhai if (!fud) 1088be2ff42cSKirill Tkhai return NULL; 1089be2ff42cSKirill Tkhai 1090be2ff42cSKirill Tkhai pq = kcalloc(FUSE_PQ_HASH_SIZE, sizeof(struct list_head), GFP_KERNEL); 1091be2ff42cSKirill Tkhai if (!pq) { 1092be2ff42cSKirill Tkhai kfree(fud); 1093be2ff42cSKirill Tkhai return NULL; 1094be2ff42cSKirill Tkhai } 1095be2ff42cSKirill Tkhai 1096be2ff42cSKirill Tkhai fud->pq.processing = pq; 1097c3696046SMiklos Szeredi fuse_pqueue_init(&fud->pq); 1098cc080e9eSMiklos Szeredi 1099cc080e9eSMiklos Szeredi return fud; 1100cc080e9eSMiklos Szeredi } 1101cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_alloc); 1102cc080e9eSMiklos Szeredi 11030cd1eb9aSVivek Goyal void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc) 11040cd1eb9aSVivek Goyal { 11050cd1eb9aSVivek Goyal fud->fc = fuse_conn_get(fc); 11060cd1eb9aSVivek Goyal spin_lock(&fc->lock); 11070cd1eb9aSVivek Goyal list_add_tail(&fud->entry, &fc->devices); 11080cd1eb9aSVivek Goyal spin_unlock(&fc->lock); 11090cd1eb9aSVivek Goyal } 11100cd1eb9aSVivek Goyal EXPORT_SYMBOL_GPL(fuse_dev_install); 11110cd1eb9aSVivek Goyal 11120cd1eb9aSVivek Goyal struct fuse_dev *fuse_dev_alloc_install(struct fuse_conn *fc) 11130cd1eb9aSVivek Goyal { 11140cd1eb9aSVivek Goyal struct fuse_dev *fud; 11150cd1eb9aSVivek Goyal 11160cd1eb9aSVivek Goyal fud = fuse_dev_alloc(); 11170cd1eb9aSVivek Goyal if (!fud) 11180cd1eb9aSVivek Goyal return NULL; 11190cd1eb9aSVivek Goyal 11200cd1eb9aSVivek Goyal fuse_dev_install(fud, fc); 11210cd1eb9aSVivek Goyal return fud; 11220cd1eb9aSVivek Goyal } 11230cd1eb9aSVivek Goyal EXPORT_SYMBOL_GPL(fuse_dev_alloc_install); 11240cd1eb9aSVivek Goyal 1125cc080e9eSMiklos Szeredi void fuse_dev_free(struct fuse_dev *fud) 1126cc080e9eSMiklos Szeredi { 1127cc080e9eSMiklos Szeredi struct fuse_conn *fc = fud->fc; 1128cc080e9eSMiklos Szeredi 1129cc080e9eSMiklos Szeredi if (fc) { 1130cc080e9eSMiklos Szeredi spin_lock(&fc->lock); 1131cc080e9eSMiklos Szeredi list_del(&fud->entry); 1132cc080e9eSMiklos Szeredi spin_unlock(&fc->lock); 1133cc080e9eSMiklos Szeredi 1134cc080e9eSMiklos Szeredi fuse_conn_put(fc); 1135cc080e9eSMiklos Szeredi } 1136d72f70daSTakeshi Misawa kfree(fud->pq.processing); 1137cc080e9eSMiklos Szeredi kfree(fud); 1138cc080e9eSMiklos Szeredi } 1139cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_free); 1140cc080e9eSMiklos Szeredi 11410cc2656cSStefan Hajnoczi int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx) 1142d8a5ba45SMiklos Szeredi { 11437fd3abfaSVivek Goyal struct fuse_dev *fud = NULL; 11440cc2656cSStefan Hajnoczi struct fuse_conn *fc = get_fuse_conn_super(sb); 1145d8a5ba45SMiklos Szeredi struct inode *root; 1146f543f253SMiklos Szeredi struct dentry *root_dentry; 1147d8a5ba45SMiklos Szeredi int err; 1148d8a5ba45SMiklos Szeredi 1149c2b8f006SMiklos Szeredi err = -EINVAL; 11501751e8a6SLinus Torvalds if (sb->s_flags & SB_MANDLOCK) 1151c2b8f006SMiklos Szeredi goto err; 115271421259SMiklos Szeredi 11531751e8a6SLinus Torvalds sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION); 11549e1f1de0SAl Viro 11550cc2656cSStefan Hajnoczi if (ctx->is_bdev) { 1156875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 1157c2b8f006SMiklos Szeredi err = -EINVAL; 1158c30da2e9SDavid Howells if (!sb_set_blocksize(sb, ctx->blksize)) 1159c2b8f006SMiklos Szeredi goto err; 1160875d95ecSMiklos Szeredi #endif 1161d8091614SMiklos Szeredi } else { 116209cbfeafSKirill A. Shutemov sb->s_blocksize = PAGE_SIZE; 116309cbfeafSKirill A. Shutemov sb->s_blocksize_bits = PAGE_SHIFT; 1164d8091614SMiklos Szeredi } 1165c30da2e9SDavid Howells 1166c30da2e9SDavid Howells sb->s_subtype = ctx->subtype; 1167c30da2e9SDavid Howells ctx->subtype = NULL; 1168d8a5ba45SMiklos Szeredi sb->s_magic = FUSE_SUPER_MAGIC; 1169d8a5ba45SMiklos Szeredi sb->s_op = &fuse_super_operations; 1170703c7362SSeth Forshee sb->s_xattr = fuse_xattr_handlers; 1171d8a5ba45SMiklos Szeredi sb->s_maxbytes = MAX_LFS_FILESIZE; 11720a2da9b2SMiklos Szeredi sb->s_time_gran = 1; 1173dbd561d2SMiklos Szeredi sb->s_export_op = &fuse_export_operations; 11740834136aSMimi Zohar sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE; 11750834136aSMimi Zohar if (sb->s_user_ns != &init_user_ns) 11760834136aSMimi Zohar sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER; 1177d8a5ba45SMiklos Szeredi 1178e45b2546SEric W. Biederman /* 1179e45b2546SEric W. Biederman * If we are not in the initial user namespace posix 1180e45b2546SEric W. Biederman * acls must be translated. 1181e45b2546SEric W. Biederman */ 1182e45b2546SEric W. Biederman if (sb->s_user_ns != &init_user_ns) 1183e45b2546SEric W. Biederman sb->s_xattr = fuse_no_acl_xattr_handlers; 1184e45b2546SEric W. Biederman 11851dd53957SVivek Goyal if (IS_ENABLED(CONFIG_FUSE_DAX)) { 11861dd53957SVivek Goyal err = fuse_dax_conn_alloc(fc, ctx->dax_dev); 11871dd53957SVivek Goyal if (err) 11881dd53957SVivek Goyal goto err; 11891dd53957SVivek Goyal } 11901dd53957SVivek Goyal 11917fd3abfaSVivek Goyal if (ctx->fudptr) { 11927fd3abfaSVivek Goyal err = -ENOMEM; 11930cd1eb9aSVivek Goyal fud = fuse_dev_alloc_install(fc); 1194cc080e9eSMiklos Szeredi if (!fud) 11951dd53957SVivek Goyal goto err_free_dax; 11967fd3abfaSVivek Goyal } 1197cc080e9eSMiklos Szeredi 1198a325f9b9STejun Heo fc->dev = sb->s_dev; 11993b463ae0SJohn Muir fc->sb = sb; 1200a325f9b9STejun Heo err = fuse_bdi_init(fc, sb); 1201a325f9b9STejun Heo if (err) 1202cc080e9eSMiklos Szeredi goto err_dev_free; 12030d179aa5STejun Heo 1204e0a43ddcSMiklos Szeredi /* Handle umasking inside the fuse code */ 12051751e8a6SLinus Torvalds if (sb->s_flags & SB_POSIXACL) 1206e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 12071751e8a6SLinus Torvalds sb->s_flags |= SB_POSIXACL; 1208e0a43ddcSMiklos Szeredi 1209c30da2e9SDavid Howells fc->default_permissions = ctx->default_permissions; 1210c30da2e9SDavid Howells fc->allow_other = ctx->allow_other; 1211c30da2e9SDavid Howells fc->user_id = ctx->user_id; 1212c30da2e9SDavid Howells fc->group_id = ctx->group_id; 1213f4fd4ae3SVivek Goyal fc->legacy_opts_show = ctx->legacy_opts_show; 1214c30da2e9SDavid Howells fc->max_read = max_t(unsigned, 4096, ctx->max_read); 1215783863d6SMiklos Szeredi fc->destroy = ctx->destroy; 121615c8e72eSVivek Goyal fc->no_control = ctx->no_control; 121715c8e72eSVivek Goyal fc->no_force_umount = ctx->no_force_umount; 1218f543f253SMiklos Szeredi 1219d8a5ba45SMiklos Szeredi err = -ENOMEM; 1220c30da2e9SDavid Howells root = fuse_get_root_inode(sb, ctx->rootmode); 12210ce267ffSMiklos Szeredi sb->s_d_op = &fuse_root_dentry_operations; 122248fde701SAl Viro root_dentry = d_make_root(root); 122348fde701SAl Viro if (!root_dentry) 1224cc080e9eSMiklos Szeredi goto err_dev_free; 12250ce267ffSMiklos Szeredi /* Root dentry doesn't have .d_revalidate */ 1226c35eebe9SAl Viro sb->s_d_op = &fuse_dentry_operations; 1227f543f253SMiklos Szeredi 1228bafa9654SMiklos Szeredi mutex_lock(&fuse_mutex); 12298aa09a50SMiklos Szeredi err = -EINVAL; 12307fd3abfaSVivek Goyal if (ctx->fudptr && *ctx->fudptr) 1231bafa9654SMiklos Szeredi goto err_unlock; 12328aa09a50SMiklos Szeredi 1233bafa9654SMiklos Szeredi err = fuse_ctl_add_conn(fc); 1234bafa9654SMiklos Szeredi if (err) 1235bafa9654SMiklos Szeredi goto err_unlock; 1236bafa9654SMiklos Szeredi 1237bafa9654SMiklos Szeredi list_add_tail(&fc->entry, &fuse_conn_list); 1238f543f253SMiklos Szeredi sb->s_root = root_dentry; 12397fd3abfaSVivek Goyal if (ctx->fudptr) 12400cc2656cSStefan Hajnoczi *ctx->fudptr = fud; 1241bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 1242d8a5ba45SMiklos Szeredi return 0; 1243d8a5ba45SMiklos Szeredi 1244bafa9654SMiklos Szeredi err_unlock: 1245bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 1246f543f253SMiklos Szeredi dput(root_dentry); 1247cc080e9eSMiklos Szeredi err_dev_free: 12487fd3abfaSVivek Goyal if (fud) 1249cc080e9eSMiklos Szeredi fuse_dev_free(fud); 12501dd53957SVivek Goyal err_free_dax: 12511dd53957SVivek Goyal if (IS_ENABLED(CONFIG_FUSE_DAX)) 12521dd53957SVivek Goyal fuse_dax_conn_free(fc); 12530cc2656cSStefan Hajnoczi err: 12540cc2656cSStefan Hajnoczi return err; 12550cc2656cSStefan Hajnoczi } 12560cc2656cSStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_fill_super_common); 12570cc2656cSStefan Hajnoczi 12580cc2656cSStefan Hajnoczi static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc) 12590cc2656cSStefan Hajnoczi { 12600cc2656cSStefan Hajnoczi struct fuse_fs_context *ctx = fsc->fs_private; 12610cc2656cSStefan Hajnoczi struct file *file; 12620cc2656cSStefan Hajnoczi int err; 12630cc2656cSStefan Hajnoczi struct fuse_conn *fc; 12640cc2656cSStefan Hajnoczi 12650cc2656cSStefan Hajnoczi err = -EINVAL; 12660cc2656cSStefan Hajnoczi file = fget(ctx->fd); 12670cc2656cSStefan Hajnoczi if (!file) 12680cc2656cSStefan Hajnoczi goto err; 12690cc2656cSStefan Hajnoczi 12700cc2656cSStefan Hajnoczi /* 12710cc2656cSStefan Hajnoczi * Require mount to happen from the same user namespace which 12720cc2656cSStefan Hajnoczi * opened /dev/fuse to prevent potential attacks. 12730cc2656cSStefan Hajnoczi */ 12740cc2656cSStefan Hajnoczi if ((file->f_op != &fuse_dev_operations) || 12750cc2656cSStefan Hajnoczi (file->f_cred->user_ns != sb->s_user_ns)) 12760cc2656cSStefan Hajnoczi goto err_fput; 12770cc2656cSStefan Hajnoczi ctx->fudptr = &file->private_data; 12780cc2656cSStefan Hajnoczi 12790cc2656cSStefan Hajnoczi fc = kmalloc(sizeof(*fc), GFP_KERNEL); 12800cc2656cSStefan Hajnoczi err = -ENOMEM; 12810cc2656cSStefan Hajnoczi if (!fc) 12820cc2656cSStefan Hajnoczi goto err_fput; 12830cc2656cSStefan Hajnoczi 1284ae3aad77SStefan Hajnoczi fuse_conn_init(fc, sb->s_user_ns, &fuse_dev_fiq_ops, NULL); 12850cc2656cSStefan Hajnoczi fc->release = fuse_free_conn; 12860cc2656cSStefan Hajnoczi sb->s_fs_info = fc; 12870cc2656cSStefan Hajnoczi 12880cc2656cSStefan Hajnoczi err = fuse_fill_super_common(sb, ctx); 12890cc2656cSStefan Hajnoczi if (err) 12900cc2656cSStefan Hajnoczi goto err_put_conn; 12910cc2656cSStefan Hajnoczi /* 12920cc2656cSStefan Hajnoczi * atomic_dec_and_test() in fput() provides the necessary 12930cc2656cSStefan Hajnoczi * memory barrier for file->private_data to be visible on all 12940cc2656cSStefan Hajnoczi * CPUs after this 12950cc2656cSStefan Hajnoczi */ 12960cc2656cSStefan Hajnoczi fput(file); 12970cc2656cSStefan Hajnoczi fuse_send_init(get_fuse_conn_super(sb)); 12980cc2656cSStefan Hajnoczi return 0; 12990cc2656cSStefan Hajnoczi 1300c2b8f006SMiklos Szeredi err_put_conn: 1301bafa9654SMiklos Szeredi fuse_conn_put(fc); 1302543b8f86STetsuo Handa sb->s_fs_info = NULL; 1303c2b8f006SMiklos Szeredi err_fput: 1304c2b8f006SMiklos Szeredi fput(file); 1305c2b8f006SMiklos Szeredi err: 1306d8a5ba45SMiklos Szeredi return err; 1307d8a5ba45SMiklos Szeredi } 1308d8a5ba45SMiklos Szeredi 1309c30da2e9SDavid Howells static int fuse_get_tree(struct fs_context *fc) 1310d8a5ba45SMiklos Szeredi { 1311c30da2e9SDavid Howells struct fuse_fs_context *ctx = fc->fs_private; 1312c30da2e9SDavid Howells 1313c30da2e9SDavid Howells if (!ctx->fd_present || !ctx->rootmode_present || 1314c30da2e9SDavid Howells !ctx->user_id_present || !ctx->group_id_present) 1315c30da2e9SDavid Howells return -EINVAL; 1316c30da2e9SDavid Howells 1317c30da2e9SDavid Howells #ifdef CONFIG_BLOCK 1318c30da2e9SDavid Howells if (ctx->is_bdev) 1319c30da2e9SDavid Howells return get_tree_bdev(fc, fuse_fill_super); 1320c30da2e9SDavid Howells #endif 1321c30da2e9SDavid Howells 1322c30da2e9SDavid Howells return get_tree_nodev(fc, fuse_fill_super); 1323c30da2e9SDavid Howells } 1324c30da2e9SDavid Howells 1325c30da2e9SDavid Howells static const struct fs_context_operations fuse_context_ops = { 1326c30da2e9SDavid Howells .free = fuse_free_fc, 1327c30da2e9SDavid Howells .parse_param = fuse_parse_param, 13280189a2d3SMiklos Szeredi .reconfigure = fuse_reconfigure, 1329c30da2e9SDavid Howells .get_tree = fuse_get_tree, 1330c30da2e9SDavid Howells }; 1331c30da2e9SDavid Howells 1332c30da2e9SDavid Howells /* 1333c30da2e9SDavid Howells * Set up the filesystem mount context. 1334c30da2e9SDavid Howells */ 1335c30da2e9SDavid Howells static int fuse_init_fs_context(struct fs_context *fc) 1336c30da2e9SDavid Howells { 1337c30da2e9SDavid Howells struct fuse_fs_context *ctx; 1338c30da2e9SDavid Howells 1339c30da2e9SDavid Howells ctx = kzalloc(sizeof(struct fuse_fs_context), GFP_KERNEL); 1340c30da2e9SDavid Howells if (!ctx) 1341c30da2e9SDavid Howells return -ENOMEM; 1342c30da2e9SDavid Howells 1343c30da2e9SDavid Howells ctx->max_read = ~0; 1344c30da2e9SDavid Howells ctx->blksize = FUSE_DEFAULT_BLKSIZE; 1345f4fd4ae3SVivek Goyal ctx->legacy_opts_show = true; 1346c30da2e9SDavid Howells 1347c30da2e9SDavid Howells #ifdef CONFIG_BLOCK 1348783863d6SMiklos Szeredi if (fc->fs_type == &fuseblk_fs_type) { 1349c30da2e9SDavid Howells ctx->is_bdev = true; 1350783863d6SMiklos Szeredi ctx->destroy = true; 1351783863d6SMiklos Szeredi } 1352c30da2e9SDavid Howells #endif 1353c30da2e9SDavid Howells 1354c30da2e9SDavid Howells fc->fs_private = ctx; 1355c30da2e9SDavid Howells fc->ops = &fuse_context_ops; 1356c30da2e9SDavid Howells return 0; 1357d8a5ba45SMiklos Szeredi } 1358d8a5ba45SMiklos Szeredi 1359e8f3bd77SMiklos Szeredi static void fuse_sb_destroy(struct super_block *sb) 13603b463ae0SJohn Muir { 13613b463ae0SJohn Muir struct fuse_conn *fc = get_fuse_conn_super(sb); 13623b463ae0SJohn Muir 13633b463ae0SJohn Muir if (fc) { 13641ccd1ea2SMiklos Szeredi if (fc->destroy) 1365e8f3bd77SMiklos Szeredi fuse_send_destroy(fc); 1366e8f3bd77SMiklos Szeredi 1367eb98e3bdSMiklos Szeredi fuse_abort_conn(fc); 1368e8f3bd77SMiklos Szeredi fuse_wait_aborted(fc); 1369e8f3bd77SMiklos Szeredi 13703b463ae0SJohn Muir down_write(&fc->killsb); 13713b463ae0SJohn Muir fc->sb = NULL; 13723b463ae0SJohn Muir up_write(&fc->killsb); 13733b463ae0SJohn Muir } 1374e8f3bd77SMiklos Szeredi } 13753b463ae0SJohn Muir 1376783863d6SMiklos Szeredi void fuse_kill_sb_anon(struct super_block *sb) 1377e8f3bd77SMiklos Szeredi { 1378e8f3bd77SMiklos Szeredi fuse_sb_destroy(sb); 13793b463ae0SJohn Muir kill_anon_super(sb); 13803b463ae0SJohn Muir } 1381783863d6SMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_kill_sb_anon); 13823b463ae0SJohn Muir 1383875d95ecSMiklos Szeredi static struct file_system_type fuse_fs_type = { 1384875d95ecSMiklos Szeredi .owner = THIS_MODULE, 1385875d95ecSMiklos Szeredi .name = "fuse", 13864ad769f3SEric W. Biederman .fs_flags = FS_HAS_SUBTYPE | FS_USERNS_MOUNT, 1387c30da2e9SDavid Howells .init_fs_context = fuse_init_fs_context, 1388d7167b14SAl Viro .parameters = fuse_fs_parameters, 13893b463ae0SJohn Muir .kill_sb = fuse_kill_sb_anon, 1390875d95ecSMiklos Szeredi }; 13917f78e035SEric W. Biederman MODULE_ALIAS_FS("fuse"); 1392875d95ecSMiklos Szeredi 1393875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 13943b463ae0SJohn Muir static void fuse_kill_sb_blk(struct super_block *sb) 13953b463ae0SJohn Muir { 1396e8f3bd77SMiklos Szeredi fuse_sb_destroy(sb); 13973b463ae0SJohn Muir kill_block_super(sb); 13983b463ae0SJohn Muir } 13993b463ae0SJohn Muir 1400d6392f87SMiklos Szeredi static struct file_system_type fuseblk_fs_type = { 1401d6392f87SMiklos Szeredi .owner = THIS_MODULE, 1402d6392f87SMiklos Szeredi .name = "fuseblk", 1403c30da2e9SDavid Howells .init_fs_context = fuse_init_fs_context, 1404d7167b14SAl Viro .parameters = fuse_fs_parameters, 14053b463ae0SJohn Muir .kill_sb = fuse_kill_sb_blk, 1406edad01e2SAlexey Dobriyan .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, 1407d6392f87SMiklos Szeredi }; 14087f78e035SEric W. Biederman MODULE_ALIAS_FS("fuseblk"); 1409d6392f87SMiklos Szeredi 1410875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1411875d95ecSMiklos Szeredi { 1412875d95ecSMiklos Szeredi return register_filesystem(&fuseblk_fs_type); 1413875d95ecSMiklos Szeredi } 1414875d95ecSMiklos Szeredi 1415875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1416875d95ecSMiklos Szeredi { 1417875d95ecSMiklos Szeredi unregister_filesystem(&fuseblk_fs_type); 1418875d95ecSMiklos Szeredi } 1419875d95ecSMiklos Szeredi #else 1420875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1421875d95ecSMiklos Szeredi { 1422875d95ecSMiklos Szeredi return 0; 1423875d95ecSMiklos Szeredi } 1424875d95ecSMiklos Szeredi 1425875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1426875d95ecSMiklos Szeredi { 1427875d95ecSMiklos Szeredi } 1428875d95ecSMiklos Szeredi #endif 1429875d95ecSMiklos Szeredi 143051cc5068SAlexey Dobriyan static void fuse_inode_init_once(void *foo) 1431d8a5ba45SMiklos Szeredi { 1432d8a5ba45SMiklos Szeredi struct inode *inode = foo; 1433d8a5ba45SMiklos Szeredi 1434d8a5ba45SMiklos Szeredi inode_init_once(inode); 1435d8a5ba45SMiklos Szeredi } 1436d8a5ba45SMiklos Szeredi 1437d8a5ba45SMiklos Szeredi static int __init fuse_fs_init(void) 1438d8a5ba45SMiklos Szeredi { 1439d8a5ba45SMiklos Szeredi int err; 1440d8a5ba45SMiklos Szeredi 1441d8a5ba45SMiklos Szeredi fuse_inode_cachep = kmem_cache_create("fuse_inode", 14425d097056SVladimir Davydov sizeof(struct fuse_inode), 0, 1443df206988SJohannes Weiner SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT|SLAB_RECLAIM_ACCOUNT, 144420c2df83SPaul Mundt fuse_inode_init_once); 1445d8a5ba45SMiklos Szeredi err = -ENOMEM; 1446d6392f87SMiklos Szeredi if (!fuse_inode_cachep) 1447988f0325SAl Viro goto out; 1448988f0325SAl Viro 1449988f0325SAl Viro err = register_fuseblk(); 1450988f0325SAl Viro if (err) 1451988f0325SAl Viro goto out2; 1452988f0325SAl Viro 1453988f0325SAl Viro err = register_filesystem(&fuse_fs_type); 1454988f0325SAl Viro if (err) 1455988f0325SAl Viro goto out3; 1456d8a5ba45SMiklos Szeredi 1457d6392f87SMiklos Szeredi return 0; 1458d6392f87SMiklos Szeredi 1459988f0325SAl Viro out3: 1460875d95ecSMiklos Szeredi unregister_fuseblk(); 1461988f0325SAl Viro out2: 1462988f0325SAl Viro kmem_cache_destroy(fuse_inode_cachep); 1463d6392f87SMiklos Szeredi out: 1464d8a5ba45SMiklos Szeredi return err; 1465d8a5ba45SMiklos Szeredi } 1466d8a5ba45SMiklos Szeredi 1467d8a5ba45SMiklos Szeredi static void fuse_fs_cleanup(void) 1468d8a5ba45SMiklos Szeredi { 1469d8a5ba45SMiklos Szeredi unregister_filesystem(&fuse_fs_type); 1470875d95ecSMiklos Szeredi unregister_fuseblk(); 14718c0a8537SKirill A. Shutemov 14728c0a8537SKirill A. Shutemov /* 14738c0a8537SKirill A. Shutemov * Make sure all delayed rcu free inodes are flushed before we 14748c0a8537SKirill A. Shutemov * destroy cache. 14758c0a8537SKirill A. Shutemov */ 14768c0a8537SKirill A. Shutemov rcu_barrier(); 1477d8a5ba45SMiklos Szeredi kmem_cache_destroy(fuse_inode_cachep); 1478d8a5ba45SMiklos Szeredi } 1479d8a5ba45SMiklos Szeredi 14805c89e17eSGreg Kroah-Hartman static struct kobject *fuse_kobj; 14815c89e17eSGreg Kroah-Hartman 1482f543f253SMiklos Szeredi static int fuse_sysfs_init(void) 1483f543f253SMiklos Szeredi { 1484f543f253SMiklos Szeredi int err; 1485f543f253SMiklos Szeredi 148600d26666SGreg Kroah-Hartman fuse_kobj = kobject_create_and_add("fuse", fs_kobj); 14875c89e17eSGreg Kroah-Hartman if (!fuse_kobj) { 14885c89e17eSGreg Kroah-Hartman err = -ENOMEM; 1489f543f253SMiklos Szeredi goto out_err; 14905c89e17eSGreg Kroah-Hartman } 1491f543f253SMiklos Szeredi 1492f9bb4882SEric W. Biederman err = sysfs_create_mount_point(fuse_kobj, "connections"); 1493f9bb4882SEric W. Biederman if (err) 1494f543f253SMiklos Szeredi goto out_fuse_unregister; 1495f543f253SMiklos Szeredi 1496f543f253SMiklos Szeredi return 0; 1497f543f253SMiklos Szeredi 1498f543f253SMiklos Szeredi out_fuse_unregister: 1499197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1500f543f253SMiklos Szeredi out_err: 1501f543f253SMiklos Szeredi return err; 1502f543f253SMiklos Szeredi } 1503f543f253SMiklos Szeredi 1504f543f253SMiklos Szeredi static void fuse_sysfs_cleanup(void) 1505f543f253SMiklos Szeredi { 1506f9bb4882SEric W. Biederman sysfs_remove_mount_point(fuse_kobj, "connections"); 1507197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1508f543f253SMiklos Szeredi } 1509f543f253SMiklos Szeredi 1510d8a5ba45SMiklos Szeredi static int __init fuse_init(void) 1511d8a5ba45SMiklos Szeredi { 1512d8a5ba45SMiklos Szeredi int res; 1513d8a5ba45SMiklos Szeredi 1514f2294482SKirill Smelkov pr_info("init (API version %i.%i)\n", 1515d8a5ba45SMiklos Szeredi FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); 1516d8a5ba45SMiklos Szeredi 1517bafa9654SMiklos Szeredi INIT_LIST_HEAD(&fuse_conn_list); 1518d8a5ba45SMiklos Szeredi res = fuse_fs_init(); 1519d8a5ba45SMiklos Szeredi if (res) 1520d8a5ba45SMiklos Szeredi goto err; 1521d8a5ba45SMiklos Szeredi 1522334f485dSMiklos Szeredi res = fuse_dev_init(); 1523334f485dSMiklos Szeredi if (res) 1524334f485dSMiklos Szeredi goto err_fs_cleanup; 1525334f485dSMiklos Szeredi 1526f543f253SMiklos Szeredi res = fuse_sysfs_init(); 1527f543f253SMiklos Szeredi if (res) 1528f543f253SMiklos Szeredi goto err_dev_cleanup; 1529f543f253SMiklos Szeredi 1530bafa9654SMiklos Szeredi res = fuse_ctl_init(); 1531bafa9654SMiklos Szeredi if (res) 1532bafa9654SMiklos Szeredi goto err_sysfs_cleanup; 1533bafa9654SMiklos Szeredi 1534487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 1535487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 1536487ea5afSCsaba Henk 1537d8a5ba45SMiklos Szeredi return 0; 1538d8a5ba45SMiklos Szeredi 1539bafa9654SMiklos Szeredi err_sysfs_cleanup: 1540bafa9654SMiklos Szeredi fuse_sysfs_cleanup(); 1541f543f253SMiklos Szeredi err_dev_cleanup: 1542f543f253SMiklos Szeredi fuse_dev_cleanup(); 1543334f485dSMiklos Szeredi err_fs_cleanup: 1544334f485dSMiklos Szeredi fuse_fs_cleanup(); 1545d8a5ba45SMiklos Szeredi err: 1546d8a5ba45SMiklos Szeredi return res; 1547d8a5ba45SMiklos Szeredi } 1548d8a5ba45SMiklos Szeredi 1549d8a5ba45SMiklos Szeredi static void __exit fuse_exit(void) 1550d8a5ba45SMiklos Szeredi { 1551f2294482SKirill Smelkov pr_debug("exit\n"); 1552d8a5ba45SMiklos Szeredi 1553bafa9654SMiklos Szeredi fuse_ctl_cleanup(); 1554f543f253SMiklos Szeredi fuse_sysfs_cleanup(); 1555d8a5ba45SMiklos Szeredi fuse_fs_cleanup(); 1556334f485dSMiklos Szeredi fuse_dev_cleanup(); 1557d8a5ba45SMiklos Szeredi } 1558d8a5ba45SMiklos Szeredi 1559d8a5ba45SMiklos Szeredi module_init(fuse_init); 1560d8a5ba45SMiklos Szeredi module_exit(fuse_exit); 1561