1e5e5558eSMiklos Szeredi /* 2e5e5558eSMiklos Szeredi FUSE: Filesystem in Userspace 31729a16cSMiklos Szeredi Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> 4e5e5558eSMiklos Szeredi 5e5e5558eSMiklos Szeredi This program can be distributed under the terms of the GNU GPL. 6e5e5558eSMiklos Szeredi See the file COPYING. 7e5e5558eSMiklos Szeredi */ 8e5e5558eSMiklos Szeredi 9e5e5558eSMiklos Szeredi #include "fuse_i.h" 10e5e5558eSMiklos Szeredi 11e5e5558eSMiklos Szeredi #include <linux/pagemap.h> 12e5e5558eSMiklos Szeredi #include <linux/file.h> 13bf109c64SMax Reitz #include <linux/fs_context.h> 14e5e5558eSMiklos Szeredi #include <linux/sched.h> 15e5e5558eSMiklos Szeredi #include <linux/namei.h> 1607e77dcaSMiklos Szeredi #include <linux/slab.h> 17703c7362SSeth Forshee #include <linux/xattr.h> 18261aaba7SMiklos Szeredi #include <linux/iversion.h> 1960bcc88aSSeth Forshee #include <linux/posix_acl.h> 20e5e5558eSMiklos Szeredi 214582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir) 224582a4abSFeng Shuo { 234582a4abSFeng Shuo struct fuse_inode *fi = get_fuse_inode(dir); 244582a4abSFeng Shuo 254582a4abSFeng Shuo set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state); 264582a4abSFeng Shuo } 274582a4abSFeng Shuo 2830c6a23dSKhazhismel Kumykov #if BITS_PER_LONG >= 64 2930c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *entry, u64 time) 3030c6a23dSKhazhismel Kumykov { 3130c6a23dSKhazhismel Kumykov entry->d_fsdata = (void *) time; 3230c6a23dSKhazhismel Kumykov } 3330c6a23dSKhazhismel Kumykov 3430c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry) 3530c6a23dSKhazhismel Kumykov { 3630c6a23dSKhazhismel Kumykov return (u64)entry->d_fsdata; 3730c6a23dSKhazhismel Kumykov } 3830c6a23dSKhazhismel Kumykov 3930c6a23dSKhazhismel Kumykov #else 40f75fdf22SMiklos Szeredi union fuse_dentry { 41f75fdf22SMiklos Szeredi u64 time; 42f75fdf22SMiklos Szeredi struct rcu_head rcu; 43f75fdf22SMiklos Szeredi }; 44f75fdf22SMiklos Szeredi 4530c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time) 4630c6a23dSKhazhismel Kumykov { 4730c6a23dSKhazhismel Kumykov ((union fuse_dentry *) dentry->d_fsdata)->time = time; 4830c6a23dSKhazhismel Kumykov } 4930c6a23dSKhazhismel Kumykov 5030c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry) 5130c6a23dSKhazhismel Kumykov { 5230c6a23dSKhazhismel Kumykov return ((union fuse_dentry *) entry->d_fsdata)->time; 5330c6a23dSKhazhismel Kumykov } 5430c6a23dSKhazhismel Kumykov #endif 5530c6a23dSKhazhismel Kumykov 568fab0106SMiklos Szeredi static void fuse_dentry_settime(struct dentry *dentry, u64 time) 570a0898cfSMiklos Szeredi { 588fab0106SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb); 598fab0106SMiklos Szeredi bool delete = !time && fc->delete_stale; 608fab0106SMiklos Szeredi /* 618fab0106SMiklos Szeredi * Mess with DCACHE_OP_DELETE because dput() will be faster without it. 628fab0106SMiklos Szeredi * Don't care about races, either way it's just an optimization 638fab0106SMiklos Szeredi */ 648fab0106SMiklos Szeredi if ((!delete && (dentry->d_flags & DCACHE_OP_DELETE)) || 658fab0106SMiklos Szeredi (delete && !(dentry->d_flags & DCACHE_OP_DELETE))) { 668fab0106SMiklos Szeredi spin_lock(&dentry->d_lock); 678fab0106SMiklos Szeredi if (!delete) 688fab0106SMiklos Szeredi dentry->d_flags &= ~DCACHE_OP_DELETE; 698fab0106SMiklos Szeredi else 708fab0106SMiklos Szeredi dentry->d_flags |= DCACHE_OP_DELETE; 718fab0106SMiklos Szeredi spin_unlock(&dentry->d_lock); 720a0898cfSMiklos Szeredi } 730a0898cfSMiklos Szeredi 7430c6a23dSKhazhismel Kumykov __fuse_dentry_settime(dentry, time); 750a0898cfSMiklos Szeredi } 760a0898cfSMiklos Szeredi 776f9f1180SMiklos Szeredi /* 786f9f1180SMiklos Szeredi * FUSE caches dentries and attributes with separate timeout. The 796f9f1180SMiklos Szeredi * time in jiffies until the dentry/attributes are valid is stored in 80f75fdf22SMiklos Szeredi * dentry->d_fsdata and fuse_inode->i_time respectively. 816f9f1180SMiklos Szeredi */ 826f9f1180SMiklos Szeredi 836f9f1180SMiklos Szeredi /* 846f9f1180SMiklos Szeredi * Calculate the time in jiffies until a dentry/attributes are valid 856f9f1180SMiklos Szeredi */ 86bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec) 87e5e5558eSMiklos Szeredi { 88685d16ddSMiklos Szeredi if (sec || nsec) { 89bcb6f6d2SMiklos Szeredi struct timespec64 ts = { 90bcb6f6d2SMiklos Szeredi sec, 9121067527SDavid Sheets min_t(u32, nsec, NSEC_PER_SEC - 1) 92bcb6f6d2SMiklos Szeredi }; 93bcb6f6d2SMiklos Szeredi 94bcb6f6d2SMiklos Szeredi return get_jiffies_64() + timespec64_to_jiffies(&ts); 95685d16ddSMiklos Szeredi } else 960a0898cfSMiklos Szeredi return 0; 97e5e5558eSMiklos Szeredi } 98e5e5558eSMiklos Szeredi 996f9f1180SMiklos Szeredi /* 1006f9f1180SMiklos Szeredi * Set dentry and possibly attribute timeouts from the lookup/mk* 1016f9f1180SMiklos Szeredi * replies 1026f9f1180SMiklos Szeredi */ 103d123d8e1SMiklos Szeredi void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o) 1040aa7c699SMiklos Szeredi { 1050a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 1060a0898cfSMiklos Szeredi time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 1071fb69e78SMiklos Szeredi } 1081fb69e78SMiklos Szeredi 1091fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o) 1101fb69e78SMiklos Szeredi { 1111fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 1121fb69e78SMiklos Szeredi } 1131fb69e78SMiklos Szeredi 114d123d8e1SMiklos Szeredi u64 entry_attr_timeout(struct fuse_entry_out *o) 1151fb69e78SMiklos Szeredi { 1161fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 1178cbdf1e6SMiklos Szeredi } 1188cbdf1e6SMiklos Szeredi 1192f1e8196SMiklos Szeredi static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask) 1202f1e8196SMiklos Szeredi { 1212f1e8196SMiklos Szeredi set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask); 1222f1e8196SMiklos Szeredi } 1232f1e8196SMiklos Szeredi 1246f9f1180SMiklos Szeredi /* 1256f9f1180SMiklos Szeredi * Mark the attributes as stale, so that at the next call to 1266f9f1180SMiklos Szeredi * ->getattr() they will be fetched from userspace 1276f9f1180SMiklos Szeredi */ 1288cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode) 1298cbdf1e6SMiklos Szeredi { 1302f1e8196SMiklos Szeredi fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS); 1318cbdf1e6SMiklos Szeredi } 1328cbdf1e6SMiklos Szeredi 133261aaba7SMiklos Szeredi static void fuse_dir_changed(struct inode *dir) 134261aaba7SMiklos Szeredi { 135261aaba7SMiklos Szeredi fuse_invalidate_attr(dir); 136261aaba7SMiklos Szeredi inode_maybe_inc_iversion(dir, false); 137261aaba7SMiklos Szeredi } 138261aaba7SMiklos Szeredi 139451418fcSAndrew Gallagher /** 140451418fcSAndrew Gallagher * Mark the attributes as stale due to an atime change. Avoid the invalidate if 141451418fcSAndrew Gallagher * atime is not used. 142451418fcSAndrew Gallagher */ 143451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode) 144451418fcSAndrew Gallagher { 145451418fcSAndrew Gallagher if (!IS_RDONLY(inode)) 1462f1e8196SMiklos Szeredi fuse_invalidate_attr_mask(inode, STATX_ATIME); 147451418fcSAndrew Gallagher } 148451418fcSAndrew Gallagher 1496f9f1180SMiklos Szeredi /* 1506f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 1516f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 1526f9f1180SMiklos Szeredi * 1536f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 1546f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 1556f9f1180SMiklos Szeredi * lookup) 1566f9f1180SMiklos Szeredi */ 157dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry) 1588cbdf1e6SMiklos Szeredi { 1590a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 1608cbdf1e6SMiklos Szeredi } 1618cbdf1e6SMiklos Szeredi 1626f9f1180SMiklos Szeredi /* 1636f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 1646f9f1180SMiklos Szeredi * dentry from the hash 1656f9f1180SMiklos Szeredi */ 1668cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1678cbdf1e6SMiklos Szeredi { 1688cbdf1e6SMiklos Szeredi d_invalidate(entry); 1698cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1700aa7c699SMiklos Szeredi } 1710aa7c699SMiklos Szeredi 1727078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, 17313983d06SAl Viro u64 nodeid, const struct qstr *name, 174e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 175e5e5558eSMiklos Szeredi { 1760e9663eeSMiklos Szeredi memset(outarg, 0, sizeof(struct fuse_entry_out)); 177d5b48543SMiklos Szeredi args->opcode = FUSE_LOOKUP; 178d5b48543SMiklos Szeredi args->nodeid = nodeid; 179d5b48543SMiklos Szeredi args->in_numargs = 1; 180d5b48543SMiklos Szeredi args->in_args[0].size = name->len + 1; 181d5b48543SMiklos Szeredi args->in_args[0].value = name->name; 182d5b48543SMiklos Szeredi args->out_numargs = 1; 183d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(struct fuse_entry_out); 184d5b48543SMiklos Szeredi args->out_args[0].value = outarg; 185e5e5558eSMiklos Szeredi } 186e5e5558eSMiklos Szeredi 1876f9f1180SMiklos Szeredi /* 1886f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1896f9f1180SMiklos Szeredi * 1906f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 1916f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 1926f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 1936f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 1946f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 1956f9f1180SMiklos Szeredi */ 1960b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) 197e5e5558eSMiklos Szeredi { 19834286d66SNick Piggin struct inode *inode; 19928420dadSMiklos Szeredi struct dentry *parent; 200fcee216bSMax Reitz struct fuse_mount *fm; 2016314efeeSMiklos Szeredi struct fuse_inode *fi; 202e2a6b952SMiklos Szeredi int ret; 2038cbdf1e6SMiklos Szeredi 2042b0143b5SDavid Howells inode = d_inode_rcu(entry); 205*5d069dbeSMiklos Szeredi if (inode && fuse_is_bad(inode)) 206e2a6b952SMiklos Szeredi goto invalid; 207154210ccSAnand Avati else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || 208df8629afSMiklos Szeredi (flags & (LOOKUP_EXCL | LOOKUP_REVAL))) { 209e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 2107078187aSMiklos Szeredi FUSE_ARGS(args); 21107e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 2121fb69e78SMiklos Szeredi u64 attr_version; 2138cbdf1e6SMiklos Szeredi 21450322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 2158cbdf1e6SMiklos Szeredi if (!inode) 216e2a6b952SMiklos Szeredi goto invalid; 2178cbdf1e6SMiklos Szeredi 218e2a6b952SMiklos Szeredi ret = -ECHILD; 2190b728e19SAl Viro if (flags & LOOKUP_RCU) 220e2a6b952SMiklos Szeredi goto out; 221e7c0a167SMiklos Szeredi 222fcee216bSMax Reitz fm = get_fuse_mount(inode); 223e5e5558eSMiklos Szeredi 22407e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 225e2a6b952SMiklos Szeredi ret = -ENOMEM; 2267078187aSMiklos Szeredi if (!forget) 227e2a6b952SMiklos Szeredi goto out; 2282d51013eSMiklos Szeredi 229fcee216bSMax Reitz attr_version = fuse_get_attr_version(fm->fc); 2301fb69e78SMiklos Szeredi 231e956edd0SMiklos Szeredi parent = dget_parent(entry); 232fcee216bSMax Reitz fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)), 233c180eebeSMiklos Szeredi &entry->d_name, &outarg); 234fcee216bSMax Reitz ret = fuse_simple_request(fm, &args); 235e956edd0SMiklos Szeredi dput(parent); 23650322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 2377078187aSMiklos Szeredi if (!ret && !outarg.nodeid) 2387078187aSMiklos Szeredi ret = -ENOENT; 2397078187aSMiklos Szeredi if (!ret) { 2406314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 241bf109c64SMax Reitz if (outarg.nodeid != get_node_id(inode) || 242bf109c64SMax Reitz (bool) IS_AUTOMOUNT(inode) != (bool) (outarg.attr.flags & FUSE_ATTR_SUBMOUNT)) { 243fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, 244fcee216bSMax Reitz outarg.nodeid, 1); 245e2a6b952SMiklos Szeredi goto invalid; 2469e6268dbSMiklos Szeredi } 247c9d8f5f0SKirill Tkhai spin_lock(&fi->lock); 2489e6268dbSMiklos Szeredi fi->nlookup++; 249c9d8f5f0SKirill Tkhai spin_unlock(&fi->lock); 2509e6268dbSMiklos Szeredi } 25107e77dcaSMiklos Szeredi kfree(forget); 2527078187aSMiklos Szeredi if (ret == -ENOMEM) 2537078187aSMiklos Szeredi goto out; 254eb59bd17SMiklos Szeredi if (ret || fuse_invalid_attr(&outarg.attr) || 255eb59bd17SMiklos Szeredi (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 256e2a6b952SMiklos Szeredi goto invalid; 257e5e5558eSMiklos Szeredi 25860bcc88aSSeth Forshee forget_all_cached_acls(inode); 2591fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2601fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2611fb69e78SMiklos Szeredi attr_version); 2621fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 26328420dadSMiklos Szeredi } else if (inode) { 2646314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2656314efeeSMiklos Szeredi if (flags & LOOKUP_RCU) { 2666314efeeSMiklos Szeredi if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) 2676314efeeSMiklos Szeredi return -ECHILD; 2686314efeeSMiklos Szeredi } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { 26928420dadSMiklos Szeredi parent = dget_parent(entry); 2702b0143b5SDavid Howells fuse_advise_use_readdirplus(d_inode(parent)); 27128420dadSMiklos Szeredi dput(parent); 272e5e5558eSMiklos Szeredi } 27328420dadSMiklos Szeredi } 274e2a6b952SMiklos Szeredi ret = 1; 275e2a6b952SMiklos Szeredi out: 276e2a6b952SMiklos Szeredi return ret; 277e2a6b952SMiklos Szeredi 278e2a6b952SMiklos Szeredi invalid: 279e2a6b952SMiklos Szeredi ret = 0; 280e2a6b952SMiklos Szeredi goto out; 281e5e5558eSMiklos Szeredi } 282e5e5558eSMiklos Szeredi 28330c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 284f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry) 285f75fdf22SMiklos Szeredi { 286dc69e98cSKhazhismel Kumykov dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), 287dc69e98cSKhazhismel Kumykov GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE); 288f75fdf22SMiklos Szeredi 289f75fdf22SMiklos Szeredi return dentry->d_fsdata ? 0 : -ENOMEM; 290f75fdf22SMiklos Szeredi } 291f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry) 292f75fdf22SMiklos Szeredi { 293f75fdf22SMiklos Szeredi union fuse_dentry *fd = dentry->d_fsdata; 294f75fdf22SMiklos Szeredi 295f75fdf22SMiklos Szeredi kfree_rcu(fd, rcu); 296f75fdf22SMiklos Szeredi } 29730c6a23dSKhazhismel Kumykov #endif 298f75fdf22SMiklos Szeredi 2998fab0106SMiklos Szeredi static int fuse_dentry_delete(const struct dentry *dentry) 3008fab0106SMiklos Szeredi { 3018fab0106SMiklos Szeredi return time_before64(fuse_dentry_time(dentry), get_jiffies_64()); 3028fab0106SMiklos Szeredi } 3038fab0106SMiklos Szeredi 304bf109c64SMax Reitz /* 305bf109c64SMax Reitz * Create a fuse_mount object with a new superblock (with path->dentry 306bf109c64SMax Reitz * as the root), and return that mount so it can be auto-mounted on 307bf109c64SMax Reitz * @path. 308bf109c64SMax Reitz */ 309bf109c64SMax Reitz static struct vfsmount *fuse_dentry_automount(struct path *path) 310bf109c64SMax Reitz { 311bf109c64SMax Reitz struct fs_context *fsc; 312bf109c64SMax Reitz struct fuse_mount *parent_fm = get_fuse_mount_super(path->mnt->mnt_sb); 313bf109c64SMax Reitz struct fuse_conn *fc = parent_fm->fc; 314bf109c64SMax Reitz struct fuse_mount *fm; 315bf109c64SMax Reitz struct vfsmount *mnt; 316bf109c64SMax Reitz struct fuse_inode *mp_fi = get_fuse_inode(d_inode(path->dentry)); 317bf109c64SMax Reitz struct super_block *sb; 318bf109c64SMax Reitz int err; 319bf109c64SMax Reitz 320bf109c64SMax Reitz fsc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry); 321bf109c64SMax Reitz if (IS_ERR(fsc)) { 322bf109c64SMax Reitz err = PTR_ERR(fsc); 323bf109c64SMax Reitz goto out; 324bf109c64SMax Reitz } 325bf109c64SMax Reitz 326bf109c64SMax Reitz err = -ENOMEM; 327bf109c64SMax Reitz fm = kzalloc(sizeof(struct fuse_mount), GFP_KERNEL); 328bf109c64SMax Reitz if (!fm) 329bf109c64SMax Reitz goto out_put_fsc; 330bf109c64SMax Reitz 331bf109c64SMax Reitz fsc->s_fs_info = fm; 332bf109c64SMax Reitz sb = sget_fc(fsc, NULL, set_anon_super_fc); 333bf109c64SMax Reitz if (IS_ERR(sb)) { 334bf109c64SMax Reitz err = PTR_ERR(sb); 335514b5e3fSMiklos Szeredi kfree(fm); 336bf109c64SMax Reitz goto out_put_fsc; 337bf109c64SMax Reitz } 338bf109c64SMax Reitz fm->fc = fuse_conn_get(fc); 339bf109c64SMax Reitz 340bf109c64SMax Reitz /* Initialize superblock, making @mp_fi its root */ 341bf109c64SMax Reitz err = fuse_fill_super_submount(sb, mp_fi); 342bf109c64SMax Reitz if (err) 343bf109c64SMax Reitz goto out_put_sb; 344bf109c64SMax Reitz 345bf109c64SMax Reitz sb->s_flags |= SB_ACTIVE; 346bf109c64SMax Reitz fsc->root = dget(sb->s_root); 347bf109c64SMax Reitz /* We are done configuring the superblock, so unlock it */ 348bf109c64SMax Reitz up_write(&sb->s_umount); 349bf109c64SMax Reitz 350bf109c64SMax Reitz down_write(&fc->killsb); 351bf109c64SMax Reitz list_add_tail(&fm->fc_entry, &fc->mounts); 352bf109c64SMax Reitz up_write(&fc->killsb); 353bf109c64SMax Reitz 354bf109c64SMax Reitz /* Create the submount */ 355bf109c64SMax Reitz mnt = vfs_create_mount(fsc); 356bf109c64SMax Reitz if (IS_ERR(mnt)) { 357bf109c64SMax Reitz err = PTR_ERR(mnt); 358bf109c64SMax Reitz goto out_put_fsc; 359bf109c64SMax Reitz } 360bf109c64SMax Reitz mntget(mnt); 361bf109c64SMax Reitz put_fs_context(fsc); 362bf109c64SMax Reitz return mnt; 363bf109c64SMax Reitz 364bf109c64SMax Reitz out_put_sb: 365bf109c64SMax Reitz /* 366bf109c64SMax Reitz * Only jump here when fsc->root is NULL and sb is still locked 367bf109c64SMax Reitz * (otherwise put_fs_context() will put the superblock) 368bf109c64SMax Reitz */ 369bf109c64SMax Reitz deactivate_locked_super(sb); 370bf109c64SMax Reitz out_put_fsc: 371bf109c64SMax Reitz put_fs_context(fsc); 372bf109c64SMax Reitz out: 373bf109c64SMax Reitz return ERR_PTR(err); 374bf109c64SMax Reitz } 375bf109c64SMax Reitz 3764269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 377e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 3788fab0106SMiklos Szeredi .d_delete = fuse_dentry_delete, 37930c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 380f75fdf22SMiklos Szeredi .d_init = fuse_dentry_init, 381f75fdf22SMiklos Szeredi .d_release = fuse_dentry_release, 38230c6a23dSKhazhismel Kumykov #endif 383bf109c64SMax Reitz .d_automount = fuse_dentry_automount, 384e5e5558eSMiklos Szeredi }; 385e5e5558eSMiklos Szeredi 3860ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = { 38730c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 3880ce267ffSMiklos Szeredi .d_init = fuse_dentry_init, 3890ce267ffSMiklos Szeredi .d_release = fuse_dentry_release, 39030c6a23dSKhazhismel Kumykov #endif 3910ce267ffSMiklos Szeredi }; 3920ce267ffSMiklos Szeredi 393a5bfffacSTimo Savola int fuse_valid_type(int m) 39439ee059aSMiklos Szeredi { 39539ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 39639ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 39739ee059aSMiklos Szeredi } 39839ee059aSMiklos Szeredi 399eb59bd17SMiklos Szeredi bool fuse_invalid_attr(struct fuse_attr *attr) 400eb59bd17SMiklos Szeredi { 401eb59bd17SMiklos Szeredi return !fuse_valid_type(attr->mode) || 402eb59bd17SMiklos Szeredi attr->size > LLONG_MAX; 403eb59bd17SMiklos Szeredi } 404eb59bd17SMiklos Szeredi 40513983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, 406c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 407c180eebeSMiklos Szeredi { 408fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount_super(sb); 4097078187aSMiklos Szeredi FUSE_ARGS(args); 41007e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 411c180eebeSMiklos Szeredi u64 attr_version; 412c180eebeSMiklos Szeredi int err; 413c180eebeSMiklos Szeredi 414c180eebeSMiklos Szeredi *inode = NULL; 415c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 416c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 417c180eebeSMiklos Szeredi goto out; 418c180eebeSMiklos Szeredi 419c180eebeSMiklos Szeredi 42007e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 42107e77dcaSMiklos Szeredi err = -ENOMEM; 4227078187aSMiklos Szeredi if (!forget) 423c180eebeSMiklos Szeredi goto out; 424c180eebeSMiklos Szeredi 425fcee216bSMax Reitz attr_version = fuse_get_attr_version(fm->fc); 426c180eebeSMiklos Szeredi 427fcee216bSMax Reitz fuse_lookup_init(fm->fc, &args, nodeid, name, outarg); 428fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 429c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 430c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 431c180eebeSMiklos Szeredi goto out_put_forget; 432c180eebeSMiklos Szeredi 433c180eebeSMiklos Szeredi err = -EIO; 434c180eebeSMiklos Szeredi if (!outarg->nodeid) 435c180eebeSMiklos Szeredi goto out_put_forget; 436eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg->attr)) 437c180eebeSMiklos Szeredi goto out_put_forget; 438c180eebeSMiklos Szeredi 439c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 440c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 441c180eebeSMiklos Szeredi attr_version); 442c180eebeSMiklos Szeredi err = -ENOMEM; 443c180eebeSMiklos Szeredi if (!*inode) { 444fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1); 445c180eebeSMiklos Szeredi goto out; 446c180eebeSMiklos Szeredi } 447c180eebeSMiklos Szeredi err = 0; 448c180eebeSMiklos Szeredi 449c180eebeSMiklos Szeredi out_put_forget: 45007e77dcaSMiklos Szeredi kfree(forget); 451c180eebeSMiklos Szeredi out: 452c180eebeSMiklos Szeredi return err; 453c180eebeSMiklos Szeredi } 454c180eebeSMiklos Szeredi 4550aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 45600cd8dd3SAl Viro unsigned int flags) 457e5e5558eSMiklos Szeredi { 458e5e5558eSMiklos Szeredi int err; 459e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 460c180eebeSMiklos Szeredi struct inode *inode; 4610de6256dSMiklos Szeredi struct dentry *newent; 462c180eebeSMiklos Szeredi bool outarg_valid = true; 46363576c13SMiklos Szeredi bool locked; 464e5e5558eSMiklos Szeredi 465*5d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 466*5d069dbeSMiklos Szeredi return ERR_PTR(-EIO); 467*5d069dbeSMiklos Szeredi 46863576c13SMiklos Szeredi locked = fuse_lock_inode(dir); 469c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 470c180eebeSMiklos Szeredi &outarg, &inode); 47163576c13SMiklos Szeredi fuse_unlock_inode(dir, locked); 472c180eebeSMiklos Szeredi if (err == -ENOENT) { 473c180eebeSMiklos Szeredi outarg_valid = false; 474c180eebeSMiklos Szeredi err = 0; 4752d51013eSMiklos Szeredi } 476c180eebeSMiklos Szeredi if (err) 477c180eebeSMiklos Szeredi goto out_err; 4782d51013eSMiklos Szeredi 479ee4e5271SMiklos Szeredi err = -EIO; 480c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 481c180eebeSMiklos Szeredi goto out_iput; 482e5e5558eSMiklos Szeredi 48341d28bcaSAl Viro newent = d_splice_alias(inode, entry); 484c180eebeSMiklos Szeredi err = PTR_ERR(newent); 485c180eebeSMiklos Szeredi if (IS_ERR(newent)) 4865835f339SMiklos Szeredi goto out_err; 487d2a85164SMiklos Szeredi 4880de6256dSMiklos Szeredi entry = newent ? newent : entry; 489c180eebeSMiklos Szeredi if (outarg_valid) 4901fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 4918cbdf1e6SMiklos Szeredi else 4928cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 493c180eebeSMiklos Szeredi 4946c26f717SMiklos Szeredi if (inode) 4954582a4abSFeng Shuo fuse_advise_use_readdirplus(dir); 4960de6256dSMiklos Szeredi return newent; 497c180eebeSMiklos Szeredi 498c180eebeSMiklos Szeredi out_iput: 499c180eebeSMiklos Szeredi iput(inode); 500c180eebeSMiklos Szeredi out_err: 501c180eebeSMiklos Szeredi return ERR_PTR(err); 502e5e5558eSMiklos Szeredi } 503e5e5558eSMiklos Szeredi 5046f9f1180SMiklos Szeredi /* 5056f9f1180SMiklos Szeredi * Atomic create+open operation 5066f9f1180SMiklos Szeredi * 5076f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 5086f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 5096f9f1180SMiklos Szeredi */ 510d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 51130d90494SAl Viro struct file *file, unsigned flags, 512b452a458SAl Viro umode_t mode) 513fd72faacSMiklos Szeredi { 514fd72faacSMiklos Szeredi int err; 515fd72faacSMiklos Szeredi struct inode *inode; 516fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 5177078187aSMiklos Szeredi FUSE_ARGS(args); 51807e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 519e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 520fd72faacSMiklos Szeredi struct fuse_open_out outopen; 521fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 522ebf84d0cSKirill Tkhai struct fuse_inode *fi; 523fd72faacSMiklos Szeredi struct fuse_file *ff; 524fd72faacSMiklos Szeredi 525af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 526af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 527af109bcaSMiklos Szeredi 52807e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 529c8ccbe03SMiklos Szeredi err = -ENOMEM; 53007e77dcaSMiklos Szeredi if (!forget) 531c8ccbe03SMiklos Szeredi goto out_err; 53251eb01e7SMiklos Szeredi 533ce1d5a49SMiklos Szeredi err = -ENOMEM; 534fcee216bSMax Reitz ff = fuse_file_alloc(fm); 535fd72faacSMiklos Szeredi if (!ff) 5367078187aSMiklos Szeredi goto out_put_forget_req; 537fd72faacSMiklos Szeredi 538fcee216bSMax Reitz if (!fm->fc->dont_mask) 539e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 540e0a43ddcSMiklos Szeredi 541fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 542fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 5430e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 544fd72faacSMiklos Szeredi inarg.flags = flags; 545fd72faacSMiklos Szeredi inarg.mode = mode; 546e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 547643a666aSVivek Goyal 548643a666aSVivek Goyal if (fm->fc->handle_killpriv_v2 && (flags & O_TRUNC) && 549643a666aSVivek Goyal !(flags & O_EXCL) && !capable(CAP_FSETID)) { 550643a666aSVivek Goyal inarg.open_flags |= FUSE_OPEN_KILL_SUIDGID; 551643a666aSVivek Goyal } 552643a666aSVivek Goyal 553d5b48543SMiklos Szeredi args.opcode = FUSE_CREATE; 554d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 555d5b48543SMiklos Szeredi args.in_numargs = 2; 556d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 557d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 558d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 559d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 560d5b48543SMiklos Szeredi args.out_numargs = 2; 561d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outentry); 562d5b48543SMiklos Szeredi args.out_args[0].value = &outentry; 563d5b48543SMiklos Szeredi args.out_args[1].size = sizeof(outopen); 564d5b48543SMiklos Szeredi args.out_args[1].value = &outopen; 565fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 566c8ccbe03SMiklos Szeredi if (err) 567fd72faacSMiklos Szeredi goto out_free_ff; 568fd72faacSMiklos Szeredi 569fd72faacSMiklos Szeredi err = -EIO; 570eb59bd17SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) || 571eb59bd17SMiklos Szeredi fuse_invalid_attr(&outentry.attr)) 572fd72faacSMiklos Szeredi goto out_free_ff; 573fd72faacSMiklos Szeredi 574c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 575c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 576c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 577fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 5781fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 579fd72faacSMiklos Szeredi if (!inode) { 580fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 581ebf84d0cSKirill Tkhai fuse_sync_release(NULL, ff, flags); 582fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1); 583c8ccbe03SMiklos Szeredi err = -ENOMEM; 584c8ccbe03SMiklos Szeredi goto out_err; 585fd72faacSMiklos Szeredi } 58607e77dcaSMiklos Szeredi kfree(forget); 587fd72faacSMiklos Szeredi d_instantiate(entry, inode); 5881fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 589261aaba7SMiklos Szeredi fuse_dir_changed(dir); 590be12af3eSAl Viro err = finish_open(file, entry, generic_file_open); 59130d90494SAl Viro if (err) { 592ebf84d0cSKirill Tkhai fi = get_fuse_inode(inode); 593ebf84d0cSKirill Tkhai fuse_sync_release(fi, ff, flags); 594c8ccbe03SMiklos Szeredi } else { 595267d8444SMiklos Szeredi file->private_data = ff; 596c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 597c8ccbe03SMiklos Szeredi } 598d9585277SAl Viro return err; 599fd72faacSMiklos Szeredi 600fd72faacSMiklos Szeredi out_free_ff: 601fd72faacSMiklos Szeredi fuse_file_free(ff); 60251eb01e7SMiklos Szeredi out_put_forget_req: 60307e77dcaSMiklos Szeredi kfree(forget); 604c8ccbe03SMiklos Szeredi out_err: 605d9585277SAl Viro return err; 606c8ccbe03SMiklos Szeredi } 607c8ccbe03SMiklos Szeredi 608c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); 609d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 61030d90494SAl Viro struct file *file, unsigned flags, 61144907d79SAl Viro umode_t mode) 612c8ccbe03SMiklos Szeredi { 613c8ccbe03SMiklos Szeredi int err; 614c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 615c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 616c8ccbe03SMiklos Szeredi 617*5d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 618*5d069dbeSMiklos Szeredi return -EIO; 619*5d069dbeSMiklos Szeredi 62000699ad8SAl Viro if (d_in_lookup(entry)) { 62100cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 622c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 623d9585277SAl Viro return PTR_ERR(res); 624c8ccbe03SMiklos Szeredi 625c8ccbe03SMiklos Szeredi if (res) 626c8ccbe03SMiklos Szeredi entry = res; 627c8ccbe03SMiklos Szeredi } 628c8ccbe03SMiklos Szeredi 6292b0143b5SDavid Howells if (!(flags & O_CREAT) || d_really_is_positive(entry)) 630c8ccbe03SMiklos Szeredi goto no_open; 631c8ccbe03SMiklos Szeredi 632c8ccbe03SMiklos Szeredi /* Only creates */ 63373a09dd9SAl Viro file->f_mode |= FMODE_CREATED; 634c8ccbe03SMiklos Szeredi 635c8ccbe03SMiklos Szeredi if (fc->no_create) 636c8ccbe03SMiklos Szeredi goto mknod; 637c8ccbe03SMiklos Szeredi 638b452a458SAl Viro err = fuse_create_open(dir, entry, file, flags, mode); 639d9585277SAl Viro if (err == -ENOSYS) { 640c8ccbe03SMiklos Szeredi fc->no_create = 1; 641c8ccbe03SMiklos Szeredi goto mknod; 642c8ccbe03SMiklos Szeredi } 643c8ccbe03SMiklos Szeredi out_dput: 644c8ccbe03SMiklos Szeredi dput(res); 645d9585277SAl Viro return err; 646c8ccbe03SMiklos Szeredi 647c8ccbe03SMiklos Szeredi mknod: 648c8ccbe03SMiklos Szeredi err = fuse_mknod(dir, entry, mode, 0); 649d9585277SAl Viro if (err) 650c8ccbe03SMiklos Szeredi goto out_dput; 651c8ccbe03SMiklos Szeredi no_open: 652e45198a6SAl Viro return finish_no_open(file, res); 653fd72faacSMiklos Szeredi } 654fd72faacSMiklos Szeredi 6556f9f1180SMiklos Szeredi /* 6566f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 6576f9f1180SMiklos Szeredi */ 658fcee216bSMax Reitz static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args, 6599e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 660541af6a0SAl Viro umode_t mode) 6619e6268dbSMiklos Szeredi { 6629e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 6639e6268dbSMiklos Szeredi struct inode *inode; 664c971e6a0SAl Viro struct dentry *d; 6659e6268dbSMiklos Szeredi int err; 66607e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 6672d51013eSMiklos Szeredi 668*5d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 669*5d069dbeSMiklos Szeredi return -EIO; 670*5d069dbeSMiklos Szeredi 67107e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 6727078187aSMiklos Szeredi if (!forget) 67307e77dcaSMiklos Szeredi return -ENOMEM; 6749e6268dbSMiklos Szeredi 6750e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 676d5b48543SMiklos Szeredi args->nodeid = get_node_id(dir); 677d5b48543SMiklos Szeredi args->out_numargs = 1; 678d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(outarg); 679d5b48543SMiklos Szeredi args->out_args[0].value = &outarg; 680fcee216bSMax Reitz err = fuse_simple_request(fm, args); 6812d51013eSMiklos Szeredi if (err) 6822d51013eSMiklos Szeredi goto out_put_forget_req; 6832d51013eSMiklos Szeredi 68439ee059aSMiklos Szeredi err = -EIO; 685eb59bd17SMiklos Szeredi if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr)) 6862d51013eSMiklos Szeredi goto out_put_forget_req; 68739ee059aSMiklos Szeredi 68839ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 6892d51013eSMiklos Szeredi goto out_put_forget_req; 69039ee059aSMiklos Szeredi 6919e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 6921fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 6939e6268dbSMiklos Szeredi if (!inode) { 694fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1); 6959e6268dbSMiklos Szeredi return -ENOMEM; 6969e6268dbSMiklos Szeredi } 69707e77dcaSMiklos Szeredi kfree(forget); 6989e6268dbSMiklos Szeredi 699c971e6a0SAl Viro d_drop(entry); 700c971e6a0SAl Viro d = d_splice_alias(inode, entry); 701c971e6a0SAl Viro if (IS_ERR(d)) 702c971e6a0SAl Viro return PTR_ERR(d); 703d2a85164SMiklos Szeredi 704c971e6a0SAl Viro if (d) { 705c971e6a0SAl Viro fuse_change_entry_timeout(d, &outarg); 706c971e6a0SAl Viro dput(d); 707c971e6a0SAl Viro } else { 7081fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 709c971e6a0SAl Viro } 710261aaba7SMiklos Szeredi fuse_dir_changed(dir); 7119e6268dbSMiklos Szeredi return 0; 71239ee059aSMiklos Szeredi 7132d51013eSMiklos Szeredi out_put_forget_req: 71407e77dcaSMiklos Szeredi kfree(forget); 71539ee059aSMiklos Szeredi return err; 7169e6268dbSMiklos Szeredi } 7179e6268dbSMiklos Szeredi 7181a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, 7199e6268dbSMiklos Szeredi dev_t rdev) 7209e6268dbSMiklos Szeredi { 7219e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 722fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 7237078187aSMiklos Szeredi FUSE_ARGS(args); 7249e6268dbSMiklos Szeredi 725fcee216bSMax Reitz if (!fm->fc->dont_mask) 726e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 727e0a43ddcSMiklos Szeredi 7289e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7299e6268dbSMiklos Szeredi inarg.mode = mode; 7309e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 731e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 732d5b48543SMiklos Szeredi args.opcode = FUSE_MKNOD; 733d5b48543SMiklos Szeredi args.in_numargs = 2; 734d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 735d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 736d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 737d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 738fcee216bSMax Reitz return create_new_entry(fm, &args, dir, entry, mode); 7399e6268dbSMiklos Szeredi } 7409e6268dbSMiklos Szeredi 7414acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, 742ebfc3b49SAl Viro bool excl) 7439e6268dbSMiklos Szeredi { 7449e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 7459e6268dbSMiklos Szeredi } 7469e6268dbSMiklos Szeredi 74718bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) 7489e6268dbSMiklos Szeredi { 7499e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 750fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 7517078187aSMiklos Szeredi FUSE_ARGS(args); 7529e6268dbSMiklos Szeredi 753fcee216bSMax Reitz if (!fm->fc->dont_mask) 754e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 755e0a43ddcSMiklos Szeredi 7569e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7579e6268dbSMiklos Szeredi inarg.mode = mode; 758e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 759d5b48543SMiklos Szeredi args.opcode = FUSE_MKDIR; 760d5b48543SMiklos Szeredi args.in_numargs = 2; 761d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 762d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 763d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 764d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 765fcee216bSMax Reitz return create_new_entry(fm, &args, dir, entry, S_IFDIR); 7669e6268dbSMiklos Szeredi } 7679e6268dbSMiklos Szeredi 7689e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 7699e6268dbSMiklos Szeredi const char *link) 7709e6268dbSMiklos Szeredi { 771fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 7729e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 7737078187aSMiklos Szeredi FUSE_ARGS(args); 7749e6268dbSMiklos Szeredi 775d5b48543SMiklos Szeredi args.opcode = FUSE_SYMLINK; 776d5b48543SMiklos Szeredi args.in_numargs = 2; 777d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 778d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 779d5b48543SMiklos Szeredi args.in_args[1].size = len; 780d5b48543SMiklos Szeredi args.in_args[1].value = link; 781fcee216bSMax Reitz return create_new_entry(fm, &args, dir, entry, S_IFLNK); 7829e6268dbSMiklos Szeredi } 7839e6268dbSMiklos Szeredi 784703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode) 78531f3267bSMaxim Patlasov { 78631f3267bSMaxim Patlasov if (!IS_NOCMTIME(inode)) { 787c2050a45SDeepa Dinamani inode->i_ctime = current_time(inode); 78831f3267bSMaxim Patlasov mark_inode_dirty_sync(inode); 78931f3267bSMaxim Patlasov } 79031f3267bSMaxim Patlasov } 79131f3267bSMaxim Patlasov 7929e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 7939e6268dbSMiklos Szeredi { 7949e6268dbSMiklos Szeredi int err; 795fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 7967078187aSMiklos Szeredi FUSE_ARGS(args); 7979e6268dbSMiklos Szeredi 798*5d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 799*5d069dbeSMiklos Szeredi return -EIO; 800*5d069dbeSMiklos Szeredi 801d5b48543SMiklos Szeredi args.opcode = FUSE_UNLINK; 802d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 803d5b48543SMiklos Szeredi args.in_numargs = 1; 804d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 805d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 806fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 8079e6268dbSMiklos Szeredi if (!err) { 8082b0143b5SDavid Howells struct inode *inode = d_inode(entry); 809ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 8109e6268dbSMiklos Szeredi 811f15ecfefSKirill Tkhai spin_lock(&fi->lock); 812fcee216bSMax Reitz fi->attr_version = atomic64_inc_return(&fm->fc->attr_version); 813dfca7cebSMiklos Szeredi /* 814dfca7cebSMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 815dfca7cebSMiklos Szeredi * happen if userspace filesystem is careless. It would be 816dfca7cebSMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 817dfca7cebSMiklos Szeredi * condition here 818dfca7cebSMiklos Szeredi */ 819dfca7cebSMiklos Szeredi if (inode->i_nlink > 0) 820ac45d613SMiklos Szeredi drop_nlink(inode); 821f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 8229e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 823261aaba7SMiklos Szeredi fuse_dir_changed(dir); 8248cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 82531f3267bSMaxim Patlasov fuse_update_ctime(inode); 8269e6268dbSMiklos Szeredi } else if (err == -EINTR) 8279e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 8289e6268dbSMiklos Szeredi return err; 8299e6268dbSMiklos Szeredi } 8309e6268dbSMiklos Szeredi 8319e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 8329e6268dbSMiklos Szeredi { 8339e6268dbSMiklos Szeredi int err; 834fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 8357078187aSMiklos Szeredi FUSE_ARGS(args); 8369e6268dbSMiklos Szeredi 837*5d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 838*5d069dbeSMiklos Szeredi return -EIO; 839*5d069dbeSMiklos Szeredi 840d5b48543SMiklos Szeredi args.opcode = FUSE_RMDIR; 841d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 842d5b48543SMiklos Szeredi args.in_numargs = 1; 843d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 844d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 845fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 8469e6268dbSMiklos Szeredi if (!err) { 8472b0143b5SDavid Howells clear_nlink(d_inode(entry)); 848261aaba7SMiklos Szeredi fuse_dir_changed(dir); 8498cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 8509e6268dbSMiklos Szeredi } else if (err == -EINTR) 8519e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 8529e6268dbSMiklos Szeredi return err; 8539e6268dbSMiklos Szeredi } 8549e6268dbSMiklos Szeredi 8551560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, 8561560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 8571560c974SMiklos Szeredi unsigned int flags, int opcode, size_t argsize) 8589e6268dbSMiklos Szeredi { 8599e6268dbSMiklos Szeredi int err; 8601560c974SMiklos Szeredi struct fuse_rename2_in inarg; 861fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(olddir); 8627078187aSMiklos Szeredi FUSE_ARGS(args); 8639e6268dbSMiklos Szeredi 8641560c974SMiklos Szeredi memset(&inarg, 0, argsize); 8659e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 8661560c974SMiklos Szeredi inarg.flags = flags; 867d5b48543SMiklos Szeredi args.opcode = opcode; 868d5b48543SMiklos Szeredi args.nodeid = get_node_id(olddir); 869d5b48543SMiklos Szeredi args.in_numargs = 3; 870d5b48543SMiklos Szeredi args.in_args[0].size = argsize; 871d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 872d5b48543SMiklos Szeredi args.in_args[1].size = oldent->d_name.len + 1; 873d5b48543SMiklos Szeredi args.in_args[1].value = oldent->d_name.name; 874d5b48543SMiklos Szeredi args.in_args[2].size = newent->d_name.len + 1; 875d5b48543SMiklos Szeredi args.in_args[2].value = newent->d_name.name; 876fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 8779e6268dbSMiklos Szeredi if (!err) { 87808b63307SMiklos Szeredi /* ctime changes */ 8792b0143b5SDavid Howells fuse_invalidate_attr(d_inode(oldent)); 8802b0143b5SDavid Howells fuse_update_ctime(d_inode(oldent)); 88108b63307SMiklos Szeredi 8821560c974SMiklos Szeredi if (flags & RENAME_EXCHANGE) { 8832b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 8842b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 8851560c974SMiklos Szeredi } 8861560c974SMiklos Szeredi 887261aaba7SMiklos Szeredi fuse_dir_changed(olddir); 8889e6268dbSMiklos Szeredi if (olddir != newdir) 889261aaba7SMiklos Szeredi fuse_dir_changed(newdir); 8908cbdf1e6SMiklos Szeredi 8918cbdf1e6SMiklos Szeredi /* newent will end up negative */ 8922b0143b5SDavid Howells if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { 8932b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 8948cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 8952b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 8965219f346SMiklos Szeredi } 8979e6268dbSMiklos Szeredi } else if (err == -EINTR) { 8989e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 8999e6268dbSMiklos Szeredi rename actually took place. If the invalidation 9009e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 9019e6268dbSMiklos Szeredi directory), then there can be inconsistency between 9029e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 9039e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 9042b0143b5SDavid Howells if (d_really_is_positive(newent)) 9059e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 9069e6268dbSMiklos Szeredi } 9079e6268dbSMiklos Szeredi 9089e6268dbSMiklos Szeredi return err; 9099e6268dbSMiklos Szeredi } 9109e6268dbSMiklos Szeredi 9111560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent, 9121560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 9131560c974SMiklos Szeredi unsigned int flags) 9141560c974SMiklos Szeredi { 9151560c974SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 9161560c974SMiklos Szeredi int err; 9171560c974SMiklos Szeredi 918*5d069dbeSMiklos Szeredi if (fuse_is_bad(olddir)) 919*5d069dbeSMiklos Szeredi return -EIO; 920*5d069dbeSMiklos Szeredi 921519525faSVivek Goyal if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) 9221560c974SMiklos Szeredi return -EINVAL; 9231560c974SMiklos Szeredi 9244237ba43SMiklos Szeredi if (flags) { 9251560c974SMiklos Szeredi if (fc->no_rename2 || fc->minor < 23) 9261560c974SMiklos Szeredi return -EINVAL; 9271560c974SMiklos Szeredi 9281560c974SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, flags, 9294237ba43SMiklos Szeredi FUSE_RENAME2, 9304237ba43SMiklos Szeredi sizeof(struct fuse_rename2_in)); 9311560c974SMiklos Szeredi if (err == -ENOSYS) { 9321560c974SMiklos Szeredi fc->no_rename2 = 1; 9331560c974SMiklos Szeredi err = -EINVAL; 9341560c974SMiklos Szeredi } 9354237ba43SMiklos Szeredi } else { 9364237ba43SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, 0, 9374237ba43SMiklos Szeredi FUSE_RENAME, 9384237ba43SMiklos Szeredi sizeof(struct fuse_rename_in)); 9394237ba43SMiklos Szeredi } 9401560c974SMiklos Szeredi 9414237ba43SMiklos Szeredi return err; 9424237ba43SMiklos Szeredi } 9434237ba43SMiklos Szeredi 9449e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 9459e6268dbSMiklos Szeredi struct dentry *newent) 9469e6268dbSMiklos Szeredi { 9479e6268dbSMiklos Szeredi int err; 9489e6268dbSMiklos Szeredi struct fuse_link_in inarg; 9492b0143b5SDavid Howells struct inode *inode = d_inode(entry); 950fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 9517078187aSMiklos Szeredi FUSE_ARGS(args); 9529e6268dbSMiklos Szeredi 9539e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 9549e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 955d5b48543SMiklos Szeredi args.opcode = FUSE_LINK; 956d5b48543SMiklos Szeredi args.in_numargs = 2; 957d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 958d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 959d5b48543SMiklos Szeredi args.in_args[1].size = newent->d_name.len + 1; 960d5b48543SMiklos Szeredi args.in_args[1].value = newent->d_name.name; 961fcee216bSMax Reitz err = create_new_entry(fm, &args, newdir, newent, inode->i_mode); 9629e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 9639e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 9649e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 9659e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 9669e6268dbSMiklos Szeredi etc.) 9679e6268dbSMiklos Szeredi */ 968ac45d613SMiklos Szeredi if (!err) { 969ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 970ac45d613SMiklos Szeredi 971f15ecfefSKirill Tkhai spin_lock(&fi->lock); 972fcee216bSMax Reitz fi->attr_version = atomic64_inc_return(&fm->fc->attr_version); 973c634da71SMiklos Szeredi if (likely(inode->i_nlink < UINT_MAX)) 974ac45d613SMiklos Szeredi inc_nlink(inode); 975f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 9769e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 97731f3267bSMaxim Patlasov fuse_update_ctime(inode); 978ac45d613SMiklos Szeredi } else if (err == -EINTR) { 979ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 980ac45d613SMiklos Szeredi } 9819e6268dbSMiklos Szeredi return err; 9829e6268dbSMiklos Szeredi } 9839e6268dbSMiklos Szeredi 9841fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 9851fb69e78SMiklos Szeredi struct kstat *stat) 9861fb69e78SMiklos Szeredi { 987203627bbSMiklos Szeredi unsigned int blkbits; 9888373200bSPavel Emelyanov struct fuse_conn *fc = get_fuse_conn(inode); 9898373200bSPavel Emelyanov 9908373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 991b0aa7606SMaxim Patlasov if (fc->writeback_cache && S_ISREG(inode->i_mode)) { 9928373200bSPavel Emelyanov attr->size = i_size_read(inode); 993b0aa7606SMaxim Patlasov attr->mtime = inode->i_mtime.tv_sec; 994b0aa7606SMaxim Patlasov attr->mtimensec = inode->i_mtime.tv_nsec; 99531f3267bSMaxim Patlasov attr->ctime = inode->i_ctime.tv_sec; 99631f3267bSMaxim Patlasov attr->ctimensec = inode->i_ctime.tv_nsec; 997b0aa7606SMaxim Patlasov } 998203627bbSMiklos Szeredi 9991fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 10001fb69e78SMiklos Szeredi stat->ino = attr->ino; 10011fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 10021fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 10038cb08329SEric W. Biederman stat->uid = make_kuid(fc->user_ns, attr->uid); 10048cb08329SEric W. Biederman stat->gid = make_kgid(fc->user_ns, attr->gid); 10051fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 10061fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 10071fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 10081fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 10091fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 10101fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 10111fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 10121fb69e78SMiklos Szeredi stat->size = attr->size; 10131fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 1014203627bbSMiklos Szeredi 1015203627bbSMiklos Szeredi if (attr->blksize != 0) 1016203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 1017203627bbSMiklos Szeredi else 1018203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 1019203627bbSMiklos Szeredi 1020203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 10211fb69e78SMiklos Szeredi } 10221fb69e78SMiklos Szeredi 1023c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 1024c79e322fSMiklos Szeredi struct file *file) 1025e5e5558eSMiklos Szeredi { 1026e5e5558eSMiklos Szeredi int err; 1027c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 1028c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 1029fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 10307078187aSMiklos Szeredi FUSE_ARGS(args); 10311fb69e78SMiklos Szeredi u64 attr_version; 10321fb69e78SMiklos Szeredi 1033fcee216bSMax Reitz attr_version = fuse_get_attr_version(fm->fc); 10341fb69e78SMiklos Szeredi 1035c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 10360e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 1037c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 1038c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 1039c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 1040c79e322fSMiklos Szeredi 1041c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 1042c79e322fSMiklos Szeredi inarg.fh = ff->fh; 1043c79e322fSMiklos Szeredi } 1044d5b48543SMiklos Szeredi args.opcode = FUSE_GETATTR; 1045d5b48543SMiklos Szeredi args.nodeid = get_node_id(inode); 1046d5b48543SMiklos Szeredi args.in_numargs = 1; 1047d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 1048d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 1049d5b48543SMiklos Szeredi args.out_numargs = 1; 1050d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outarg); 1051d5b48543SMiklos Szeredi args.out_args[0].value = &outarg; 1052fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 1053e5e5558eSMiklos Szeredi if (!err) { 1054eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg.attr) || 1055eb59bd17SMiklos Szeredi (inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 1056*5d069dbeSMiklos Szeredi fuse_make_bad(inode); 1057e5e5558eSMiklos Szeredi err = -EIO; 1058e5e5558eSMiklos Szeredi } else { 1059c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 1060c79e322fSMiklos Szeredi attr_timeout(&outarg), 10611fb69e78SMiklos Szeredi attr_version); 10621fb69e78SMiklos Szeredi if (stat) 1063c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 1064e5e5558eSMiklos Szeredi } 1065e5e5558eSMiklos Szeredi } 1066e5e5558eSMiklos Szeredi return err; 1067e5e5558eSMiklos Szeredi } 1068e5e5558eSMiklos Szeredi 10695b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file, 10702f1e8196SMiklos Szeredi struct kstat *stat, u32 request_mask, 10712f1e8196SMiklos Szeredi unsigned int flags) 1072bcb4be80SMiklos Szeredi { 1073bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 10745b97eeacSMiklos Szeredi int err = 0; 1075bf5c1898SMiklos Szeredi bool sync; 1076bcb4be80SMiklos Szeredi 1077bf5c1898SMiklos Szeredi if (flags & AT_STATX_FORCE_SYNC) 1078bf5c1898SMiklos Szeredi sync = true; 1079bf5c1898SMiklos Szeredi else if (flags & AT_STATX_DONT_SYNC) 1080bf5c1898SMiklos Szeredi sync = false; 10812f1e8196SMiklos Szeredi else if (request_mask & READ_ONCE(fi->inval_mask)) 10822f1e8196SMiklos Szeredi sync = true; 1083bf5c1898SMiklos Szeredi else 1084bf5c1898SMiklos Szeredi sync = time_before64(fi->i_time, get_jiffies_64()); 1085bf5c1898SMiklos Szeredi 1086bf5c1898SMiklos Szeredi if (sync) { 108760bcc88aSSeth Forshee forget_all_cached_acls(inode); 1088bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 10895b97eeacSMiklos Szeredi } else if (stat) { 1090bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 1091bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 109245c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 1093bcb4be80SMiklos Szeredi } 1094bcb4be80SMiklos Szeredi 1095bcb4be80SMiklos Szeredi return err; 1096bcb4be80SMiklos Szeredi } 1097bcb4be80SMiklos Szeredi 10985b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file) 10995b97eeacSMiklos Szeredi { 1100802dc049SMiklos Szeredi /* Do *not* need to get atime for internal purposes */ 1101802dc049SMiklos Szeredi return fuse_update_get_attr(inode, file, NULL, 1102802dc049SMiklos Szeredi STATX_BASIC_STATS & ~STATX_ATIME, 0); 11035b97eeacSMiklos Szeredi } 11045b97eeacSMiklos Szeredi 1105fcee216bSMax Reitz int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid, 1106451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 11073b463ae0SJohn Muir { 11083b463ae0SJohn Muir int err = -ENOTDIR; 11093b463ae0SJohn Muir struct inode *parent; 11103b463ae0SJohn Muir struct dentry *dir; 11113b463ae0SJohn Muir struct dentry *entry; 11123b463ae0SJohn Muir 1113fcee216bSMax Reitz parent = fuse_ilookup(fc, parent_nodeid, NULL); 11143b463ae0SJohn Muir if (!parent) 11153b463ae0SJohn Muir return -ENOENT; 11163b463ae0SJohn Muir 11175955102cSAl Viro inode_lock(parent); 11183b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 11193b463ae0SJohn Muir goto unlock; 11203b463ae0SJohn Muir 11213b463ae0SJohn Muir err = -ENOENT; 11223b463ae0SJohn Muir dir = d_find_alias(parent); 11233b463ae0SJohn Muir if (!dir) 11243b463ae0SJohn Muir goto unlock; 11253b463ae0SJohn Muir 11268387ff25SLinus Torvalds name->hash = full_name_hash(dir, name->name, name->len); 11273b463ae0SJohn Muir entry = d_lookup(dir, name); 11283b463ae0SJohn Muir dput(dir); 11293b463ae0SJohn Muir if (!entry) 11303b463ae0SJohn Muir goto unlock; 11313b463ae0SJohn Muir 1132261aaba7SMiklos Szeredi fuse_dir_changed(parent); 11333b463ae0SJohn Muir fuse_invalidate_entry(entry); 1134451d0f59SJohn Muir 11352b0143b5SDavid Howells if (child_nodeid != 0 && d_really_is_positive(entry)) { 11365955102cSAl Viro inode_lock(d_inode(entry)); 11372b0143b5SDavid Howells if (get_node_id(d_inode(entry)) != child_nodeid) { 1138451d0f59SJohn Muir err = -ENOENT; 1139451d0f59SJohn Muir goto badentry; 1140451d0f59SJohn Muir } 1141451d0f59SJohn Muir if (d_mountpoint(entry)) { 1142451d0f59SJohn Muir err = -EBUSY; 1143451d0f59SJohn Muir goto badentry; 1144451d0f59SJohn Muir } 1145e36cb0b8SDavid Howells if (d_is_dir(entry)) { 1146451d0f59SJohn Muir shrink_dcache_parent(entry); 1147451d0f59SJohn Muir if (!simple_empty(entry)) { 1148451d0f59SJohn Muir err = -ENOTEMPTY; 1149451d0f59SJohn Muir goto badentry; 1150451d0f59SJohn Muir } 11512b0143b5SDavid Howells d_inode(entry)->i_flags |= S_DEAD; 1152451d0f59SJohn Muir } 1153451d0f59SJohn Muir dont_mount(entry); 11542b0143b5SDavid Howells clear_nlink(d_inode(entry)); 11553b463ae0SJohn Muir err = 0; 1156451d0f59SJohn Muir badentry: 11575955102cSAl Viro inode_unlock(d_inode(entry)); 1158451d0f59SJohn Muir if (!err) 1159451d0f59SJohn Muir d_delete(entry); 1160451d0f59SJohn Muir } else { 1161451d0f59SJohn Muir err = 0; 1162451d0f59SJohn Muir } 1163451d0f59SJohn Muir dput(entry); 11643b463ae0SJohn Muir 11653b463ae0SJohn Muir unlock: 11665955102cSAl Viro inode_unlock(parent); 11673b463ae0SJohn Muir iput(parent); 11683b463ae0SJohn Muir return err; 11693b463ae0SJohn Muir } 11703b463ae0SJohn Muir 117187729a55SMiklos Szeredi /* 117287729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1173c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 117487729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 117587729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 117687729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 117787729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 117887729a55SMiklos Szeredi * DoS against the requester. 117987729a55SMiklos Szeredi * 118087729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 118187729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 118287729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 118387729a55SMiklos Szeredi */ 1184c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc) 118587729a55SMiklos Szeredi { 1186c69e8d9cSDavid Howells const struct cred *cred; 1187c69e8d9cSDavid Howells 118829433a29SMiklos Szeredi if (fc->allow_other) 118973f03c2bSSeth Forshee return current_in_userns(fc->user_ns); 119087729a55SMiklos Szeredi 1191c2132c1bSAnatol Pomozov cred = current_cred(); 1192499dcf20SEric W. Biederman if (uid_eq(cred->euid, fc->user_id) && 1193499dcf20SEric W. Biederman uid_eq(cred->suid, fc->user_id) && 1194499dcf20SEric W. Biederman uid_eq(cred->uid, fc->user_id) && 1195499dcf20SEric W. Biederman gid_eq(cred->egid, fc->group_id) && 1196499dcf20SEric W. Biederman gid_eq(cred->sgid, fc->group_id) && 1197499dcf20SEric W. Biederman gid_eq(cred->gid, fc->group_id)) 1198c2132c1bSAnatol Pomozov return 1; 119987729a55SMiklos Szeredi 1200c2132c1bSAnatol Pomozov return 0; 120187729a55SMiklos Szeredi } 120287729a55SMiklos Szeredi 120331d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 120431d40d74SMiklos Szeredi { 1205fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 12067078187aSMiklos Szeredi FUSE_ARGS(args); 120731d40d74SMiklos Szeredi struct fuse_access_in inarg; 120831d40d74SMiklos Szeredi int err; 120931d40d74SMiklos Szeredi 1210698fa1d1SMiklos Szeredi BUG_ON(mask & MAY_NOT_BLOCK); 1211698fa1d1SMiklos Szeredi 1212fcee216bSMax Reitz if (fm->fc->no_access) 121331d40d74SMiklos Szeredi return 0; 121431d40d74SMiklos Szeredi 121531d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1216e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 1217d5b48543SMiklos Szeredi args.opcode = FUSE_ACCESS; 1218d5b48543SMiklos Szeredi args.nodeid = get_node_id(inode); 1219d5b48543SMiklos Szeredi args.in_numargs = 1; 1220d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 1221d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 1222fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 122331d40d74SMiklos Szeredi if (err == -ENOSYS) { 1224fcee216bSMax Reitz fm->fc->no_access = 1; 122531d40d74SMiklos Szeredi err = 0; 122631d40d74SMiklos Szeredi } 122731d40d74SMiklos Szeredi return err; 122831d40d74SMiklos Szeredi } 122931d40d74SMiklos Szeredi 123010556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 123119690ddbSMiklos Szeredi { 123210556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 123319690ddbSMiklos Szeredi return -ECHILD; 123419690ddbSMiklos Szeredi 123560bcc88aSSeth Forshee forget_all_cached_acls(inode); 123619690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 123719690ddbSMiklos Szeredi } 123819690ddbSMiklos Szeredi 12396f9f1180SMiklos Szeredi /* 12406f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 12416f9f1180SMiklos Szeredi * 12426f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 12436f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 12446f9f1180SMiklos Szeredi * modell. 12456f9f1180SMiklos Szeredi * 12466f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 12476f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 12486f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 12496f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 12506f9f1180SMiklos Szeredi * locally based on file mode. 12516f9f1180SMiklos Szeredi */ 125210556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask) 1253e5e5558eSMiklos Szeredi { 1254e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1255244f6385SMiklos Szeredi bool refreshed = false; 1256244f6385SMiklos Szeredi int err = 0; 1257e5e5558eSMiklos Szeredi 1258*5d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 1259*5d069dbeSMiklos Szeredi return -EIO; 1260*5d069dbeSMiklos Szeredi 1261c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1262e5e5558eSMiklos Szeredi return -EACCES; 1263244f6385SMiklos Szeredi 1264244f6385SMiklos Szeredi /* 1265e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1266244f6385SMiklos Szeredi */ 126729433a29SMiklos Szeredi if (fc->default_permissions || 1268e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 126919690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1270d233c7ddSMiklos Szeredi u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID; 127119690ddbSMiklos Szeredi 1272d233c7ddSMiklos Szeredi if (perm_mask & READ_ONCE(fi->inval_mask) || 1273d233c7ddSMiklos Szeredi time_before64(fi->i_time, get_jiffies_64())) { 127419690ddbSMiklos Szeredi refreshed = true; 127519690ddbSMiklos Szeredi 127610556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1277244f6385SMiklos Szeredi if (err) 1278244f6385SMiklos Szeredi return err; 12791fb69e78SMiklos Szeredi } 128019690ddbSMiklos Szeredi } 1281244f6385SMiklos Szeredi 128229433a29SMiklos Szeredi if (fc->default_permissions) { 12832830ba7fSAl Viro err = generic_permission(inode, mask); 12841e9a4ed9SMiklos Szeredi 12851e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 12861e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 12871e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1288244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 128910556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 12901e9a4ed9SMiklos Szeredi if (!err) 12912830ba7fSAl Viro err = generic_permission(inode, mask); 12921e9a4ed9SMiklos Szeredi } 12931e9a4ed9SMiklos Szeredi 12946f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 12956f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 12966f9f1180SMiklos Szeredi noticed immediately, only after the attribute 12976f9f1180SMiklos Szeredi timeout has expired */ 12989cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1299e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1300e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1301e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1302e8e96157SMiklos Szeredi if (refreshed) 1303e5e5558eSMiklos Szeredi return -EACCES; 130431d40d74SMiklos Szeredi 130510556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1306e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1307e8e96157SMiklos Szeredi return -EACCES; 1308e8e96157SMiklos Szeredi } 1309e5e5558eSMiklos Szeredi } 1310244f6385SMiklos Szeredi return err; 1311e5e5558eSMiklos Szeredi } 1312e5e5558eSMiklos Szeredi 13135571f1e6SDan Schatzberg static int fuse_readlink_page(struct inode *inode, struct page *page) 1314e5e5558eSMiklos Szeredi { 1315fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 13164c29afecSMiklos Szeredi struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 }; 13174c29afecSMiklos Szeredi struct fuse_args_pages ap = { 13184c29afecSMiklos Szeredi .num_pages = 1, 13194c29afecSMiklos Szeredi .pages = &page, 13204c29afecSMiklos Szeredi .descs = &desc, 13214c29afecSMiklos Szeredi }; 13224c29afecSMiklos Szeredi char *link; 13234c29afecSMiklos Szeredi ssize_t res; 1324e5e5558eSMiklos Szeredi 13254c29afecSMiklos Szeredi ap.args.opcode = FUSE_READLINK; 13264c29afecSMiklos Szeredi ap.args.nodeid = get_node_id(inode); 13274c29afecSMiklos Szeredi ap.args.out_pages = true; 13284c29afecSMiklos Szeredi ap.args.out_argvar = true; 13294c29afecSMiklos Szeredi ap.args.page_zeroing = true; 13304c29afecSMiklos Szeredi ap.args.out_numargs = 1; 13314c29afecSMiklos Szeredi ap.args.out_args[0].size = desc.length; 1332fcee216bSMax Reitz res = fuse_simple_request(fm, &ap.args); 13336b255391SAl Viro 1334451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 13355571f1e6SDan Schatzberg 13364c29afecSMiklos Szeredi if (res < 0) 13374c29afecSMiklos Szeredi return res; 13384c29afecSMiklos Szeredi 13394c29afecSMiklos Szeredi if (WARN_ON(res >= PAGE_SIZE)) 13404c29afecSMiklos Szeredi return -EIO; 13414c29afecSMiklos Szeredi 13424c29afecSMiklos Szeredi link = page_address(page); 13434c29afecSMiklos Szeredi link[res] = '\0'; 13444c29afecSMiklos Szeredi 13454c29afecSMiklos Szeredi return 0; 13465571f1e6SDan Schatzberg } 13475571f1e6SDan Schatzberg 13485571f1e6SDan Schatzberg static const char *fuse_get_link(struct dentry *dentry, struct inode *inode, 13495571f1e6SDan Schatzberg struct delayed_call *callback) 13505571f1e6SDan Schatzberg { 13515571f1e6SDan Schatzberg struct fuse_conn *fc = get_fuse_conn(inode); 13525571f1e6SDan Schatzberg struct page *page; 13535571f1e6SDan Schatzberg int err; 13545571f1e6SDan Schatzberg 13555571f1e6SDan Schatzberg err = -EIO; 1356*5d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 13575571f1e6SDan Schatzberg goto out_err; 13585571f1e6SDan Schatzberg 13595571f1e6SDan Schatzberg if (fc->cache_symlinks) 13605571f1e6SDan Schatzberg return page_get_link(dentry, inode, callback); 13615571f1e6SDan Schatzberg 13625571f1e6SDan Schatzberg err = -ECHILD; 13635571f1e6SDan Schatzberg if (!dentry) 13645571f1e6SDan Schatzberg goto out_err; 13655571f1e6SDan Schatzberg 13665571f1e6SDan Schatzberg page = alloc_page(GFP_KERNEL); 13675571f1e6SDan Schatzberg err = -ENOMEM; 13685571f1e6SDan Schatzberg if (!page) 13695571f1e6SDan Schatzberg goto out_err; 13705571f1e6SDan Schatzberg 13715571f1e6SDan Schatzberg err = fuse_readlink_page(inode, page); 13725571f1e6SDan Schatzberg if (err) { 13735571f1e6SDan Schatzberg __free_page(page); 13745571f1e6SDan Schatzberg goto out_err; 13755571f1e6SDan Schatzberg } 13765571f1e6SDan Schatzberg 13775571f1e6SDan Schatzberg set_delayed_call(callback, page_put_link, page); 13785571f1e6SDan Schatzberg 13795571f1e6SDan Schatzberg return page_address(page); 13805571f1e6SDan Schatzberg 13815571f1e6SDan Schatzberg out_err: 13825571f1e6SDan Schatzberg return ERR_PTR(err); 1383e5e5558eSMiklos Szeredi } 1384e5e5558eSMiklos Szeredi 1385e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1386e5e5558eSMiklos Szeredi { 138791fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1388e5e5558eSMiklos Szeredi } 1389e5e5558eSMiklos Szeredi 1390e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1391e5e5558eSMiklos Szeredi { 13922e64ff15SChad Austin fuse_release_common(file, true); 13938b0797a4SMiklos Szeredi 13948b0797a4SMiklos Szeredi return 0; 1395e5e5558eSMiklos Szeredi } 1396e5e5558eSMiklos Szeredi 139702c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 139802c24a82SJosef Bacik int datasync) 139982547981SMiklos Szeredi { 1400a9c2d1e8SMiklos Szeredi struct inode *inode = file->f_mapping->host; 1401a9c2d1e8SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1402a9c2d1e8SMiklos Szeredi int err; 1403a9c2d1e8SMiklos Szeredi 1404*5d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 1405a9c2d1e8SMiklos Szeredi return -EIO; 1406a9c2d1e8SMiklos Szeredi 1407a9c2d1e8SMiklos Szeredi if (fc->no_fsyncdir) 1408a9c2d1e8SMiklos Szeredi return 0; 1409a9c2d1e8SMiklos Szeredi 1410a9c2d1e8SMiklos Szeredi inode_lock(inode); 1411a9c2d1e8SMiklos Szeredi err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR); 1412a9c2d1e8SMiklos Szeredi if (err == -ENOSYS) { 1413a9c2d1e8SMiklos Szeredi fc->no_fsyncdir = 1; 1414a9c2d1e8SMiklos Szeredi err = 0; 1415a9c2d1e8SMiklos Szeredi } 1416a9c2d1e8SMiklos Szeredi inode_unlock(inode); 1417a9c2d1e8SMiklos Szeredi 1418a9c2d1e8SMiklos Szeredi return err; 141982547981SMiklos Szeredi } 142082547981SMiklos Szeredi 1421b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1422b18da0c5SMiklos Szeredi unsigned long arg) 1423b18da0c5SMiklos Szeredi { 1424b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1425b18da0c5SMiklos Szeredi 1426b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1427b18da0c5SMiklos Szeredi if (fc->minor < 18) 1428b18da0c5SMiklos Szeredi return -ENOTTY; 1429b18da0c5SMiklos Szeredi 1430b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1431b18da0c5SMiklos Szeredi } 1432b18da0c5SMiklos Szeredi 1433b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1434b18da0c5SMiklos Szeredi unsigned long arg) 1435b18da0c5SMiklos Szeredi { 1436b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1437b18da0c5SMiklos Szeredi 1438b18da0c5SMiklos Szeredi if (fc->minor < 18) 1439b18da0c5SMiklos Szeredi return -ENOTTY; 1440b18da0c5SMiklos Szeredi 1441b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1442b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1443b18da0c5SMiklos Szeredi } 1444b18da0c5SMiklos Szeredi 1445b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime) 144617637cbaSMiklos Szeredi { 144717637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 144817637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 144917637cbaSMiklos Szeredi return true; 145017637cbaSMiklos Szeredi 1451b0aa7606SMaxim Patlasov /* Or if kernel i_mtime is the official one */ 1452b0aa7606SMaxim Patlasov if (trust_local_mtime) 1453b0aa7606SMaxim Patlasov return true; 1454b0aa7606SMaxim Patlasov 145517637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 145617637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 145717637cbaSMiklos Szeredi return false; 145817637cbaSMiklos Szeredi 145917637cbaSMiklos Szeredi /* In all other cases update */ 146017637cbaSMiklos Szeredi return true; 146117637cbaSMiklos Szeredi } 146217637cbaSMiklos Szeredi 14638cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr, 14648cb08329SEric W. Biederman struct fuse_setattr_in *arg, bool trust_local_cmtime) 14659e6268dbSMiklos Szeredi { 14669e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 14679e6268dbSMiklos Szeredi 14689e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1469befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 14709e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 14718cb08329SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid); 14729e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 14738cb08329SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid); 14749e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1475befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 147617637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 147717637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1478befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 147917637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 148017637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 148117637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 148217637cbaSMiklos Szeredi } 14833ad22c62SMaxim Patlasov if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) { 148417637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1485befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 148617637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 14873ad22c62SMaxim Patlasov if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime) 148817637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 14899e6268dbSMiklos Szeredi } 14903ad22c62SMaxim Patlasov if ((ivalid & ATTR_CTIME) && trust_local_cmtime) { 14913ad22c62SMaxim Patlasov arg->valid |= FATTR_CTIME; 14923ad22c62SMaxim Patlasov arg->ctime = iattr->ia_ctime.tv_sec; 14933ad22c62SMaxim Patlasov arg->ctimensec = iattr->ia_ctime.tv_nsec; 14943ad22c62SMaxim Patlasov } 14959e6268dbSMiklos Szeredi } 14969e6268dbSMiklos Szeredi 14976f9f1180SMiklos Szeredi /* 14983be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 14993be5a52bSMiklos Szeredi * 15003be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 15013be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 15023be5a52bSMiklos Szeredi */ 15033be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 15043be5a52bSMiklos Szeredi { 15053be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15063be5a52bSMiklos Szeredi 15075955102cSAl Viro BUG_ON(!inode_is_locked(inode)); 15083be5a52bSMiklos Szeredi 1509f15ecfefSKirill Tkhai spin_lock(&fi->lock); 15103be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 15113be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 1512f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 15133be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 15143be5a52bSMiklos Szeredi } 15153be5a52bSMiklos Szeredi 15163be5a52bSMiklos Szeredi /* 15173be5a52bSMiklos Szeredi * Allow writepages on inode 15183be5a52bSMiklos Szeredi * 15193be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 15203be5a52bSMiklos Szeredi * writepages. 15213be5a52bSMiklos Szeredi */ 15223be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 15233be5a52bSMiklos Szeredi { 15243be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15253be5a52bSMiklos Szeredi 15263be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 15273be5a52bSMiklos Szeredi fi->writectr = 0; 15283be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 15293be5a52bSMiklos Szeredi } 15303be5a52bSMiklos Szeredi 15313be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 15323be5a52bSMiklos Szeredi { 1533f15ecfefSKirill Tkhai struct fuse_inode *fi = get_fuse_inode(inode); 15343be5a52bSMiklos Szeredi 1535f15ecfefSKirill Tkhai spin_lock(&fi->lock); 15363be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 1537f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 15383be5a52bSMiklos Szeredi } 15393be5a52bSMiklos Szeredi 15407078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, 1541b0aa7606SMaxim Patlasov struct inode *inode, 1542b0aa7606SMaxim Patlasov struct fuse_setattr_in *inarg_p, 1543b0aa7606SMaxim Patlasov struct fuse_attr_out *outarg_p) 1544b0aa7606SMaxim Patlasov { 1545d5b48543SMiklos Szeredi args->opcode = FUSE_SETATTR; 1546d5b48543SMiklos Szeredi args->nodeid = get_node_id(inode); 1547d5b48543SMiklos Szeredi args->in_numargs = 1; 1548d5b48543SMiklos Szeredi args->in_args[0].size = sizeof(*inarg_p); 1549d5b48543SMiklos Szeredi args->in_args[0].value = inarg_p; 1550d5b48543SMiklos Szeredi args->out_numargs = 1; 1551d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(*outarg_p); 1552d5b48543SMiklos Szeredi args->out_args[0].value = outarg_p; 1553b0aa7606SMaxim Patlasov } 1554b0aa7606SMaxim Patlasov 1555b0aa7606SMaxim Patlasov /* 1556b0aa7606SMaxim Patlasov * Flush inode->i_mtime to the server 1557b0aa7606SMaxim Patlasov */ 1558ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff) 1559b0aa7606SMaxim Patlasov { 1560fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 15617078187aSMiklos Szeredi FUSE_ARGS(args); 1562b0aa7606SMaxim Patlasov struct fuse_setattr_in inarg; 1563b0aa7606SMaxim Patlasov struct fuse_attr_out outarg; 1564b0aa7606SMaxim Patlasov 1565b0aa7606SMaxim Patlasov memset(&inarg, 0, sizeof(inarg)); 1566b0aa7606SMaxim Patlasov memset(&outarg, 0, sizeof(outarg)); 1567b0aa7606SMaxim Patlasov 1568ab9e13f7SMaxim Patlasov inarg.valid = FATTR_MTIME; 1569b0aa7606SMaxim Patlasov inarg.mtime = inode->i_mtime.tv_sec; 1570b0aa7606SMaxim Patlasov inarg.mtimensec = inode->i_mtime.tv_nsec; 1571fcee216bSMax Reitz if (fm->fc->minor >= 23) { 1572ab9e13f7SMaxim Patlasov inarg.valid |= FATTR_CTIME; 1573ab9e13f7SMaxim Patlasov inarg.ctime = inode->i_ctime.tv_sec; 1574ab9e13f7SMaxim Patlasov inarg.ctimensec = inode->i_ctime.tv_nsec; 1575ab9e13f7SMaxim Patlasov } 15761e18bda8SMiklos Szeredi if (ff) { 15771e18bda8SMiklos Szeredi inarg.valid |= FATTR_FH; 15781e18bda8SMiklos Szeredi inarg.fh = ff->fh; 15791e18bda8SMiklos Szeredi } 1580fcee216bSMax Reitz fuse_setattr_fill(fm->fc, &args, inode, &inarg, &outarg); 1581b0aa7606SMaxim Patlasov 1582fcee216bSMax Reitz return fuse_simple_request(fm, &args); 1583b0aa7606SMaxim Patlasov } 1584b0aa7606SMaxim Patlasov 15853be5a52bSMiklos Szeredi /* 15866f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 15876f9f1180SMiklos Szeredi * 15886f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 15896f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 15909ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 15919ffbb916SMiklos Szeredi * and the actual truncation by hand. 15926f9f1180SMiklos Szeredi */ 159362490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, 159449d4914fSMiklos Szeredi struct file *file) 15959e6268dbSMiklos Szeredi { 159662490330SJan Kara struct inode *inode = d_inode(dentry); 1597fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 1598fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 159906a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 16007078187aSMiklos Szeredi FUSE_ARGS(args); 16019e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 16029e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 16033be5a52bSMiklos Szeredi bool is_truncate = false; 16048373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 16053be5a52bSMiklos Szeredi loff_t oldsize; 16069e6268dbSMiklos Szeredi int err; 16073ad22c62SMaxim Patlasov bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode); 16086ae330caSVivek Goyal bool fault_blocked = false; 16099e6268dbSMiklos Szeredi 161029433a29SMiklos Szeredi if (!fc->default_permissions) 1611db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1612db78b877SChristoph Hellwig 161331051c85SJan Kara err = setattr_prepare(dentry, attr); 16141e9a4ed9SMiklos Szeredi if (err) 16151e9a4ed9SMiklos Szeredi return err; 16161e9a4ed9SMiklos Szeredi 16176ae330caSVivek Goyal if (attr->ia_valid & ATTR_SIZE) { 16186ae330caSVivek Goyal if (WARN_ON(!S_ISREG(inode->i_mode))) 16196ae330caSVivek Goyal return -EIO; 16206ae330caSVivek Goyal is_truncate = true; 16216ae330caSVivek Goyal } 16226ae330caSVivek Goyal 16236ae330caSVivek Goyal if (FUSE_IS_DAX(inode) && is_truncate) { 16246ae330caSVivek Goyal down_write(&fi->i_mmap_sem); 16256ae330caSVivek Goyal fault_blocked = true; 16266ae330caSVivek Goyal err = fuse_dax_break_layouts(inode, 0, 0); 16276ae330caSVivek Goyal if (err) { 16286ae330caSVivek Goyal up_write(&fi->i_mmap_sem); 16296ae330caSVivek Goyal return err; 16306ae330caSVivek Goyal } 16316ae330caSVivek Goyal } 16326ae330caSVivek Goyal 16338d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 1634df0e91d4SMiklos Szeredi /* This is coming from open(..., ... | O_TRUNC); */ 1635df0e91d4SMiklos Szeredi WARN_ON(!(attr->ia_valid & ATTR_SIZE)); 1636df0e91d4SMiklos Szeredi WARN_ON(attr->ia_size != 0); 1637df0e91d4SMiklos Szeredi if (fc->atomic_o_trunc) { 1638df0e91d4SMiklos Szeredi /* 1639df0e91d4SMiklos Szeredi * No need to send request to userspace, since actual 1640df0e91d4SMiklos Szeredi * truncation has already been done by OPEN. But still 1641df0e91d4SMiklos Szeredi * need to truncate page cache. 1642df0e91d4SMiklos Szeredi */ 1643df0e91d4SMiklos Szeredi i_size_write(inode, 0); 1644df0e91d4SMiklos Szeredi truncate_pagecache(inode, 0); 16456ae330caSVivek Goyal goto out; 1646df0e91d4SMiklos Szeredi } 16478d56adddSMiklos Szeredi file = NULL; 16488d56adddSMiklos Szeredi } 16496ff958edSMiklos Szeredi 1650b24e7598SMiklos Szeredi /* Flush dirty data/metadata before non-truncate SETATTR */ 1651b24e7598SMiklos Szeredi if (is_wb && S_ISREG(inode->i_mode) && 1652b24e7598SMiklos Szeredi attr->ia_valid & 1653b24e7598SMiklos Szeredi (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET | 1654b24e7598SMiklos Szeredi ATTR_TIMES_SET)) { 1655b24e7598SMiklos Szeredi err = write_inode_now(inode, true); 1656b24e7598SMiklos Szeredi if (err) 1657b24e7598SMiklos Szeredi return err; 1658b24e7598SMiklos Szeredi 1659b24e7598SMiklos Szeredi fuse_set_nowrite(inode); 1660b24e7598SMiklos Szeredi fuse_release_nowrite(inode); 1661b24e7598SMiklos Szeredi } 1662b24e7598SMiklos Szeredi 166306a7c3c2SMaxim Patlasov if (is_truncate) { 16643be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 166506a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 16663ad22c62SMaxim Patlasov if (trust_local_cmtime && attr->ia_size != inode->i_size) 16673ad22c62SMaxim Patlasov attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; 166806a7c3c2SMaxim Patlasov } 16693be5a52bSMiklos Szeredi 16709e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 16710e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 16728cb08329SEric W. Biederman iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime); 167349d4914fSMiklos Szeredi if (file) { 167449d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 167549d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 167649d4914fSMiklos Szeredi inarg.fh = ff->fh; 167749d4914fSMiklos Szeredi } 167831792161SVivek Goyal 167931792161SVivek Goyal /* Kill suid/sgid for non-directory chown unconditionally */ 168031792161SVivek Goyal if (fc->handle_killpriv_v2 && !S_ISDIR(inode->i_mode) && 168131792161SVivek Goyal attr->ia_valid & (ATTR_UID | ATTR_GID)) 168231792161SVivek Goyal inarg.valid |= FATTR_KILL_SUIDGID; 168331792161SVivek Goyal 1684f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1685f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1686f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1687f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 168831792161SVivek Goyal 168931792161SVivek Goyal /* Kill suid/sgid for truncate only if no CAP_FSETID */ 169031792161SVivek Goyal if (fc->handle_killpriv_v2 && !capable(CAP_FSETID)) 169131792161SVivek Goyal inarg.valid |= FATTR_KILL_SUIDGID; 1692f3332114SMiklos Szeredi } 16937078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 1694fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 1695e00d2c2dSMiklos Szeredi if (err) { 1696e00d2c2dSMiklos Szeredi if (err == -EINTR) 1697e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 16983be5a52bSMiklos Szeredi goto error; 1699e00d2c2dSMiklos Szeredi } 1700e00d2c2dSMiklos Szeredi 1701eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg.attr) || 1702eb59bd17SMiklos Szeredi (inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 1703*5d069dbeSMiklos Szeredi fuse_make_bad(inode); 17043be5a52bSMiklos Szeredi err = -EIO; 17053be5a52bSMiklos Szeredi goto error; 17069e6268dbSMiklos Szeredi } 17079e6268dbSMiklos Szeredi 1708f15ecfefSKirill Tkhai spin_lock(&fi->lock); 1709b0aa7606SMaxim Patlasov /* the kernel maintains i_mtime locally */ 17103ad22c62SMaxim Patlasov if (trust_local_cmtime) { 17113ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_MTIME) 1712b0aa7606SMaxim Patlasov inode->i_mtime = attr->ia_mtime; 17133ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_CTIME) 17143ad22c62SMaxim Patlasov inode->i_ctime = attr->ia_ctime; 17151e18bda8SMiklos Szeredi /* FIXME: clear I_DIRTY_SYNC? */ 1716b0aa7606SMaxim Patlasov } 1717b0aa7606SMaxim Patlasov 17183be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 17193be5a52bSMiklos Szeredi attr_timeout(&outarg)); 17203be5a52bSMiklos Szeredi oldsize = inode->i_size; 17218373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 17228373200bSPavel Emelyanov if (!is_wb || is_truncate || !S_ISREG(inode->i_mode)) 17233be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 17243be5a52bSMiklos Szeredi 17253be5a52bSMiklos Szeredi if (is_truncate) { 1726f15ecfefSKirill Tkhai /* NOTE: this may release/reacquire fi->lock */ 17273be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 17283be5a52bSMiklos Szeredi } 1729f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 17303be5a52bSMiklos Szeredi 17313be5a52bSMiklos Szeredi /* 17323be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 17333be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 17343be5a52bSMiklos Szeredi */ 17358373200bSPavel Emelyanov if ((is_truncate || !is_wb) && 17368373200bSPavel Emelyanov S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 17377caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 17383be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 17393be5a52bSMiklos Szeredi } 17403be5a52bSMiklos Szeredi 174106a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 17426ae330caSVivek Goyal out: 17436ae330caSVivek Goyal if (fault_blocked) 17446ae330caSVivek Goyal up_write(&fi->i_mmap_sem); 17456ae330caSVivek Goyal 1746e00d2c2dSMiklos Szeredi return 0; 17473be5a52bSMiklos Szeredi 17483be5a52bSMiklos Szeredi error: 17493be5a52bSMiklos Szeredi if (is_truncate) 17503be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 17513be5a52bSMiklos Szeredi 175206a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 17536ae330caSVivek Goyal 17546ae330caSVivek Goyal if (fault_blocked) 17556ae330caSVivek Goyal up_write(&fi->i_mmap_sem); 17563be5a52bSMiklos Szeredi return err; 17579e6268dbSMiklos Szeredi } 17589e6268dbSMiklos Szeredi 175949d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 176049d4914fSMiklos Szeredi { 17612b0143b5SDavid Howells struct inode *inode = d_inode(entry); 17625e940c1dSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1763a09f99edSMiklos Szeredi struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL; 17645e2b8828SMiklos Szeredi int ret; 1765efb9fa9eSMaxim Patlasov 1766*5d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 1767*5d069dbeSMiklos Szeredi return -EIO; 1768*5d069dbeSMiklos Szeredi 1769efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1770efb9fa9eSMaxim Patlasov return -EACCES; 1771efb9fa9eSMaxim Patlasov 1772a09f99edSMiklos Szeredi if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) { 1773a09f99edSMiklos Szeredi attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | 1774a09f99edSMiklos Szeredi ATTR_MODE); 17755e940c1dSMiklos Szeredi 1776a09f99edSMiklos Szeredi /* 17775e940c1dSMiklos Szeredi * The only sane way to reliably kill suid/sgid is to do it in 17785e940c1dSMiklos Szeredi * the userspace filesystem 17795e940c1dSMiklos Szeredi * 17805e940c1dSMiklos Szeredi * This should be done on write(), truncate() and chown(). 17815e940c1dSMiklos Szeredi */ 17828981bdfdSVivek Goyal if (!fc->handle_killpriv && !fc->handle_killpriv_v2) { 17835e940c1dSMiklos Szeredi /* 17845e940c1dSMiklos Szeredi * ia_mode calculation may have used stale i_mode. 17855e940c1dSMiklos Szeredi * Refresh and recalculate. 1786a09f99edSMiklos Szeredi */ 1787a09f99edSMiklos Szeredi ret = fuse_do_getattr(inode, NULL, file); 1788a09f99edSMiklos Szeredi if (ret) 1789a09f99edSMiklos Szeredi return ret; 1790a09f99edSMiklos Szeredi 1791a09f99edSMiklos Szeredi attr->ia_mode = inode->i_mode; 1792c01638f5SMiklos Szeredi if (inode->i_mode & S_ISUID) { 1793a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1794a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISUID; 1795a09f99edSMiklos Szeredi } 1796c01638f5SMiklos Szeredi if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 1797a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1798a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISGID; 1799a09f99edSMiklos Szeredi } 1800a09f99edSMiklos Szeredi } 18015e940c1dSMiklos Szeredi } 1802a09f99edSMiklos Szeredi if (!attr->ia_valid) 1803a09f99edSMiklos Szeredi return 0; 1804a09f99edSMiklos Szeredi 1805abb5a14fSLinus Torvalds ret = fuse_do_setattr(entry, attr, file); 18065e2b8828SMiklos Szeredi if (!ret) { 180760bcc88aSSeth Forshee /* 180860bcc88aSSeth Forshee * If filesystem supports acls it may have updated acl xattrs in 180960bcc88aSSeth Forshee * the filesystem, so forget cached acls for the inode. 181060bcc88aSSeth Forshee */ 181160bcc88aSSeth Forshee if (fc->posix_acl) 181260bcc88aSSeth Forshee forget_all_cached_acls(inode); 181360bcc88aSSeth Forshee 18145e2b8828SMiklos Szeredi /* Directory mode changed, may need to revalidate access */ 18155e2b8828SMiklos Szeredi if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE)) 18165e2b8828SMiklos Szeredi fuse_invalidate_entry_cache(entry); 18175e2b8828SMiklos Szeredi } 18185e2b8828SMiklos Szeredi return ret; 181949d4914fSMiklos Szeredi } 182049d4914fSMiklos Szeredi 1821a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat, 1822a528d35eSDavid Howells u32 request_mask, unsigned int flags) 1823e5e5558eSMiklos Szeredi { 1824a528d35eSDavid Howells struct inode *inode = d_inode(path->dentry); 1825244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1826244f6385SMiklos Szeredi 1827*5d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 1828*5d069dbeSMiklos Szeredi return -EIO; 1829*5d069dbeSMiklos Szeredi 18305157da2cSMiklos Szeredi if (!fuse_allow_current_process(fc)) { 18315157da2cSMiklos Szeredi if (!request_mask) { 18325157da2cSMiklos Szeredi /* 18335157da2cSMiklos Szeredi * If user explicitly requested *nothing* then don't 18345157da2cSMiklos Szeredi * error out, but return st_dev only. 18355157da2cSMiklos Szeredi */ 18365157da2cSMiklos Szeredi stat->result_mask = 0; 18375157da2cSMiklos Szeredi stat->dev = inode->i_sb->s_dev; 18385157da2cSMiklos Szeredi return 0; 18395157da2cSMiklos Szeredi } 1840244f6385SMiklos Szeredi return -EACCES; 18415157da2cSMiklos Szeredi } 1842244f6385SMiklos Szeredi 18432f1e8196SMiklos Szeredi return fuse_update_get_attr(inode, NULL, stat, request_mask, flags); 1844e5e5558eSMiklos Szeredi } 1845e5e5558eSMiklos Szeredi 1846754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1847e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 18489e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 18499e6268dbSMiklos Szeredi .symlink = fuse_symlink, 18509e6268dbSMiklos Szeredi .unlink = fuse_unlink, 18519e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 18522773bf00SMiklos Szeredi .rename = fuse_rename2, 18539e6268dbSMiklos Szeredi .link = fuse_link, 18549e6268dbSMiklos Szeredi .setattr = fuse_setattr, 18559e6268dbSMiklos Szeredi .create = fuse_create, 1856c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 18579e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1858e5e5558eSMiklos Szeredi .permission = fuse_permission, 1859e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 186092a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 186160bcc88aSSeth Forshee .get_acl = fuse_get_acl, 186260bcc88aSSeth Forshee .set_acl = fuse_set_acl, 1863e5e5558eSMiklos Szeredi }; 1864e5e5558eSMiklos Szeredi 18654b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1866b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1867e5e5558eSMiklos Szeredi .read = generic_read_dir, 1868d9b3dbdcSAl Viro .iterate_shared = fuse_readdir, 1869e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1870e5e5558eSMiklos Szeredi .release = fuse_dir_release, 187182547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1872b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 1873b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 1874e5e5558eSMiklos Szeredi }; 1875e5e5558eSMiklos Szeredi 1876754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 18779e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1878e5e5558eSMiklos Szeredi .permission = fuse_permission, 1879e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 188092a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 188160bcc88aSSeth Forshee .get_acl = fuse_get_acl, 188260bcc88aSSeth Forshee .set_acl = fuse_set_acl, 1883e5e5558eSMiklos Szeredi }; 1884e5e5558eSMiklos Szeredi 1885754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 18869e6268dbSMiklos Szeredi .setattr = fuse_setattr, 18876b255391SAl Viro .get_link = fuse_get_link, 1888e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 188992a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 1890e5e5558eSMiklos Szeredi }; 1891e5e5558eSMiklos Szeredi 1892e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1893e5e5558eSMiklos Szeredi { 1894e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1895e5e5558eSMiklos Szeredi } 1896e5e5558eSMiklos Szeredi 1897e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1898e5e5558eSMiklos Szeredi { 1899ab2257e9SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1900ab2257e9SMiklos Szeredi 1901e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1902e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1903ab2257e9SMiklos Szeredi 1904ab2257e9SMiklos Szeredi spin_lock_init(&fi->rdc.lock); 1905ab2257e9SMiklos Szeredi fi->rdc.cached = false; 1906ab2257e9SMiklos Szeredi fi->rdc.size = 0; 1907ab2257e9SMiklos Szeredi fi->rdc.pos = 0; 1908ab2257e9SMiklos Szeredi fi->rdc.version = 0; 1909e5e5558eSMiklos Szeredi } 1910e5e5558eSMiklos Szeredi 19115571f1e6SDan Schatzberg static int fuse_symlink_readpage(struct file *null, struct page *page) 19125571f1e6SDan Schatzberg { 19135571f1e6SDan Schatzberg int err = fuse_readlink_page(page->mapping->host, page); 19145571f1e6SDan Schatzberg 19155571f1e6SDan Schatzberg if (!err) 19165571f1e6SDan Schatzberg SetPageUptodate(page); 19175571f1e6SDan Schatzberg 19185571f1e6SDan Schatzberg unlock_page(page); 19195571f1e6SDan Schatzberg 19205571f1e6SDan Schatzberg return err; 19215571f1e6SDan Schatzberg } 19225571f1e6SDan Schatzberg 19235571f1e6SDan Schatzberg static const struct address_space_operations fuse_symlink_aops = { 19245571f1e6SDan Schatzberg .readpage = fuse_symlink_readpage, 19255571f1e6SDan Schatzberg }; 19265571f1e6SDan Schatzberg 1927e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1928e5e5558eSMiklos Szeredi { 1929e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 19305571f1e6SDan Schatzberg inode->i_data.a_ops = &fuse_symlink_aops; 19315571f1e6SDan Schatzberg inode_nohighmem(inode); 1932e5e5558eSMiklos Szeredi } 1933