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> 13e5e5558eSMiklos Szeredi #include <linux/sched.h> 14e5e5558eSMiklos Szeredi #include <linux/namei.h> 1507e77dcaSMiklos Szeredi #include <linux/slab.h> 16703c7362SSeth Forshee #include <linux/xattr.h> 17261aaba7SMiklos Szeredi #include <linux/iversion.h> 1860bcc88aSSeth Forshee #include <linux/posix_acl.h> 19e5e5558eSMiklos Szeredi 204582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir) 214582a4abSFeng Shuo { 224582a4abSFeng Shuo struct fuse_inode *fi = get_fuse_inode(dir); 234582a4abSFeng Shuo 244582a4abSFeng Shuo set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state); 254582a4abSFeng Shuo } 264582a4abSFeng Shuo 2730c6a23dSKhazhismel Kumykov #if BITS_PER_LONG >= 64 2830c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *entry, u64 time) 2930c6a23dSKhazhismel Kumykov { 3030c6a23dSKhazhismel Kumykov entry->d_fsdata = (void *) time; 3130c6a23dSKhazhismel Kumykov } 3230c6a23dSKhazhismel Kumykov 3330c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry) 3430c6a23dSKhazhismel Kumykov { 3530c6a23dSKhazhismel Kumykov return (u64)entry->d_fsdata; 3630c6a23dSKhazhismel Kumykov } 3730c6a23dSKhazhismel Kumykov 3830c6a23dSKhazhismel Kumykov #else 39f75fdf22SMiklos Szeredi union fuse_dentry { 40f75fdf22SMiklos Szeredi u64 time; 41f75fdf22SMiklos Szeredi struct rcu_head rcu; 42f75fdf22SMiklos Szeredi }; 43f75fdf22SMiklos Szeredi 4430c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time) 4530c6a23dSKhazhismel Kumykov { 4630c6a23dSKhazhismel Kumykov ((union fuse_dentry *) dentry->d_fsdata)->time = time; 4730c6a23dSKhazhismel Kumykov } 4830c6a23dSKhazhismel Kumykov 4930c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry) 5030c6a23dSKhazhismel Kumykov { 5130c6a23dSKhazhismel Kumykov return ((union fuse_dentry *) entry->d_fsdata)->time; 5230c6a23dSKhazhismel Kumykov } 5330c6a23dSKhazhismel Kumykov #endif 5430c6a23dSKhazhismel Kumykov 558fab0106SMiklos Szeredi static void fuse_dentry_settime(struct dentry *dentry, u64 time) 560a0898cfSMiklos Szeredi { 578fab0106SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb); 588fab0106SMiklos Szeredi bool delete = !time && fc->delete_stale; 598fab0106SMiklos Szeredi /* 608fab0106SMiklos Szeredi * Mess with DCACHE_OP_DELETE because dput() will be faster without it. 618fab0106SMiklos Szeredi * Don't care about races, either way it's just an optimization 628fab0106SMiklos Szeredi */ 638fab0106SMiklos Szeredi if ((!delete && (dentry->d_flags & DCACHE_OP_DELETE)) || 648fab0106SMiklos Szeredi (delete && !(dentry->d_flags & DCACHE_OP_DELETE))) { 658fab0106SMiklos Szeredi spin_lock(&dentry->d_lock); 668fab0106SMiklos Szeredi if (!delete) 678fab0106SMiklos Szeredi dentry->d_flags &= ~DCACHE_OP_DELETE; 688fab0106SMiklos Szeredi else 698fab0106SMiklos Szeredi dentry->d_flags |= DCACHE_OP_DELETE; 708fab0106SMiklos Szeredi spin_unlock(&dentry->d_lock); 710a0898cfSMiklos Szeredi } 720a0898cfSMiklos Szeredi 7330c6a23dSKhazhismel Kumykov __fuse_dentry_settime(dentry, time); 740a0898cfSMiklos Szeredi } 750a0898cfSMiklos Szeredi 766f9f1180SMiklos Szeredi /* 776f9f1180SMiklos Szeredi * FUSE caches dentries and attributes with separate timeout. The 786f9f1180SMiklos Szeredi * time in jiffies until the dentry/attributes are valid is stored in 79f75fdf22SMiklos Szeredi * dentry->d_fsdata and fuse_inode->i_time respectively. 806f9f1180SMiklos Szeredi */ 816f9f1180SMiklos Szeredi 826f9f1180SMiklos Szeredi /* 836f9f1180SMiklos Szeredi * Calculate the time in jiffies until a dentry/attributes are valid 846f9f1180SMiklos Szeredi */ 85bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec) 86e5e5558eSMiklos Szeredi { 87685d16ddSMiklos Szeredi if (sec || nsec) { 88bcb6f6d2SMiklos Szeredi struct timespec64 ts = { 89bcb6f6d2SMiklos Szeredi sec, 9021067527SDavid Sheets min_t(u32, nsec, NSEC_PER_SEC - 1) 91bcb6f6d2SMiklos Szeredi }; 92bcb6f6d2SMiklos Szeredi 93bcb6f6d2SMiklos Szeredi return get_jiffies_64() + timespec64_to_jiffies(&ts); 94685d16ddSMiklos Szeredi } else 950a0898cfSMiklos Szeredi return 0; 96e5e5558eSMiklos Szeredi } 97e5e5558eSMiklos Szeredi 986f9f1180SMiklos Szeredi /* 996f9f1180SMiklos Szeredi * Set dentry and possibly attribute timeouts from the lookup/mk* 1006f9f1180SMiklos Szeredi * replies 1016f9f1180SMiklos Szeredi */ 102d123d8e1SMiklos Szeredi void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o) 1030aa7c699SMiklos Szeredi { 1040a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 1050a0898cfSMiklos Szeredi time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 1061fb69e78SMiklos Szeredi } 1071fb69e78SMiklos Szeredi 1081fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o) 1091fb69e78SMiklos Szeredi { 1101fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 1111fb69e78SMiklos Szeredi } 1121fb69e78SMiklos Szeredi 113d123d8e1SMiklos Szeredi u64 entry_attr_timeout(struct fuse_entry_out *o) 1141fb69e78SMiklos Szeredi { 1151fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 1168cbdf1e6SMiklos Szeredi } 1178cbdf1e6SMiklos Szeredi 1182f1e8196SMiklos Szeredi static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask) 1192f1e8196SMiklos Szeredi { 1202f1e8196SMiklos Szeredi set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask); 1212f1e8196SMiklos Szeredi } 1222f1e8196SMiklos Szeredi 1236f9f1180SMiklos Szeredi /* 1246f9f1180SMiklos Szeredi * Mark the attributes as stale, so that at the next call to 1256f9f1180SMiklos Szeredi * ->getattr() they will be fetched from userspace 1266f9f1180SMiklos Szeredi */ 1278cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode) 1288cbdf1e6SMiklos Szeredi { 1292f1e8196SMiklos Szeredi fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS); 1308cbdf1e6SMiklos Szeredi } 1318cbdf1e6SMiklos Szeredi 132261aaba7SMiklos Szeredi static void fuse_dir_changed(struct inode *dir) 133261aaba7SMiklos Szeredi { 134261aaba7SMiklos Szeredi fuse_invalidate_attr(dir); 135261aaba7SMiklos Szeredi inode_maybe_inc_iversion(dir, false); 136261aaba7SMiklos Szeredi } 137261aaba7SMiklos Szeredi 138451418fcSAndrew Gallagher /** 139451418fcSAndrew Gallagher * Mark the attributes as stale due to an atime change. Avoid the invalidate if 140451418fcSAndrew Gallagher * atime is not used. 141451418fcSAndrew Gallagher */ 142451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode) 143451418fcSAndrew Gallagher { 144451418fcSAndrew Gallagher if (!IS_RDONLY(inode)) 1452f1e8196SMiklos Szeredi fuse_invalidate_attr_mask(inode, STATX_ATIME); 146451418fcSAndrew Gallagher } 147451418fcSAndrew Gallagher 1486f9f1180SMiklos Szeredi /* 1496f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 1506f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 1516f9f1180SMiklos Szeredi * 1526f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 1536f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 1546f9f1180SMiklos Szeredi * lookup) 1556f9f1180SMiklos Szeredi */ 156dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry) 1578cbdf1e6SMiklos Szeredi { 1580a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 1598cbdf1e6SMiklos Szeredi } 1608cbdf1e6SMiklos Szeredi 1616f9f1180SMiklos Szeredi /* 1626f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 1636f9f1180SMiklos Szeredi * dentry from the hash 1646f9f1180SMiklos Szeredi */ 1658cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1668cbdf1e6SMiklos Szeredi { 1678cbdf1e6SMiklos Szeredi d_invalidate(entry); 1688cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1690aa7c699SMiklos Szeredi } 1700aa7c699SMiklos Szeredi 1717078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, 17213983d06SAl Viro u64 nodeid, const struct qstr *name, 173e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 174e5e5558eSMiklos Szeredi { 1750e9663eeSMiklos Szeredi memset(outarg, 0, sizeof(struct fuse_entry_out)); 176d5b48543SMiklos Szeredi args->opcode = FUSE_LOOKUP; 177d5b48543SMiklos Szeredi args->nodeid = nodeid; 178d5b48543SMiklos Szeredi args->in_numargs = 1; 179d5b48543SMiklos Szeredi args->in_args[0].size = name->len + 1; 180d5b48543SMiklos Szeredi args->in_args[0].value = name->name; 181d5b48543SMiklos Szeredi args->out_numargs = 1; 182d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(struct fuse_entry_out); 183d5b48543SMiklos Szeredi args->out_args[0].value = outarg; 184e5e5558eSMiklos Szeredi } 185e5e5558eSMiklos Szeredi 1866f9f1180SMiklos Szeredi /* 1876f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1886f9f1180SMiklos Szeredi * 1896f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 1906f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 1916f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 1926f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 1936f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 1946f9f1180SMiklos Szeredi */ 1950b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) 196e5e5558eSMiklos Szeredi { 19734286d66SNick Piggin struct inode *inode; 19828420dadSMiklos Szeredi struct dentry *parent; 19928420dadSMiklos Szeredi struct fuse_conn *fc; 2006314efeeSMiklos Szeredi struct fuse_inode *fi; 201e2a6b952SMiklos Szeredi int ret; 2028cbdf1e6SMiklos Szeredi 2032b0143b5SDavid Howells inode = d_inode_rcu(entry); 2048cbdf1e6SMiklos Szeredi if (inode && is_bad_inode(inode)) 205e2a6b952SMiklos Szeredi goto invalid; 206154210ccSAnand Avati else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || 207154210ccSAnand Avati (flags & LOOKUP_REVAL)) { 208e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 2097078187aSMiklos Szeredi FUSE_ARGS(args); 21007e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 2111fb69e78SMiklos Szeredi u64 attr_version; 2128cbdf1e6SMiklos Szeredi 21350322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 2148cbdf1e6SMiklos Szeredi if (!inode) 215e2a6b952SMiklos Szeredi goto invalid; 2168cbdf1e6SMiklos Szeredi 217e2a6b952SMiklos Szeredi ret = -ECHILD; 2180b728e19SAl Viro if (flags & LOOKUP_RCU) 219e2a6b952SMiklos Szeredi goto out; 220e7c0a167SMiklos Szeredi 2218cbdf1e6SMiklos Szeredi fc = get_fuse_conn(inode); 222e5e5558eSMiklos Szeredi 22307e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 224e2a6b952SMiklos Szeredi ret = -ENOMEM; 2257078187aSMiklos Szeredi if (!forget) 226e2a6b952SMiklos Szeredi goto out; 2272d51013eSMiklos Szeredi 2287dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 2291fb69e78SMiklos Szeredi 230e956edd0SMiklos Szeredi parent = dget_parent(entry); 2312b0143b5SDavid Howells fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)), 232c180eebeSMiklos Szeredi &entry->d_name, &outarg); 2337078187aSMiklos Szeredi ret = fuse_simple_request(fc, &args); 234e956edd0SMiklos Szeredi dput(parent); 23550322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 2367078187aSMiklos Szeredi if (!ret && !outarg.nodeid) 2377078187aSMiklos Szeredi ret = -ENOENT; 2387078187aSMiklos Szeredi if (!ret) { 2396314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2409e6268dbSMiklos Szeredi if (outarg.nodeid != get_node_id(inode)) { 24107e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 242e2a6b952SMiklos Szeredi goto invalid; 2439e6268dbSMiklos Szeredi } 244c9d8f5f0SKirill Tkhai spin_lock(&fi->lock); 2459e6268dbSMiklos Szeredi fi->nlookup++; 246c9d8f5f0SKirill Tkhai spin_unlock(&fi->lock); 2479e6268dbSMiklos Szeredi } 24807e77dcaSMiklos Szeredi kfree(forget); 2497078187aSMiklos Szeredi if (ret == -ENOMEM) 2507078187aSMiklos Szeredi goto out; 251eb59bd17SMiklos Szeredi if (ret || fuse_invalid_attr(&outarg.attr) || 252eb59bd17SMiklos Szeredi (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 253e2a6b952SMiklos Szeredi goto invalid; 254e5e5558eSMiklos Szeredi 25560bcc88aSSeth Forshee forget_all_cached_acls(inode); 2561fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2571fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2581fb69e78SMiklos Szeredi attr_version); 2591fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 26028420dadSMiklos Szeredi } else if (inode) { 2616314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2626314efeeSMiklos Szeredi if (flags & LOOKUP_RCU) { 2636314efeeSMiklos Szeredi if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) 2646314efeeSMiklos Szeredi return -ECHILD; 2656314efeeSMiklos Szeredi } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { 26628420dadSMiklos Szeredi parent = dget_parent(entry); 2672b0143b5SDavid Howells fuse_advise_use_readdirplus(d_inode(parent)); 26828420dadSMiklos Szeredi dput(parent); 269e5e5558eSMiklos Szeredi } 27028420dadSMiklos Szeredi } 271e2a6b952SMiklos Szeredi ret = 1; 272e2a6b952SMiklos Szeredi out: 273e2a6b952SMiklos Szeredi return ret; 274e2a6b952SMiklos Szeredi 275e2a6b952SMiklos Szeredi invalid: 276e2a6b952SMiklos Szeredi ret = 0; 277e2a6b952SMiklos Szeredi goto out; 278e5e5558eSMiklos Szeredi } 279e5e5558eSMiklos Szeredi 28030c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 281f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry) 282f75fdf22SMiklos Szeredi { 283dc69e98cSKhazhismel Kumykov dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), 284dc69e98cSKhazhismel Kumykov GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE); 285f75fdf22SMiklos Szeredi 286f75fdf22SMiklos Szeredi return dentry->d_fsdata ? 0 : -ENOMEM; 287f75fdf22SMiklos Szeredi } 288f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry) 289f75fdf22SMiklos Szeredi { 290f75fdf22SMiklos Szeredi union fuse_dentry *fd = dentry->d_fsdata; 291f75fdf22SMiklos Szeredi 292f75fdf22SMiklos Szeredi kfree_rcu(fd, rcu); 293f75fdf22SMiklos Szeredi } 29430c6a23dSKhazhismel Kumykov #endif 295f75fdf22SMiklos Szeredi 2968fab0106SMiklos Szeredi static int fuse_dentry_delete(const struct dentry *dentry) 2978fab0106SMiklos Szeredi { 2988fab0106SMiklos Szeredi return time_before64(fuse_dentry_time(dentry), get_jiffies_64()); 2998fab0106SMiklos Szeredi } 3008fab0106SMiklos Szeredi 3014269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 302e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 3038fab0106SMiklos Szeredi .d_delete = fuse_dentry_delete, 30430c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 305f75fdf22SMiklos Szeredi .d_init = fuse_dentry_init, 306f75fdf22SMiklos Szeredi .d_release = fuse_dentry_release, 30730c6a23dSKhazhismel Kumykov #endif 308e5e5558eSMiklos Szeredi }; 309e5e5558eSMiklos Szeredi 3100ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = { 31130c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 3120ce267ffSMiklos Szeredi .d_init = fuse_dentry_init, 3130ce267ffSMiklos Szeredi .d_release = fuse_dentry_release, 31430c6a23dSKhazhismel Kumykov #endif 3150ce267ffSMiklos Szeredi }; 3160ce267ffSMiklos Szeredi 317a5bfffacSTimo Savola int fuse_valid_type(int m) 31839ee059aSMiklos Szeredi { 31939ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 32039ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 32139ee059aSMiklos Szeredi } 32239ee059aSMiklos Szeredi 323eb59bd17SMiklos Szeredi bool fuse_invalid_attr(struct fuse_attr *attr) 324eb59bd17SMiklos Szeredi { 325eb59bd17SMiklos Szeredi return !fuse_valid_type(attr->mode) || 326eb59bd17SMiklos Szeredi attr->size > LLONG_MAX; 327eb59bd17SMiklos Szeredi } 328eb59bd17SMiklos Szeredi 32913983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, 330c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 331c180eebeSMiklos Szeredi { 332c180eebeSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 3337078187aSMiklos Szeredi FUSE_ARGS(args); 33407e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 335c180eebeSMiklos Szeredi u64 attr_version; 336c180eebeSMiklos Szeredi int err; 337c180eebeSMiklos Szeredi 338c180eebeSMiklos Szeredi *inode = NULL; 339c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 340c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 341c180eebeSMiklos Szeredi goto out; 342c180eebeSMiklos Szeredi 343c180eebeSMiklos Szeredi 34407e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 34507e77dcaSMiklos Szeredi err = -ENOMEM; 3467078187aSMiklos Szeredi if (!forget) 347c180eebeSMiklos Szeredi goto out; 348c180eebeSMiklos Szeredi 349c180eebeSMiklos Szeredi attr_version = fuse_get_attr_version(fc); 350c180eebeSMiklos Szeredi 3517078187aSMiklos Szeredi fuse_lookup_init(fc, &args, nodeid, name, outarg); 3527078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 353c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 354c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 355c180eebeSMiklos Szeredi goto out_put_forget; 356c180eebeSMiklos Szeredi 357c180eebeSMiklos Szeredi err = -EIO; 358c180eebeSMiklos Szeredi if (!outarg->nodeid) 359c180eebeSMiklos Szeredi goto out_put_forget; 360eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg->attr)) 361c180eebeSMiklos Szeredi goto out_put_forget; 362c180eebeSMiklos Szeredi 363c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 364c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 365c180eebeSMiklos Szeredi attr_version); 366c180eebeSMiklos Szeredi err = -ENOMEM; 367c180eebeSMiklos Szeredi if (!*inode) { 36807e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg->nodeid, 1); 369c180eebeSMiklos Szeredi goto out; 370c180eebeSMiklos Szeredi } 371c180eebeSMiklos Szeredi err = 0; 372c180eebeSMiklos Szeredi 373c180eebeSMiklos Szeredi out_put_forget: 37407e77dcaSMiklos Szeredi kfree(forget); 375c180eebeSMiklos Szeredi out: 376c180eebeSMiklos Szeredi return err; 377c180eebeSMiklos Szeredi } 378c180eebeSMiklos Szeredi 3790aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 38000cd8dd3SAl Viro unsigned int flags) 381e5e5558eSMiklos Szeredi { 382e5e5558eSMiklos Szeredi int err; 383e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 384c180eebeSMiklos Szeredi struct inode *inode; 3850de6256dSMiklos Szeredi struct dentry *newent; 386c180eebeSMiklos Szeredi bool outarg_valid = true; 38763576c13SMiklos Szeredi bool locked; 388e5e5558eSMiklos Szeredi 38963576c13SMiklos Szeredi locked = fuse_lock_inode(dir); 390c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 391c180eebeSMiklos Szeredi &outarg, &inode); 39263576c13SMiklos Szeredi fuse_unlock_inode(dir, locked); 393c180eebeSMiklos Szeredi if (err == -ENOENT) { 394c180eebeSMiklos Szeredi outarg_valid = false; 395c180eebeSMiklos Szeredi err = 0; 3962d51013eSMiklos Szeredi } 397c180eebeSMiklos Szeredi if (err) 398c180eebeSMiklos Szeredi goto out_err; 3992d51013eSMiklos Szeredi 400ee4e5271SMiklos Szeredi err = -EIO; 401c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 402c180eebeSMiklos Szeredi goto out_iput; 403e5e5558eSMiklos Szeredi 40441d28bcaSAl Viro newent = d_splice_alias(inode, entry); 405c180eebeSMiklos Szeredi err = PTR_ERR(newent); 406c180eebeSMiklos Szeredi if (IS_ERR(newent)) 4075835f339SMiklos Szeredi goto out_err; 408d2a85164SMiklos Szeredi 4090de6256dSMiklos Szeredi entry = newent ? newent : entry; 410c180eebeSMiklos Szeredi if (outarg_valid) 4111fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 4128cbdf1e6SMiklos Szeredi else 4138cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 414c180eebeSMiklos Szeredi 4156c26f717SMiklos Szeredi if (inode) 4164582a4abSFeng Shuo fuse_advise_use_readdirplus(dir); 4170de6256dSMiklos Szeredi return newent; 418c180eebeSMiklos Szeredi 419c180eebeSMiklos Szeredi out_iput: 420c180eebeSMiklos Szeredi iput(inode); 421c180eebeSMiklos Szeredi out_err: 422c180eebeSMiklos Szeredi return ERR_PTR(err); 423e5e5558eSMiklos Szeredi } 424e5e5558eSMiklos Szeredi 4256f9f1180SMiklos Szeredi /* 4266f9f1180SMiklos Szeredi * Atomic create+open operation 4276f9f1180SMiklos Szeredi * 4286f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 4296f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 4306f9f1180SMiklos Szeredi */ 431d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 43230d90494SAl Viro struct file *file, unsigned flags, 433b452a458SAl Viro umode_t mode) 434fd72faacSMiklos Szeredi { 435fd72faacSMiklos Szeredi int err; 436fd72faacSMiklos Szeredi struct inode *inode; 437fd72faacSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 4387078187aSMiklos Szeredi FUSE_ARGS(args); 43907e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 440e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 441fd72faacSMiklos Szeredi struct fuse_open_out outopen; 442fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 443ebf84d0cSKirill Tkhai struct fuse_inode *fi; 444fd72faacSMiklos Szeredi struct fuse_file *ff; 445fd72faacSMiklos Szeredi 446af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 447af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 448af109bcaSMiklos Szeredi 44907e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 450c8ccbe03SMiklos Szeredi err = -ENOMEM; 45107e77dcaSMiklos Szeredi if (!forget) 452c8ccbe03SMiklos Szeredi goto out_err; 45351eb01e7SMiklos Szeredi 454ce1d5a49SMiklos Szeredi err = -ENOMEM; 455acf99433STejun Heo ff = fuse_file_alloc(fc); 456fd72faacSMiklos Szeredi if (!ff) 4577078187aSMiklos Szeredi goto out_put_forget_req; 458fd72faacSMiklos Szeredi 459e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 460e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 461e0a43ddcSMiklos Szeredi 462fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 463fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4640e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 465fd72faacSMiklos Szeredi inarg.flags = flags; 466fd72faacSMiklos Szeredi inarg.mode = mode; 467e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 468d5b48543SMiklos Szeredi args.opcode = FUSE_CREATE; 469d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 470d5b48543SMiklos Szeredi args.in_numargs = 2; 471d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 472d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 473d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 474d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 475d5b48543SMiklos Szeredi args.out_numargs = 2; 476d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outentry); 477d5b48543SMiklos Szeredi args.out_args[0].value = &outentry; 478d5b48543SMiklos Szeredi args.out_args[1].size = sizeof(outopen); 479d5b48543SMiklos Szeredi args.out_args[1].value = &outopen; 4807078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 481c8ccbe03SMiklos Szeredi if (err) 482fd72faacSMiklos Szeredi goto out_free_ff; 483fd72faacSMiklos Szeredi 484fd72faacSMiklos Szeredi err = -EIO; 485eb59bd17SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) || 486eb59bd17SMiklos Szeredi fuse_invalid_attr(&outentry.attr)) 487fd72faacSMiklos Szeredi goto out_free_ff; 488fd72faacSMiklos Szeredi 489c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 490c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 491c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 492fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 4931fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 494fd72faacSMiklos Szeredi if (!inode) { 495fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 496ebf84d0cSKirill Tkhai fuse_sync_release(NULL, ff, flags); 49707e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outentry.nodeid, 1); 498c8ccbe03SMiklos Szeredi err = -ENOMEM; 499c8ccbe03SMiklos Szeredi goto out_err; 500fd72faacSMiklos Szeredi } 50107e77dcaSMiklos Szeredi kfree(forget); 502fd72faacSMiklos Szeredi d_instantiate(entry, inode); 5031fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 504261aaba7SMiklos Szeredi fuse_dir_changed(dir); 505be12af3eSAl Viro err = finish_open(file, entry, generic_file_open); 50630d90494SAl Viro if (err) { 507ebf84d0cSKirill Tkhai fi = get_fuse_inode(inode); 508ebf84d0cSKirill Tkhai fuse_sync_release(fi, ff, flags); 509c8ccbe03SMiklos Szeredi } else { 510267d8444SMiklos Szeredi file->private_data = ff; 511c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 512c8ccbe03SMiklos Szeredi } 513d9585277SAl Viro return err; 514fd72faacSMiklos Szeredi 515fd72faacSMiklos Szeredi out_free_ff: 516fd72faacSMiklos Szeredi fuse_file_free(ff); 51751eb01e7SMiklos Szeredi out_put_forget_req: 51807e77dcaSMiklos Szeredi kfree(forget); 519c8ccbe03SMiklos Szeredi out_err: 520d9585277SAl Viro return err; 521c8ccbe03SMiklos Szeredi } 522c8ccbe03SMiklos Szeredi 523c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); 524d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 52530d90494SAl Viro struct file *file, unsigned flags, 52644907d79SAl Viro umode_t mode) 527c8ccbe03SMiklos Szeredi { 528c8ccbe03SMiklos Szeredi int err; 529c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 530c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 531c8ccbe03SMiklos Szeredi 53200699ad8SAl Viro if (d_in_lookup(entry)) { 53300cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 534c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 535d9585277SAl Viro return PTR_ERR(res); 536c8ccbe03SMiklos Szeredi 537c8ccbe03SMiklos Szeredi if (res) 538c8ccbe03SMiklos Szeredi entry = res; 539c8ccbe03SMiklos Szeredi } 540c8ccbe03SMiklos Szeredi 5412b0143b5SDavid Howells if (!(flags & O_CREAT) || d_really_is_positive(entry)) 542c8ccbe03SMiklos Szeredi goto no_open; 543c8ccbe03SMiklos Szeredi 544c8ccbe03SMiklos Szeredi /* Only creates */ 54573a09dd9SAl Viro file->f_mode |= FMODE_CREATED; 546c8ccbe03SMiklos Szeredi 547c8ccbe03SMiklos Szeredi if (fc->no_create) 548c8ccbe03SMiklos Szeredi goto mknod; 549c8ccbe03SMiklos Szeredi 550b452a458SAl Viro err = fuse_create_open(dir, entry, file, flags, mode); 551d9585277SAl Viro if (err == -ENOSYS) { 552c8ccbe03SMiklos Szeredi fc->no_create = 1; 553c8ccbe03SMiklos Szeredi goto mknod; 554c8ccbe03SMiklos Szeredi } 555c8ccbe03SMiklos Szeredi out_dput: 556c8ccbe03SMiklos Szeredi dput(res); 557d9585277SAl Viro return err; 558c8ccbe03SMiklos Szeredi 559c8ccbe03SMiklos Szeredi mknod: 560c8ccbe03SMiklos Szeredi err = fuse_mknod(dir, entry, mode, 0); 561d9585277SAl Viro if (err) 562c8ccbe03SMiklos Szeredi goto out_dput; 563c8ccbe03SMiklos Szeredi no_open: 564e45198a6SAl Viro return finish_no_open(file, res); 565fd72faacSMiklos Szeredi } 566fd72faacSMiklos Szeredi 5676f9f1180SMiklos Szeredi /* 5686f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 5696f9f1180SMiklos Szeredi */ 5707078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, 5719e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 572541af6a0SAl Viro umode_t mode) 5739e6268dbSMiklos Szeredi { 5749e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 5759e6268dbSMiklos Szeredi struct inode *inode; 576c971e6a0SAl Viro struct dentry *d; 5779e6268dbSMiklos Szeredi int err; 57807e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 5792d51013eSMiklos Szeredi 58007e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 5817078187aSMiklos Szeredi if (!forget) 58207e77dcaSMiklos Szeredi return -ENOMEM; 5839e6268dbSMiklos Szeredi 5840e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 585d5b48543SMiklos Szeredi args->nodeid = get_node_id(dir); 586d5b48543SMiklos Szeredi args->out_numargs = 1; 587d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(outarg); 588d5b48543SMiklos Szeredi args->out_args[0].value = &outarg; 5897078187aSMiklos Szeredi err = fuse_simple_request(fc, args); 5902d51013eSMiklos Szeredi if (err) 5912d51013eSMiklos Szeredi goto out_put_forget_req; 5922d51013eSMiklos Szeredi 59339ee059aSMiklos Szeredi err = -EIO; 594eb59bd17SMiklos Szeredi if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr)) 5952d51013eSMiklos Szeredi goto out_put_forget_req; 59639ee059aSMiklos Szeredi 59739ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 5982d51013eSMiklos Szeredi goto out_put_forget_req; 59939ee059aSMiklos Szeredi 6009e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 6011fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 6029e6268dbSMiklos Szeredi if (!inode) { 60307e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 6049e6268dbSMiklos Szeredi return -ENOMEM; 6059e6268dbSMiklos Szeredi } 60607e77dcaSMiklos Szeredi kfree(forget); 6079e6268dbSMiklos Szeredi 608c971e6a0SAl Viro d_drop(entry); 609c971e6a0SAl Viro d = d_splice_alias(inode, entry); 610c971e6a0SAl Viro if (IS_ERR(d)) 611c971e6a0SAl Viro return PTR_ERR(d); 612d2a85164SMiklos Szeredi 613c971e6a0SAl Viro if (d) { 614c971e6a0SAl Viro fuse_change_entry_timeout(d, &outarg); 615c971e6a0SAl Viro dput(d); 616c971e6a0SAl Viro } else { 6171fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 618c971e6a0SAl Viro } 619261aaba7SMiklos Szeredi fuse_dir_changed(dir); 6209e6268dbSMiklos Szeredi return 0; 62139ee059aSMiklos Szeredi 6222d51013eSMiklos Szeredi out_put_forget_req: 62307e77dcaSMiklos Szeredi kfree(forget); 62439ee059aSMiklos Szeredi return err; 6259e6268dbSMiklos Szeredi } 6269e6268dbSMiklos Szeredi 6271a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, 6289e6268dbSMiklos Szeredi dev_t rdev) 6299e6268dbSMiklos Szeredi { 6309e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 6319e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6327078187aSMiklos Szeredi FUSE_ARGS(args); 6339e6268dbSMiklos Szeredi 634e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 635e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 636e0a43ddcSMiklos Szeredi 6379e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6389e6268dbSMiklos Szeredi inarg.mode = mode; 6399e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 640e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 641d5b48543SMiklos Szeredi args.opcode = FUSE_MKNOD; 642d5b48543SMiklos Szeredi args.in_numargs = 2; 643d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 644d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 645d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 646d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 6477078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, mode); 6489e6268dbSMiklos Szeredi } 6499e6268dbSMiklos Szeredi 6504acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, 651ebfc3b49SAl Viro bool excl) 6529e6268dbSMiklos Szeredi { 6539e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 6549e6268dbSMiklos Szeredi } 6559e6268dbSMiklos Szeredi 65618bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) 6579e6268dbSMiklos Szeredi { 6589e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 6599e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6607078187aSMiklos Szeredi FUSE_ARGS(args); 6619e6268dbSMiklos Szeredi 662e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 663e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 664e0a43ddcSMiklos Szeredi 6659e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6669e6268dbSMiklos Szeredi inarg.mode = mode; 667e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 668d5b48543SMiklos Szeredi args.opcode = FUSE_MKDIR; 669d5b48543SMiklos Szeredi args.in_numargs = 2; 670d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 671d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 672d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 673d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 6747078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, S_IFDIR); 6759e6268dbSMiklos Szeredi } 6769e6268dbSMiklos Szeredi 6779e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 6789e6268dbSMiklos Szeredi const char *link) 6799e6268dbSMiklos Szeredi { 6809e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6819e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 6827078187aSMiklos Szeredi FUSE_ARGS(args); 6839e6268dbSMiklos Szeredi 684d5b48543SMiklos Szeredi args.opcode = FUSE_SYMLINK; 685d5b48543SMiklos Szeredi args.in_numargs = 2; 686d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 687d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 688d5b48543SMiklos Szeredi args.in_args[1].size = len; 689d5b48543SMiklos Szeredi args.in_args[1].value = link; 6907078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, S_IFLNK); 6919e6268dbSMiklos Szeredi } 6929e6268dbSMiklos Szeredi 693703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode) 69431f3267bSMaxim Patlasov { 69531f3267bSMaxim Patlasov if (!IS_NOCMTIME(inode)) { 696c2050a45SDeepa Dinamani inode->i_ctime = current_time(inode); 69731f3267bSMaxim Patlasov mark_inode_dirty_sync(inode); 69831f3267bSMaxim Patlasov } 69931f3267bSMaxim Patlasov } 70031f3267bSMaxim Patlasov 7019e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 7029e6268dbSMiklos Szeredi { 7039e6268dbSMiklos Szeredi int err; 7049e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 7057078187aSMiklos Szeredi FUSE_ARGS(args); 7069e6268dbSMiklos Szeredi 707d5b48543SMiklos Szeredi args.opcode = FUSE_UNLINK; 708d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 709d5b48543SMiklos Szeredi args.in_numargs = 1; 710d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 711d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 7127078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 7139e6268dbSMiklos Szeredi if (!err) { 7142b0143b5SDavid Howells struct inode *inode = d_inode(entry); 715ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 7169e6268dbSMiklos Szeredi 717f15ecfefSKirill Tkhai spin_lock(&fi->lock); 7184510d86fSKirill Tkhai fi->attr_version = atomic64_inc_return(&fc->attr_version); 719dfca7cebSMiklos Szeredi /* 720dfca7cebSMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 721dfca7cebSMiklos Szeredi * happen if userspace filesystem is careless. It would be 722dfca7cebSMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 723dfca7cebSMiklos Szeredi * condition here 724dfca7cebSMiklos Szeredi */ 725dfca7cebSMiklos Szeredi if (inode->i_nlink > 0) 726ac45d613SMiklos Szeredi drop_nlink(inode); 727f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 7289e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 729261aaba7SMiklos Szeredi fuse_dir_changed(dir); 7308cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 73131f3267bSMaxim Patlasov fuse_update_ctime(inode); 7329e6268dbSMiklos Szeredi } else if (err == -EINTR) 7339e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7349e6268dbSMiklos Szeredi return err; 7359e6268dbSMiklos Szeredi } 7369e6268dbSMiklos Szeredi 7379e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 7389e6268dbSMiklos Szeredi { 7399e6268dbSMiklos Szeredi int err; 7409e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 7417078187aSMiklos Szeredi FUSE_ARGS(args); 7429e6268dbSMiklos Szeredi 743d5b48543SMiklos Szeredi args.opcode = FUSE_RMDIR; 744d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 745d5b48543SMiklos Szeredi args.in_numargs = 1; 746d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 747d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 7487078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 7499e6268dbSMiklos Szeredi if (!err) { 7502b0143b5SDavid Howells clear_nlink(d_inode(entry)); 751261aaba7SMiklos Szeredi fuse_dir_changed(dir); 7528cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 7539e6268dbSMiklos Szeredi } else if (err == -EINTR) 7549e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7559e6268dbSMiklos Szeredi return err; 7569e6268dbSMiklos Szeredi } 7579e6268dbSMiklos Szeredi 7581560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, 7591560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 7601560c974SMiklos Szeredi unsigned int flags, int opcode, size_t argsize) 7619e6268dbSMiklos Szeredi { 7629e6268dbSMiklos Szeredi int err; 7631560c974SMiklos Szeredi struct fuse_rename2_in inarg; 7649e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 7657078187aSMiklos Szeredi FUSE_ARGS(args); 7669e6268dbSMiklos Szeredi 7671560c974SMiklos Szeredi memset(&inarg, 0, argsize); 7689e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 7691560c974SMiklos Szeredi inarg.flags = flags; 770d5b48543SMiklos Szeredi args.opcode = opcode; 771d5b48543SMiklos Szeredi args.nodeid = get_node_id(olddir); 772d5b48543SMiklos Szeredi args.in_numargs = 3; 773d5b48543SMiklos Szeredi args.in_args[0].size = argsize; 774d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 775d5b48543SMiklos Szeredi args.in_args[1].size = oldent->d_name.len + 1; 776d5b48543SMiklos Szeredi args.in_args[1].value = oldent->d_name.name; 777d5b48543SMiklos Szeredi args.in_args[2].size = newent->d_name.len + 1; 778d5b48543SMiklos Szeredi args.in_args[2].value = newent->d_name.name; 7797078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 7809e6268dbSMiklos Szeredi if (!err) { 78108b63307SMiklos Szeredi /* ctime changes */ 7822b0143b5SDavid Howells fuse_invalidate_attr(d_inode(oldent)); 7832b0143b5SDavid Howells fuse_update_ctime(d_inode(oldent)); 78408b63307SMiklos Szeredi 7851560c974SMiklos Szeredi if (flags & RENAME_EXCHANGE) { 7862b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 7872b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 7881560c974SMiklos Szeredi } 7891560c974SMiklos Szeredi 790261aaba7SMiklos Szeredi fuse_dir_changed(olddir); 7919e6268dbSMiklos Szeredi if (olddir != newdir) 792261aaba7SMiklos Szeredi fuse_dir_changed(newdir); 7938cbdf1e6SMiklos Szeredi 7948cbdf1e6SMiklos Szeredi /* newent will end up negative */ 7952b0143b5SDavid Howells if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { 7962b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 7978cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 7982b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 7995219f346SMiklos Szeredi } 8009e6268dbSMiklos Szeredi } else if (err == -EINTR) { 8019e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 8029e6268dbSMiklos Szeredi rename actually took place. If the invalidation 8039e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 8049e6268dbSMiklos Szeredi directory), then there can be inconsistency between 8059e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 8069e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 8072b0143b5SDavid Howells if (d_really_is_positive(newent)) 8089e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 8099e6268dbSMiklos Szeredi } 8109e6268dbSMiklos Szeredi 8119e6268dbSMiklos Szeredi return err; 8129e6268dbSMiklos Szeredi } 8139e6268dbSMiklos Szeredi 8141560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent, 8151560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 8161560c974SMiklos Szeredi unsigned int flags) 8171560c974SMiklos Szeredi { 8181560c974SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 8191560c974SMiklos Szeredi int err; 8201560c974SMiklos Szeredi 821*519525faSVivek Goyal if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) 8221560c974SMiklos Szeredi return -EINVAL; 8231560c974SMiklos Szeredi 8244237ba43SMiklos Szeredi if (flags) { 8251560c974SMiklos Szeredi if (fc->no_rename2 || fc->minor < 23) 8261560c974SMiklos Szeredi return -EINVAL; 8271560c974SMiklos Szeredi 8281560c974SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, flags, 8294237ba43SMiklos Szeredi FUSE_RENAME2, 8304237ba43SMiklos Szeredi sizeof(struct fuse_rename2_in)); 8311560c974SMiklos Szeredi if (err == -ENOSYS) { 8321560c974SMiklos Szeredi fc->no_rename2 = 1; 8331560c974SMiklos Szeredi err = -EINVAL; 8341560c974SMiklos Szeredi } 8354237ba43SMiklos Szeredi } else { 8364237ba43SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, 0, 8374237ba43SMiklos Szeredi FUSE_RENAME, 8384237ba43SMiklos Szeredi sizeof(struct fuse_rename_in)); 8394237ba43SMiklos Szeredi } 8401560c974SMiklos Szeredi 8414237ba43SMiklos Szeredi return err; 8424237ba43SMiklos Szeredi } 8434237ba43SMiklos Szeredi 8449e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 8459e6268dbSMiklos Szeredi struct dentry *newent) 8469e6268dbSMiklos Szeredi { 8479e6268dbSMiklos Szeredi int err; 8489e6268dbSMiklos Szeredi struct fuse_link_in inarg; 8492b0143b5SDavid Howells struct inode *inode = d_inode(entry); 8509e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 8517078187aSMiklos Szeredi FUSE_ARGS(args); 8529e6268dbSMiklos Szeredi 8539e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8549e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 855d5b48543SMiklos Szeredi args.opcode = FUSE_LINK; 856d5b48543SMiklos Szeredi args.in_numargs = 2; 857d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 858d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 859d5b48543SMiklos Szeredi args.in_args[1].size = newent->d_name.len + 1; 860d5b48543SMiklos Szeredi args.in_args[1].value = newent->d_name.name; 8617078187aSMiklos Szeredi err = create_new_entry(fc, &args, newdir, newent, inode->i_mode); 8629e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 8639e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 8649e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 8659e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 8669e6268dbSMiklos Szeredi etc.) 8679e6268dbSMiklos Szeredi */ 868ac45d613SMiklos Szeredi if (!err) { 869ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 870ac45d613SMiklos Szeredi 871f15ecfefSKirill Tkhai spin_lock(&fi->lock); 8724510d86fSKirill Tkhai fi->attr_version = atomic64_inc_return(&fc->attr_version); 873c634da71SMiklos Szeredi if (likely(inode->i_nlink < UINT_MAX)) 874ac45d613SMiklos Szeredi inc_nlink(inode); 875f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 8769e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 87731f3267bSMaxim Patlasov fuse_update_ctime(inode); 878ac45d613SMiklos Szeredi } else if (err == -EINTR) { 879ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 880ac45d613SMiklos Szeredi } 8819e6268dbSMiklos Szeredi return err; 8829e6268dbSMiklos Szeredi } 8839e6268dbSMiklos Szeredi 8841fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 8851fb69e78SMiklos Szeredi struct kstat *stat) 8861fb69e78SMiklos Szeredi { 887203627bbSMiklos Szeredi unsigned int blkbits; 8888373200bSPavel Emelyanov struct fuse_conn *fc = get_fuse_conn(inode); 8898373200bSPavel Emelyanov 8908373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 891b0aa7606SMaxim Patlasov if (fc->writeback_cache && S_ISREG(inode->i_mode)) { 8928373200bSPavel Emelyanov attr->size = i_size_read(inode); 893b0aa7606SMaxim Patlasov attr->mtime = inode->i_mtime.tv_sec; 894b0aa7606SMaxim Patlasov attr->mtimensec = inode->i_mtime.tv_nsec; 89531f3267bSMaxim Patlasov attr->ctime = inode->i_ctime.tv_sec; 89631f3267bSMaxim Patlasov attr->ctimensec = inode->i_ctime.tv_nsec; 897b0aa7606SMaxim Patlasov } 898203627bbSMiklos Szeredi 8991fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 9001fb69e78SMiklos Szeredi stat->ino = attr->ino; 9011fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 9021fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 9038cb08329SEric W. Biederman stat->uid = make_kuid(fc->user_ns, attr->uid); 9048cb08329SEric W. Biederman stat->gid = make_kgid(fc->user_ns, attr->gid); 9051fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 9061fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 9071fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 9081fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 9091fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 9101fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 9111fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 9121fb69e78SMiklos Szeredi stat->size = attr->size; 9131fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 914203627bbSMiklos Szeredi 915203627bbSMiklos Szeredi if (attr->blksize != 0) 916203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 917203627bbSMiklos Szeredi else 918203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 919203627bbSMiklos Szeredi 920203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 9211fb69e78SMiklos Szeredi } 9221fb69e78SMiklos Szeredi 923c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 924c79e322fSMiklos Szeredi struct file *file) 925e5e5558eSMiklos Szeredi { 926e5e5558eSMiklos Szeredi int err; 927c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 928c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 929e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 9307078187aSMiklos Szeredi FUSE_ARGS(args); 9311fb69e78SMiklos Szeredi u64 attr_version; 9321fb69e78SMiklos Szeredi 9337dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 9341fb69e78SMiklos Szeredi 935c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 9360e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 937c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 938c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 939c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 940c79e322fSMiklos Szeredi 941c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 942c79e322fSMiklos Szeredi inarg.fh = ff->fh; 943c79e322fSMiklos Szeredi } 944d5b48543SMiklos Szeredi args.opcode = FUSE_GETATTR; 945d5b48543SMiklos Szeredi args.nodeid = get_node_id(inode); 946d5b48543SMiklos Szeredi args.in_numargs = 1; 947d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 948d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 949d5b48543SMiklos Szeredi args.out_numargs = 1; 950d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outarg); 951d5b48543SMiklos Szeredi args.out_args[0].value = &outarg; 9527078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 953e5e5558eSMiklos Szeredi if (!err) { 954eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg.attr) || 955eb59bd17SMiklos Szeredi (inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 956e5e5558eSMiklos Szeredi make_bad_inode(inode); 957e5e5558eSMiklos Szeredi err = -EIO; 958e5e5558eSMiklos Szeredi } else { 959c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 960c79e322fSMiklos Szeredi attr_timeout(&outarg), 9611fb69e78SMiklos Szeredi attr_version); 9621fb69e78SMiklos Szeredi if (stat) 963c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 964e5e5558eSMiklos Szeredi } 965e5e5558eSMiklos Szeredi } 966e5e5558eSMiklos Szeredi return err; 967e5e5558eSMiklos Szeredi } 968e5e5558eSMiklos Szeredi 9695b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file, 9702f1e8196SMiklos Szeredi struct kstat *stat, u32 request_mask, 9712f1e8196SMiklos Szeredi unsigned int flags) 972bcb4be80SMiklos Szeredi { 973bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 9745b97eeacSMiklos Szeredi int err = 0; 975bf5c1898SMiklos Szeredi bool sync; 976bcb4be80SMiklos Szeredi 977bf5c1898SMiklos Szeredi if (flags & AT_STATX_FORCE_SYNC) 978bf5c1898SMiklos Szeredi sync = true; 979bf5c1898SMiklos Szeredi else if (flags & AT_STATX_DONT_SYNC) 980bf5c1898SMiklos Szeredi sync = false; 9812f1e8196SMiklos Szeredi else if (request_mask & READ_ONCE(fi->inval_mask)) 9822f1e8196SMiklos Szeredi sync = true; 983bf5c1898SMiklos Szeredi else 984bf5c1898SMiklos Szeredi sync = time_before64(fi->i_time, get_jiffies_64()); 985bf5c1898SMiklos Szeredi 986bf5c1898SMiklos Szeredi if (sync) { 98760bcc88aSSeth Forshee forget_all_cached_acls(inode); 988bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 9895b97eeacSMiklos Szeredi } else if (stat) { 990bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 991bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 99245c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 993bcb4be80SMiklos Szeredi } 994bcb4be80SMiklos Szeredi 995bcb4be80SMiklos Szeredi return err; 996bcb4be80SMiklos Szeredi } 997bcb4be80SMiklos Szeredi 9985b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file) 9995b97eeacSMiklos Szeredi { 1000802dc049SMiklos Szeredi /* Do *not* need to get atime for internal purposes */ 1001802dc049SMiklos Szeredi return fuse_update_get_attr(inode, file, NULL, 1002802dc049SMiklos Szeredi STATX_BASIC_STATS & ~STATX_ATIME, 0); 10035b97eeacSMiklos Szeredi } 10045b97eeacSMiklos Szeredi 10053b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 1006451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 10073b463ae0SJohn Muir { 10083b463ae0SJohn Muir int err = -ENOTDIR; 10093b463ae0SJohn Muir struct inode *parent; 10103b463ae0SJohn Muir struct dentry *dir; 10113b463ae0SJohn Muir struct dentry *entry; 10123b463ae0SJohn Muir 10133b463ae0SJohn Muir parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); 10143b463ae0SJohn Muir if (!parent) 10153b463ae0SJohn Muir return -ENOENT; 10163b463ae0SJohn Muir 10175955102cSAl Viro inode_lock(parent); 10183b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 10193b463ae0SJohn Muir goto unlock; 10203b463ae0SJohn Muir 10213b463ae0SJohn Muir err = -ENOENT; 10223b463ae0SJohn Muir dir = d_find_alias(parent); 10233b463ae0SJohn Muir if (!dir) 10243b463ae0SJohn Muir goto unlock; 10253b463ae0SJohn Muir 10268387ff25SLinus Torvalds name->hash = full_name_hash(dir, name->name, name->len); 10273b463ae0SJohn Muir entry = d_lookup(dir, name); 10283b463ae0SJohn Muir dput(dir); 10293b463ae0SJohn Muir if (!entry) 10303b463ae0SJohn Muir goto unlock; 10313b463ae0SJohn Muir 1032261aaba7SMiklos Szeredi fuse_dir_changed(parent); 10333b463ae0SJohn Muir fuse_invalidate_entry(entry); 1034451d0f59SJohn Muir 10352b0143b5SDavid Howells if (child_nodeid != 0 && d_really_is_positive(entry)) { 10365955102cSAl Viro inode_lock(d_inode(entry)); 10372b0143b5SDavid Howells if (get_node_id(d_inode(entry)) != child_nodeid) { 1038451d0f59SJohn Muir err = -ENOENT; 1039451d0f59SJohn Muir goto badentry; 1040451d0f59SJohn Muir } 1041451d0f59SJohn Muir if (d_mountpoint(entry)) { 1042451d0f59SJohn Muir err = -EBUSY; 1043451d0f59SJohn Muir goto badentry; 1044451d0f59SJohn Muir } 1045e36cb0b8SDavid Howells if (d_is_dir(entry)) { 1046451d0f59SJohn Muir shrink_dcache_parent(entry); 1047451d0f59SJohn Muir if (!simple_empty(entry)) { 1048451d0f59SJohn Muir err = -ENOTEMPTY; 1049451d0f59SJohn Muir goto badentry; 1050451d0f59SJohn Muir } 10512b0143b5SDavid Howells d_inode(entry)->i_flags |= S_DEAD; 1052451d0f59SJohn Muir } 1053451d0f59SJohn Muir dont_mount(entry); 10542b0143b5SDavid Howells clear_nlink(d_inode(entry)); 10553b463ae0SJohn Muir err = 0; 1056451d0f59SJohn Muir badentry: 10575955102cSAl Viro inode_unlock(d_inode(entry)); 1058451d0f59SJohn Muir if (!err) 1059451d0f59SJohn Muir d_delete(entry); 1060451d0f59SJohn Muir } else { 1061451d0f59SJohn Muir err = 0; 1062451d0f59SJohn Muir } 1063451d0f59SJohn Muir dput(entry); 10643b463ae0SJohn Muir 10653b463ae0SJohn Muir unlock: 10665955102cSAl Viro inode_unlock(parent); 10673b463ae0SJohn Muir iput(parent); 10683b463ae0SJohn Muir return err; 10693b463ae0SJohn Muir } 10703b463ae0SJohn Muir 107187729a55SMiklos Szeredi /* 107287729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1073c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 107487729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 107587729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 107687729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 107787729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 107887729a55SMiklos Szeredi * DoS against the requester. 107987729a55SMiklos Szeredi * 108087729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 108187729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 108287729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 108387729a55SMiklos Szeredi */ 1084c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc) 108587729a55SMiklos Szeredi { 1086c69e8d9cSDavid Howells const struct cred *cred; 1087c69e8d9cSDavid Howells 108829433a29SMiklos Szeredi if (fc->allow_other) 108973f03c2bSSeth Forshee return current_in_userns(fc->user_ns); 109087729a55SMiklos Szeredi 1091c2132c1bSAnatol Pomozov cred = current_cred(); 1092499dcf20SEric W. Biederman if (uid_eq(cred->euid, fc->user_id) && 1093499dcf20SEric W. Biederman uid_eq(cred->suid, fc->user_id) && 1094499dcf20SEric W. Biederman uid_eq(cred->uid, fc->user_id) && 1095499dcf20SEric W. Biederman gid_eq(cred->egid, fc->group_id) && 1096499dcf20SEric W. Biederman gid_eq(cred->sgid, fc->group_id) && 1097499dcf20SEric W. Biederman gid_eq(cred->gid, fc->group_id)) 1098c2132c1bSAnatol Pomozov return 1; 109987729a55SMiklos Szeredi 1100c2132c1bSAnatol Pomozov return 0; 110187729a55SMiklos Szeredi } 110287729a55SMiklos Szeredi 110331d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 110431d40d74SMiklos Szeredi { 110531d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 11067078187aSMiklos Szeredi FUSE_ARGS(args); 110731d40d74SMiklos Szeredi struct fuse_access_in inarg; 110831d40d74SMiklos Szeredi int err; 110931d40d74SMiklos Szeredi 1110698fa1d1SMiklos Szeredi BUG_ON(mask & MAY_NOT_BLOCK); 1111698fa1d1SMiklos Szeredi 111231d40d74SMiklos Szeredi if (fc->no_access) 111331d40d74SMiklos Szeredi return 0; 111431d40d74SMiklos Szeredi 111531d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1116e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 1117d5b48543SMiklos Szeredi args.opcode = FUSE_ACCESS; 1118d5b48543SMiklos Szeredi args.nodeid = get_node_id(inode); 1119d5b48543SMiklos Szeredi args.in_numargs = 1; 1120d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 1121d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 11227078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 112331d40d74SMiklos Szeredi if (err == -ENOSYS) { 112431d40d74SMiklos Szeredi fc->no_access = 1; 112531d40d74SMiklos Szeredi err = 0; 112631d40d74SMiklos Szeredi } 112731d40d74SMiklos Szeredi return err; 112831d40d74SMiklos Szeredi } 112931d40d74SMiklos Szeredi 113010556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 113119690ddbSMiklos Szeredi { 113210556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 113319690ddbSMiklos Szeredi return -ECHILD; 113419690ddbSMiklos Szeredi 113560bcc88aSSeth Forshee forget_all_cached_acls(inode); 113619690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 113719690ddbSMiklos Szeredi } 113819690ddbSMiklos Szeredi 11396f9f1180SMiklos Szeredi /* 11406f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 11416f9f1180SMiklos Szeredi * 11426f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 11436f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 11446f9f1180SMiklos Szeredi * modell. 11456f9f1180SMiklos Szeredi * 11466f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 11476f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 11486f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 11496f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 11506f9f1180SMiklos Szeredi * locally based on file mode. 11516f9f1180SMiklos Szeredi */ 115210556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask) 1153e5e5558eSMiklos Szeredi { 1154e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1155244f6385SMiklos Szeredi bool refreshed = false; 1156244f6385SMiklos Szeredi int err = 0; 1157e5e5558eSMiklos Szeredi 1158c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1159e5e5558eSMiklos Szeredi return -EACCES; 1160244f6385SMiklos Szeredi 1161244f6385SMiklos Szeredi /* 1162e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1163244f6385SMiklos Szeredi */ 116429433a29SMiklos Szeredi if (fc->default_permissions || 1165e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 116619690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1167d233c7ddSMiklos Szeredi u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID; 116819690ddbSMiklos Szeredi 1169d233c7ddSMiklos Szeredi if (perm_mask & READ_ONCE(fi->inval_mask) || 1170d233c7ddSMiklos Szeredi time_before64(fi->i_time, get_jiffies_64())) { 117119690ddbSMiklos Szeredi refreshed = true; 117219690ddbSMiklos Szeredi 117310556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1174244f6385SMiklos Szeredi if (err) 1175244f6385SMiklos Szeredi return err; 11761fb69e78SMiklos Szeredi } 117719690ddbSMiklos Szeredi } 1178244f6385SMiklos Szeredi 117929433a29SMiklos Szeredi if (fc->default_permissions) { 11802830ba7fSAl Viro err = generic_permission(inode, mask); 11811e9a4ed9SMiklos Szeredi 11821e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 11831e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 11841e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1185244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 118610556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 11871e9a4ed9SMiklos Szeredi if (!err) 11882830ba7fSAl Viro err = generic_permission(inode, mask); 11891e9a4ed9SMiklos Szeredi } 11901e9a4ed9SMiklos Szeredi 11916f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 11926f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 11936f9f1180SMiklos Szeredi noticed immediately, only after the attribute 11946f9f1180SMiklos Szeredi timeout has expired */ 11959cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1196e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1197e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1198e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1199e8e96157SMiklos Szeredi if (refreshed) 1200e5e5558eSMiklos Szeredi return -EACCES; 120131d40d74SMiklos Szeredi 120210556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1203e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1204e8e96157SMiklos Szeredi return -EACCES; 1205e8e96157SMiklos Szeredi } 1206e5e5558eSMiklos Szeredi } 1207244f6385SMiklos Szeredi return err; 1208e5e5558eSMiklos Szeredi } 1209e5e5558eSMiklos Szeredi 12105571f1e6SDan Schatzberg static int fuse_readlink_page(struct inode *inode, struct page *page) 1211e5e5558eSMiklos Szeredi { 1212e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 12134c29afecSMiklos Szeredi struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 }; 12144c29afecSMiklos Szeredi struct fuse_args_pages ap = { 12154c29afecSMiklos Szeredi .num_pages = 1, 12164c29afecSMiklos Szeredi .pages = &page, 12174c29afecSMiklos Szeredi .descs = &desc, 12184c29afecSMiklos Szeredi }; 12194c29afecSMiklos Szeredi char *link; 12204c29afecSMiklos Szeredi ssize_t res; 1221e5e5558eSMiklos Szeredi 12224c29afecSMiklos Szeredi ap.args.opcode = FUSE_READLINK; 12234c29afecSMiklos Szeredi ap.args.nodeid = get_node_id(inode); 12244c29afecSMiklos Szeredi ap.args.out_pages = true; 12254c29afecSMiklos Szeredi ap.args.out_argvar = true; 12264c29afecSMiklos Szeredi ap.args.page_zeroing = true; 12274c29afecSMiklos Szeredi ap.args.out_numargs = 1; 12284c29afecSMiklos Szeredi ap.args.out_args[0].size = desc.length; 12294c29afecSMiklos Szeredi res = fuse_simple_request(fc, &ap.args); 12306b255391SAl Viro 1231451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 12325571f1e6SDan Schatzberg 12334c29afecSMiklos Szeredi if (res < 0) 12344c29afecSMiklos Szeredi return res; 12354c29afecSMiklos Szeredi 12364c29afecSMiklos Szeredi if (WARN_ON(res >= PAGE_SIZE)) 12374c29afecSMiklos Szeredi return -EIO; 12384c29afecSMiklos Szeredi 12394c29afecSMiklos Szeredi link = page_address(page); 12404c29afecSMiklos Szeredi link[res] = '\0'; 12414c29afecSMiklos Szeredi 12424c29afecSMiklos Szeredi return 0; 12435571f1e6SDan Schatzberg } 12445571f1e6SDan Schatzberg 12455571f1e6SDan Schatzberg static const char *fuse_get_link(struct dentry *dentry, struct inode *inode, 12465571f1e6SDan Schatzberg struct delayed_call *callback) 12475571f1e6SDan Schatzberg { 12485571f1e6SDan Schatzberg struct fuse_conn *fc = get_fuse_conn(inode); 12495571f1e6SDan Schatzberg struct page *page; 12505571f1e6SDan Schatzberg int err; 12515571f1e6SDan Schatzberg 12525571f1e6SDan Schatzberg err = -EIO; 12535571f1e6SDan Schatzberg if (is_bad_inode(inode)) 12545571f1e6SDan Schatzberg goto out_err; 12555571f1e6SDan Schatzberg 12565571f1e6SDan Schatzberg if (fc->cache_symlinks) 12575571f1e6SDan Schatzberg return page_get_link(dentry, inode, callback); 12585571f1e6SDan Schatzberg 12595571f1e6SDan Schatzberg err = -ECHILD; 12605571f1e6SDan Schatzberg if (!dentry) 12615571f1e6SDan Schatzberg goto out_err; 12625571f1e6SDan Schatzberg 12635571f1e6SDan Schatzberg page = alloc_page(GFP_KERNEL); 12645571f1e6SDan Schatzberg err = -ENOMEM; 12655571f1e6SDan Schatzberg if (!page) 12665571f1e6SDan Schatzberg goto out_err; 12675571f1e6SDan Schatzberg 12685571f1e6SDan Schatzberg err = fuse_readlink_page(inode, page); 12695571f1e6SDan Schatzberg if (err) { 12705571f1e6SDan Schatzberg __free_page(page); 12715571f1e6SDan Schatzberg goto out_err; 12725571f1e6SDan Schatzberg } 12735571f1e6SDan Schatzberg 12745571f1e6SDan Schatzberg set_delayed_call(callback, page_put_link, page); 12755571f1e6SDan Schatzberg 12765571f1e6SDan Schatzberg return page_address(page); 12775571f1e6SDan Schatzberg 12785571f1e6SDan Schatzberg out_err: 12795571f1e6SDan Schatzberg return ERR_PTR(err); 1280e5e5558eSMiklos Szeredi } 1281e5e5558eSMiklos Szeredi 1282e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1283e5e5558eSMiklos Szeredi { 128491fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1285e5e5558eSMiklos Szeredi } 1286e5e5558eSMiklos Szeredi 1287e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1288e5e5558eSMiklos Szeredi { 12892e64ff15SChad Austin fuse_release_common(file, true); 12908b0797a4SMiklos Szeredi 12918b0797a4SMiklos Szeredi return 0; 1292e5e5558eSMiklos Szeredi } 1293e5e5558eSMiklos Szeredi 129402c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 129502c24a82SJosef Bacik int datasync) 129682547981SMiklos Szeredi { 1297a9c2d1e8SMiklos Szeredi struct inode *inode = file->f_mapping->host; 1298a9c2d1e8SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1299a9c2d1e8SMiklos Szeredi int err; 1300a9c2d1e8SMiklos Szeredi 1301a9c2d1e8SMiklos Szeredi if (is_bad_inode(inode)) 1302a9c2d1e8SMiklos Szeredi return -EIO; 1303a9c2d1e8SMiklos Szeredi 1304a9c2d1e8SMiklos Szeredi if (fc->no_fsyncdir) 1305a9c2d1e8SMiklos Szeredi return 0; 1306a9c2d1e8SMiklos Szeredi 1307a9c2d1e8SMiklos Szeredi inode_lock(inode); 1308a9c2d1e8SMiklos Szeredi err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR); 1309a9c2d1e8SMiklos Szeredi if (err == -ENOSYS) { 1310a9c2d1e8SMiklos Szeredi fc->no_fsyncdir = 1; 1311a9c2d1e8SMiklos Szeredi err = 0; 1312a9c2d1e8SMiklos Szeredi } 1313a9c2d1e8SMiklos Szeredi inode_unlock(inode); 1314a9c2d1e8SMiklos Szeredi 1315a9c2d1e8SMiklos Szeredi return err; 131682547981SMiklos Szeredi } 131782547981SMiklos Szeredi 1318b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1319b18da0c5SMiklos Szeredi unsigned long arg) 1320b18da0c5SMiklos Szeredi { 1321b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1322b18da0c5SMiklos Szeredi 1323b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1324b18da0c5SMiklos Szeredi if (fc->minor < 18) 1325b18da0c5SMiklos Szeredi return -ENOTTY; 1326b18da0c5SMiklos Szeredi 1327b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1328b18da0c5SMiklos Szeredi } 1329b18da0c5SMiklos Szeredi 1330b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1331b18da0c5SMiklos Szeredi unsigned long arg) 1332b18da0c5SMiklos Szeredi { 1333b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1334b18da0c5SMiklos Szeredi 1335b18da0c5SMiklos Szeredi if (fc->minor < 18) 1336b18da0c5SMiklos Szeredi return -ENOTTY; 1337b18da0c5SMiklos Szeredi 1338b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1339b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1340b18da0c5SMiklos Szeredi } 1341b18da0c5SMiklos Szeredi 1342b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime) 134317637cbaSMiklos Szeredi { 134417637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 134517637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 134617637cbaSMiklos Szeredi return true; 134717637cbaSMiklos Szeredi 1348b0aa7606SMaxim Patlasov /* Or if kernel i_mtime is the official one */ 1349b0aa7606SMaxim Patlasov if (trust_local_mtime) 1350b0aa7606SMaxim Patlasov return true; 1351b0aa7606SMaxim Patlasov 135217637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 135317637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 135417637cbaSMiklos Szeredi return false; 135517637cbaSMiklos Szeredi 135617637cbaSMiklos Szeredi /* In all other cases update */ 135717637cbaSMiklos Szeredi return true; 135817637cbaSMiklos Szeredi } 135917637cbaSMiklos Szeredi 13608cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr, 13618cb08329SEric W. Biederman struct fuse_setattr_in *arg, bool trust_local_cmtime) 13629e6268dbSMiklos Szeredi { 13639e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 13649e6268dbSMiklos Szeredi 13659e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1366befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 13679e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 13688cb08329SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid); 13699e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 13708cb08329SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid); 13719e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1372befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 137317637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 137417637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1375befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 137617637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 137717637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 137817637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 137917637cbaSMiklos Szeredi } 13803ad22c62SMaxim Patlasov if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) { 138117637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1382befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 138317637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 13843ad22c62SMaxim Patlasov if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime) 138517637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 13869e6268dbSMiklos Szeredi } 13873ad22c62SMaxim Patlasov if ((ivalid & ATTR_CTIME) && trust_local_cmtime) { 13883ad22c62SMaxim Patlasov arg->valid |= FATTR_CTIME; 13893ad22c62SMaxim Patlasov arg->ctime = iattr->ia_ctime.tv_sec; 13903ad22c62SMaxim Patlasov arg->ctimensec = iattr->ia_ctime.tv_nsec; 13913ad22c62SMaxim Patlasov } 13929e6268dbSMiklos Szeredi } 13939e6268dbSMiklos Szeredi 13946f9f1180SMiklos Szeredi /* 13953be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 13963be5a52bSMiklos Szeredi * 13973be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 13983be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 13993be5a52bSMiklos Szeredi */ 14003be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 14013be5a52bSMiklos Szeredi { 14023be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 14033be5a52bSMiklos Szeredi 14045955102cSAl Viro BUG_ON(!inode_is_locked(inode)); 14053be5a52bSMiklos Szeredi 1406f15ecfefSKirill Tkhai spin_lock(&fi->lock); 14073be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 14083be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 1409f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 14103be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 14113be5a52bSMiklos Szeredi } 14123be5a52bSMiklos Szeredi 14133be5a52bSMiklos Szeredi /* 14143be5a52bSMiklos Szeredi * Allow writepages on inode 14153be5a52bSMiklos Szeredi * 14163be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 14173be5a52bSMiklos Szeredi * writepages. 14183be5a52bSMiklos Szeredi */ 14193be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 14203be5a52bSMiklos Szeredi { 14213be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 14223be5a52bSMiklos Szeredi 14233be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 14243be5a52bSMiklos Szeredi fi->writectr = 0; 14253be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 14263be5a52bSMiklos Szeredi } 14273be5a52bSMiklos Szeredi 14283be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 14293be5a52bSMiklos Szeredi { 1430f15ecfefSKirill Tkhai struct fuse_inode *fi = get_fuse_inode(inode); 14313be5a52bSMiklos Szeredi 1432f15ecfefSKirill Tkhai spin_lock(&fi->lock); 14333be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 1434f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 14353be5a52bSMiklos Szeredi } 14363be5a52bSMiklos Szeredi 14377078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, 1438b0aa7606SMaxim Patlasov struct inode *inode, 1439b0aa7606SMaxim Patlasov struct fuse_setattr_in *inarg_p, 1440b0aa7606SMaxim Patlasov struct fuse_attr_out *outarg_p) 1441b0aa7606SMaxim Patlasov { 1442d5b48543SMiklos Szeredi args->opcode = FUSE_SETATTR; 1443d5b48543SMiklos Szeredi args->nodeid = get_node_id(inode); 1444d5b48543SMiklos Szeredi args->in_numargs = 1; 1445d5b48543SMiklos Szeredi args->in_args[0].size = sizeof(*inarg_p); 1446d5b48543SMiklos Szeredi args->in_args[0].value = inarg_p; 1447d5b48543SMiklos Szeredi args->out_numargs = 1; 1448d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(*outarg_p); 1449d5b48543SMiklos Szeredi args->out_args[0].value = outarg_p; 1450b0aa7606SMaxim Patlasov } 1451b0aa7606SMaxim Patlasov 1452b0aa7606SMaxim Patlasov /* 1453b0aa7606SMaxim Patlasov * Flush inode->i_mtime to the server 1454b0aa7606SMaxim Patlasov */ 1455ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff) 1456b0aa7606SMaxim Patlasov { 1457b0aa7606SMaxim Patlasov struct fuse_conn *fc = get_fuse_conn(inode); 14587078187aSMiklos Szeredi FUSE_ARGS(args); 1459b0aa7606SMaxim Patlasov struct fuse_setattr_in inarg; 1460b0aa7606SMaxim Patlasov struct fuse_attr_out outarg; 1461b0aa7606SMaxim Patlasov 1462b0aa7606SMaxim Patlasov memset(&inarg, 0, sizeof(inarg)); 1463b0aa7606SMaxim Patlasov memset(&outarg, 0, sizeof(outarg)); 1464b0aa7606SMaxim Patlasov 1465ab9e13f7SMaxim Patlasov inarg.valid = FATTR_MTIME; 1466b0aa7606SMaxim Patlasov inarg.mtime = inode->i_mtime.tv_sec; 1467b0aa7606SMaxim Patlasov inarg.mtimensec = inode->i_mtime.tv_nsec; 1468ab9e13f7SMaxim Patlasov if (fc->minor >= 23) { 1469ab9e13f7SMaxim Patlasov inarg.valid |= FATTR_CTIME; 1470ab9e13f7SMaxim Patlasov inarg.ctime = inode->i_ctime.tv_sec; 1471ab9e13f7SMaxim Patlasov inarg.ctimensec = inode->i_ctime.tv_nsec; 1472ab9e13f7SMaxim Patlasov } 14731e18bda8SMiklos Szeredi if (ff) { 14741e18bda8SMiklos Szeredi inarg.valid |= FATTR_FH; 14751e18bda8SMiklos Szeredi inarg.fh = ff->fh; 14761e18bda8SMiklos Szeredi } 14777078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 1478b0aa7606SMaxim Patlasov 14797078187aSMiklos Szeredi return fuse_simple_request(fc, &args); 1480b0aa7606SMaxim Patlasov } 1481b0aa7606SMaxim Patlasov 14823be5a52bSMiklos Szeredi /* 14836f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 14846f9f1180SMiklos Szeredi * 14856f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 14866f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 14879ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 14889ffbb916SMiklos Szeredi * and the actual truncation by hand. 14896f9f1180SMiklos Szeredi */ 149062490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, 149149d4914fSMiklos Szeredi struct file *file) 14929e6268dbSMiklos Szeredi { 149362490330SJan Kara struct inode *inode = d_inode(dentry); 14949e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 149506a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 14967078187aSMiklos Szeredi FUSE_ARGS(args); 14979e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 14989e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 14993be5a52bSMiklos Szeredi bool is_truncate = false; 15008373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 15013be5a52bSMiklos Szeredi loff_t oldsize; 15029e6268dbSMiklos Szeredi int err; 15033ad22c62SMaxim Patlasov bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode); 15049e6268dbSMiklos Szeredi 150529433a29SMiklos Szeredi if (!fc->default_permissions) 1506db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1507db78b877SChristoph Hellwig 150831051c85SJan Kara err = setattr_prepare(dentry, attr); 15091e9a4ed9SMiklos Szeredi if (err) 15101e9a4ed9SMiklos Szeredi return err; 15111e9a4ed9SMiklos Szeredi 15128d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 1513df0e91d4SMiklos Szeredi /* This is coming from open(..., ... | O_TRUNC); */ 1514df0e91d4SMiklos Szeredi WARN_ON(!(attr->ia_valid & ATTR_SIZE)); 1515df0e91d4SMiklos Szeredi WARN_ON(attr->ia_size != 0); 1516df0e91d4SMiklos Szeredi if (fc->atomic_o_trunc) { 1517df0e91d4SMiklos Szeredi /* 1518df0e91d4SMiklos Szeredi * No need to send request to userspace, since actual 1519df0e91d4SMiklos Szeredi * truncation has already been done by OPEN. But still 1520df0e91d4SMiklos Szeredi * need to truncate page cache. 1521df0e91d4SMiklos Szeredi */ 1522df0e91d4SMiklos Szeredi i_size_write(inode, 0); 1523df0e91d4SMiklos Szeredi truncate_pagecache(inode, 0); 15246ff958edSMiklos Szeredi return 0; 1525df0e91d4SMiklos Szeredi } 15268d56adddSMiklos Szeredi file = NULL; 15278d56adddSMiklos Szeredi } 15286ff958edSMiklos Szeredi 1529ab2257e9SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1530ab2257e9SMiklos Szeredi if (WARN_ON(!S_ISREG(inode->i_mode))) 1531ab2257e9SMiklos Szeredi return -EIO; 15323be5a52bSMiklos Szeredi is_truncate = true; 1533ab2257e9SMiklos Szeredi } 15349e6268dbSMiklos Szeredi 1535b24e7598SMiklos Szeredi /* Flush dirty data/metadata before non-truncate SETATTR */ 1536b24e7598SMiklos Szeredi if (is_wb && S_ISREG(inode->i_mode) && 1537b24e7598SMiklos Szeredi attr->ia_valid & 1538b24e7598SMiklos Szeredi (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET | 1539b24e7598SMiklos Szeredi ATTR_TIMES_SET)) { 1540b24e7598SMiklos Szeredi err = write_inode_now(inode, true); 1541b24e7598SMiklos Szeredi if (err) 1542b24e7598SMiklos Szeredi return err; 1543b24e7598SMiklos Szeredi 1544b24e7598SMiklos Szeredi fuse_set_nowrite(inode); 1545b24e7598SMiklos Szeredi fuse_release_nowrite(inode); 1546b24e7598SMiklos Szeredi } 1547b24e7598SMiklos Szeredi 154806a7c3c2SMaxim Patlasov if (is_truncate) { 15493be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 155006a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 15513ad22c62SMaxim Patlasov if (trust_local_cmtime && attr->ia_size != inode->i_size) 15523ad22c62SMaxim Patlasov attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; 155306a7c3c2SMaxim Patlasov } 15543be5a52bSMiklos Szeredi 15559e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 15560e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 15578cb08329SEric W. Biederman iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime); 155849d4914fSMiklos Szeredi if (file) { 155949d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 156049d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 156149d4914fSMiklos Szeredi inarg.fh = ff->fh; 156249d4914fSMiklos Szeredi } 1563f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1564f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1565f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1566f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 1567f3332114SMiklos Szeredi } 15687078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 15697078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 1570e00d2c2dSMiklos Szeredi if (err) { 1571e00d2c2dSMiklos Szeredi if (err == -EINTR) 1572e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 15733be5a52bSMiklos Szeredi goto error; 1574e00d2c2dSMiklos Szeredi } 1575e00d2c2dSMiklos Szeredi 1576eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg.attr) || 1577eb59bd17SMiklos Szeredi (inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 15789e6268dbSMiklos Szeredi make_bad_inode(inode); 15793be5a52bSMiklos Szeredi err = -EIO; 15803be5a52bSMiklos Szeredi goto error; 15819e6268dbSMiklos Szeredi } 15829e6268dbSMiklos Szeredi 1583f15ecfefSKirill Tkhai spin_lock(&fi->lock); 1584b0aa7606SMaxim Patlasov /* the kernel maintains i_mtime locally */ 15853ad22c62SMaxim Patlasov if (trust_local_cmtime) { 15863ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_MTIME) 1587b0aa7606SMaxim Patlasov inode->i_mtime = attr->ia_mtime; 15883ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_CTIME) 15893ad22c62SMaxim Patlasov inode->i_ctime = attr->ia_ctime; 15901e18bda8SMiklos Szeredi /* FIXME: clear I_DIRTY_SYNC? */ 1591b0aa7606SMaxim Patlasov } 1592b0aa7606SMaxim Patlasov 15933be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 15943be5a52bSMiklos Szeredi attr_timeout(&outarg)); 15953be5a52bSMiklos Szeredi oldsize = inode->i_size; 15968373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 15978373200bSPavel Emelyanov if (!is_wb || is_truncate || !S_ISREG(inode->i_mode)) 15983be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 15993be5a52bSMiklos Szeredi 16003be5a52bSMiklos Szeredi if (is_truncate) { 1601f15ecfefSKirill Tkhai /* NOTE: this may release/reacquire fi->lock */ 16023be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 16033be5a52bSMiklos Szeredi } 1604f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 16053be5a52bSMiklos Szeredi 16063be5a52bSMiklos Szeredi /* 16073be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 16083be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 16093be5a52bSMiklos Szeredi */ 16108373200bSPavel Emelyanov if ((is_truncate || !is_wb) && 16118373200bSPavel Emelyanov S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 16127caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 16133be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 16143be5a52bSMiklos Szeredi } 16153be5a52bSMiklos Szeredi 161606a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 1617e00d2c2dSMiklos Szeredi return 0; 16183be5a52bSMiklos Szeredi 16193be5a52bSMiklos Szeredi error: 16203be5a52bSMiklos Szeredi if (is_truncate) 16213be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 16223be5a52bSMiklos Szeredi 162306a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 16243be5a52bSMiklos Szeredi return err; 16259e6268dbSMiklos Szeredi } 16269e6268dbSMiklos Szeredi 162749d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 162849d4914fSMiklos Szeredi { 16292b0143b5SDavid Howells struct inode *inode = d_inode(entry); 16305e940c1dSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1631a09f99edSMiklos Szeredi struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL; 16325e2b8828SMiklos Szeredi int ret; 1633efb9fa9eSMaxim Patlasov 1634efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1635efb9fa9eSMaxim Patlasov return -EACCES; 1636efb9fa9eSMaxim Patlasov 1637a09f99edSMiklos Szeredi if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) { 1638a09f99edSMiklos Szeredi attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | 1639a09f99edSMiklos Szeredi ATTR_MODE); 16405e940c1dSMiklos Szeredi 1641a09f99edSMiklos Szeredi /* 16425e940c1dSMiklos Szeredi * The only sane way to reliably kill suid/sgid is to do it in 16435e940c1dSMiklos Szeredi * the userspace filesystem 16445e940c1dSMiklos Szeredi * 16455e940c1dSMiklos Szeredi * This should be done on write(), truncate() and chown(). 16465e940c1dSMiklos Szeredi */ 16475e940c1dSMiklos Szeredi if (!fc->handle_killpriv) { 16485e940c1dSMiklos Szeredi /* 16495e940c1dSMiklos Szeredi * ia_mode calculation may have used stale i_mode. 16505e940c1dSMiklos Szeredi * Refresh and recalculate. 1651a09f99edSMiklos Szeredi */ 1652a09f99edSMiklos Szeredi ret = fuse_do_getattr(inode, NULL, file); 1653a09f99edSMiklos Szeredi if (ret) 1654a09f99edSMiklos Szeredi return ret; 1655a09f99edSMiklos Szeredi 1656a09f99edSMiklos Szeredi attr->ia_mode = inode->i_mode; 1657c01638f5SMiklos Szeredi if (inode->i_mode & S_ISUID) { 1658a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1659a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISUID; 1660a09f99edSMiklos Szeredi } 1661c01638f5SMiklos Szeredi if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 1662a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1663a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISGID; 1664a09f99edSMiklos Szeredi } 1665a09f99edSMiklos Szeredi } 16665e940c1dSMiklos Szeredi } 1667a09f99edSMiklos Szeredi if (!attr->ia_valid) 1668a09f99edSMiklos Szeredi return 0; 1669a09f99edSMiklos Szeredi 1670abb5a14fSLinus Torvalds ret = fuse_do_setattr(entry, attr, file); 16715e2b8828SMiklos Szeredi if (!ret) { 167260bcc88aSSeth Forshee /* 167360bcc88aSSeth Forshee * If filesystem supports acls it may have updated acl xattrs in 167460bcc88aSSeth Forshee * the filesystem, so forget cached acls for the inode. 167560bcc88aSSeth Forshee */ 167660bcc88aSSeth Forshee if (fc->posix_acl) 167760bcc88aSSeth Forshee forget_all_cached_acls(inode); 167860bcc88aSSeth Forshee 16795e2b8828SMiklos Szeredi /* Directory mode changed, may need to revalidate access */ 16805e2b8828SMiklos Szeredi if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE)) 16815e2b8828SMiklos Szeredi fuse_invalidate_entry_cache(entry); 16825e2b8828SMiklos Szeredi } 16835e2b8828SMiklos Szeredi return ret; 168449d4914fSMiklos Szeredi } 168549d4914fSMiklos Szeredi 1686a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat, 1687a528d35eSDavid Howells u32 request_mask, unsigned int flags) 1688e5e5558eSMiklos Szeredi { 1689a528d35eSDavid Howells struct inode *inode = d_inode(path->dentry); 1690244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1691244f6385SMiklos Szeredi 1692c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1693244f6385SMiklos Szeredi return -EACCES; 1694244f6385SMiklos Szeredi 16952f1e8196SMiklos Szeredi return fuse_update_get_attr(inode, NULL, stat, request_mask, flags); 1696e5e5558eSMiklos Szeredi } 1697e5e5558eSMiklos Szeredi 1698754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1699e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 17009e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 17019e6268dbSMiklos Szeredi .symlink = fuse_symlink, 17029e6268dbSMiklos Szeredi .unlink = fuse_unlink, 17039e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 17042773bf00SMiklos Szeredi .rename = fuse_rename2, 17059e6268dbSMiklos Szeredi .link = fuse_link, 17069e6268dbSMiklos Szeredi .setattr = fuse_setattr, 17079e6268dbSMiklos Szeredi .create = fuse_create, 1708c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 17099e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1710e5e5558eSMiklos Szeredi .permission = fuse_permission, 1711e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 171292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 171360bcc88aSSeth Forshee .get_acl = fuse_get_acl, 171460bcc88aSSeth Forshee .set_acl = fuse_set_acl, 1715e5e5558eSMiklos Szeredi }; 1716e5e5558eSMiklos Szeredi 17174b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1718b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1719e5e5558eSMiklos Szeredi .read = generic_read_dir, 1720d9b3dbdcSAl Viro .iterate_shared = fuse_readdir, 1721e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1722e5e5558eSMiklos Szeredi .release = fuse_dir_release, 172382547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1724b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 1725b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 1726e5e5558eSMiklos Szeredi }; 1727e5e5558eSMiklos Szeredi 1728754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 17299e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1730e5e5558eSMiklos Szeredi .permission = fuse_permission, 1731e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 173292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 173360bcc88aSSeth Forshee .get_acl = fuse_get_acl, 173460bcc88aSSeth Forshee .set_acl = fuse_set_acl, 1735e5e5558eSMiklos Szeredi }; 1736e5e5558eSMiklos Szeredi 1737754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 17389e6268dbSMiklos Szeredi .setattr = fuse_setattr, 17396b255391SAl Viro .get_link = fuse_get_link, 1740e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 174192a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 1742e5e5558eSMiklos Szeredi }; 1743e5e5558eSMiklos Szeredi 1744e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1745e5e5558eSMiklos Szeredi { 1746e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1747e5e5558eSMiklos Szeredi } 1748e5e5558eSMiklos Szeredi 1749e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1750e5e5558eSMiklos Szeredi { 1751ab2257e9SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1752ab2257e9SMiklos Szeredi 1753e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1754e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1755ab2257e9SMiklos Szeredi 1756ab2257e9SMiklos Szeredi spin_lock_init(&fi->rdc.lock); 1757ab2257e9SMiklos Szeredi fi->rdc.cached = false; 1758ab2257e9SMiklos Szeredi fi->rdc.size = 0; 1759ab2257e9SMiklos Szeredi fi->rdc.pos = 0; 1760ab2257e9SMiklos Szeredi fi->rdc.version = 0; 1761e5e5558eSMiklos Szeredi } 1762e5e5558eSMiklos Szeredi 17635571f1e6SDan Schatzberg static int fuse_symlink_readpage(struct file *null, struct page *page) 17645571f1e6SDan Schatzberg { 17655571f1e6SDan Schatzberg int err = fuse_readlink_page(page->mapping->host, page); 17665571f1e6SDan Schatzberg 17675571f1e6SDan Schatzberg if (!err) 17685571f1e6SDan Schatzberg SetPageUptodate(page); 17695571f1e6SDan Schatzberg 17705571f1e6SDan Schatzberg unlock_page(page); 17715571f1e6SDan Schatzberg 17725571f1e6SDan Schatzberg return err; 17735571f1e6SDan Schatzberg } 17745571f1e6SDan Schatzberg 17755571f1e6SDan Schatzberg static const struct address_space_operations fuse_symlink_aops = { 17765571f1e6SDan Schatzberg .readpage = fuse_symlink_readpage, 17775571f1e6SDan Schatzberg }; 17785571f1e6SDan Schatzberg 1779e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1780e5e5558eSMiklos Szeredi { 1781e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 17825571f1e6SDan Schatzberg inode->i_data.a_ops = &fuse_symlink_aops; 17835571f1e6SDan Schatzberg inode_nohighmem(inode); 1784e5e5558eSMiklos Szeredi } 1785