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); 2055d069dbeSMiklos 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) || 25515db1683SAmir Goldstein fuse_stale_inode(inode, outarg.generation, &outarg.attr)) 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 vfsmount *mnt; 313bf109c64SMax Reitz struct fuse_inode *mp_fi = get_fuse_inode(d_inode(path->dentry)); 314bf109c64SMax Reitz 315bf109c64SMax Reitz fsc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry); 31629e0e4dfSGreg Kurz if (IS_ERR(fsc)) 31729e0e4dfSGreg Kurz return ERR_CAST(fsc); 318bf109c64SMax Reitz 319266eb3f2SGreg Kurz /* Pass the FUSE inode of the mount for fuse_get_tree_submount() */ 320266eb3f2SGreg Kurz fsc->fs_private = mp_fi; 321266eb3f2SGreg Kurz 322bf109c64SMax Reitz /* Create the submount */ 32329e0e4dfSGreg Kurz mnt = fc_mount(fsc); 32429e0e4dfSGreg Kurz if (!IS_ERR(mnt)) 325bf109c64SMax Reitz mntget(mnt); 32629e0e4dfSGreg Kurz 327bf109c64SMax Reitz put_fs_context(fsc); 328bf109c64SMax Reitz return mnt; 329bf109c64SMax Reitz } 330bf109c64SMax Reitz 3314269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 332e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 3338fab0106SMiklos Szeredi .d_delete = fuse_dentry_delete, 33430c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 335f75fdf22SMiklos Szeredi .d_init = fuse_dentry_init, 336f75fdf22SMiklos Szeredi .d_release = fuse_dentry_release, 33730c6a23dSKhazhismel Kumykov #endif 338bf109c64SMax Reitz .d_automount = fuse_dentry_automount, 339e5e5558eSMiklos Szeredi }; 340e5e5558eSMiklos Szeredi 3410ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = { 34230c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 3430ce267ffSMiklos Szeredi .d_init = fuse_dentry_init, 3440ce267ffSMiklos Szeredi .d_release = fuse_dentry_release, 34530c6a23dSKhazhismel Kumykov #endif 3460ce267ffSMiklos Szeredi }; 3470ce267ffSMiklos Szeredi 348a5bfffacSTimo Savola int fuse_valid_type(int m) 34939ee059aSMiklos Szeredi { 35039ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 35139ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 35239ee059aSMiklos Szeredi } 35339ee059aSMiklos Szeredi 354eb59bd17SMiklos Szeredi bool fuse_invalid_attr(struct fuse_attr *attr) 355eb59bd17SMiklos Szeredi { 356eb59bd17SMiklos Szeredi return !fuse_valid_type(attr->mode) || 357eb59bd17SMiklos Szeredi attr->size > LLONG_MAX; 358eb59bd17SMiklos Szeredi } 359eb59bd17SMiklos Szeredi 36013983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, 361c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 362c180eebeSMiklos Szeredi { 363fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount_super(sb); 3647078187aSMiklos Szeredi FUSE_ARGS(args); 36507e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 366c180eebeSMiklos Szeredi u64 attr_version; 367c180eebeSMiklos Szeredi int err; 368c180eebeSMiklos Szeredi 369c180eebeSMiklos Szeredi *inode = NULL; 370c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 371c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 372c180eebeSMiklos Szeredi goto out; 373c180eebeSMiklos Szeredi 374c180eebeSMiklos Szeredi 37507e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 37607e77dcaSMiklos Szeredi err = -ENOMEM; 3777078187aSMiklos Szeredi if (!forget) 378c180eebeSMiklos Szeredi goto out; 379c180eebeSMiklos Szeredi 380fcee216bSMax Reitz attr_version = fuse_get_attr_version(fm->fc); 381c180eebeSMiklos Szeredi 382fcee216bSMax Reitz fuse_lookup_init(fm->fc, &args, nodeid, name, outarg); 383fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 384c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 385c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 386c180eebeSMiklos Szeredi goto out_put_forget; 387c180eebeSMiklos Szeredi 388c180eebeSMiklos Szeredi err = -EIO; 389c180eebeSMiklos Szeredi if (!outarg->nodeid) 390c180eebeSMiklos Szeredi goto out_put_forget; 391eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg->attr)) 392c180eebeSMiklos Szeredi goto out_put_forget; 393c180eebeSMiklos Szeredi 394c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 395c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 396c180eebeSMiklos Szeredi attr_version); 397c180eebeSMiklos Szeredi err = -ENOMEM; 398c180eebeSMiklos Szeredi if (!*inode) { 399fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1); 400c180eebeSMiklos Szeredi goto out; 401c180eebeSMiklos Szeredi } 402c180eebeSMiklos Szeredi err = 0; 403c180eebeSMiklos Szeredi 404c180eebeSMiklos Szeredi out_put_forget: 40507e77dcaSMiklos Szeredi kfree(forget); 406c180eebeSMiklos Szeredi out: 407c180eebeSMiklos Szeredi return err; 408c180eebeSMiklos Szeredi } 409c180eebeSMiklos Szeredi 4100aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 41100cd8dd3SAl Viro unsigned int flags) 412e5e5558eSMiklos Szeredi { 413e5e5558eSMiklos Szeredi int err; 414e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 415c180eebeSMiklos Szeredi struct inode *inode; 4160de6256dSMiklos Szeredi struct dentry *newent; 417c180eebeSMiklos Szeredi bool outarg_valid = true; 41863576c13SMiklos Szeredi bool locked; 419e5e5558eSMiklos Szeredi 4205d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 4215d069dbeSMiklos Szeredi return ERR_PTR(-EIO); 4225d069dbeSMiklos Szeredi 42363576c13SMiklos Szeredi locked = fuse_lock_inode(dir); 424c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 425c180eebeSMiklos Szeredi &outarg, &inode); 42663576c13SMiklos Szeredi fuse_unlock_inode(dir, locked); 427c180eebeSMiklos Szeredi if (err == -ENOENT) { 428c180eebeSMiklos Szeredi outarg_valid = false; 429c180eebeSMiklos Szeredi err = 0; 4302d51013eSMiklos Szeredi } 431c180eebeSMiklos Szeredi if (err) 432c180eebeSMiklos Szeredi goto out_err; 4332d51013eSMiklos Szeredi 434ee4e5271SMiklos Szeredi err = -EIO; 435c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 436c180eebeSMiklos Szeredi goto out_iput; 437e5e5558eSMiklos Szeredi 43841d28bcaSAl Viro newent = d_splice_alias(inode, entry); 439c180eebeSMiklos Szeredi err = PTR_ERR(newent); 440c180eebeSMiklos Szeredi if (IS_ERR(newent)) 4415835f339SMiklos Szeredi goto out_err; 442d2a85164SMiklos Szeredi 4430de6256dSMiklos Szeredi entry = newent ? newent : entry; 444c180eebeSMiklos Szeredi if (outarg_valid) 4451fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 4468cbdf1e6SMiklos Szeredi else 4478cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 448c180eebeSMiklos Szeredi 4496c26f717SMiklos Szeredi if (inode) 4504582a4abSFeng Shuo fuse_advise_use_readdirplus(dir); 4510de6256dSMiklos Szeredi return newent; 452c180eebeSMiklos Szeredi 453c180eebeSMiklos Szeredi out_iput: 454c180eebeSMiklos Szeredi iput(inode); 455c180eebeSMiklos Szeredi out_err: 456c180eebeSMiklos Szeredi return ERR_PTR(err); 457e5e5558eSMiklos Szeredi } 458e5e5558eSMiklos Szeredi 4596f9f1180SMiklos Szeredi /* 4606f9f1180SMiklos Szeredi * Atomic create+open operation 4616f9f1180SMiklos Szeredi * 4626f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 4636f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 4646f9f1180SMiklos Szeredi */ 465d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 46654d601cbSMiklos Szeredi struct file *file, unsigned int flags, 467b452a458SAl Viro umode_t mode) 468fd72faacSMiklos Szeredi { 469fd72faacSMiklos Szeredi int err; 470fd72faacSMiklos Szeredi struct inode *inode; 471fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 4727078187aSMiklos Szeredi FUSE_ARGS(args); 47307e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 474e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 475fd72faacSMiklos Szeredi struct fuse_open_out outopen; 476fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 477ebf84d0cSKirill Tkhai struct fuse_inode *fi; 478fd72faacSMiklos Szeredi struct fuse_file *ff; 479fd72faacSMiklos Szeredi 480af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 481af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 482af109bcaSMiklos Szeredi 48307e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 484c8ccbe03SMiklos Szeredi err = -ENOMEM; 48507e77dcaSMiklos Szeredi if (!forget) 486c8ccbe03SMiklos Szeredi goto out_err; 48751eb01e7SMiklos Szeredi 488ce1d5a49SMiklos Szeredi err = -ENOMEM; 489fcee216bSMax Reitz ff = fuse_file_alloc(fm); 490fd72faacSMiklos Szeredi if (!ff) 4917078187aSMiklos Szeredi goto out_put_forget_req; 492fd72faacSMiklos Szeredi 493fcee216bSMax Reitz if (!fm->fc->dont_mask) 494e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 495e0a43ddcSMiklos Szeredi 496fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 497fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4980e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 499fd72faacSMiklos Szeredi inarg.flags = flags; 500fd72faacSMiklos Szeredi inarg.mode = mode; 501e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 502643a666aSVivek Goyal 503643a666aSVivek Goyal if (fm->fc->handle_killpriv_v2 && (flags & O_TRUNC) && 504643a666aSVivek Goyal !(flags & O_EXCL) && !capable(CAP_FSETID)) { 505643a666aSVivek Goyal inarg.open_flags |= FUSE_OPEN_KILL_SUIDGID; 506643a666aSVivek Goyal } 507643a666aSVivek Goyal 508d5b48543SMiklos Szeredi args.opcode = FUSE_CREATE; 509d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 510d5b48543SMiklos Szeredi args.in_numargs = 2; 511d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 512d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 513d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 514d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 515d5b48543SMiklos Szeredi args.out_numargs = 2; 516d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outentry); 517d5b48543SMiklos Szeredi args.out_args[0].value = &outentry; 518d5b48543SMiklos Szeredi args.out_args[1].size = sizeof(outopen); 519d5b48543SMiklos Szeredi args.out_args[1].value = &outopen; 520fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 521c8ccbe03SMiklos Szeredi if (err) 522fd72faacSMiklos Szeredi goto out_free_ff; 523fd72faacSMiklos Szeredi 524fd72faacSMiklos Szeredi err = -EIO; 525eb59bd17SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) || 526eb59bd17SMiklos Szeredi fuse_invalid_attr(&outentry.attr)) 527fd72faacSMiklos Szeredi goto out_free_ff; 528fd72faacSMiklos Szeredi 529c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 530c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 531c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 532fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 5331fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 534fd72faacSMiklos Szeredi if (!inode) { 535fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 536ebf84d0cSKirill Tkhai fuse_sync_release(NULL, ff, flags); 537fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1); 538c8ccbe03SMiklos Szeredi err = -ENOMEM; 539c8ccbe03SMiklos Szeredi goto out_err; 540fd72faacSMiklos Szeredi } 54107e77dcaSMiklos Szeredi kfree(forget); 542fd72faacSMiklos Szeredi d_instantiate(entry, inode); 5431fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 544261aaba7SMiklos Szeredi fuse_dir_changed(dir); 545be12af3eSAl Viro err = finish_open(file, entry, generic_file_open); 54630d90494SAl Viro if (err) { 547ebf84d0cSKirill Tkhai fi = get_fuse_inode(inode); 548ebf84d0cSKirill Tkhai fuse_sync_release(fi, ff, flags); 549c8ccbe03SMiklos Szeredi } else { 550267d8444SMiklos Szeredi file->private_data = ff; 551c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 552c8ccbe03SMiklos Szeredi } 553d9585277SAl Viro return err; 554fd72faacSMiklos Szeredi 555fd72faacSMiklos Szeredi out_free_ff: 556fd72faacSMiklos Szeredi fuse_file_free(ff); 55751eb01e7SMiklos Szeredi out_put_forget_req: 55807e77dcaSMiklos Szeredi kfree(forget); 559c8ccbe03SMiklos Szeredi out_err: 560d9585277SAl Viro return err; 561c8ccbe03SMiklos Szeredi } 562c8ccbe03SMiklos Szeredi 563549c7297SChristian Brauner static int fuse_mknod(struct user_namespace *, struct inode *, struct dentry *, 564549c7297SChristian Brauner umode_t, dev_t); 565d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 56630d90494SAl Viro struct file *file, unsigned flags, 56744907d79SAl Viro umode_t mode) 568c8ccbe03SMiklos Szeredi { 569c8ccbe03SMiklos Szeredi int err; 570c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 571c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 572c8ccbe03SMiklos Szeredi 5735d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 5745d069dbeSMiklos Szeredi return -EIO; 5755d069dbeSMiklos Szeredi 57600699ad8SAl Viro if (d_in_lookup(entry)) { 57700cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 578c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 579d9585277SAl Viro return PTR_ERR(res); 580c8ccbe03SMiklos Szeredi 581c8ccbe03SMiklos Szeredi if (res) 582c8ccbe03SMiklos Szeredi entry = res; 583c8ccbe03SMiklos Szeredi } 584c8ccbe03SMiklos Szeredi 5852b0143b5SDavid Howells if (!(flags & O_CREAT) || d_really_is_positive(entry)) 586c8ccbe03SMiklos Szeredi goto no_open; 587c8ccbe03SMiklos Szeredi 588c8ccbe03SMiklos Szeredi /* Only creates */ 58973a09dd9SAl Viro file->f_mode |= FMODE_CREATED; 590c8ccbe03SMiklos Szeredi 591c8ccbe03SMiklos Szeredi if (fc->no_create) 592c8ccbe03SMiklos Szeredi goto mknod; 593c8ccbe03SMiklos Szeredi 594b452a458SAl Viro err = fuse_create_open(dir, entry, file, flags, mode); 595d9585277SAl Viro if (err == -ENOSYS) { 596c8ccbe03SMiklos Szeredi fc->no_create = 1; 597c8ccbe03SMiklos Szeredi goto mknod; 598c8ccbe03SMiklos Szeredi } 599c8ccbe03SMiklos Szeredi out_dput: 600c8ccbe03SMiklos Szeredi dput(res); 601d9585277SAl Viro return err; 602c8ccbe03SMiklos Szeredi 603c8ccbe03SMiklos Szeredi mknod: 604549c7297SChristian Brauner err = fuse_mknod(&init_user_ns, dir, entry, mode, 0); 605d9585277SAl Viro if (err) 606c8ccbe03SMiklos Szeredi goto out_dput; 607c8ccbe03SMiklos Szeredi no_open: 608e45198a6SAl Viro return finish_no_open(file, res); 609fd72faacSMiklos Szeredi } 610fd72faacSMiklos Szeredi 6116f9f1180SMiklos Szeredi /* 6126f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 6136f9f1180SMiklos Szeredi */ 614fcee216bSMax Reitz static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args, 6159e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 616541af6a0SAl Viro umode_t mode) 6179e6268dbSMiklos Szeredi { 6189e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 6199e6268dbSMiklos Szeredi struct inode *inode; 620c971e6a0SAl Viro struct dentry *d; 6219e6268dbSMiklos Szeredi int err; 62207e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 6232d51013eSMiklos Szeredi 6245d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 6255d069dbeSMiklos Szeredi return -EIO; 6265d069dbeSMiklos Szeredi 62707e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 6287078187aSMiklos Szeredi if (!forget) 62907e77dcaSMiklos Szeredi return -ENOMEM; 6309e6268dbSMiklos Szeredi 6310e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 632d5b48543SMiklos Szeredi args->nodeid = get_node_id(dir); 633d5b48543SMiklos Szeredi args->out_numargs = 1; 634d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(outarg); 635d5b48543SMiklos Szeredi args->out_args[0].value = &outarg; 636fcee216bSMax Reitz err = fuse_simple_request(fm, args); 6372d51013eSMiklos Szeredi if (err) 6382d51013eSMiklos Szeredi goto out_put_forget_req; 6392d51013eSMiklos Szeredi 64039ee059aSMiklos Szeredi err = -EIO; 641eb59bd17SMiklos Szeredi if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr)) 6422d51013eSMiklos Szeredi goto out_put_forget_req; 64339ee059aSMiklos Szeredi 64439ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 6452d51013eSMiklos Szeredi goto out_put_forget_req; 64639ee059aSMiklos Szeredi 6479e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 6481fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 6499e6268dbSMiklos Szeredi if (!inode) { 650fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1); 6519e6268dbSMiklos Szeredi return -ENOMEM; 6529e6268dbSMiklos Szeredi } 65307e77dcaSMiklos Szeredi kfree(forget); 6549e6268dbSMiklos Szeredi 655c971e6a0SAl Viro d_drop(entry); 656c971e6a0SAl Viro d = d_splice_alias(inode, entry); 657c971e6a0SAl Viro if (IS_ERR(d)) 658c971e6a0SAl Viro return PTR_ERR(d); 659d2a85164SMiklos Szeredi 660c971e6a0SAl Viro if (d) { 661c971e6a0SAl Viro fuse_change_entry_timeout(d, &outarg); 662c971e6a0SAl Viro dput(d); 663c971e6a0SAl Viro } else { 6641fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 665c971e6a0SAl Viro } 666261aaba7SMiklos Szeredi fuse_dir_changed(dir); 6679e6268dbSMiklos Szeredi return 0; 66839ee059aSMiklos Szeredi 6692d51013eSMiklos Szeredi out_put_forget_req: 67007e77dcaSMiklos Szeredi kfree(forget); 67139ee059aSMiklos Szeredi return err; 6729e6268dbSMiklos Szeredi } 6739e6268dbSMiklos Szeredi 674549c7297SChristian Brauner static int fuse_mknod(struct user_namespace *mnt_userns, struct inode *dir, 675549c7297SChristian Brauner struct dentry *entry, umode_t mode, dev_t rdev) 6769e6268dbSMiklos Szeredi { 6779e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 678fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 6797078187aSMiklos Szeredi FUSE_ARGS(args); 6809e6268dbSMiklos Szeredi 681fcee216bSMax Reitz if (!fm->fc->dont_mask) 682e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 683e0a43ddcSMiklos Szeredi 6849e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6859e6268dbSMiklos Szeredi inarg.mode = mode; 6869e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 687e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 688d5b48543SMiklos Szeredi args.opcode = FUSE_MKNOD; 689d5b48543SMiklos Szeredi args.in_numargs = 2; 690d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 691d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 692d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 693d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 694fcee216bSMax Reitz return create_new_entry(fm, &args, dir, entry, mode); 6959e6268dbSMiklos Szeredi } 6969e6268dbSMiklos Szeredi 697549c7297SChristian Brauner static int fuse_create(struct user_namespace *mnt_userns, struct inode *dir, 698549c7297SChristian Brauner struct dentry *entry, umode_t mode, bool excl) 6999e6268dbSMiklos Szeredi { 700549c7297SChristian Brauner return fuse_mknod(&init_user_ns, dir, entry, mode, 0); 7019e6268dbSMiklos Szeredi } 7029e6268dbSMiklos Szeredi 703549c7297SChristian Brauner static int fuse_mkdir(struct user_namespace *mnt_userns, struct inode *dir, 704549c7297SChristian Brauner struct dentry *entry, umode_t mode) 7059e6268dbSMiklos Szeredi { 7069e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 707fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 7087078187aSMiklos Szeredi FUSE_ARGS(args); 7099e6268dbSMiklos Szeredi 710fcee216bSMax Reitz if (!fm->fc->dont_mask) 711e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 712e0a43ddcSMiklos Szeredi 7139e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7149e6268dbSMiklos Szeredi inarg.mode = mode; 715e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 716d5b48543SMiklos Szeredi args.opcode = FUSE_MKDIR; 717d5b48543SMiklos Szeredi args.in_numargs = 2; 718d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 719d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 720d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 721d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 722fcee216bSMax Reitz return create_new_entry(fm, &args, dir, entry, S_IFDIR); 7239e6268dbSMiklos Szeredi } 7249e6268dbSMiklos Szeredi 725549c7297SChristian Brauner static int fuse_symlink(struct user_namespace *mnt_userns, struct inode *dir, 726549c7297SChristian Brauner struct dentry *entry, const char *link) 7279e6268dbSMiklos Szeredi { 728fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 7299e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 7307078187aSMiklos Szeredi FUSE_ARGS(args); 7319e6268dbSMiklos Szeredi 732d5b48543SMiklos Szeredi args.opcode = FUSE_SYMLINK; 733d5b48543SMiklos Szeredi args.in_numargs = 2; 734d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 735d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 736d5b48543SMiklos Szeredi args.in_args[1].size = len; 737d5b48543SMiklos Szeredi args.in_args[1].value = link; 738fcee216bSMax Reitz return create_new_entry(fm, &args, dir, entry, S_IFLNK); 7399e6268dbSMiklos Szeredi } 7409e6268dbSMiklos Szeredi 741703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode) 74231f3267bSMaxim Patlasov { 74331f3267bSMaxim Patlasov if (!IS_NOCMTIME(inode)) { 744c2050a45SDeepa Dinamani inode->i_ctime = current_time(inode); 74531f3267bSMaxim Patlasov mark_inode_dirty_sync(inode); 74631f3267bSMaxim Patlasov } 74731f3267bSMaxim Patlasov } 74831f3267bSMaxim Patlasov 7499e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 7509e6268dbSMiklos Szeredi { 7519e6268dbSMiklos Szeredi int err; 752fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 7537078187aSMiklos Szeredi FUSE_ARGS(args); 7549e6268dbSMiklos Szeredi 7555d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 7565d069dbeSMiklos Szeredi return -EIO; 7575d069dbeSMiklos Szeredi 758d5b48543SMiklos Szeredi args.opcode = FUSE_UNLINK; 759d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 760d5b48543SMiklos Szeredi args.in_numargs = 1; 761d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 762d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 763fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 7649e6268dbSMiklos Szeredi if (!err) { 7652b0143b5SDavid Howells struct inode *inode = d_inode(entry); 766ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 7679e6268dbSMiklos Szeredi 768f15ecfefSKirill Tkhai spin_lock(&fi->lock); 769fcee216bSMax Reitz fi->attr_version = atomic64_inc_return(&fm->fc->attr_version); 770dfca7cebSMiklos Szeredi /* 771dfca7cebSMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 772dfca7cebSMiklos Szeredi * happen if userspace filesystem is careless. It would be 773dfca7cebSMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 774dfca7cebSMiklos Szeredi * condition here 775dfca7cebSMiklos Szeredi */ 776dfca7cebSMiklos Szeredi if (inode->i_nlink > 0) 777ac45d613SMiklos Szeredi drop_nlink(inode); 778f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 7799e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 780261aaba7SMiklos Szeredi fuse_dir_changed(dir); 7818cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 78231f3267bSMaxim Patlasov fuse_update_ctime(inode); 7839e6268dbSMiklos Szeredi } else if (err == -EINTR) 7849e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7859e6268dbSMiklos Szeredi return err; 7869e6268dbSMiklos Szeredi } 7879e6268dbSMiklos Szeredi 7889e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 7899e6268dbSMiklos Szeredi { 7909e6268dbSMiklos Szeredi int err; 791fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 7927078187aSMiklos Szeredi FUSE_ARGS(args); 7939e6268dbSMiklos Szeredi 7945d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 7955d069dbeSMiklos Szeredi return -EIO; 7965d069dbeSMiklos Szeredi 797d5b48543SMiklos Szeredi args.opcode = FUSE_RMDIR; 798d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 799d5b48543SMiklos Szeredi args.in_numargs = 1; 800d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 801d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 802fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 8039e6268dbSMiklos Szeredi if (!err) { 8042b0143b5SDavid Howells clear_nlink(d_inode(entry)); 805261aaba7SMiklos Szeredi fuse_dir_changed(dir); 8068cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 8079e6268dbSMiklos Szeredi } else if (err == -EINTR) 8089e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 8099e6268dbSMiklos Szeredi return err; 8109e6268dbSMiklos Szeredi } 8119e6268dbSMiklos Szeredi 8121560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, 8131560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 8141560c974SMiklos Szeredi unsigned int flags, int opcode, size_t argsize) 8159e6268dbSMiklos Szeredi { 8169e6268dbSMiklos Szeredi int err; 8171560c974SMiklos Szeredi struct fuse_rename2_in inarg; 818fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(olddir); 8197078187aSMiklos Szeredi FUSE_ARGS(args); 8209e6268dbSMiklos Szeredi 8211560c974SMiklos Szeredi memset(&inarg, 0, argsize); 8229e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 8231560c974SMiklos Szeredi inarg.flags = flags; 824d5b48543SMiklos Szeredi args.opcode = opcode; 825d5b48543SMiklos Szeredi args.nodeid = get_node_id(olddir); 826d5b48543SMiklos Szeredi args.in_numargs = 3; 827d5b48543SMiklos Szeredi args.in_args[0].size = argsize; 828d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 829d5b48543SMiklos Szeredi args.in_args[1].size = oldent->d_name.len + 1; 830d5b48543SMiklos Szeredi args.in_args[1].value = oldent->d_name.name; 831d5b48543SMiklos Szeredi args.in_args[2].size = newent->d_name.len + 1; 832d5b48543SMiklos Szeredi args.in_args[2].value = newent->d_name.name; 833fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 8349e6268dbSMiklos Szeredi if (!err) { 83508b63307SMiklos Szeredi /* ctime changes */ 8362b0143b5SDavid Howells fuse_invalidate_attr(d_inode(oldent)); 8372b0143b5SDavid Howells fuse_update_ctime(d_inode(oldent)); 83808b63307SMiklos Szeredi 8391560c974SMiklos Szeredi if (flags & RENAME_EXCHANGE) { 8402b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 8412b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 8421560c974SMiklos Szeredi } 8431560c974SMiklos Szeredi 844261aaba7SMiklos Szeredi fuse_dir_changed(olddir); 8459e6268dbSMiklos Szeredi if (olddir != newdir) 846261aaba7SMiklos Szeredi fuse_dir_changed(newdir); 8478cbdf1e6SMiklos Szeredi 8488cbdf1e6SMiklos Szeredi /* newent will end up negative */ 8492b0143b5SDavid Howells if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { 8502b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 8518cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 8522b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 8535219f346SMiklos Szeredi } 8549e6268dbSMiklos Szeredi } else if (err == -EINTR) { 8559e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 8569e6268dbSMiklos Szeredi rename actually took place. If the invalidation 8579e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 8589e6268dbSMiklos Szeredi directory), then there can be inconsistency between 8599e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 8609e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 8612b0143b5SDavid Howells if (d_really_is_positive(newent)) 8629e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 8639e6268dbSMiklos Szeredi } 8649e6268dbSMiklos Szeredi 8659e6268dbSMiklos Szeredi return err; 8669e6268dbSMiklos Szeredi } 8679e6268dbSMiklos Szeredi 868549c7297SChristian Brauner static int fuse_rename2(struct user_namespace *mnt_userns, struct inode *olddir, 869549c7297SChristian Brauner struct dentry *oldent, struct inode *newdir, 870549c7297SChristian Brauner struct dentry *newent, unsigned int flags) 8711560c974SMiklos Szeredi { 8721560c974SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 8731560c974SMiklos Szeredi int err; 8741560c974SMiklos Szeredi 8755d069dbeSMiklos Szeredi if (fuse_is_bad(olddir)) 8765d069dbeSMiklos Szeredi return -EIO; 8775d069dbeSMiklos Szeredi 878519525faSVivek Goyal if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) 8791560c974SMiklos Szeredi return -EINVAL; 8801560c974SMiklos Szeredi 8814237ba43SMiklos Szeredi if (flags) { 8821560c974SMiklos Szeredi if (fc->no_rename2 || fc->minor < 23) 8831560c974SMiklos Szeredi return -EINVAL; 8841560c974SMiklos Szeredi 8851560c974SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, flags, 8864237ba43SMiklos Szeredi FUSE_RENAME2, 8874237ba43SMiklos Szeredi sizeof(struct fuse_rename2_in)); 8881560c974SMiklos Szeredi if (err == -ENOSYS) { 8891560c974SMiklos Szeredi fc->no_rename2 = 1; 8901560c974SMiklos Szeredi err = -EINVAL; 8911560c974SMiklos Szeredi } 8924237ba43SMiklos Szeredi } else { 8934237ba43SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, 0, 8944237ba43SMiklos Szeredi FUSE_RENAME, 8954237ba43SMiklos Szeredi sizeof(struct fuse_rename_in)); 8964237ba43SMiklos Szeredi } 8971560c974SMiklos Szeredi 8984237ba43SMiklos Szeredi return err; 8994237ba43SMiklos Szeredi } 9004237ba43SMiklos Szeredi 9019e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 9029e6268dbSMiklos Szeredi struct dentry *newent) 9039e6268dbSMiklos Szeredi { 9049e6268dbSMiklos Szeredi int err; 9059e6268dbSMiklos Szeredi struct fuse_link_in inarg; 9062b0143b5SDavid Howells struct inode *inode = d_inode(entry); 907fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 9087078187aSMiklos Szeredi FUSE_ARGS(args); 9099e6268dbSMiklos Szeredi 9109e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 9119e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 912d5b48543SMiklos Szeredi args.opcode = FUSE_LINK; 913d5b48543SMiklos Szeredi args.in_numargs = 2; 914d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 915d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 916d5b48543SMiklos Szeredi args.in_args[1].size = newent->d_name.len + 1; 917d5b48543SMiklos Szeredi args.in_args[1].value = newent->d_name.name; 918fcee216bSMax Reitz err = create_new_entry(fm, &args, newdir, newent, inode->i_mode); 9199e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 9209e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 9219e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 9229e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 9239e6268dbSMiklos Szeredi etc.) 9249e6268dbSMiklos Szeredi */ 925ac45d613SMiklos Szeredi if (!err) { 926ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 927ac45d613SMiklos Szeredi 928f15ecfefSKirill Tkhai spin_lock(&fi->lock); 929fcee216bSMax Reitz fi->attr_version = atomic64_inc_return(&fm->fc->attr_version); 930c634da71SMiklos Szeredi if (likely(inode->i_nlink < UINT_MAX)) 931ac45d613SMiklos Szeredi inc_nlink(inode); 932f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 9339e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 93431f3267bSMaxim Patlasov fuse_update_ctime(inode); 935ac45d613SMiklos Szeredi } else if (err == -EINTR) { 936ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 937ac45d613SMiklos Szeredi } 9389e6268dbSMiklos Szeredi return err; 9399e6268dbSMiklos Szeredi } 9409e6268dbSMiklos Szeredi 9411fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 9421fb69e78SMiklos Szeredi struct kstat *stat) 9431fb69e78SMiklos Szeredi { 944203627bbSMiklos Szeredi unsigned int blkbits; 9458373200bSPavel Emelyanov struct fuse_conn *fc = get_fuse_conn(inode); 9468373200bSPavel Emelyanov 9478373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 948b0aa7606SMaxim Patlasov if (fc->writeback_cache && S_ISREG(inode->i_mode)) { 9498373200bSPavel Emelyanov attr->size = i_size_read(inode); 950b0aa7606SMaxim Patlasov attr->mtime = inode->i_mtime.tv_sec; 951b0aa7606SMaxim Patlasov attr->mtimensec = inode->i_mtime.tv_nsec; 95231f3267bSMaxim Patlasov attr->ctime = inode->i_ctime.tv_sec; 95331f3267bSMaxim Patlasov attr->ctimensec = inode->i_ctime.tv_nsec; 954b0aa7606SMaxim Patlasov } 955203627bbSMiklos Szeredi 9561fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 9571fb69e78SMiklos Szeredi stat->ino = attr->ino; 9581fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 9591fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 9608cb08329SEric W. Biederman stat->uid = make_kuid(fc->user_ns, attr->uid); 9618cb08329SEric W. Biederman stat->gid = make_kgid(fc->user_ns, attr->gid); 9621fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 9631fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 9641fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 9651fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 9661fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 9671fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 9681fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 9691fb69e78SMiklos Szeredi stat->size = attr->size; 9701fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 971203627bbSMiklos Szeredi 972203627bbSMiklos Szeredi if (attr->blksize != 0) 973203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 974203627bbSMiklos Szeredi else 975203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 976203627bbSMiklos Szeredi 977203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 9781fb69e78SMiklos Szeredi } 9791fb69e78SMiklos Szeredi 980c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 981c79e322fSMiklos Szeredi struct file *file) 982e5e5558eSMiklos Szeredi { 983e5e5558eSMiklos Szeredi int err; 984c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 985c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 986fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 9877078187aSMiklos Szeredi FUSE_ARGS(args); 9881fb69e78SMiklos Szeredi u64 attr_version; 9891fb69e78SMiklos Szeredi 990fcee216bSMax Reitz attr_version = fuse_get_attr_version(fm->fc); 9911fb69e78SMiklos Szeredi 992c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 9930e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 994c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 995c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 996c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 997c79e322fSMiklos Szeredi 998c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 999c79e322fSMiklos Szeredi inarg.fh = ff->fh; 1000c79e322fSMiklos Szeredi } 1001d5b48543SMiklos Szeredi args.opcode = FUSE_GETATTR; 1002d5b48543SMiklos Szeredi args.nodeid = get_node_id(inode); 1003d5b48543SMiklos Szeredi args.in_numargs = 1; 1004d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 1005d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 1006d5b48543SMiklos Szeredi args.out_numargs = 1; 1007d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outarg); 1008d5b48543SMiklos Szeredi args.out_args[0].value = &outarg; 1009fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 1010e5e5558eSMiklos Szeredi if (!err) { 1011eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg.attr) || 10126e3e2c43SAl Viro inode_wrong_type(inode, outarg.attr.mode)) { 10135d069dbeSMiklos Szeredi fuse_make_bad(inode); 1014e5e5558eSMiklos Szeredi err = -EIO; 1015e5e5558eSMiklos Szeredi } else { 1016c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 1017c79e322fSMiklos Szeredi attr_timeout(&outarg), 10181fb69e78SMiklos Szeredi attr_version); 10191fb69e78SMiklos Szeredi if (stat) 1020c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 1021e5e5558eSMiklos Szeredi } 1022e5e5558eSMiklos Szeredi } 1023e5e5558eSMiklos Szeredi return err; 1024e5e5558eSMiklos Szeredi } 1025e5e5558eSMiklos Szeredi 10265b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file, 10272f1e8196SMiklos Szeredi struct kstat *stat, u32 request_mask, 10282f1e8196SMiklos Szeredi unsigned int flags) 1029bcb4be80SMiklos Szeredi { 1030bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 10315b97eeacSMiklos Szeredi int err = 0; 1032bf5c1898SMiklos Szeredi bool sync; 1033bcb4be80SMiklos Szeredi 1034bf5c1898SMiklos Szeredi if (flags & AT_STATX_FORCE_SYNC) 1035bf5c1898SMiklos Szeredi sync = true; 1036bf5c1898SMiklos Szeredi else if (flags & AT_STATX_DONT_SYNC) 1037bf5c1898SMiklos Szeredi sync = false; 10382f1e8196SMiklos Szeredi else if (request_mask & READ_ONCE(fi->inval_mask)) 10392f1e8196SMiklos Szeredi sync = true; 1040bf5c1898SMiklos Szeredi else 1041bf5c1898SMiklos Szeredi sync = time_before64(fi->i_time, get_jiffies_64()); 1042bf5c1898SMiklos Szeredi 1043bf5c1898SMiklos Szeredi if (sync) { 104460bcc88aSSeth Forshee forget_all_cached_acls(inode); 1045bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 10465b97eeacSMiklos Szeredi } else if (stat) { 10470d56a451SChristian Brauner generic_fillattr(&init_user_ns, inode, stat); 1048bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 104945c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 1050bcb4be80SMiklos Szeredi } 1051bcb4be80SMiklos Szeredi 1052bcb4be80SMiklos Szeredi return err; 1053bcb4be80SMiklos Szeredi } 1054bcb4be80SMiklos Szeredi 10555b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file) 10565b97eeacSMiklos Szeredi { 1057802dc049SMiklos Szeredi /* Do *not* need to get atime for internal purposes */ 1058802dc049SMiklos Szeredi return fuse_update_get_attr(inode, file, NULL, 1059802dc049SMiklos Szeredi STATX_BASIC_STATS & ~STATX_ATIME, 0); 10605b97eeacSMiklos Szeredi } 10615b97eeacSMiklos Szeredi 1062fcee216bSMax Reitz int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid, 1063451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 10643b463ae0SJohn Muir { 10653b463ae0SJohn Muir int err = -ENOTDIR; 10663b463ae0SJohn Muir struct inode *parent; 10673b463ae0SJohn Muir struct dentry *dir; 10683b463ae0SJohn Muir struct dentry *entry; 10693b463ae0SJohn Muir 1070fcee216bSMax Reitz parent = fuse_ilookup(fc, parent_nodeid, NULL); 10713b463ae0SJohn Muir if (!parent) 10723b463ae0SJohn Muir return -ENOENT; 10733b463ae0SJohn Muir 10745955102cSAl Viro inode_lock(parent); 10753b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 10763b463ae0SJohn Muir goto unlock; 10773b463ae0SJohn Muir 10783b463ae0SJohn Muir err = -ENOENT; 10793b463ae0SJohn Muir dir = d_find_alias(parent); 10803b463ae0SJohn Muir if (!dir) 10813b463ae0SJohn Muir goto unlock; 10823b463ae0SJohn Muir 10838387ff25SLinus Torvalds name->hash = full_name_hash(dir, name->name, name->len); 10843b463ae0SJohn Muir entry = d_lookup(dir, name); 10853b463ae0SJohn Muir dput(dir); 10863b463ae0SJohn Muir if (!entry) 10873b463ae0SJohn Muir goto unlock; 10883b463ae0SJohn Muir 1089261aaba7SMiklos Szeredi fuse_dir_changed(parent); 10903b463ae0SJohn Muir fuse_invalidate_entry(entry); 1091451d0f59SJohn Muir 10922b0143b5SDavid Howells if (child_nodeid != 0 && d_really_is_positive(entry)) { 10935955102cSAl Viro inode_lock(d_inode(entry)); 10942b0143b5SDavid Howells if (get_node_id(d_inode(entry)) != child_nodeid) { 1095451d0f59SJohn Muir err = -ENOENT; 1096451d0f59SJohn Muir goto badentry; 1097451d0f59SJohn Muir } 1098451d0f59SJohn Muir if (d_mountpoint(entry)) { 1099451d0f59SJohn Muir err = -EBUSY; 1100451d0f59SJohn Muir goto badentry; 1101451d0f59SJohn Muir } 1102e36cb0b8SDavid Howells if (d_is_dir(entry)) { 1103451d0f59SJohn Muir shrink_dcache_parent(entry); 1104451d0f59SJohn Muir if (!simple_empty(entry)) { 1105451d0f59SJohn Muir err = -ENOTEMPTY; 1106451d0f59SJohn Muir goto badentry; 1107451d0f59SJohn Muir } 11082b0143b5SDavid Howells d_inode(entry)->i_flags |= S_DEAD; 1109451d0f59SJohn Muir } 1110451d0f59SJohn Muir dont_mount(entry); 11112b0143b5SDavid Howells clear_nlink(d_inode(entry)); 11123b463ae0SJohn Muir err = 0; 1113451d0f59SJohn Muir badentry: 11145955102cSAl Viro inode_unlock(d_inode(entry)); 1115451d0f59SJohn Muir if (!err) 1116451d0f59SJohn Muir d_delete(entry); 1117451d0f59SJohn Muir } else { 1118451d0f59SJohn Muir err = 0; 1119451d0f59SJohn Muir } 1120451d0f59SJohn Muir dput(entry); 11213b463ae0SJohn Muir 11223b463ae0SJohn Muir unlock: 11235955102cSAl Viro inode_unlock(parent); 11243b463ae0SJohn Muir iput(parent); 11253b463ae0SJohn Muir return err; 11263b463ae0SJohn Muir } 11273b463ae0SJohn Muir 112887729a55SMiklos Szeredi /* 112987729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1130c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 113187729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 113287729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 113387729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 113487729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 113587729a55SMiklos Szeredi * DoS against the requester. 113687729a55SMiklos Szeredi * 113787729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 113887729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 113987729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 114087729a55SMiklos Szeredi */ 1141c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc) 114287729a55SMiklos Szeredi { 1143c69e8d9cSDavid Howells const struct cred *cred; 1144c69e8d9cSDavid Howells 114529433a29SMiklos Szeredi if (fc->allow_other) 114673f03c2bSSeth Forshee return current_in_userns(fc->user_ns); 114787729a55SMiklos Szeredi 1148c2132c1bSAnatol Pomozov cred = current_cred(); 1149499dcf20SEric W. Biederman if (uid_eq(cred->euid, fc->user_id) && 1150499dcf20SEric W. Biederman uid_eq(cred->suid, fc->user_id) && 1151499dcf20SEric W. Biederman uid_eq(cred->uid, fc->user_id) && 1152499dcf20SEric W. Biederman gid_eq(cred->egid, fc->group_id) && 1153499dcf20SEric W. Biederman gid_eq(cred->sgid, fc->group_id) && 1154499dcf20SEric W. Biederman gid_eq(cred->gid, fc->group_id)) 1155c2132c1bSAnatol Pomozov return 1; 115687729a55SMiklos Szeredi 1157c2132c1bSAnatol Pomozov return 0; 115887729a55SMiklos Szeredi } 115987729a55SMiklos Szeredi 116031d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 116131d40d74SMiklos Szeredi { 1162fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 11637078187aSMiklos Szeredi FUSE_ARGS(args); 116431d40d74SMiklos Szeredi struct fuse_access_in inarg; 116531d40d74SMiklos Szeredi int err; 116631d40d74SMiklos Szeredi 1167698fa1d1SMiklos Szeredi BUG_ON(mask & MAY_NOT_BLOCK); 1168698fa1d1SMiklos Szeredi 1169fcee216bSMax Reitz if (fm->fc->no_access) 117031d40d74SMiklos Szeredi return 0; 117131d40d74SMiklos Szeredi 117231d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1173e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 1174d5b48543SMiklos Szeredi args.opcode = FUSE_ACCESS; 1175d5b48543SMiklos Szeredi args.nodeid = get_node_id(inode); 1176d5b48543SMiklos Szeredi args.in_numargs = 1; 1177d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 1178d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 1179fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 118031d40d74SMiklos Szeredi if (err == -ENOSYS) { 1181fcee216bSMax Reitz fm->fc->no_access = 1; 118231d40d74SMiklos Szeredi err = 0; 118331d40d74SMiklos Szeredi } 118431d40d74SMiklos Szeredi return err; 118531d40d74SMiklos Szeredi } 118631d40d74SMiklos Szeredi 118710556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 118819690ddbSMiklos Szeredi { 118910556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 119019690ddbSMiklos Szeredi return -ECHILD; 119119690ddbSMiklos Szeredi 119260bcc88aSSeth Forshee forget_all_cached_acls(inode); 119319690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 119419690ddbSMiklos Szeredi } 119519690ddbSMiklos Szeredi 11966f9f1180SMiklos Szeredi /* 11976f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 11986f9f1180SMiklos Szeredi * 11996f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 12006f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 12016f9f1180SMiklos Szeredi * modell. 12026f9f1180SMiklos Szeredi * 12036f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 12046f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 12056f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 12066f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 12076f9f1180SMiklos Szeredi * locally based on file mode. 12086f9f1180SMiklos Szeredi */ 1209549c7297SChristian Brauner static int fuse_permission(struct user_namespace *mnt_userns, 1210549c7297SChristian Brauner struct inode *inode, int mask) 1211e5e5558eSMiklos Szeredi { 1212e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1213244f6385SMiklos Szeredi bool refreshed = false; 1214244f6385SMiklos Szeredi int err = 0; 1215e5e5558eSMiklos Szeredi 12165d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 12175d069dbeSMiklos Szeredi return -EIO; 12185d069dbeSMiklos Szeredi 1219c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1220e5e5558eSMiklos Szeredi return -EACCES; 1221244f6385SMiklos Szeredi 1222244f6385SMiklos Szeredi /* 1223e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1224244f6385SMiklos Szeredi */ 122529433a29SMiklos Szeredi if (fc->default_permissions || 1226e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 122719690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1228d233c7ddSMiklos Szeredi u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID; 122919690ddbSMiklos Szeredi 1230d233c7ddSMiklos Szeredi if (perm_mask & READ_ONCE(fi->inval_mask) || 1231d233c7ddSMiklos Szeredi time_before64(fi->i_time, get_jiffies_64())) { 123219690ddbSMiklos Szeredi refreshed = true; 123319690ddbSMiklos Szeredi 123410556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1235244f6385SMiklos Szeredi if (err) 1236244f6385SMiklos Szeredi return err; 12371fb69e78SMiklos Szeredi } 123819690ddbSMiklos Szeredi } 1239244f6385SMiklos Szeredi 124029433a29SMiklos Szeredi if (fc->default_permissions) { 124147291baaSChristian Brauner err = generic_permission(&init_user_ns, inode, mask); 12421e9a4ed9SMiklos Szeredi 12431e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 12441e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 12451e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1246244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 124710556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 12481e9a4ed9SMiklos Szeredi if (!err) 124947291baaSChristian Brauner err = generic_permission(&init_user_ns, 125047291baaSChristian Brauner inode, mask); 12511e9a4ed9SMiklos Szeredi } 12521e9a4ed9SMiklos Szeredi 12536f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 12546f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 12556f9f1180SMiklos Szeredi noticed immediately, only after the attribute 12566f9f1180SMiklos Szeredi timeout has expired */ 12579cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1258e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1259e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1260e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1261e8e96157SMiklos Szeredi if (refreshed) 1262e5e5558eSMiklos Szeredi return -EACCES; 126331d40d74SMiklos Szeredi 126410556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1265e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1266e8e96157SMiklos Szeredi return -EACCES; 1267e8e96157SMiklos Szeredi } 1268e5e5558eSMiklos Szeredi } 1269244f6385SMiklos Szeredi return err; 1270e5e5558eSMiklos Szeredi } 1271e5e5558eSMiklos Szeredi 12725571f1e6SDan Schatzberg static int fuse_readlink_page(struct inode *inode, struct page *page) 1273e5e5558eSMiklos Szeredi { 1274fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 12754c29afecSMiklos Szeredi struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 }; 12764c29afecSMiklos Szeredi struct fuse_args_pages ap = { 12774c29afecSMiklos Szeredi .num_pages = 1, 12784c29afecSMiklos Szeredi .pages = &page, 12794c29afecSMiklos Szeredi .descs = &desc, 12804c29afecSMiklos Szeredi }; 12814c29afecSMiklos Szeredi char *link; 12824c29afecSMiklos Szeredi ssize_t res; 1283e5e5558eSMiklos Szeredi 12844c29afecSMiklos Szeredi ap.args.opcode = FUSE_READLINK; 12854c29afecSMiklos Szeredi ap.args.nodeid = get_node_id(inode); 12864c29afecSMiklos Szeredi ap.args.out_pages = true; 12874c29afecSMiklos Szeredi ap.args.out_argvar = true; 12884c29afecSMiklos Szeredi ap.args.page_zeroing = true; 12894c29afecSMiklos Szeredi ap.args.out_numargs = 1; 12904c29afecSMiklos Szeredi ap.args.out_args[0].size = desc.length; 1291fcee216bSMax Reitz res = fuse_simple_request(fm, &ap.args); 12926b255391SAl Viro 1293451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 12945571f1e6SDan Schatzberg 12954c29afecSMiklos Szeredi if (res < 0) 12964c29afecSMiklos Szeredi return res; 12974c29afecSMiklos Szeredi 12984c29afecSMiklos Szeredi if (WARN_ON(res >= PAGE_SIZE)) 12994c29afecSMiklos Szeredi return -EIO; 13004c29afecSMiklos Szeredi 13014c29afecSMiklos Szeredi link = page_address(page); 13024c29afecSMiklos Szeredi link[res] = '\0'; 13034c29afecSMiklos Szeredi 13044c29afecSMiklos Szeredi return 0; 13055571f1e6SDan Schatzberg } 13065571f1e6SDan Schatzberg 13075571f1e6SDan Schatzberg static const char *fuse_get_link(struct dentry *dentry, struct inode *inode, 13085571f1e6SDan Schatzberg struct delayed_call *callback) 13095571f1e6SDan Schatzberg { 13105571f1e6SDan Schatzberg struct fuse_conn *fc = get_fuse_conn(inode); 13115571f1e6SDan Schatzberg struct page *page; 13125571f1e6SDan Schatzberg int err; 13135571f1e6SDan Schatzberg 13145571f1e6SDan Schatzberg err = -EIO; 13155d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 13165571f1e6SDan Schatzberg goto out_err; 13175571f1e6SDan Schatzberg 13185571f1e6SDan Schatzberg if (fc->cache_symlinks) 13195571f1e6SDan Schatzberg return page_get_link(dentry, inode, callback); 13205571f1e6SDan Schatzberg 13215571f1e6SDan Schatzberg err = -ECHILD; 13225571f1e6SDan Schatzberg if (!dentry) 13235571f1e6SDan Schatzberg goto out_err; 13245571f1e6SDan Schatzberg 13255571f1e6SDan Schatzberg page = alloc_page(GFP_KERNEL); 13265571f1e6SDan Schatzberg err = -ENOMEM; 13275571f1e6SDan Schatzberg if (!page) 13285571f1e6SDan Schatzberg goto out_err; 13295571f1e6SDan Schatzberg 13305571f1e6SDan Schatzberg err = fuse_readlink_page(inode, page); 13315571f1e6SDan Schatzberg if (err) { 13325571f1e6SDan Schatzberg __free_page(page); 13335571f1e6SDan Schatzberg goto out_err; 13345571f1e6SDan Schatzberg } 13355571f1e6SDan Schatzberg 13365571f1e6SDan Schatzberg set_delayed_call(callback, page_put_link, page); 13375571f1e6SDan Schatzberg 13385571f1e6SDan Schatzberg return page_address(page); 13395571f1e6SDan Schatzberg 13405571f1e6SDan Schatzberg out_err: 13415571f1e6SDan Schatzberg return ERR_PTR(err); 1342e5e5558eSMiklos Szeredi } 1343e5e5558eSMiklos Szeredi 1344e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1345e5e5558eSMiklos Szeredi { 134691fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1347e5e5558eSMiklos Szeredi } 1348e5e5558eSMiklos Szeredi 1349e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1350e5e5558eSMiklos Szeredi { 13512e64ff15SChad Austin fuse_release_common(file, true); 13528b0797a4SMiklos Szeredi 13538b0797a4SMiklos Szeredi return 0; 1354e5e5558eSMiklos Szeredi } 1355e5e5558eSMiklos Szeredi 135602c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 135702c24a82SJosef Bacik int datasync) 135882547981SMiklos Szeredi { 1359a9c2d1e8SMiklos Szeredi struct inode *inode = file->f_mapping->host; 1360a9c2d1e8SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1361a9c2d1e8SMiklos Szeredi int err; 1362a9c2d1e8SMiklos Szeredi 13635d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 1364a9c2d1e8SMiklos Szeredi return -EIO; 1365a9c2d1e8SMiklos Szeredi 1366a9c2d1e8SMiklos Szeredi if (fc->no_fsyncdir) 1367a9c2d1e8SMiklos Szeredi return 0; 1368a9c2d1e8SMiklos Szeredi 1369a9c2d1e8SMiklos Szeredi inode_lock(inode); 1370a9c2d1e8SMiklos Szeredi err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR); 1371a9c2d1e8SMiklos Szeredi if (err == -ENOSYS) { 1372a9c2d1e8SMiklos Szeredi fc->no_fsyncdir = 1; 1373a9c2d1e8SMiklos Szeredi err = 0; 1374a9c2d1e8SMiklos Szeredi } 1375a9c2d1e8SMiklos Szeredi inode_unlock(inode); 1376a9c2d1e8SMiklos Szeredi 1377a9c2d1e8SMiklos Szeredi return err; 137882547981SMiklos Szeredi } 137982547981SMiklos Szeredi 1380b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1381b18da0c5SMiklos Szeredi unsigned long arg) 1382b18da0c5SMiklos Szeredi { 1383b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1384b18da0c5SMiklos Szeredi 1385b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1386b18da0c5SMiklos Szeredi if (fc->minor < 18) 1387b18da0c5SMiklos Szeredi return -ENOTTY; 1388b18da0c5SMiklos Szeredi 1389b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1390b18da0c5SMiklos Szeredi } 1391b18da0c5SMiklos Szeredi 1392b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1393b18da0c5SMiklos Szeredi unsigned long arg) 1394b18da0c5SMiklos Szeredi { 1395b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1396b18da0c5SMiklos Szeredi 1397b18da0c5SMiklos Szeredi if (fc->minor < 18) 1398b18da0c5SMiklos Szeredi return -ENOTTY; 1399b18da0c5SMiklos Szeredi 1400b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1401b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1402b18da0c5SMiklos Szeredi } 1403b18da0c5SMiklos Szeredi 1404b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime) 140517637cbaSMiklos Szeredi { 140617637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 140717637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 140817637cbaSMiklos Szeredi return true; 140917637cbaSMiklos Szeredi 1410b0aa7606SMaxim Patlasov /* Or if kernel i_mtime is the official one */ 1411b0aa7606SMaxim Patlasov if (trust_local_mtime) 1412b0aa7606SMaxim Patlasov return true; 1413b0aa7606SMaxim Patlasov 141417637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 141517637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 141617637cbaSMiklos Szeredi return false; 141717637cbaSMiklos Szeredi 141817637cbaSMiklos Szeredi /* In all other cases update */ 141917637cbaSMiklos Szeredi return true; 142017637cbaSMiklos Szeredi } 142117637cbaSMiklos Szeredi 14228cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr, 14238cb08329SEric W. Biederman struct fuse_setattr_in *arg, bool trust_local_cmtime) 14249e6268dbSMiklos Szeredi { 14259e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 14269e6268dbSMiklos Szeredi 14279e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1428befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 14299e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 14308cb08329SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid); 14319e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 14328cb08329SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid); 14339e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1434befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 143517637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 143617637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1437befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 143817637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 143917637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 144017637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 144117637cbaSMiklos Szeredi } 14423ad22c62SMaxim Patlasov if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) { 144317637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1444befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 144517637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 14463ad22c62SMaxim Patlasov if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime) 144717637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 14489e6268dbSMiklos Szeredi } 14493ad22c62SMaxim Patlasov if ((ivalid & ATTR_CTIME) && trust_local_cmtime) { 14503ad22c62SMaxim Patlasov arg->valid |= FATTR_CTIME; 14513ad22c62SMaxim Patlasov arg->ctime = iattr->ia_ctime.tv_sec; 14523ad22c62SMaxim Patlasov arg->ctimensec = iattr->ia_ctime.tv_nsec; 14533ad22c62SMaxim Patlasov } 14549e6268dbSMiklos Szeredi } 14559e6268dbSMiklos Szeredi 14566f9f1180SMiklos Szeredi /* 14573be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 14583be5a52bSMiklos Szeredi * 14593be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 14603be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 14613be5a52bSMiklos Szeredi */ 14623be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 14633be5a52bSMiklos Szeredi { 14643be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 14653be5a52bSMiklos Szeredi 14665955102cSAl Viro BUG_ON(!inode_is_locked(inode)); 14673be5a52bSMiklos Szeredi 1468f15ecfefSKirill Tkhai spin_lock(&fi->lock); 14693be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 14703be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 1471f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 14723be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 14733be5a52bSMiklos Szeredi } 14743be5a52bSMiklos Szeredi 14753be5a52bSMiklos Szeredi /* 14763be5a52bSMiklos Szeredi * Allow writepages on inode 14773be5a52bSMiklos Szeredi * 14783be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 14793be5a52bSMiklos Szeredi * writepages. 14803be5a52bSMiklos Szeredi */ 14813be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 14823be5a52bSMiklos Szeredi { 14833be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 14843be5a52bSMiklos Szeredi 14853be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 14863be5a52bSMiklos Szeredi fi->writectr = 0; 14873be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 14883be5a52bSMiklos Szeredi } 14893be5a52bSMiklos Szeredi 14903be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 14913be5a52bSMiklos Szeredi { 1492f15ecfefSKirill Tkhai struct fuse_inode *fi = get_fuse_inode(inode); 14933be5a52bSMiklos Szeredi 1494f15ecfefSKirill Tkhai spin_lock(&fi->lock); 14953be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 1496f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 14973be5a52bSMiklos Szeredi } 14983be5a52bSMiklos Szeredi 14997078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, 1500b0aa7606SMaxim Patlasov struct inode *inode, 1501b0aa7606SMaxim Patlasov struct fuse_setattr_in *inarg_p, 1502b0aa7606SMaxim Patlasov struct fuse_attr_out *outarg_p) 1503b0aa7606SMaxim Patlasov { 1504d5b48543SMiklos Szeredi args->opcode = FUSE_SETATTR; 1505d5b48543SMiklos Szeredi args->nodeid = get_node_id(inode); 1506d5b48543SMiklos Szeredi args->in_numargs = 1; 1507d5b48543SMiklos Szeredi args->in_args[0].size = sizeof(*inarg_p); 1508d5b48543SMiklos Szeredi args->in_args[0].value = inarg_p; 1509d5b48543SMiklos Szeredi args->out_numargs = 1; 1510d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(*outarg_p); 1511d5b48543SMiklos Szeredi args->out_args[0].value = outarg_p; 1512b0aa7606SMaxim Patlasov } 1513b0aa7606SMaxim Patlasov 1514b0aa7606SMaxim Patlasov /* 1515b0aa7606SMaxim Patlasov * Flush inode->i_mtime to the server 1516b0aa7606SMaxim Patlasov */ 1517ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff) 1518b0aa7606SMaxim Patlasov { 1519fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 15207078187aSMiklos Szeredi FUSE_ARGS(args); 1521b0aa7606SMaxim Patlasov struct fuse_setattr_in inarg; 1522b0aa7606SMaxim Patlasov struct fuse_attr_out outarg; 1523b0aa7606SMaxim Patlasov 1524b0aa7606SMaxim Patlasov memset(&inarg, 0, sizeof(inarg)); 1525b0aa7606SMaxim Patlasov memset(&outarg, 0, sizeof(outarg)); 1526b0aa7606SMaxim Patlasov 1527ab9e13f7SMaxim Patlasov inarg.valid = FATTR_MTIME; 1528b0aa7606SMaxim Patlasov inarg.mtime = inode->i_mtime.tv_sec; 1529b0aa7606SMaxim Patlasov inarg.mtimensec = inode->i_mtime.tv_nsec; 1530fcee216bSMax Reitz if (fm->fc->minor >= 23) { 1531ab9e13f7SMaxim Patlasov inarg.valid |= FATTR_CTIME; 1532ab9e13f7SMaxim Patlasov inarg.ctime = inode->i_ctime.tv_sec; 1533ab9e13f7SMaxim Patlasov inarg.ctimensec = inode->i_ctime.tv_nsec; 1534ab9e13f7SMaxim Patlasov } 15351e18bda8SMiklos Szeredi if (ff) { 15361e18bda8SMiklos Szeredi inarg.valid |= FATTR_FH; 15371e18bda8SMiklos Szeredi inarg.fh = ff->fh; 15381e18bda8SMiklos Szeredi } 1539fcee216bSMax Reitz fuse_setattr_fill(fm->fc, &args, inode, &inarg, &outarg); 1540b0aa7606SMaxim Patlasov 1541fcee216bSMax Reitz return fuse_simple_request(fm, &args); 1542b0aa7606SMaxim Patlasov } 1543b0aa7606SMaxim Patlasov 15443be5a52bSMiklos Szeredi /* 15456f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 15466f9f1180SMiklos Szeredi * 15476f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 15486f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 15499ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 15509ffbb916SMiklos Szeredi * and the actual truncation by hand. 15516f9f1180SMiklos Szeredi */ 155262490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, 155349d4914fSMiklos Szeredi struct file *file) 15549e6268dbSMiklos Szeredi { 155562490330SJan Kara struct inode *inode = d_inode(dentry); 1556fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 1557fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 155806a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 1559*8bcbbe9cSJan Kara struct address_space *mapping = inode->i_mapping; 15607078187aSMiklos Szeredi FUSE_ARGS(args); 15619e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 15629e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 15633be5a52bSMiklos Szeredi bool is_truncate = false; 15648373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 15653be5a52bSMiklos Szeredi loff_t oldsize; 15669e6268dbSMiklos Szeredi int err; 15673ad22c62SMaxim Patlasov bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode); 15686ae330caSVivek Goyal bool fault_blocked = false; 15699e6268dbSMiklos Szeredi 157029433a29SMiklos Szeredi if (!fc->default_permissions) 1571db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1572db78b877SChristoph Hellwig 15732f221d6fSChristian Brauner err = setattr_prepare(&init_user_ns, dentry, attr); 15741e9a4ed9SMiklos Szeredi if (err) 15751e9a4ed9SMiklos Szeredi return err; 15761e9a4ed9SMiklos Szeredi 15776ae330caSVivek Goyal if (attr->ia_valid & ATTR_SIZE) { 15786ae330caSVivek Goyal if (WARN_ON(!S_ISREG(inode->i_mode))) 15796ae330caSVivek Goyal return -EIO; 15806ae330caSVivek Goyal is_truncate = true; 15816ae330caSVivek Goyal } 15826ae330caSVivek Goyal 15836ae330caSVivek Goyal if (FUSE_IS_DAX(inode) && is_truncate) { 1584*8bcbbe9cSJan Kara filemap_invalidate_lock(mapping); 15856ae330caSVivek Goyal fault_blocked = true; 15866ae330caSVivek Goyal err = fuse_dax_break_layouts(inode, 0, 0); 15876ae330caSVivek Goyal if (err) { 1588*8bcbbe9cSJan Kara filemap_invalidate_unlock(mapping); 15896ae330caSVivek Goyal return err; 15906ae330caSVivek Goyal } 15916ae330caSVivek Goyal } 15926ae330caSVivek Goyal 15938d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 1594df0e91d4SMiklos Szeredi /* This is coming from open(..., ... | O_TRUNC); */ 1595df0e91d4SMiklos Szeredi WARN_ON(!(attr->ia_valid & ATTR_SIZE)); 1596df0e91d4SMiklos Szeredi WARN_ON(attr->ia_size != 0); 1597df0e91d4SMiklos Szeredi if (fc->atomic_o_trunc) { 1598df0e91d4SMiklos Szeredi /* 1599df0e91d4SMiklos Szeredi * No need to send request to userspace, since actual 1600df0e91d4SMiklos Szeredi * truncation has already been done by OPEN. But still 1601df0e91d4SMiklos Szeredi * need to truncate page cache. 1602df0e91d4SMiklos Szeredi */ 1603df0e91d4SMiklos Szeredi i_size_write(inode, 0); 1604df0e91d4SMiklos Szeredi truncate_pagecache(inode, 0); 16056ae330caSVivek Goyal goto out; 1606df0e91d4SMiklos Szeredi } 16078d56adddSMiklos Szeredi file = NULL; 16088d56adddSMiklos Szeredi } 16096ff958edSMiklos Szeredi 1610b24e7598SMiklos Szeredi /* Flush dirty data/metadata before non-truncate SETATTR */ 1611b24e7598SMiklos Szeredi if (is_wb && S_ISREG(inode->i_mode) && 1612b24e7598SMiklos Szeredi attr->ia_valid & 1613b24e7598SMiklos Szeredi (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET | 1614b24e7598SMiklos Szeredi ATTR_TIMES_SET)) { 1615b24e7598SMiklos Szeredi err = write_inode_now(inode, true); 1616b24e7598SMiklos Szeredi if (err) 1617b24e7598SMiklos Szeredi return err; 1618b24e7598SMiklos Szeredi 1619b24e7598SMiklos Szeredi fuse_set_nowrite(inode); 1620b24e7598SMiklos Szeredi fuse_release_nowrite(inode); 1621b24e7598SMiklos Szeredi } 1622b24e7598SMiklos Szeredi 162306a7c3c2SMaxim Patlasov if (is_truncate) { 16243be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 162506a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 16263ad22c62SMaxim Patlasov if (trust_local_cmtime && attr->ia_size != inode->i_size) 16273ad22c62SMaxim Patlasov attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; 162806a7c3c2SMaxim Patlasov } 16293be5a52bSMiklos Szeredi 16309e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 16310e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 16328cb08329SEric W. Biederman iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime); 163349d4914fSMiklos Szeredi if (file) { 163449d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 163549d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 163649d4914fSMiklos Szeredi inarg.fh = ff->fh; 163749d4914fSMiklos Szeredi } 163831792161SVivek Goyal 163931792161SVivek Goyal /* Kill suid/sgid for non-directory chown unconditionally */ 164031792161SVivek Goyal if (fc->handle_killpriv_v2 && !S_ISDIR(inode->i_mode) && 164131792161SVivek Goyal attr->ia_valid & (ATTR_UID | ATTR_GID)) 164231792161SVivek Goyal inarg.valid |= FATTR_KILL_SUIDGID; 164331792161SVivek Goyal 1644f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1645f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1646f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1647f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 164831792161SVivek Goyal 164931792161SVivek Goyal /* Kill suid/sgid for truncate only if no CAP_FSETID */ 165031792161SVivek Goyal if (fc->handle_killpriv_v2 && !capable(CAP_FSETID)) 165131792161SVivek Goyal inarg.valid |= FATTR_KILL_SUIDGID; 1652f3332114SMiklos Szeredi } 16537078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 1654fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 1655e00d2c2dSMiklos Szeredi if (err) { 1656e00d2c2dSMiklos Szeredi if (err == -EINTR) 1657e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 16583be5a52bSMiklos Szeredi goto error; 1659e00d2c2dSMiklos Szeredi } 1660e00d2c2dSMiklos Szeredi 1661eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg.attr) || 16626e3e2c43SAl Viro inode_wrong_type(inode, outarg.attr.mode)) { 16635d069dbeSMiklos Szeredi fuse_make_bad(inode); 16643be5a52bSMiklos Szeredi err = -EIO; 16653be5a52bSMiklos Szeredi goto error; 16669e6268dbSMiklos Szeredi } 16679e6268dbSMiklos Szeredi 1668f15ecfefSKirill Tkhai spin_lock(&fi->lock); 1669b0aa7606SMaxim Patlasov /* the kernel maintains i_mtime locally */ 16703ad22c62SMaxim Patlasov if (trust_local_cmtime) { 16713ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_MTIME) 1672b0aa7606SMaxim Patlasov inode->i_mtime = attr->ia_mtime; 16733ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_CTIME) 16743ad22c62SMaxim Patlasov inode->i_ctime = attr->ia_ctime; 16751e18bda8SMiklos Szeredi /* FIXME: clear I_DIRTY_SYNC? */ 1676b0aa7606SMaxim Patlasov } 1677b0aa7606SMaxim Patlasov 16783be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 16793be5a52bSMiklos Szeredi attr_timeout(&outarg)); 16803be5a52bSMiklos Szeredi oldsize = inode->i_size; 16818373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 16828373200bSPavel Emelyanov if (!is_wb || is_truncate || !S_ISREG(inode->i_mode)) 16833be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 16843be5a52bSMiklos Szeredi 16853be5a52bSMiklos Szeredi if (is_truncate) { 1686f15ecfefSKirill Tkhai /* NOTE: this may release/reacquire fi->lock */ 16873be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 16883be5a52bSMiklos Szeredi } 1689f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 16903be5a52bSMiklos Szeredi 16913be5a52bSMiklos Szeredi /* 16923be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 16933be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 16943be5a52bSMiklos Szeredi */ 16958373200bSPavel Emelyanov if ((is_truncate || !is_wb) && 16968373200bSPavel Emelyanov S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 16977caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 1698*8bcbbe9cSJan Kara invalidate_inode_pages2(mapping); 16993be5a52bSMiklos Szeredi } 17003be5a52bSMiklos Szeredi 170106a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 17026ae330caSVivek Goyal out: 17036ae330caSVivek Goyal if (fault_blocked) 1704*8bcbbe9cSJan Kara filemap_invalidate_unlock(mapping); 17056ae330caSVivek Goyal 1706e00d2c2dSMiklos Szeredi return 0; 17073be5a52bSMiklos Szeredi 17083be5a52bSMiklos Szeredi error: 17093be5a52bSMiklos Szeredi if (is_truncate) 17103be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 17113be5a52bSMiklos Szeredi 171206a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 17136ae330caSVivek Goyal 17146ae330caSVivek Goyal if (fault_blocked) 1715*8bcbbe9cSJan Kara filemap_invalidate_unlock(mapping); 17163be5a52bSMiklos Szeredi return err; 17179e6268dbSMiklos Szeredi } 17189e6268dbSMiklos Szeredi 1719549c7297SChristian Brauner static int fuse_setattr(struct user_namespace *mnt_userns, struct dentry *entry, 1720549c7297SChristian Brauner struct iattr *attr) 172149d4914fSMiklos Szeredi { 17222b0143b5SDavid Howells struct inode *inode = d_inode(entry); 17235e940c1dSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1724a09f99edSMiklos Szeredi struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL; 17255e2b8828SMiklos Szeredi int ret; 1726efb9fa9eSMaxim Patlasov 17275d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 17285d069dbeSMiklos Szeredi return -EIO; 17295d069dbeSMiklos Szeredi 1730efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1731efb9fa9eSMaxim Patlasov return -EACCES; 1732efb9fa9eSMaxim Patlasov 1733a09f99edSMiklos Szeredi if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) { 1734a09f99edSMiklos Szeredi attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | 1735a09f99edSMiklos Szeredi ATTR_MODE); 17365e940c1dSMiklos Szeredi 1737a09f99edSMiklos Szeredi /* 17385e940c1dSMiklos Szeredi * The only sane way to reliably kill suid/sgid is to do it in 17395e940c1dSMiklos Szeredi * the userspace filesystem 17405e940c1dSMiklos Szeredi * 17415e940c1dSMiklos Szeredi * This should be done on write(), truncate() and chown(). 17425e940c1dSMiklos Szeredi */ 17438981bdfdSVivek Goyal if (!fc->handle_killpriv && !fc->handle_killpriv_v2) { 17445e940c1dSMiklos Szeredi /* 17455e940c1dSMiklos Szeredi * ia_mode calculation may have used stale i_mode. 17465e940c1dSMiklos Szeredi * Refresh and recalculate. 1747a09f99edSMiklos Szeredi */ 1748a09f99edSMiklos Szeredi ret = fuse_do_getattr(inode, NULL, file); 1749a09f99edSMiklos Szeredi if (ret) 1750a09f99edSMiklos Szeredi return ret; 1751a09f99edSMiklos Szeredi 1752a09f99edSMiklos Szeredi attr->ia_mode = inode->i_mode; 1753c01638f5SMiklos Szeredi if (inode->i_mode & S_ISUID) { 1754a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1755a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISUID; 1756a09f99edSMiklos Szeredi } 1757c01638f5SMiklos Szeredi if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 1758a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1759a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISGID; 1760a09f99edSMiklos Szeredi } 1761a09f99edSMiklos Szeredi } 17625e940c1dSMiklos Szeredi } 1763a09f99edSMiklos Szeredi if (!attr->ia_valid) 1764a09f99edSMiklos Szeredi return 0; 1765a09f99edSMiklos Szeredi 1766abb5a14fSLinus Torvalds ret = fuse_do_setattr(entry, attr, file); 17675e2b8828SMiklos Szeredi if (!ret) { 176860bcc88aSSeth Forshee /* 176960bcc88aSSeth Forshee * If filesystem supports acls it may have updated acl xattrs in 177060bcc88aSSeth Forshee * the filesystem, so forget cached acls for the inode. 177160bcc88aSSeth Forshee */ 177260bcc88aSSeth Forshee if (fc->posix_acl) 177360bcc88aSSeth Forshee forget_all_cached_acls(inode); 177460bcc88aSSeth Forshee 17755e2b8828SMiklos Szeredi /* Directory mode changed, may need to revalidate access */ 17765e2b8828SMiklos Szeredi if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE)) 17775e2b8828SMiklos Szeredi fuse_invalidate_entry_cache(entry); 17785e2b8828SMiklos Szeredi } 17795e2b8828SMiklos Szeredi return ret; 178049d4914fSMiklos Szeredi } 178149d4914fSMiklos Szeredi 1782549c7297SChristian Brauner static int fuse_getattr(struct user_namespace *mnt_userns, 1783549c7297SChristian Brauner const struct path *path, struct kstat *stat, 1784a528d35eSDavid Howells u32 request_mask, unsigned int flags) 1785e5e5558eSMiklos Szeredi { 1786a528d35eSDavid Howells struct inode *inode = d_inode(path->dentry); 1787244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1788244f6385SMiklos Szeredi 17895d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 17905d069dbeSMiklos Szeredi return -EIO; 17915d069dbeSMiklos Szeredi 17925157da2cSMiklos Szeredi if (!fuse_allow_current_process(fc)) { 17935157da2cSMiklos Szeredi if (!request_mask) { 17945157da2cSMiklos Szeredi /* 17955157da2cSMiklos Szeredi * If user explicitly requested *nothing* then don't 17965157da2cSMiklos Szeredi * error out, but return st_dev only. 17975157da2cSMiklos Szeredi */ 17985157da2cSMiklos Szeredi stat->result_mask = 0; 17995157da2cSMiklos Szeredi stat->dev = inode->i_sb->s_dev; 18005157da2cSMiklos Szeredi return 0; 18015157da2cSMiklos Szeredi } 1802244f6385SMiklos Szeredi return -EACCES; 18035157da2cSMiklos Szeredi } 1804244f6385SMiklos Szeredi 18052f1e8196SMiklos Szeredi return fuse_update_get_attr(inode, NULL, stat, request_mask, flags); 1806e5e5558eSMiklos Szeredi } 1807e5e5558eSMiklos Szeredi 1808754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1809e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 18109e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 18119e6268dbSMiklos Szeredi .symlink = fuse_symlink, 18129e6268dbSMiklos Szeredi .unlink = fuse_unlink, 18139e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 18142773bf00SMiklos Szeredi .rename = fuse_rename2, 18159e6268dbSMiklos Szeredi .link = fuse_link, 18169e6268dbSMiklos Szeredi .setattr = fuse_setattr, 18179e6268dbSMiklos Szeredi .create = fuse_create, 1818c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 18199e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1820e5e5558eSMiklos Szeredi .permission = fuse_permission, 1821e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 182292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 182360bcc88aSSeth Forshee .get_acl = fuse_get_acl, 182460bcc88aSSeth Forshee .set_acl = fuse_set_acl, 182572227eacSMiklos Szeredi .fileattr_get = fuse_fileattr_get, 182672227eacSMiklos Szeredi .fileattr_set = fuse_fileattr_set, 1827e5e5558eSMiklos Szeredi }; 1828e5e5558eSMiklos Szeredi 18294b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1830b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1831e5e5558eSMiklos Szeredi .read = generic_read_dir, 1832d9b3dbdcSAl Viro .iterate_shared = fuse_readdir, 1833e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1834e5e5558eSMiklos Szeredi .release = fuse_dir_release, 183582547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1836b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 1837b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 1838e5e5558eSMiklos Szeredi }; 1839e5e5558eSMiklos Szeredi 1840754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 18419e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1842e5e5558eSMiklos Szeredi .permission = fuse_permission, 1843e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 184492a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 184560bcc88aSSeth Forshee .get_acl = fuse_get_acl, 184660bcc88aSSeth Forshee .set_acl = fuse_set_acl, 184772227eacSMiklos Szeredi .fileattr_get = fuse_fileattr_get, 184872227eacSMiklos Szeredi .fileattr_set = fuse_fileattr_set, 1849e5e5558eSMiklos Szeredi }; 1850e5e5558eSMiklos Szeredi 1851754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 18529e6268dbSMiklos Szeredi .setattr = fuse_setattr, 18536b255391SAl Viro .get_link = fuse_get_link, 1854e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 185592a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 1856e5e5558eSMiklos Szeredi }; 1857e5e5558eSMiklos Szeredi 1858e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1859e5e5558eSMiklos Szeredi { 1860e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1861e5e5558eSMiklos Szeredi } 1862e5e5558eSMiklos Szeredi 1863e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1864e5e5558eSMiklos Szeredi { 1865ab2257e9SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1866ab2257e9SMiklos Szeredi 1867e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1868e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1869ab2257e9SMiklos Szeredi 1870ab2257e9SMiklos Szeredi spin_lock_init(&fi->rdc.lock); 1871ab2257e9SMiklos Szeredi fi->rdc.cached = false; 1872ab2257e9SMiklos Szeredi fi->rdc.size = 0; 1873ab2257e9SMiklos Szeredi fi->rdc.pos = 0; 1874ab2257e9SMiklos Szeredi fi->rdc.version = 0; 1875e5e5558eSMiklos Szeredi } 1876e5e5558eSMiklos Szeredi 18775571f1e6SDan Schatzberg static int fuse_symlink_readpage(struct file *null, struct page *page) 18785571f1e6SDan Schatzberg { 18795571f1e6SDan Schatzberg int err = fuse_readlink_page(page->mapping->host, page); 18805571f1e6SDan Schatzberg 18815571f1e6SDan Schatzberg if (!err) 18825571f1e6SDan Schatzberg SetPageUptodate(page); 18835571f1e6SDan Schatzberg 18845571f1e6SDan Schatzberg unlock_page(page); 18855571f1e6SDan Schatzberg 18865571f1e6SDan Schatzberg return err; 18875571f1e6SDan Schatzberg } 18885571f1e6SDan Schatzberg 18895571f1e6SDan Schatzberg static const struct address_space_operations fuse_symlink_aops = { 18905571f1e6SDan Schatzberg .readpage = fuse_symlink_readpage, 18915571f1e6SDan Schatzberg }; 18925571f1e6SDan Schatzberg 1893e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1894e5e5558eSMiklos Szeredi { 1895e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 18965571f1e6SDan Schatzberg inode->i_data.a_ops = &fuse_symlink_aops; 18975571f1e6SDan Schatzberg inode_nohighmem(inode); 1898e5e5558eSMiklos Szeredi } 1899