1d8a5ba45SMiklos Szeredi /* 2d8a5ba45SMiklos Szeredi FUSE: Filesystem in Userspace 31729a16cSMiklos Szeredi Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> 4d8a5ba45SMiklos Szeredi 5d8a5ba45SMiklos Szeredi This program can be distributed under the terms of the GNU GPL. 6d8a5ba45SMiklos Szeredi See the file COPYING. 7d8a5ba45SMiklos Szeredi */ 8d8a5ba45SMiklos Szeredi 9d8a5ba45SMiklos Szeredi #include "fuse_i.h" 10d8a5ba45SMiklos Szeredi 11d8a5ba45SMiklos Szeredi #include <linux/pagemap.h> 12d8a5ba45SMiklos Szeredi #include <linux/slab.h> 13d8a5ba45SMiklos Szeredi #include <linux/file.h> 14d8a5ba45SMiklos Szeredi #include <linux/seq_file.h> 15d8a5ba45SMiklos Szeredi #include <linux/init.h> 16d8a5ba45SMiklos Szeredi #include <linux/module.h> 17487ea5afSCsaba Henk #include <linux/moduleparam.h> 18d8a5ba45SMiklos Szeredi #include <linux/parser.h> 19d8a5ba45SMiklos Szeredi #include <linux/statfs.h> 209c8ef561SMiklos Szeredi #include <linux/random.h> 21e8edc6e0SAlexey Dobriyan #include <linux/sched.h> 22dbd561d2SMiklos Szeredi #include <linux/exportfs.h> 23d8a5ba45SMiklos Szeredi 24d8a5ba45SMiklos Szeredi MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); 25d8a5ba45SMiklos Szeredi MODULE_DESCRIPTION("Filesystem in Userspace"); 26d8a5ba45SMiklos Szeredi MODULE_LICENSE("GPL"); 27d8a5ba45SMiklos Szeredi 28e18b890bSChristoph Lameter static struct kmem_cache *fuse_inode_cachep; 29bafa9654SMiklos Szeredi struct list_head fuse_conn_list; 30bafa9654SMiklos Szeredi DEFINE_MUTEX(fuse_mutex); 31d8a5ba45SMiklos Szeredi 32487ea5afSCsaba Henk static int set_global_limit(const char *val, struct kernel_param *kp); 33487ea5afSCsaba Henk 3479a9d994SCsaba Henk unsigned max_user_bgreq; 35487ea5afSCsaba Henk module_param_call(max_user_bgreq, set_global_limit, param_get_uint, 36487ea5afSCsaba Henk &max_user_bgreq, 0644); 37487ea5afSCsaba Henk __MODULE_PARM_TYPE(max_user_bgreq, "uint"); 38487ea5afSCsaba Henk MODULE_PARM_DESC(max_user_bgreq, 39487ea5afSCsaba Henk "Global limit for the maximum number of backgrounded requests an " 40487ea5afSCsaba Henk "unprivileged user can set"); 41487ea5afSCsaba Henk 4279a9d994SCsaba Henk unsigned max_user_congthresh; 43487ea5afSCsaba Henk module_param_call(max_user_congthresh, set_global_limit, param_get_uint, 44487ea5afSCsaba Henk &max_user_congthresh, 0644); 45487ea5afSCsaba Henk __MODULE_PARM_TYPE(max_user_congthresh, "uint"); 46487ea5afSCsaba Henk MODULE_PARM_DESC(max_user_congthresh, 47487ea5afSCsaba Henk "Global limit for the maximum congestion threshold an " 48487ea5afSCsaba Henk "unprivileged user can set"); 49487ea5afSCsaba Henk 50d8a5ba45SMiklos Szeredi #define FUSE_SUPER_MAGIC 0x65735546 51d8a5ba45SMiklos Szeredi 52d1875dbaSMiklos Szeredi #define FUSE_DEFAULT_BLKSIZE 512 53d1875dbaSMiklos Szeredi 547a6d3c8bSCsaba Henk /** Maximum number of outstanding background requests */ 557a6d3c8bSCsaba Henk #define FUSE_DEFAULT_MAX_BACKGROUND 12 567a6d3c8bSCsaba Henk 577a6d3c8bSCsaba Henk /** Congestion starts at 75% of maximum */ 587a6d3c8bSCsaba Henk #define FUSE_DEFAULT_CONGESTION_THRESHOLD (FUSE_DEFAULT_MAX_BACKGROUND * 3 / 4) 597a6d3c8bSCsaba Henk 60d8a5ba45SMiklos Szeredi struct fuse_mount_data { 61d8a5ba45SMiklos Szeredi int fd; 62d8a5ba45SMiklos Szeredi unsigned rootmode; 63499dcf20SEric W. Biederman kuid_t user_id; 64499dcf20SEric W. Biederman kgid_t group_id; 655a533682SMiklos Szeredi unsigned fd_present:1; 665a533682SMiklos Szeredi unsigned rootmode_present:1; 675a533682SMiklos Szeredi unsigned user_id_present:1; 685a533682SMiklos Szeredi unsigned group_id_present:1; 691e9a4ed9SMiklos Szeredi unsigned flags; 70db50b96cSMiklos Szeredi unsigned max_read; 71d8091614SMiklos Szeredi unsigned blksize; 72d8a5ba45SMiklos Szeredi }; 73d8a5ba45SMiklos Szeredi 74a2daff68SRandy Dunlap struct fuse_forget_link *fuse_alloc_forget(void) 7507e77dcaSMiklos Szeredi { 7607e77dcaSMiklos Szeredi return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); 7707e77dcaSMiklos Szeredi } 7807e77dcaSMiklos Szeredi 79d8a5ba45SMiklos Szeredi static struct inode *fuse_alloc_inode(struct super_block *sb) 80d8a5ba45SMiklos Szeredi { 81d8a5ba45SMiklos Szeredi struct inode *inode; 82d8a5ba45SMiklos Szeredi struct fuse_inode *fi; 83d8a5ba45SMiklos Szeredi 84e94b1766SChristoph Lameter inode = kmem_cache_alloc(fuse_inode_cachep, GFP_KERNEL); 85d8a5ba45SMiklos Szeredi if (!inode) 86d8a5ba45SMiklos Szeredi return NULL; 87d8a5ba45SMiklos Szeredi 88d8a5ba45SMiklos Szeredi fi = get_fuse_inode(inode); 890a0898cfSMiklos Szeredi fi->i_time = 0; 90d8a5ba45SMiklos Szeredi fi->nodeid = 0; 919e6268dbSMiklos Szeredi fi->nlookup = 0; 92fbee36b9SJohn Muir fi->attr_version = 0; 933be5a52bSMiklos Szeredi fi->writectr = 0; 9445c72cd7SPavel Shilovsky fi->orig_ino = 0; 954582a4abSFeng Shuo fi->state = 0; 9693a8c3cdSMiklos Szeredi INIT_LIST_HEAD(&fi->write_files); 973be5a52bSMiklos Szeredi INIT_LIST_HEAD(&fi->queued_writes); 983be5a52bSMiklos Szeredi INIT_LIST_HEAD(&fi->writepages); 993be5a52bSMiklos Szeredi init_waitqueue_head(&fi->page_waitq); 10007e77dcaSMiklos Szeredi fi->forget = fuse_alloc_forget(); 10107e77dcaSMiklos Szeredi if (!fi->forget) { 102e5e5558eSMiklos Szeredi kmem_cache_free(fuse_inode_cachep, inode); 103e5e5558eSMiklos Szeredi return NULL; 104e5e5558eSMiklos Szeredi } 105d8a5ba45SMiklos Szeredi 106d8a5ba45SMiklos Szeredi return inode; 107d8a5ba45SMiklos Szeredi } 108d8a5ba45SMiklos Szeredi 109fa0d7e3dSNick Piggin static void fuse_i_callback(struct rcu_head *head) 110fa0d7e3dSNick Piggin { 111fa0d7e3dSNick Piggin struct inode *inode = container_of(head, struct inode, i_rcu); 112fa0d7e3dSNick Piggin kmem_cache_free(fuse_inode_cachep, inode); 113fa0d7e3dSNick Piggin } 114fa0d7e3dSNick Piggin 115d8a5ba45SMiklos Szeredi static void fuse_destroy_inode(struct inode *inode) 116d8a5ba45SMiklos Szeredi { 117e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 11893a8c3cdSMiklos Szeredi BUG_ON(!list_empty(&fi->write_files)); 1193be5a52bSMiklos Szeredi BUG_ON(!list_empty(&fi->queued_writes)); 12007e77dcaSMiklos Szeredi kfree(fi->forget); 121fa0d7e3dSNick Piggin call_rcu(&inode->i_rcu, fuse_i_callback); 122d8a5ba45SMiklos Szeredi } 123d8a5ba45SMiklos Szeredi 124b57922d9SAl Viro static void fuse_evict_inode(struct inode *inode) 125d8a5ba45SMiklos Szeredi { 12691b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data); 127dbd5768fSJan Kara clear_inode(inode); 1281e9a4ed9SMiklos Szeredi if (inode->i_sb->s_flags & MS_ACTIVE) { 129e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 130e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 13107e77dcaSMiklos Szeredi fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup); 13207e77dcaSMiklos Szeredi fi->forget = NULL; 133e5e5558eSMiklos Szeredi } 134d8a5ba45SMiklos Szeredi } 135d8a5ba45SMiklos Szeredi 13671421259SMiklos Szeredi static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) 13771421259SMiklos Szeredi { 13802b9984dSTheodore Ts'o sync_filesystem(sb); 13971421259SMiklos Szeredi if (*flags & MS_MANDLOCK) 14071421259SMiklos Szeredi return -EINVAL; 14171421259SMiklos Szeredi 14271421259SMiklos Szeredi return 0; 14371421259SMiklos Szeredi } 14471421259SMiklos Szeredi 14545c72cd7SPavel Shilovsky /* 14645c72cd7SPavel Shilovsky * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down 14745c72cd7SPavel Shilovsky * so that it will fit. 14845c72cd7SPavel Shilovsky */ 14945c72cd7SPavel Shilovsky static ino_t fuse_squash_ino(u64 ino64) 15045c72cd7SPavel Shilovsky { 15145c72cd7SPavel Shilovsky ino_t ino = (ino_t) ino64; 15245c72cd7SPavel Shilovsky if (sizeof(ino_t) < sizeof(u64)) 15345c72cd7SPavel Shilovsky ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8; 15445c72cd7SPavel Shilovsky return ino; 15545c72cd7SPavel Shilovsky } 15645c72cd7SPavel Shilovsky 1573be5a52bSMiklos Szeredi void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 1583be5a52bSMiklos Szeredi u64 attr_valid) 159d8a5ba45SMiklos Szeredi { 1609ffbb916SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 161ebc14c4dSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 162d8a5ba45SMiklos Szeredi 1631fb69e78SMiklos Szeredi fi->attr_version = ++fc->attr_version; 1641fb69e78SMiklos Szeredi fi->i_time = attr_valid; 1651fb69e78SMiklos Szeredi 16645c72cd7SPavel Shilovsky inode->i_ino = fuse_squash_ino(attr->ino); 167ebc14c4dSMiklos Szeredi inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 168bfe86848SMiklos Szeredi set_nlink(inode, attr->nlink); 169499dcf20SEric W. Biederman inode->i_uid = make_kuid(&init_user_ns, attr->uid); 170499dcf20SEric W. Biederman inode->i_gid = make_kgid(&init_user_ns, attr->gid); 171d8a5ba45SMiklos Szeredi inode->i_blocks = attr->blocks; 172d8a5ba45SMiklos Szeredi inode->i_atime.tv_sec = attr->atime; 173d8a5ba45SMiklos Szeredi inode->i_atime.tv_nsec = attr->atimensec; 174b0aa7606SMaxim Patlasov /* mtime from server may be stale due to local buffered write */ 175b0aa7606SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) { 176d8a5ba45SMiklos Szeredi inode->i_mtime.tv_sec = attr->mtime; 177d8a5ba45SMiklos Szeredi inode->i_mtime.tv_nsec = attr->mtimensec; 178d8a5ba45SMiklos Szeredi inode->i_ctime.tv_sec = attr->ctime; 179d8a5ba45SMiklos Szeredi inode->i_ctime.tv_nsec = attr->ctimensec; 18031f3267bSMaxim Patlasov } 181e00d2c2dSMiklos Szeredi 1820e9663eeSMiklos Szeredi if (attr->blksize != 0) 1830e9663eeSMiklos Szeredi inode->i_blkbits = ilog2(attr->blksize); 1840e9663eeSMiklos Szeredi else 1850e9663eeSMiklos Szeredi inode->i_blkbits = inode->i_sb->s_blocksize_bits; 1860e9663eeSMiklos Szeredi 187ebc14c4dSMiklos Szeredi /* 188ebc14c4dSMiklos Szeredi * Don't set the sticky bit in i_mode, unless we want the VFS 189ebc14c4dSMiklos Szeredi * to check permissions. This prevents failures due to the 190ebc14c4dSMiklos Szeredi * check in may_delete(). 191ebc14c4dSMiklos Szeredi */ 192ebc14c4dSMiklos Szeredi fi->orig_i_mode = inode->i_mode; 193ebc14c4dSMiklos Szeredi if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 194ebc14c4dSMiklos Szeredi inode->i_mode &= ~S_ISVTX; 19545c72cd7SPavel Shilovsky 19645c72cd7SPavel Shilovsky fi->orig_ino = attr->ino; 1973be5a52bSMiklos Szeredi } 1983be5a52bSMiklos Szeredi 1993be5a52bSMiklos Szeredi void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, 2003be5a52bSMiklos Szeredi u64 attr_valid, u64 attr_version) 2013be5a52bSMiklos Szeredi { 2023be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 2033be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 2048373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 2053be5a52bSMiklos Szeredi loff_t oldsize; 206eed2179eSBrian Foster struct timespec old_mtime; 2073be5a52bSMiklos Szeredi 2083be5a52bSMiklos Szeredi spin_lock(&fc->lock); 20906a7c3c2SMaxim Patlasov if ((attr_version != 0 && fi->attr_version > attr_version) || 21006a7c3c2SMaxim Patlasov test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { 2113be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 2123be5a52bSMiklos Szeredi return; 2133be5a52bSMiklos Szeredi } 2143be5a52bSMiklos Szeredi 215eed2179eSBrian Foster old_mtime = inode->i_mtime; 2163be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, attr, attr_valid); 217ebc14c4dSMiklos Szeredi 218e00d2c2dSMiklos Szeredi oldsize = inode->i_size; 2198373200bSPavel Emelyanov /* 2208373200bSPavel Emelyanov * In case of writeback_cache enabled, the cached writes beyond EOF 2218373200bSPavel Emelyanov * extend local i_size without keeping userspace server in sync. So, 2228373200bSPavel Emelyanov * attr->size coming from server can be stale. We cannot trust it. 2238373200bSPavel Emelyanov */ 2248373200bSPavel Emelyanov if (!is_wb || !S_ISREG(inode->i_mode)) 225e00d2c2dSMiklos Szeredi i_size_write(inode, attr->size); 226e00d2c2dSMiklos Szeredi spin_unlock(&fc->lock); 227e00d2c2dSMiklos Szeredi 2288373200bSPavel Emelyanov if (!is_wb && S_ISREG(inode->i_mode)) { 229eed2179eSBrian Foster bool inval = false; 230eed2179eSBrian Foster 231eed2179eSBrian Foster if (oldsize != attr->size) { 2327caef267SKirill A. Shutemov truncate_pagecache(inode, attr->size); 233eed2179eSBrian Foster inval = true; 234eed2179eSBrian Foster } else if (fc->auto_inval_data) { 235eed2179eSBrian Foster struct timespec new_mtime = { 236eed2179eSBrian Foster .tv_sec = attr->mtime, 237eed2179eSBrian Foster .tv_nsec = attr->mtimensec, 238eed2179eSBrian Foster }; 239eed2179eSBrian Foster 240eed2179eSBrian Foster /* 241eed2179eSBrian Foster * Auto inval mode also checks and invalidates if mtime 242eed2179eSBrian Foster * has changed. 243eed2179eSBrian Foster */ 244eed2179eSBrian Foster if (!timespec_equal(&old_mtime, &new_mtime)) 245eed2179eSBrian Foster inval = true; 246eed2179eSBrian Foster } 247eed2179eSBrian Foster 248eed2179eSBrian Foster if (inval) 249b1009979SMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 250e00d2c2dSMiklos Szeredi } 251d8a5ba45SMiklos Szeredi } 252d8a5ba45SMiklos Szeredi 253d8a5ba45SMiklos Szeredi static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) 254d8a5ba45SMiklos Szeredi { 255d8a5ba45SMiklos Szeredi inode->i_mode = attr->mode & S_IFMT; 2569ffbb916SMiklos Szeredi inode->i_size = attr->size; 257b0aa7606SMaxim Patlasov inode->i_mtime.tv_sec = attr->mtime; 258b0aa7606SMaxim Patlasov inode->i_mtime.tv_nsec = attr->mtimensec; 25931f3267bSMaxim Patlasov inode->i_ctime.tv_sec = attr->ctime; 26031f3267bSMaxim Patlasov inode->i_ctime.tv_nsec = attr->ctimensec; 261e5e5558eSMiklos Szeredi if (S_ISREG(inode->i_mode)) { 262e5e5558eSMiklos Szeredi fuse_init_common(inode); 263b6aeadedSMiklos Szeredi fuse_init_file_inode(inode); 264e5e5558eSMiklos Szeredi } else if (S_ISDIR(inode->i_mode)) 265e5e5558eSMiklos Szeredi fuse_init_dir(inode); 266e5e5558eSMiklos Szeredi else if (S_ISLNK(inode->i_mode)) 267e5e5558eSMiklos Szeredi fuse_init_symlink(inode); 268e5e5558eSMiklos Szeredi else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || 269e5e5558eSMiklos Szeredi S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 270e5e5558eSMiklos Szeredi fuse_init_common(inode); 271e5e5558eSMiklos Szeredi init_special_inode(inode, inode->i_mode, 272e5e5558eSMiklos Szeredi new_decode_dev(attr->rdev)); 27339ee059aSMiklos Szeredi } else 27439ee059aSMiklos Szeredi BUG(); 275d8a5ba45SMiklos Szeredi } 276d8a5ba45SMiklos Szeredi 2773b463ae0SJohn Muir int fuse_inode_eq(struct inode *inode, void *_nodeidp) 278d8a5ba45SMiklos Szeredi { 279b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 280d8a5ba45SMiklos Szeredi if (get_node_id(inode) == nodeid) 281d8a5ba45SMiklos Szeredi return 1; 282d8a5ba45SMiklos Szeredi else 283d8a5ba45SMiklos Szeredi return 0; 284d8a5ba45SMiklos Szeredi } 285d8a5ba45SMiklos Szeredi 286d8a5ba45SMiklos Szeredi static int fuse_inode_set(struct inode *inode, void *_nodeidp) 287d8a5ba45SMiklos Szeredi { 288b48badf0SMiklos Szeredi u64 nodeid = *(u64 *) _nodeidp; 289d8a5ba45SMiklos Szeredi get_fuse_inode(inode)->nodeid = nodeid; 290d8a5ba45SMiklos Szeredi return 0; 291d8a5ba45SMiklos Szeredi } 292d8a5ba45SMiklos Szeredi 293b48badf0SMiklos Szeredi struct inode *fuse_iget(struct super_block *sb, u64 nodeid, 2941fb69e78SMiklos Szeredi int generation, struct fuse_attr *attr, 2951fb69e78SMiklos Szeredi u64 attr_valid, u64 attr_version) 296d8a5ba45SMiklos Szeredi { 297d8a5ba45SMiklos Szeredi struct inode *inode; 2989e6268dbSMiklos Szeredi struct fuse_inode *fi; 299d8a5ba45SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 300d8a5ba45SMiklos Szeredi 301d8a5ba45SMiklos Szeredi retry: 302d8a5ba45SMiklos Szeredi inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid); 303d8a5ba45SMiklos Szeredi if (!inode) 304d8a5ba45SMiklos Szeredi return NULL; 305d8a5ba45SMiklos Szeredi 306d8a5ba45SMiklos Szeredi if ((inode->i_state & I_NEW)) { 307b0aa7606SMaxim Patlasov inode->i_flags |= S_NOATIME; 308d31433c8SMaxim Patlasov if (!fc->writeback_cache || !S_ISREG(attr->mode)) 309b0aa7606SMaxim Patlasov inode->i_flags |= S_NOCMTIME; 310d8a5ba45SMiklos Szeredi inode->i_generation = generation; 311d8a5ba45SMiklos Szeredi fuse_init_inode(inode, attr); 312d8a5ba45SMiklos Szeredi unlock_new_inode(inode); 313d8a5ba45SMiklos Szeredi } else if ((inode->i_mode ^ attr->mode) & S_IFMT) { 314d8a5ba45SMiklos Szeredi /* Inode has changed type, any I/O on the old should fail */ 315d8a5ba45SMiklos Szeredi make_bad_inode(inode); 316d8a5ba45SMiklos Szeredi iput(inode); 317d8a5ba45SMiklos Szeredi goto retry; 318d8a5ba45SMiklos Szeredi } 319d8a5ba45SMiklos Szeredi 3209e6268dbSMiklos Szeredi fi = get_fuse_inode(inode); 3218da5ff23SMiklos Szeredi spin_lock(&fc->lock); 3229e6268dbSMiklos Szeredi fi->nlookup++; 3238da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 3241fb69e78SMiklos Szeredi fuse_change_attributes(inode, attr, attr_valid, attr_version); 3251fb69e78SMiklos Szeredi 326d8a5ba45SMiklos Szeredi return inode; 327d8a5ba45SMiklos Szeredi } 328d8a5ba45SMiklos Szeredi 3293b463ae0SJohn Muir int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, 3303b463ae0SJohn Muir loff_t offset, loff_t len) 3313b463ae0SJohn Muir { 3323b463ae0SJohn Muir struct inode *inode; 3333b463ae0SJohn Muir pgoff_t pg_start; 3343b463ae0SJohn Muir pgoff_t pg_end; 3353b463ae0SJohn Muir 3363b463ae0SJohn Muir inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid); 3373b463ae0SJohn Muir if (!inode) 3383b463ae0SJohn Muir return -ENOENT; 3393b463ae0SJohn Muir 3403b463ae0SJohn Muir fuse_invalidate_attr(inode); 3413b463ae0SJohn Muir if (offset >= 0) { 34209cbfeafSKirill A. Shutemov pg_start = offset >> PAGE_SHIFT; 3433b463ae0SJohn Muir if (len <= 0) 3443b463ae0SJohn Muir pg_end = -1; 3453b463ae0SJohn Muir else 34609cbfeafSKirill A. Shutemov pg_end = (offset + len - 1) >> PAGE_SHIFT; 3473b463ae0SJohn Muir invalidate_inode_pages2_range(inode->i_mapping, 3483b463ae0SJohn Muir pg_start, pg_end); 3493b463ae0SJohn Muir } 3503b463ae0SJohn Muir iput(inode); 3513b463ae0SJohn Muir return 0; 3523b463ae0SJohn Muir } 3533b463ae0SJohn Muir 35442faad99SAl Viro static void fuse_umount_begin(struct super_block *sb) 35569a53bf2SMiklos Szeredi { 35642faad99SAl Viro fuse_abort_conn(get_fuse_conn_super(sb)); 35769a53bf2SMiklos Szeredi } 35869a53bf2SMiklos Szeredi 3590ec7ca41SMiklos Szeredi static void fuse_send_destroy(struct fuse_conn *fc) 3600ec7ca41SMiklos Szeredi { 3610ec7ca41SMiklos Szeredi struct fuse_req *req = fc->destroy_req; 3620ec7ca41SMiklos Szeredi if (req && fc->conn_init) { 3630ec7ca41SMiklos Szeredi fc->destroy_req = NULL; 3640ec7ca41SMiklos Szeredi req->in.h.opcode = FUSE_DESTROY; 365825d6d33SMiklos Szeredi __set_bit(FR_FORCE, &req->flags); 366825d6d33SMiklos Szeredi __clear_bit(FR_BACKGROUND, &req->flags); 367b93f858aSTejun Heo fuse_request_send(fc, req); 3680ec7ca41SMiklos Szeredi fuse_put_request(fc, req); 3690ec7ca41SMiklos Szeredi } 3700ec7ca41SMiklos Szeredi } 3710ec7ca41SMiklos Szeredi 372a325f9b9STejun Heo static void fuse_bdi_destroy(struct fuse_conn *fc) 373d8a5ba45SMiklos Szeredi { 374a325f9b9STejun Heo if (fc->bdi_initialized) 375a325f9b9STejun Heo bdi_destroy(&fc->bdi); 376a325f9b9STejun Heo } 377d8a5ba45SMiklos Szeredi 378a325f9b9STejun Heo static void fuse_put_super(struct super_block *sb) 379a325f9b9STejun Heo { 380a325f9b9STejun Heo struct fuse_conn *fc = get_fuse_conn_super(sb); 381a325f9b9STejun Heo 382a325f9b9STejun Heo fuse_send_destroy(fc); 383bbd99797SMiklos Szeredi 384580640baSMiklos Szeredi fuse_abort_conn(fc); 385bbd99797SMiklos Szeredi mutex_lock(&fuse_mutex); 386bbd99797SMiklos Szeredi list_del(&fc->entry); 387bbd99797SMiklos Szeredi fuse_ctl_remove_conn(fc); 388bbd99797SMiklos Szeredi mutex_unlock(&fuse_mutex); 389bbd99797SMiklos Szeredi fuse_bdi_destroy(fc); 390bbd99797SMiklos Szeredi 391bafa9654SMiklos Szeredi fuse_conn_put(fc); 392d8a5ba45SMiklos Szeredi } 393d8a5ba45SMiklos Szeredi 394e5e5558eSMiklos Szeredi static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 395e5e5558eSMiklos Szeredi { 396e5e5558eSMiklos Szeredi stbuf->f_type = FUSE_SUPER_MAGIC; 397e5e5558eSMiklos Szeredi stbuf->f_bsize = attr->bsize; 398de5f1202SMiklos Szeredi stbuf->f_frsize = attr->frsize; 399e5e5558eSMiklos Szeredi stbuf->f_blocks = attr->blocks; 400e5e5558eSMiklos Szeredi stbuf->f_bfree = attr->bfree; 401e5e5558eSMiklos Szeredi stbuf->f_bavail = attr->bavail; 402e5e5558eSMiklos Szeredi stbuf->f_files = attr->files; 403e5e5558eSMiklos Szeredi stbuf->f_ffree = attr->ffree; 404e5e5558eSMiklos Szeredi stbuf->f_namelen = attr->namelen; 405e5e5558eSMiklos Szeredi /* fsid is left zero */ 406e5e5558eSMiklos Szeredi } 407e5e5558eSMiklos Szeredi 408726c3342SDavid Howells static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) 409e5e5558eSMiklos Szeredi { 410726c3342SDavid Howells struct super_block *sb = dentry->d_sb; 411e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 4127078187aSMiklos Szeredi FUSE_ARGS(args); 413e5e5558eSMiklos Szeredi struct fuse_statfs_out outarg; 414e5e5558eSMiklos Szeredi int err; 415e5e5558eSMiklos Szeredi 416c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) { 417e57ac683SMiklos Szeredi buf->f_type = FUSE_SUPER_MAGIC; 418e57ac683SMiklos Szeredi return 0; 419e57ac683SMiklos Szeredi } 420e57ac683SMiklos Szeredi 421de5f1202SMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 4227078187aSMiklos Szeredi args.in.numargs = 0; 4237078187aSMiklos Szeredi args.in.h.opcode = FUSE_STATFS; 4242b0143b5SDavid Howells args.in.h.nodeid = get_node_id(d_inode(dentry)); 4257078187aSMiklos Szeredi args.out.numargs = 1; 42621f62174SMiklos Szeredi args.out.args[0].size = sizeof(outarg); 4277078187aSMiklos Szeredi args.out.args[0].value = &outarg; 4287078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 429e5e5558eSMiklos Szeredi if (!err) 430e5e5558eSMiklos Szeredi convert_fuse_statfs(buf, &outarg.st); 431e5e5558eSMiklos Szeredi return err; 432e5e5558eSMiklos Szeredi } 433e5e5558eSMiklos Szeredi 434d8a5ba45SMiklos Szeredi enum { 435d8a5ba45SMiklos Szeredi OPT_FD, 436d8a5ba45SMiklos Szeredi OPT_ROOTMODE, 437d8a5ba45SMiklos Szeredi OPT_USER_ID, 43887729a55SMiklos Szeredi OPT_GROUP_ID, 439d8a5ba45SMiklos Szeredi OPT_DEFAULT_PERMISSIONS, 440d8a5ba45SMiklos Szeredi OPT_ALLOW_OTHER, 441db50b96cSMiklos Szeredi OPT_MAX_READ, 442d8091614SMiklos Szeredi OPT_BLKSIZE, 443d8a5ba45SMiklos Szeredi OPT_ERR 444d8a5ba45SMiklos Szeredi }; 445d8a5ba45SMiklos Szeredi 446a447c093SSteven Whitehouse static const match_table_t tokens = { 447d8a5ba45SMiklos Szeredi {OPT_FD, "fd=%u"}, 448d8a5ba45SMiklos Szeredi {OPT_ROOTMODE, "rootmode=%o"}, 449d8a5ba45SMiklos Szeredi {OPT_USER_ID, "user_id=%u"}, 45087729a55SMiklos Szeredi {OPT_GROUP_ID, "group_id=%u"}, 451d8a5ba45SMiklos Szeredi {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, 452d8a5ba45SMiklos Szeredi {OPT_ALLOW_OTHER, "allow_other"}, 453db50b96cSMiklos Szeredi {OPT_MAX_READ, "max_read=%u"}, 454d8091614SMiklos Szeredi {OPT_BLKSIZE, "blksize=%u"}, 455d8a5ba45SMiklos Szeredi {OPT_ERR, NULL} 456d8a5ba45SMiklos Szeredi }; 457d8a5ba45SMiklos Szeredi 458233a01faSMiklos Szeredi static int fuse_match_uint(substring_t *s, unsigned int *res) 459233a01faSMiklos Szeredi { 460233a01faSMiklos Szeredi int err = -ENOMEM; 461233a01faSMiklos Szeredi char *buf = match_strdup(s); 462233a01faSMiklos Szeredi if (buf) { 463233a01faSMiklos Szeredi err = kstrtouint(buf, 10, res); 464233a01faSMiklos Szeredi kfree(buf); 465233a01faSMiklos Szeredi } 466233a01faSMiklos Szeredi return err; 467233a01faSMiklos Szeredi } 468233a01faSMiklos Szeredi 469d8091614SMiklos Szeredi static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) 470d8a5ba45SMiklos Szeredi { 471d8a5ba45SMiklos Szeredi char *p; 472d8a5ba45SMiklos Szeredi memset(d, 0, sizeof(struct fuse_mount_data)); 473db50b96cSMiklos Szeredi d->max_read = ~0; 474d1875dbaSMiklos Szeredi d->blksize = FUSE_DEFAULT_BLKSIZE; 475d8a5ba45SMiklos Szeredi 476d8a5ba45SMiklos Szeredi while ((p = strsep(&opt, ",")) != NULL) { 477d8a5ba45SMiklos Szeredi int token; 478d8a5ba45SMiklos Szeredi int value; 479233a01faSMiklos Szeredi unsigned uv; 480d8a5ba45SMiklos Szeredi substring_t args[MAX_OPT_ARGS]; 481d8a5ba45SMiklos Szeredi if (!*p) 482d8a5ba45SMiklos Szeredi continue; 483d8a5ba45SMiklos Szeredi 484d8a5ba45SMiklos Szeredi token = match_token(p, tokens, args); 485d8a5ba45SMiklos Szeredi switch (token) { 486d8a5ba45SMiklos Szeredi case OPT_FD: 487d8a5ba45SMiklos Szeredi if (match_int(&args[0], &value)) 488d8a5ba45SMiklos Szeredi return 0; 489d8a5ba45SMiklos Szeredi d->fd = value; 4905a533682SMiklos Szeredi d->fd_present = 1; 491d8a5ba45SMiklos Szeredi break; 492d8a5ba45SMiklos Szeredi 493d8a5ba45SMiklos Szeredi case OPT_ROOTMODE: 494d8a5ba45SMiklos Szeredi if (match_octal(&args[0], &value)) 495d8a5ba45SMiklos Szeredi return 0; 496a5bfffacSTimo Savola if (!fuse_valid_type(value)) 497a5bfffacSTimo Savola return 0; 498d8a5ba45SMiklos Szeredi d->rootmode = value; 4995a533682SMiklos Szeredi d->rootmode_present = 1; 500d8a5ba45SMiklos Szeredi break; 501d8a5ba45SMiklos Szeredi 502d8a5ba45SMiklos Szeredi case OPT_USER_ID: 503233a01faSMiklos Szeredi if (fuse_match_uint(&args[0], &uv)) 504d8a5ba45SMiklos Szeredi return 0; 505233a01faSMiklos Szeredi d->user_id = make_kuid(current_user_ns(), uv); 506499dcf20SEric W. Biederman if (!uid_valid(d->user_id)) 507499dcf20SEric W. Biederman return 0; 5085a533682SMiklos Szeredi d->user_id_present = 1; 509d8a5ba45SMiklos Szeredi break; 510d8a5ba45SMiklos Szeredi 51187729a55SMiklos Szeredi case OPT_GROUP_ID: 512233a01faSMiklos Szeredi if (fuse_match_uint(&args[0], &uv)) 51387729a55SMiklos Szeredi return 0; 514233a01faSMiklos Szeredi d->group_id = make_kgid(current_user_ns(), uv); 515499dcf20SEric W. Biederman if (!gid_valid(d->group_id)) 516499dcf20SEric W. Biederman return 0; 5175a533682SMiklos Szeredi d->group_id_present = 1; 51887729a55SMiklos Szeredi break; 51987729a55SMiklos Szeredi 5201e9a4ed9SMiklos Szeredi case OPT_DEFAULT_PERMISSIONS: 5211e9a4ed9SMiklos Szeredi d->flags |= FUSE_DEFAULT_PERMISSIONS; 5221e9a4ed9SMiklos Szeredi break; 5231e9a4ed9SMiklos Szeredi 5241e9a4ed9SMiklos Szeredi case OPT_ALLOW_OTHER: 5251e9a4ed9SMiklos Szeredi d->flags |= FUSE_ALLOW_OTHER; 5261e9a4ed9SMiklos Szeredi break; 5271e9a4ed9SMiklos Szeredi 528db50b96cSMiklos Szeredi case OPT_MAX_READ: 529db50b96cSMiklos Szeredi if (match_int(&args[0], &value)) 530db50b96cSMiklos Szeredi return 0; 531db50b96cSMiklos Szeredi d->max_read = value; 532db50b96cSMiklos Szeredi break; 533db50b96cSMiklos Szeredi 534d8091614SMiklos Szeredi case OPT_BLKSIZE: 535d8091614SMiklos Szeredi if (!is_bdev || match_int(&args[0], &value)) 536d8091614SMiklos Szeredi return 0; 537d8091614SMiklos Szeredi d->blksize = value; 538d8091614SMiklos Szeredi break; 539d8091614SMiklos Szeredi 540d8a5ba45SMiklos Szeredi default: 541d8a5ba45SMiklos Szeredi return 0; 542d8a5ba45SMiklos Szeredi } 543d8a5ba45SMiklos Szeredi } 5445a533682SMiklos Szeredi 5455a533682SMiklos Szeredi if (!d->fd_present || !d->rootmode_present || 5465a533682SMiklos Szeredi !d->user_id_present || !d->group_id_present) 547d8a5ba45SMiklos Szeredi return 0; 548d8a5ba45SMiklos Szeredi 549d8a5ba45SMiklos Szeredi return 1; 550d8a5ba45SMiklos Szeredi } 551d8a5ba45SMiklos Szeredi 55234c80b1dSAl Viro static int fuse_show_options(struct seq_file *m, struct dentry *root) 553d8a5ba45SMiklos Szeredi { 55434c80b1dSAl Viro struct super_block *sb = root->d_sb; 55534c80b1dSAl Viro struct fuse_conn *fc = get_fuse_conn_super(sb); 556d8a5ba45SMiklos Szeredi 557499dcf20SEric W. Biederman seq_printf(m, ",user_id=%u", from_kuid_munged(&init_user_ns, fc->user_id)); 558499dcf20SEric W. Biederman seq_printf(m, ",group_id=%u", from_kgid_munged(&init_user_ns, fc->group_id)); 5591e9a4ed9SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) 5601e9a4ed9SMiklos Szeredi seq_puts(m, ",default_permissions"); 5611e9a4ed9SMiklos Szeredi if (fc->flags & FUSE_ALLOW_OTHER) 5621e9a4ed9SMiklos Szeredi seq_puts(m, ",allow_other"); 563db50b96cSMiklos Szeredi if (fc->max_read != ~0) 564db50b96cSMiklos Szeredi seq_printf(m, ",max_read=%u", fc->max_read); 56534c80b1dSAl Viro if (sb->s_bdev && sb->s_blocksize != FUSE_DEFAULT_BLKSIZE) 56634c80b1dSAl Viro seq_printf(m, ",blksize=%lu", sb->s_blocksize); 567d8a5ba45SMiklos Szeredi return 0; 568d8a5ba45SMiklos Szeredi } 569d8a5ba45SMiklos Szeredi 570f88996a9SMiklos Szeredi static void fuse_iqueue_init(struct fuse_iqueue *fiq) 571f88996a9SMiklos Szeredi { 572f88996a9SMiklos Szeredi memset(fiq, 0, sizeof(struct fuse_iqueue)); 573f88996a9SMiklos Szeredi init_waitqueue_head(&fiq->waitq); 574f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->pending); 575f88996a9SMiklos Szeredi INIT_LIST_HEAD(&fiq->interrupts); 576f88996a9SMiklos Szeredi fiq->forget_list_tail = &fiq->forget_list_head; 577e16714d8SMiklos Szeredi fiq->connected = 1; 578f88996a9SMiklos Szeredi } 579f88996a9SMiklos Szeredi 5803a2b5b9cSMiklos Szeredi static void fuse_pqueue_init(struct fuse_pqueue *fpq) 5813a2b5b9cSMiklos Szeredi { 5823a2b5b9cSMiklos Szeredi memset(fpq, 0, sizeof(struct fuse_pqueue)); 58345a91cb1SMiklos Szeredi spin_lock_init(&fpq->lock); 5843a2b5b9cSMiklos Szeredi INIT_LIST_HEAD(&fpq->processing); 5853a2b5b9cSMiklos Szeredi INIT_LIST_HEAD(&fpq->io); 586e96edd94SMiklos Szeredi fpq->connected = 1; 5873a2b5b9cSMiklos Szeredi } 5883a2b5b9cSMiklos Szeredi 589a325f9b9STejun Heo void fuse_conn_init(struct fuse_conn *fc) 590d8a5ba45SMiklos Szeredi { 5910d179aa5STejun Heo memset(fc, 0, sizeof(*fc)); 592d7133114SMiklos Szeredi spin_lock_init(&fc->lock); 5933b463ae0SJohn Muir init_rwsem(&fc->killsb); 594bafa9654SMiklos Szeredi atomic_set(&fc->count, 1); 595c3696046SMiklos Szeredi atomic_set(&fc->dev_count, 1); 59608a53cdcSMiklos Szeredi init_waitqueue_head(&fc->blocked_waitq); 597de5e3decSMiklos Szeredi init_waitqueue_head(&fc->reserved_req_waitq); 598f88996a9SMiklos Szeredi fuse_iqueue_init(&fc->iq); 599d12def1bSMiklos Szeredi INIT_LIST_HEAD(&fc->bg_queue); 6000d179aa5STejun Heo INIT_LIST_HEAD(&fc->entry); 601cc080e9eSMiklos Szeredi INIT_LIST_HEAD(&fc->devices); 602095da6cbSMiklos Szeredi atomic_set(&fc->num_waiting, 0); 6037a6d3c8bSCsaba Henk fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; 6047a6d3c8bSCsaba Henk fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; 605acf99433STejun Heo fc->khctr = 0; 60695668a69STejun Heo fc->polled_files = RB_ROOT; 6070aada884SMaxim Patlasov fc->blocked = 0; 608796523fbSMaxim Patlasov fc->initialized = 0; 609e16714d8SMiklos Szeredi fc->connected = 1; 6101fb69e78SMiklos Szeredi fc->attr_version = 1; 6119c8ef561SMiklos Szeredi get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); 612d8a5ba45SMiklos Szeredi } 6130d179aa5STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_init); 614d8a5ba45SMiklos Szeredi 615bafa9654SMiklos Szeredi void fuse_conn_put(struct fuse_conn *fc) 616bafa9654SMiklos Szeredi { 617d2a85164SMiklos Szeredi if (atomic_dec_and_test(&fc->count)) { 6180ec7ca41SMiklos Szeredi if (fc->destroy_req) 6190ec7ca41SMiklos Szeredi fuse_request_free(fc->destroy_req); 62043901aabSTejun Heo fc->release(fc); 621bafa9654SMiklos Szeredi } 622d2a85164SMiklos Szeredi } 62308cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_put); 624bafa9654SMiklos Szeredi 625bafa9654SMiklos Szeredi struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) 626bafa9654SMiklos Szeredi { 627bafa9654SMiklos Szeredi atomic_inc(&fc->count); 628bafa9654SMiklos Szeredi return fc; 629bafa9654SMiklos Szeredi } 63008cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_conn_get); 631bafa9654SMiklos Szeredi 632b93f858aSTejun Heo static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) 633d8a5ba45SMiklos Szeredi { 634d8a5ba45SMiklos Szeredi struct fuse_attr attr; 635d8a5ba45SMiklos Szeredi memset(&attr, 0, sizeof(attr)); 636d8a5ba45SMiklos Szeredi 637d8a5ba45SMiklos Szeredi attr.mode = mode; 638d8a5ba45SMiklos Szeredi attr.ino = FUSE_ROOT_ID; 639074406faSMiklos Szeredi attr.nlink = 1; 6401fb69e78SMiklos Szeredi return fuse_iget(sb, 1, 0, &attr, 0, 0); 641d8a5ba45SMiklos Szeredi } 642d8a5ba45SMiklos Szeredi 6431729a16cSMiklos Szeredi struct fuse_inode_handle { 644dbd561d2SMiklos Szeredi u64 nodeid; 645dbd561d2SMiklos Szeredi u32 generation; 646dbd561d2SMiklos Szeredi }; 647dbd561d2SMiklos Szeredi 648dbd561d2SMiklos Szeredi static struct dentry *fuse_get_dentry(struct super_block *sb, 649dbd561d2SMiklos Szeredi struct fuse_inode_handle *handle) 650dbd561d2SMiklos Szeredi { 65133670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 652dbd561d2SMiklos Szeredi struct inode *inode; 653dbd561d2SMiklos Szeredi struct dentry *entry; 654dbd561d2SMiklos Szeredi int err = -ESTALE; 655dbd561d2SMiklos Szeredi 656dbd561d2SMiklos Szeredi if (handle->nodeid == 0) 657dbd561d2SMiklos Szeredi goto out_err; 658dbd561d2SMiklos Szeredi 659dbd561d2SMiklos Szeredi inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid); 66033670fa2SMiklos Szeredi if (!inode) { 66133670fa2SMiklos Szeredi struct fuse_entry_out outarg; 66233670fa2SMiklos Szeredi struct qstr name; 66333670fa2SMiklos Szeredi 66433670fa2SMiklos Szeredi if (!fc->export_support) 665dbd561d2SMiklos Szeredi goto out_err; 66633670fa2SMiklos Szeredi 66733670fa2SMiklos Szeredi name.len = 1; 66833670fa2SMiklos Szeredi name.name = "."; 66933670fa2SMiklos Szeredi err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg, 67033670fa2SMiklos Szeredi &inode); 67133670fa2SMiklos Szeredi if (err && err != -ENOENT) 67233670fa2SMiklos Szeredi goto out_err; 67333670fa2SMiklos Szeredi if (err || !inode) { 67433670fa2SMiklos Szeredi err = -ESTALE; 67533670fa2SMiklos Szeredi goto out_err; 67633670fa2SMiklos Szeredi } 67733670fa2SMiklos Szeredi err = -EIO; 67833670fa2SMiklos Szeredi if (get_node_id(inode) != handle->nodeid) 67933670fa2SMiklos Szeredi goto out_iput; 68033670fa2SMiklos Szeredi } 681dbd561d2SMiklos Szeredi err = -ESTALE; 682dbd561d2SMiklos Szeredi if (inode->i_generation != handle->generation) 683dbd561d2SMiklos Szeredi goto out_iput; 684dbd561d2SMiklos Szeredi 68544003728SChristoph Hellwig entry = d_obtain_alias(inode); 686c35eebe9SAl Viro if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) 687dbd561d2SMiklos Szeredi fuse_invalidate_entry_cache(entry); 688dbd561d2SMiklos Szeredi 689dbd561d2SMiklos Szeredi return entry; 690dbd561d2SMiklos Szeredi 691dbd561d2SMiklos Szeredi out_iput: 692dbd561d2SMiklos Szeredi iput(inode); 693dbd561d2SMiklos Szeredi out_err: 694dbd561d2SMiklos Szeredi return ERR_PTR(err); 695dbd561d2SMiklos Szeredi } 696dbd561d2SMiklos Szeredi 697b0b0382bSAl Viro static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len, 698b0b0382bSAl Viro struct inode *parent) 699dbd561d2SMiklos Szeredi { 700b0b0382bSAl Viro int len = parent ? 6 : 3; 701dbd561d2SMiklos Szeredi u64 nodeid; 702dbd561d2SMiklos Szeredi u32 generation; 703dbd561d2SMiklos Szeredi 7045fe0c237SAneesh Kumar K.V if (*max_len < len) { 7055fe0c237SAneesh Kumar K.V *max_len = len; 70694e07a75SNamjae Jeon return FILEID_INVALID; 7075fe0c237SAneesh Kumar K.V } 708dbd561d2SMiklos Szeredi 709dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(inode)->nodeid; 710dbd561d2SMiklos Szeredi generation = inode->i_generation; 711dbd561d2SMiklos Szeredi 712dbd561d2SMiklos Szeredi fh[0] = (u32)(nodeid >> 32); 713dbd561d2SMiklos Szeredi fh[1] = (u32)(nodeid & 0xffffffff); 714dbd561d2SMiklos Szeredi fh[2] = generation; 715dbd561d2SMiklos Szeredi 716b0b0382bSAl Viro if (parent) { 717dbd561d2SMiklos Szeredi nodeid = get_fuse_inode(parent)->nodeid; 718dbd561d2SMiklos Szeredi generation = parent->i_generation; 719dbd561d2SMiklos Szeredi 720dbd561d2SMiklos Szeredi fh[3] = (u32)(nodeid >> 32); 721dbd561d2SMiklos Szeredi fh[4] = (u32)(nodeid & 0xffffffff); 722dbd561d2SMiklos Szeredi fh[5] = generation; 723dbd561d2SMiklos Szeredi } 724dbd561d2SMiklos Szeredi 725dbd561d2SMiklos Szeredi *max_len = len; 726b0b0382bSAl Viro return parent ? 0x82 : 0x81; 727dbd561d2SMiklos Szeredi } 728dbd561d2SMiklos Szeredi 729dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_dentry(struct super_block *sb, 730dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 731dbd561d2SMiklos Szeredi { 732dbd561d2SMiklos Szeredi struct fuse_inode_handle handle; 733dbd561d2SMiklos Szeredi 734dbd561d2SMiklos Szeredi if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3) 735dbd561d2SMiklos Szeredi return NULL; 736dbd561d2SMiklos Szeredi 737dbd561d2SMiklos Szeredi handle.nodeid = (u64) fid->raw[0] << 32; 738dbd561d2SMiklos Szeredi handle.nodeid |= (u64) fid->raw[1]; 739dbd561d2SMiklos Szeredi handle.generation = fid->raw[2]; 740dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &handle); 741dbd561d2SMiklos Szeredi } 742dbd561d2SMiklos Szeredi 743dbd561d2SMiklos Szeredi static struct dentry *fuse_fh_to_parent(struct super_block *sb, 744dbd561d2SMiklos Szeredi struct fid *fid, int fh_len, int fh_type) 745dbd561d2SMiklos Szeredi { 746dbd561d2SMiklos Szeredi struct fuse_inode_handle parent; 747dbd561d2SMiklos Szeredi 748dbd561d2SMiklos Szeredi if (fh_type != 0x82 || fh_len < 6) 749dbd561d2SMiklos Szeredi return NULL; 750dbd561d2SMiklos Szeredi 751dbd561d2SMiklos Szeredi parent.nodeid = (u64) fid->raw[3] << 32; 752dbd561d2SMiklos Szeredi parent.nodeid |= (u64) fid->raw[4]; 753dbd561d2SMiklos Szeredi parent.generation = fid->raw[5]; 754dbd561d2SMiklos Szeredi return fuse_get_dentry(sb, &parent); 755dbd561d2SMiklos Szeredi } 756dbd561d2SMiklos Szeredi 75733670fa2SMiklos Szeredi static struct dentry *fuse_get_parent(struct dentry *child) 75833670fa2SMiklos Szeredi { 7592b0143b5SDavid Howells struct inode *child_inode = d_inode(child); 76033670fa2SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(child_inode); 76133670fa2SMiklos Szeredi struct inode *inode; 76233670fa2SMiklos Szeredi struct dentry *parent; 76333670fa2SMiklos Szeredi struct fuse_entry_out outarg; 76433670fa2SMiklos Szeredi struct qstr name; 76533670fa2SMiklos Szeredi int err; 76633670fa2SMiklos Szeredi 76733670fa2SMiklos Szeredi if (!fc->export_support) 76833670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 76933670fa2SMiklos Szeredi 77033670fa2SMiklos Szeredi name.len = 2; 77133670fa2SMiklos Szeredi name.name = ".."; 77233670fa2SMiklos Szeredi err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode), 77333670fa2SMiklos Szeredi &name, &outarg, &inode); 77444003728SChristoph Hellwig if (err) { 77544003728SChristoph Hellwig if (err == -ENOENT) 77633670fa2SMiklos Szeredi return ERR_PTR(-ESTALE); 77744003728SChristoph Hellwig return ERR_PTR(err); 77833670fa2SMiklos Szeredi } 77944003728SChristoph Hellwig 78044003728SChristoph Hellwig parent = d_obtain_alias(inode); 781c35eebe9SAl Viro if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) 78233670fa2SMiklos Szeredi fuse_invalidate_entry_cache(parent); 78333670fa2SMiklos Szeredi 78433670fa2SMiklos Szeredi return parent; 78533670fa2SMiklos Szeredi } 786dbd561d2SMiklos Szeredi 787dbd561d2SMiklos Szeredi static const struct export_operations fuse_export_operations = { 788dbd561d2SMiklos Szeredi .fh_to_dentry = fuse_fh_to_dentry, 789dbd561d2SMiklos Szeredi .fh_to_parent = fuse_fh_to_parent, 790dbd561d2SMiklos Szeredi .encode_fh = fuse_encode_fh, 79133670fa2SMiklos Szeredi .get_parent = fuse_get_parent, 792dbd561d2SMiklos Szeredi }; 793dbd561d2SMiklos Szeredi 794ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations fuse_super_operations = { 795d8a5ba45SMiklos Szeredi .alloc_inode = fuse_alloc_inode, 796d8a5ba45SMiklos Szeredi .destroy_inode = fuse_destroy_inode, 797b57922d9SAl Viro .evict_inode = fuse_evict_inode, 7981e18bda8SMiklos Szeredi .write_inode = fuse_write_inode, 799ead5f0b5SMiklos Szeredi .drop_inode = generic_delete_inode, 80071421259SMiklos Szeredi .remount_fs = fuse_remount_fs, 801d8a5ba45SMiklos Szeredi .put_super = fuse_put_super, 80269a53bf2SMiklos Szeredi .umount_begin = fuse_umount_begin, 803e5e5558eSMiklos Szeredi .statfs = fuse_statfs, 804d8a5ba45SMiklos Szeredi .show_options = fuse_show_options, 805d8a5ba45SMiklos Szeredi }; 806d8a5ba45SMiklos Szeredi 807487ea5afSCsaba Henk static void sanitize_global_limit(unsigned *limit) 808487ea5afSCsaba Henk { 809487ea5afSCsaba Henk if (*limit == 0) 8100ed5fd13SJiang Liu *limit = ((totalram_pages << PAGE_SHIFT) >> 13) / 811487ea5afSCsaba Henk sizeof(struct fuse_req); 812487ea5afSCsaba Henk 813487ea5afSCsaba Henk if (*limit >= 1 << 16) 814487ea5afSCsaba Henk *limit = (1 << 16) - 1; 815487ea5afSCsaba Henk } 816487ea5afSCsaba Henk 817487ea5afSCsaba Henk static int set_global_limit(const char *val, struct kernel_param *kp) 818487ea5afSCsaba Henk { 819487ea5afSCsaba Henk int rv; 820487ea5afSCsaba Henk 821487ea5afSCsaba Henk rv = param_set_uint(val, kp); 822487ea5afSCsaba Henk if (rv) 823487ea5afSCsaba Henk return rv; 824487ea5afSCsaba Henk 825487ea5afSCsaba Henk sanitize_global_limit((unsigned *)kp->arg); 826487ea5afSCsaba Henk 827487ea5afSCsaba Henk return 0; 828487ea5afSCsaba Henk } 829487ea5afSCsaba Henk 830487ea5afSCsaba Henk static void process_init_limits(struct fuse_conn *fc, struct fuse_init_out *arg) 831487ea5afSCsaba Henk { 832487ea5afSCsaba Henk int cap_sys_admin = capable(CAP_SYS_ADMIN); 833487ea5afSCsaba Henk 834487ea5afSCsaba Henk if (arg->minor < 13) 835487ea5afSCsaba Henk return; 836487ea5afSCsaba Henk 837487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 838487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 839487ea5afSCsaba Henk 840487ea5afSCsaba Henk if (arg->max_background) { 841487ea5afSCsaba Henk fc->max_background = arg->max_background; 842487ea5afSCsaba Henk 843487ea5afSCsaba Henk if (!cap_sys_admin && fc->max_background > max_user_bgreq) 844487ea5afSCsaba Henk fc->max_background = max_user_bgreq; 845487ea5afSCsaba Henk } 846487ea5afSCsaba Henk if (arg->congestion_threshold) { 847487ea5afSCsaba Henk fc->congestion_threshold = arg->congestion_threshold; 848487ea5afSCsaba Henk 849487ea5afSCsaba Henk if (!cap_sys_admin && 850487ea5afSCsaba Henk fc->congestion_threshold > max_user_congthresh) 851487ea5afSCsaba Henk fc->congestion_threshold = max_user_congthresh; 852487ea5afSCsaba Henk } 853487ea5afSCsaba Henk } 854487ea5afSCsaba Henk 8559b9a0469SMiklos Szeredi static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) 8569b9a0469SMiklos Szeredi { 8579b9a0469SMiklos Szeredi struct fuse_init_out *arg = &req->misc.init_out; 8589b9a0469SMiklos Szeredi 8599b9a0469SMiklos Szeredi if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) 8609b9a0469SMiklos Szeredi fc->conn_error = 1; 8619b9a0469SMiklos Szeredi else { 8629cd68455SMiklos Szeredi unsigned long ra_pages; 8639cd68455SMiklos Szeredi 864487ea5afSCsaba Henk process_init_limits(fc, arg); 865487ea5afSCsaba Henk 8669cd68455SMiklos Szeredi if (arg->minor >= 6) { 86709cbfeafSKirill A. Shutemov ra_pages = arg->max_readahead / PAGE_SIZE; 8689cd68455SMiklos Szeredi if (arg->flags & FUSE_ASYNC_READ) 8699cd68455SMiklos Szeredi fc->async_read = 1; 87071421259SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 87171421259SMiklos Szeredi fc->no_lock = 1; 87237fb3a30SMiklos Szeredi if (arg->minor >= 17) { 87337fb3a30SMiklos Szeredi if (!(arg->flags & FUSE_FLOCK_LOCKS)) 87437fb3a30SMiklos Szeredi fc->no_flock = 1; 87524114504SMiklos Szeredi } else { 87624114504SMiklos Szeredi if (!(arg->flags & FUSE_POSIX_LOCKS)) 87724114504SMiklos Szeredi fc->no_flock = 1; 87837fb3a30SMiklos Szeredi } 8796ff958edSMiklos Szeredi if (arg->flags & FUSE_ATOMIC_O_TRUNC) 8806ff958edSMiklos Szeredi fc->atomic_o_trunc = 1; 88133670fa2SMiklos Szeredi if (arg->minor >= 9) { 88233670fa2SMiklos Szeredi /* LOOKUP has dependency on proto version */ 88333670fa2SMiklos Szeredi if (arg->flags & FUSE_EXPORT_SUPPORT) 88433670fa2SMiklos Szeredi fc->export_support = 1; 88533670fa2SMiklos Szeredi } 88678bb6cb9SMiklos Szeredi if (arg->flags & FUSE_BIG_WRITES) 88778bb6cb9SMiklos Szeredi fc->big_writes = 1; 888e0a43ddcSMiklos Szeredi if (arg->flags & FUSE_DONT_MASK) 889e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 89072d0d248SBrian Foster if (arg->flags & FUSE_AUTO_INVAL_DATA) 89172d0d248SBrian Foster fc->auto_inval_data = 1; 89228420dadSMiklos Szeredi if (arg->flags & FUSE_DO_READDIRPLUS) { 8930b05b183SAnand V. Avati fc->do_readdirplus = 1; 894634734b6SEric Wong if (arg->flags & FUSE_READDIRPLUS_AUTO) 895634734b6SEric Wong fc->readdirplus_auto = 1; 89628420dadSMiklos Szeredi } 89760b9df7aSMiklos Szeredi if (arg->flags & FUSE_ASYNC_DIO) 89860b9df7aSMiklos Szeredi fc->async_dio = 1; 8994d99ff8fSPavel Emelyanov if (arg->flags & FUSE_WRITEBACK_CACHE) 9004d99ff8fSPavel Emelyanov fc->writeback_cache = 1; 901e27c9d38SMiklos Szeredi if (arg->time_gran && arg->time_gran <= 1000000000) 902e27c9d38SMiklos Szeredi fc->sb->s_time_gran = arg->time_gran; 90371421259SMiklos Szeredi } else { 90409cbfeafSKirill A. Shutemov ra_pages = fc->max_read / PAGE_SIZE; 90571421259SMiklos Szeredi fc->no_lock = 1; 90637fb3a30SMiklos Szeredi fc->no_flock = 1; 90771421259SMiklos Szeredi } 9089cd68455SMiklos Szeredi 9099cd68455SMiklos Szeredi fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); 9109b9a0469SMiklos Szeredi fc->minor = arg->minor; 9119b9a0469SMiklos Szeredi fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 912f948d564SMiklos Szeredi fc->max_write = max_t(unsigned, 4096, fc->max_write); 9130ec7ca41SMiklos Szeredi fc->conn_init = 1; 9149b9a0469SMiklos Szeredi } 9159759bd51SMiklos Szeredi fuse_set_initialized(fc); 91608a53cdcSMiklos Szeredi wake_up_all(&fc->blocked_waitq); 9179b9a0469SMiklos Szeredi } 9189b9a0469SMiklos Szeredi 919ce1d5a49SMiklos Szeredi static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) 9209b9a0469SMiklos Szeredi { 9219b9a0469SMiklos Szeredi struct fuse_init_in *arg = &req->misc.init_in; 922095da6cbSMiklos Szeredi 9239b9a0469SMiklos Szeredi arg->major = FUSE_KERNEL_VERSION; 9249b9a0469SMiklos Szeredi arg->minor = FUSE_KERNEL_MINOR_VERSION; 92509cbfeafSKirill A. Shutemov arg->max_readahead = fc->bdi.ra_pages * PAGE_SIZE; 92678bb6cb9SMiklos Szeredi arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | 92737fb3a30SMiklos Szeredi FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | 92869fe05c9SMiklos Szeredi FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | 9290b05b183SAnand V. Avati FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | 9304d99ff8fSPavel Emelyanov FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | 931d7afaec0SAndrew Gallagher FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT; 9329b9a0469SMiklos Szeredi req->in.h.opcode = FUSE_INIT; 9339b9a0469SMiklos Szeredi req->in.numargs = 1; 9349b9a0469SMiklos Szeredi req->in.args[0].size = sizeof(*arg); 9359b9a0469SMiklos Szeredi req->in.args[0].value = arg; 9369b9a0469SMiklos Szeredi req->out.numargs = 1; 9373ad2f3fbSDaniel Mack /* Variable length argument used for backward compatibility 9389b9a0469SMiklos Szeredi with interface version < 7.5. Rest of init_out is zeroed 9399b9a0469SMiklos Szeredi by do_get_request(), so a short reply is not a problem */ 9409b9a0469SMiklos Szeredi req->out.argvar = 1; 9419b9a0469SMiklos Szeredi req->out.args[0].size = sizeof(struct fuse_init_out); 9429b9a0469SMiklos Szeredi req->out.args[0].value = &req->misc.init_out; 9439b9a0469SMiklos Szeredi req->end = process_init_reply; 944b93f858aSTejun Heo fuse_request_send_background(fc, req); 9459b9a0469SMiklos Szeredi } 9469b9a0469SMiklos Szeredi 94743901aabSTejun Heo static void fuse_free_conn(struct fuse_conn *fc) 94843901aabSTejun Heo { 949cc080e9eSMiklos Szeredi WARN_ON(!list_empty(&fc->devices)); 950dd3e2c55SAl Viro kfree_rcu(fc, rcu); 95143901aabSTejun Heo } 95243901aabSTejun Heo 953a325f9b9STejun Heo static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) 954a325f9b9STejun Heo { 955a325f9b9STejun Heo int err; 956a325f9b9STejun Heo 957d993831fSJens Axboe fc->bdi.name = "fuse"; 95809cbfeafSKirill A. Shutemov fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_SIZE; 959a325f9b9STejun Heo /* fuse does it's own writeback accounting */ 9605a537485SMaxim Patlasov fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB | BDI_CAP_STRICTLIMIT; 961a325f9b9STejun Heo 962a325f9b9STejun Heo err = bdi_init(&fc->bdi); 963a325f9b9STejun Heo if (err) 964a325f9b9STejun Heo return err; 965a325f9b9STejun Heo 966a325f9b9STejun Heo fc->bdi_initialized = 1; 967a325f9b9STejun Heo 968a325f9b9STejun Heo if (sb->s_bdev) { 969a325f9b9STejun Heo err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", 970a325f9b9STejun Heo MAJOR(fc->dev), MINOR(fc->dev)); 971a325f9b9STejun Heo } else { 972a325f9b9STejun Heo err = bdi_register_dev(&fc->bdi, fc->dev); 973a325f9b9STejun Heo } 974a325f9b9STejun Heo 975a325f9b9STejun Heo if (err) 976a325f9b9STejun Heo return err; 977a325f9b9STejun Heo 978a325f9b9STejun Heo /* 979a325f9b9STejun Heo * For a single fuse filesystem use max 1% of dirty + 980a325f9b9STejun Heo * writeback threshold. 981a325f9b9STejun Heo * 982a325f9b9STejun Heo * This gives about 1M of write buffer for memory maps on a 983a325f9b9STejun Heo * machine with 1G and 10% dirty_ratio, which should be more 984a325f9b9STejun Heo * than enough. 985a325f9b9STejun Heo * 986a325f9b9STejun Heo * Privileged users can raise it by writing to 987a325f9b9STejun Heo * 988a325f9b9STejun Heo * /sys/class/bdi/<bdi>/max_ratio 989a325f9b9STejun Heo */ 990a325f9b9STejun Heo bdi_set_max_ratio(&fc->bdi, 1); 991a325f9b9STejun Heo 992a325f9b9STejun Heo return 0; 993a325f9b9STejun Heo } 994a325f9b9STejun Heo 995cc080e9eSMiklos Szeredi struct fuse_dev *fuse_dev_alloc(struct fuse_conn *fc) 996cc080e9eSMiklos Szeredi { 997cc080e9eSMiklos Szeredi struct fuse_dev *fud; 998cc080e9eSMiklos Szeredi 999cc080e9eSMiklos Szeredi fud = kzalloc(sizeof(struct fuse_dev), GFP_KERNEL); 1000cc080e9eSMiklos Szeredi if (fud) { 1001cc080e9eSMiklos Szeredi fud->fc = fuse_conn_get(fc); 1002c3696046SMiklos Szeredi fuse_pqueue_init(&fud->pq); 1003cc080e9eSMiklos Szeredi 1004cc080e9eSMiklos Szeredi spin_lock(&fc->lock); 1005cc080e9eSMiklos Szeredi list_add_tail(&fud->entry, &fc->devices); 1006cc080e9eSMiklos Szeredi spin_unlock(&fc->lock); 1007cc080e9eSMiklos Szeredi } 1008cc080e9eSMiklos Szeredi 1009cc080e9eSMiklos Szeredi return fud; 1010cc080e9eSMiklos Szeredi } 1011cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_alloc); 1012cc080e9eSMiklos Szeredi 1013cc080e9eSMiklos Szeredi void fuse_dev_free(struct fuse_dev *fud) 1014cc080e9eSMiklos Szeredi { 1015cc080e9eSMiklos Szeredi struct fuse_conn *fc = fud->fc; 1016cc080e9eSMiklos Szeredi 1017cc080e9eSMiklos Szeredi if (fc) { 1018cc080e9eSMiklos Szeredi spin_lock(&fc->lock); 1019cc080e9eSMiklos Szeredi list_del(&fud->entry); 1020cc080e9eSMiklos Szeredi spin_unlock(&fc->lock); 1021cc080e9eSMiklos Szeredi 1022cc080e9eSMiklos Szeredi fuse_conn_put(fc); 1023cc080e9eSMiklos Szeredi } 1024cc080e9eSMiklos Szeredi kfree(fud); 1025cc080e9eSMiklos Szeredi } 1026cc080e9eSMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_dev_free); 1027cc080e9eSMiklos Szeredi 1028d8a5ba45SMiklos Szeredi static int fuse_fill_super(struct super_block *sb, void *data, int silent) 1029d8a5ba45SMiklos Szeredi { 1030cc080e9eSMiklos Szeredi struct fuse_dev *fud; 1031d8a5ba45SMiklos Szeredi struct fuse_conn *fc; 1032d8a5ba45SMiklos Szeredi struct inode *root; 1033d8a5ba45SMiklos Szeredi struct fuse_mount_data d; 1034d8a5ba45SMiklos Szeredi struct file *file; 1035f543f253SMiklos Szeredi struct dentry *root_dentry; 1036ce1d5a49SMiklos Szeredi struct fuse_req *init_req; 1037d8a5ba45SMiklos Szeredi int err; 1038d8091614SMiklos Szeredi int is_bdev = sb->s_bdev != NULL; 1039d8a5ba45SMiklos Szeredi 1040c2b8f006SMiklos Szeredi err = -EINVAL; 104171421259SMiklos Szeredi if (sb->s_flags & MS_MANDLOCK) 1042c2b8f006SMiklos Szeredi goto err; 104371421259SMiklos Szeredi 10444ace1f85SMiklos Szeredi sb->s_flags &= ~(MS_NOSEC | MS_I_VERSION); 10459e1f1de0SAl Viro 10467b3d8bf7SHimangi Saraogi if (!parse_fuse_opt(data, &d, is_bdev)) 1047c2b8f006SMiklos Szeredi goto err; 1048d8a5ba45SMiklos Szeredi 1049d8091614SMiklos Szeredi if (is_bdev) { 1050875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 1051c2b8f006SMiklos Szeredi err = -EINVAL; 1052d8091614SMiklos Szeredi if (!sb_set_blocksize(sb, d.blksize)) 1053c2b8f006SMiklos Szeredi goto err; 1054875d95ecSMiklos Szeredi #endif 1055d8091614SMiklos Szeredi } else { 105609cbfeafSKirill A. Shutemov sb->s_blocksize = PAGE_SIZE; 105709cbfeafSKirill A. Shutemov sb->s_blocksize_bits = PAGE_SHIFT; 1058d8091614SMiklos Szeredi } 1059d8a5ba45SMiklos Szeredi sb->s_magic = FUSE_SUPER_MAGIC; 1060d8a5ba45SMiklos Szeredi sb->s_op = &fuse_super_operations; 1061d8a5ba45SMiklos Szeredi sb->s_maxbytes = MAX_LFS_FILESIZE; 10620a2da9b2SMiklos Szeredi sb->s_time_gran = 1; 1063dbd561d2SMiklos Szeredi sb->s_export_op = &fuse_export_operations; 1064d8a5ba45SMiklos Szeredi 1065d8a5ba45SMiklos Szeredi file = fget(d.fd); 1066c2b8f006SMiklos Szeredi err = -EINVAL; 1067d8a5ba45SMiklos Szeredi if (!file) 1068c2b8f006SMiklos Szeredi goto err; 1069d8a5ba45SMiklos Szeredi 1070499dcf20SEric W. Biederman if ((file->f_op != &fuse_dev_operations) || 1071499dcf20SEric W. Biederman (file->f_cred->user_ns != &init_user_ns)) 1072c2b8f006SMiklos Szeredi goto err_fput; 10730720b315SMiklos Szeredi 10740d179aa5STejun Heo fc = kmalloc(sizeof(*fc), GFP_KERNEL); 1075c2b8f006SMiklos Szeredi err = -ENOMEM; 1076c2b8f006SMiklos Szeredi if (!fc) 1077c2b8f006SMiklos Szeredi goto err_fput; 1078d8a5ba45SMiklos Szeredi 1079a325f9b9STejun Heo fuse_conn_init(fc); 10800ad0b325SMiklos Szeredi fc->release = fuse_free_conn; 1081a325f9b9STejun Heo 1082cc080e9eSMiklos Szeredi fud = fuse_dev_alloc(fc); 1083cc080e9eSMiklos Szeredi if (!fud) 1084cc080e9eSMiklos Szeredi goto err_put_conn; 1085cc080e9eSMiklos Szeredi 1086a325f9b9STejun Heo fc->dev = sb->s_dev; 10873b463ae0SJohn Muir fc->sb = sb; 1088a325f9b9STejun Heo err = fuse_bdi_init(fc, sb); 1089a325f9b9STejun Heo if (err) 1090cc080e9eSMiklos Szeredi goto err_dev_free; 10910d179aa5STejun Heo 109232a88aa1SJens Axboe sb->s_bdi = &fc->bdi; 109332a88aa1SJens Axboe 1094e0a43ddcSMiklos Szeredi /* Handle umasking inside the fuse code */ 1095e0a43ddcSMiklos Szeredi if (sb->s_flags & MS_POSIXACL) 1096e0a43ddcSMiklos Szeredi fc->dont_mask = 1; 1097e0a43ddcSMiklos Szeredi sb->s_flags |= MS_POSIXACL; 1098e0a43ddcSMiklos Szeredi 10991e9a4ed9SMiklos Szeredi fc->flags = d.flags; 1100d8a5ba45SMiklos Szeredi fc->user_id = d.user_id; 110187729a55SMiklos Szeredi fc->group_id = d.group_id; 1102f948d564SMiklos Szeredi fc->max_read = max_t(unsigned, 4096, d.max_read); 1103d8a5ba45SMiklos Szeredi 1104f543f253SMiklos Szeredi /* Used by get_root_inode() */ 1105f543f253SMiklos Szeredi sb->s_fs_info = fc; 1106f543f253SMiklos Szeredi 1107d8a5ba45SMiklos Szeredi err = -ENOMEM; 1108b93f858aSTejun Heo root = fuse_get_root_inode(sb, d.rootmode); 110948fde701SAl Viro root_dentry = d_make_root(root); 111048fde701SAl Viro if (!root_dentry) 1111cc080e9eSMiklos Szeredi goto err_dev_free; 1112c35eebe9SAl Viro /* only now - we want root dentry with NULL ->d_op */ 1113c35eebe9SAl Viro sb->s_d_op = &fuse_dentry_operations; 1114f543f253SMiklos Szeredi 11154250c066SMaxim Patlasov init_req = fuse_request_alloc(0); 1116ce1d5a49SMiklos Szeredi if (!init_req) 1117ce1d5a49SMiklos Szeredi goto err_put_root; 1118825d6d33SMiklos Szeredi __set_bit(FR_BACKGROUND, &init_req->flags); 1119ce1d5a49SMiklos Szeredi 11200ec7ca41SMiklos Szeredi if (is_bdev) { 11214250c066SMaxim Patlasov fc->destroy_req = fuse_request_alloc(0); 11220ec7ca41SMiklos Szeredi if (!fc->destroy_req) 112317e18ab6SJulia Lawall goto err_free_init_req; 11240ec7ca41SMiklos Szeredi } 11250ec7ca41SMiklos Szeredi 1126bafa9654SMiklos Szeredi mutex_lock(&fuse_mutex); 11278aa09a50SMiklos Szeredi err = -EINVAL; 11288aa09a50SMiklos Szeredi if (file->private_data) 1129bafa9654SMiklos Szeredi goto err_unlock; 11308aa09a50SMiklos Szeredi 1131bafa9654SMiklos Szeredi err = fuse_ctl_add_conn(fc); 1132bafa9654SMiklos Szeredi if (err) 1133bafa9654SMiklos Szeredi goto err_unlock; 1134bafa9654SMiklos Szeredi 1135bafa9654SMiklos Szeredi list_add_tail(&fc->entry, &fuse_conn_list); 1136f543f253SMiklos Szeredi sb->s_root = root_dentry; 1137cc080e9eSMiklos Szeredi file->private_data = fud; 1138bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 11390720b315SMiklos Szeredi /* 11400720b315SMiklos Szeredi * atomic_dec_and_test() in fput() provides the necessary 11410720b315SMiklos Szeredi * memory barrier for file->private_data to be visible on all 11420720b315SMiklos Szeredi * CPUs after this 11430720b315SMiklos Szeredi */ 11440720b315SMiklos Szeredi fput(file); 1145f543f253SMiklos Szeredi 1146ce1d5a49SMiklos Szeredi fuse_send_init(fc, init_req); 1147f543f253SMiklos Szeredi 1148d8a5ba45SMiklos Szeredi return 0; 1149d8a5ba45SMiklos Szeredi 1150bafa9654SMiklos Szeredi err_unlock: 1151bafa9654SMiklos Szeredi mutex_unlock(&fuse_mutex); 115217e18ab6SJulia Lawall err_free_init_req: 1153ce1d5a49SMiklos Szeredi fuse_request_free(init_req); 1154f543f253SMiklos Szeredi err_put_root: 1155f543f253SMiklos Szeredi dput(root_dentry); 1156cc080e9eSMiklos Szeredi err_dev_free: 1157cc080e9eSMiklos Szeredi fuse_dev_free(fud); 1158c2b8f006SMiklos Szeredi err_put_conn: 1159a325f9b9STejun Heo fuse_bdi_destroy(fc); 1160bafa9654SMiklos Szeredi fuse_conn_put(fc); 1161c2b8f006SMiklos Szeredi err_fput: 1162c2b8f006SMiklos Szeredi fput(file); 1163c2b8f006SMiklos Szeredi err: 1164d8a5ba45SMiklos Szeredi return err; 1165d8a5ba45SMiklos Szeredi } 1166d8a5ba45SMiklos Szeredi 11673c26ff6eSAl Viro static struct dentry *fuse_mount(struct file_system_type *fs_type, 1168d8a5ba45SMiklos Szeredi int flags, const char *dev_name, 11693c26ff6eSAl Viro void *raw_data) 1170d8a5ba45SMiklos Szeredi { 11713c26ff6eSAl Viro return mount_nodev(fs_type, flags, raw_data, fuse_fill_super); 1172d8a5ba45SMiklos Szeredi } 1173d8a5ba45SMiklos Szeredi 11743b463ae0SJohn Muir static void fuse_kill_sb_anon(struct super_block *sb) 11753b463ae0SJohn Muir { 11763b463ae0SJohn Muir struct fuse_conn *fc = get_fuse_conn_super(sb); 11773b463ae0SJohn Muir 11783b463ae0SJohn Muir if (fc) { 11793b463ae0SJohn Muir down_write(&fc->killsb); 11803b463ae0SJohn Muir fc->sb = NULL; 11813b463ae0SJohn Muir up_write(&fc->killsb); 11823b463ae0SJohn Muir } 11833b463ae0SJohn Muir 11843b463ae0SJohn Muir kill_anon_super(sb); 11853b463ae0SJohn Muir } 11863b463ae0SJohn Muir 1187875d95ecSMiklos Szeredi static struct file_system_type fuse_fs_type = { 1188875d95ecSMiklos Szeredi .owner = THIS_MODULE, 1189875d95ecSMiklos Szeredi .name = "fuse", 119079c0b2dfSMiklos Szeredi .fs_flags = FS_HAS_SUBTYPE, 11913c26ff6eSAl Viro .mount = fuse_mount, 11923b463ae0SJohn Muir .kill_sb = fuse_kill_sb_anon, 1193875d95ecSMiklos Szeredi }; 11947f78e035SEric W. Biederman MODULE_ALIAS_FS("fuse"); 1195875d95ecSMiklos Szeredi 1196875d95ecSMiklos Szeredi #ifdef CONFIG_BLOCK 1197152a0836SAl Viro static struct dentry *fuse_mount_blk(struct file_system_type *fs_type, 1198d6392f87SMiklos Szeredi int flags, const char *dev_name, 1199152a0836SAl Viro void *raw_data) 1200d6392f87SMiklos Szeredi { 1201152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, raw_data, fuse_fill_super); 1202d6392f87SMiklos Szeredi } 1203d6392f87SMiklos Szeredi 12043b463ae0SJohn Muir static void fuse_kill_sb_blk(struct super_block *sb) 12053b463ae0SJohn Muir { 12063b463ae0SJohn Muir struct fuse_conn *fc = get_fuse_conn_super(sb); 12073b463ae0SJohn Muir 12083b463ae0SJohn Muir if (fc) { 12093b463ae0SJohn Muir down_write(&fc->killsb); 12103b463ae0SJohn Muir fc->sb = NULL; 12113b463ae0SJohn Muir up_write(&fc->killsb); 12123b463ae0SJohn Muir } 12133b463ae0SJohn Muir 12143b463ae0SJohn Muir kill_block_super(sb); 12153b463ae0SJohn Muir } 12163b463ae0SJohn Muir 1217d6392f87SMiklos Szeredi static struct file_system_type fuseblk_fs_type = { 1218d6392f87SMiklos Szeredi .owner = THIS_MODULE, 1219d6392f87SMiklos Szeredi .name = "fuseblk", 1220152a0836SAl Viro .mount = fuse_mount_blk, 12213b463ae0SJohn Muir .kill_sb = fuse_kill_sb_blk, 1222edad01e2SAlexey Dobriyan .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, 1223d6392f87SMiklos Szeredi }; 12247f78e035SEric W. Biederman MODULE_ALIAS_FS("fuseblk"); 1225d6392f87SMiklos Szeredi 1226875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1227875d95ecSMiklos Szeredi { 1228875d95ecSMiklos Szeredi return register_filesystem(&fuseblk_fs_type); 1229875d95ecSMiklos Szeredi } 1230875d95ecSMiklos Szeredi 1231875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1232875d95ecSMiklos Szeredi { 1233875d95ecSMiklos Szeredi unregister_filesystem(&fuseblk_fs_type); 1234875d95ecSMiklos Szeredi } 1235875d95ecSMiklos Szeredi #else 1236875d95ecSMiklos Szeredi static inline int register_fuseblk(void) 1237875d95ecSMiklos Szeredi { 1238875d95ecSMiklos Szeredi return 0; 1239875d95ecSMiklos Szeredi } 1240875d95ecSMiklos Szeredi 1241875d95ecSMiklos Szeredi static inline void unregister_fuseblk(void) 1242875d95ecSMiklos Szeredi { 1243875d95ecSMiklos Szeredi } 1244875d95ecSMiklos Szeredi #endif 1245875d95ecSMiklos Szeredi 124651cc5068SAlexey Dobriyan static void fuse_inode_init_once(void *foo) 1247d8a5ba45SMiklos Szeredi { 1248d8a5ba45SMiklos Szeredi struct inode *inode = foo; 1249d8a5ba45SMiklos Szeredi 1250d8a5ba45SMiklos Szeredi inode_init_once(inode); 1251d8a5ba45SMiklos Szeredi } 1252d8a5ba45SMiklos Szeredi 1253d8a5ba45SMiklos Szeredi static int __init fuse_fs_init(void) 1254d8a5ba45SMiklos Szeredi { 1255d8a5ba45SMiklos Szeredi int err; 1256d8a5ba45SMiklos Szeredi 1257d8a5ba45SMiklos Szeredi fuse_inode_cachep = kmem_cache_create("fuse_inode", 12585d097056SVladimir Davydov sizeof(struct fuse_inode), 0, 12595d097056SVladimir Davydov SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT, 126020c2df83SPaul Mundt fuse_inode_init_once); 1261d8a5ba45SMiklos Szeredi err = -ENOMEM; 1262d6392f87SMiklos Szeredi if (!fuse_inode_cachep) 1263988f0325SAl Viro goto out; 1264988f0325SAl Viro 1265988f0325SAl Viro err = register_fuseblk(); 1266988f0325SAl Viro if (err) 1267988f0325SAl Viro goto out2; 1268988f0325SAl Viro 1269988f0325SAl Viro err = register_filesystem(&fuse_fs_type); 1270988f0325SAl Viro if (err) 1271988f0325SAl Viro goto out3; 1272d8a5ba45SMiklos Szeredi 1273d6392f87SMiklos Szeredi return 0; 1274d6392f87SMiklos Szeredi 1275988f0325SAl Viro out3: 1276875d95ecSMiklos Szeredi unregister_fuseblk(); 1277988f0325SAl Viro out2: 1278988f0325SAl Viro kmem_cache_destroy(fuse_inode_cachep); 1279d6392f87SMiklos Szeredi out: 1280d8a5ba45SMiklos Szeredi return err; 1281d8a5ba45SMiklos Szeredi } 1282d8a5ba45SMiklos Szeredi 1283d8a5ba45SMiklos Szeredi static void fuse_fs_cleanup(void) 1284d8a5ba45SMiklos Szeredi { 1285d8a5ba45SMiklos Szeredi unregister_filesystem(&fuse_fs_type); 1286875d95ecSMiklos Szeredi unregister_fuseblk(); 12878c0a8537SKirill A. Shutemov 12888c0a8537SKirill A. Shutemov /* 12898c0a8537SKirill A. Shutemov * Make sure all delayed rcu free inodes are flushed before we 12908c0a8537SKirill A. Shutemov * destroy cache. 12918c0a8537SKirill A. Shutemov */ 12928c0a8537SKirill A. Shutemov rcu_barrier(); 1293d8a5ba45SMiklos Szeredi kmem_cache_destroy(fuse_inode_cachep); 1294d8a5ba45SMiklos Szeredi } 1295d8a5ba45SMiklos Szeredi 12965c89e17eSGreg Kroah-Hartman static struct kobject *fuse_kobj; 12975c89e17eSGreg Kroah-Hartman 1298f543f253SMiklos Szeredi static int fuse_sysfs_init(void) 1299f543f253SMiklos Szeredi { 1300f543f253SMiklos Szeredi int err; 1301f543f253SMiklos Szeredi 130200d26666SGreg Kroah-Hartman fuse_kobj = kobject_create_and_add("fuse", fs_kobj); 13035c89e17eSGreg Kroah-Hartman if (!fuse_kobj) { 13045c89e17eSGreg Kroah-Hartman err = -ENOMEM; 1305f543f253SMiklos Szeredi goto out_err; 13065c89e17eSGreg Kroah-Hartman } 1307f543f253SMiklos Szeredi 1308f9bb4882SEric W. Biederman err = sysfs_create_mount_point(fuse_kobj, "connections"); 1309f9bb4882SEric W. Biederman if (err) 1310f543f253SMiklos Szeredi goto out_fuse_unregister; 1311f543f253SMiklos Szeredi 1312f543f253SMiklos Szeredi return 0; 1313f543f253SMiklos Szeredi 1314f543f253SMiklos Szeredi out_fuse_unregister: 1315197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1316f543f253SMiklos Szeredi out_err: 1317f543f253SMiklos Szeredi return err; 1318f543f253SMiklos Szeredi } 1319f543f253SMiklos Szeredi 1320f543f253SMiklos Szeredi static void fuse_sysfs_cleanup(void) 1321f543f253SMiklos Szeredi { 1322f9bb4882SEric W. Biederman sysfs_remove_mount_point(fuse_kobj, "connections"); 1323197b12d6SGreg Kroah-Hartman kobject_put(fuse_kobj); 1324f543f253SMiklos Szeredi } 1325f543f253SMiklos Szeredi 1326d8a5ba45SMiklos Szeredi static int __init fuse_init(void) 1327d8a5ba45SMiklos Szeredi { 1328d8a5ba45SMiklos Szeredi int res; 1329d8a5ba45SMiklos Szeredi 13301729a16cSMiklos Szeredi printk(KERN_INFO "fuse init (API version %i.%i)\n", 1331d8a5ba45SMiklos Szeredi FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); 1332d8a5ba45SMiklos Szeredi 1333bafa9654SMiklos Szeredi INIT_LIST_HEAD(&fuse_conn_list); 1334d8a5ba45SMiklos Szeredi res = fuse_fs_init(); 1335d8a5ba45SMiklos Szeredi if (res) 1336d8a5ba45SMiklos Szeredi goto err; 1337d8a5ba45SMiklos Szeredi 1338334f485dSMiklos Szeredi res = fuse_dev_init(); 1339334f485dSMiklos Szeredi if (res) 1340334f485dSMiklos Szeredi goto err_fs_cleanup; 1341334f485dSMiklos Szeredi 1342f543f253SMiklos Szeredi res = fuse_sysfs_init(); 1343f543f253SMiklos Szeredi if (res) 1344f543f253SMiklos Szeredi goto err_dev_cleanup; 1345f543f253SMiklos Szeredi 1346bafa9654SMiklos Szeredi res = fuse_ctl_init(); 1347bafa9654SMiklos Szeredi if (res) 1348bafa9654SMiklos Szeredi goto err_sysfs_cleanup; 1349bafa9654SMiklos Szeredi 1350487ea5afSCsaba Henk sanitize_global_limit(&max_user_bgreq); 1351487ea5afSCsaba Henk sanitize_global_limit(&max_user_congthresh); 1352487ea5afSCsaba Henk 1353d8a5ba45SMiklos Szeredi return 0; 1354d8a5ba45SMiklos Szeredi 1355bafa9654SMiklos Szeredi err_sysfs_cleanup: 1356bafa9654SMiklos Szeredi fuse_sysfs_cleanup(); 1357f543f253SMiklos Szeredi err_dev_cleanup: 1358f543f253SMiklos Szeredi fuse_dev_cleanup(); 1359334f485dSMiklos Szeredi err_fs_cleanup: 1360334f485dSMiklos Szeredi fuse_fs_cleanup(); 1361d8a5ba45SMiklos Szeredi err: 1362d8a5ba45SMiklos Szeredi return res; 1363d8a5ba45SMiklos Szeredi } 1364d8a5ba45SMiklos Szeredi 1365d8a5ba45SMiklos Szeredi static void __exit fuse_exit(void) 1366d8a5ba45SMiklos Szeredi { 1367d8a5ba45SMiklos Szeredi printk(KERN_DEBUG "fuse exit\n"); 1368d8a5ba45SMiklos Szeredi 1369bafa9654SMiklos Szeredi fuse_ctl_cleanup(); 1370f543f253SMiklos Szeredi fuse_sysfs_cleanup(); 1371d8a5ba45SMiklos Szeredi fuse_fs_cleanup(); 1372334f485dSMiklos Szeredi fuse_dev_cleanup(); 1373d8a5ba45SMiklos Szeredi } 1374d8a5ba45SMiklos Szeredi 1375d8a5ba45SMiklos Szeredi module_init(fuse_init); 1376d8a5ba45SMiklos Szeredi module_exit(fuse_exit); 1377