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 27f75fdf22SMiklos Szeredi union fuse_dentry { 28f75fdf22SMiklos Szeredi u64 time; 29f75fdf22SMiklos Szeredi struct rcu_head rcu; 30f75fdf22SMiklos Szeredi }; 31f75fdf22SMiklos Szeredi 320a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time) 330a0898cfSMiklos Szeredi { 34f75fdf22SMiklos Szeredi ((union fuse_dentry *) entry->d_fsdata)->time = time; 350a0898cfSMiklos Szeredi } 360a0898cfSMiklos Szeredi 370a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry) 380a0898cfSMiklos Szeredi { 39f75fdf22SMiklos Szeredi return ((union fuse_dentry *) entry->d_fsdata)->time; 400a0898cfSMiklos Szeredi } 410a0898cfSMiklos Szeredi 426f9f1180SMiklos Szeredi /* 436f9f1180SMiklos Szeredi * FUSE caches dentries and attributes with separate timeout. The 446f9f1180SMiklos Szeredi * time in jiffies until the dentry/attributes are valid is stored in 45f75fdf22SMiklos Szeredi * dentry->d_fsdata and fuse_inode->i_time respectively. 466f9f1180SMiklos Szeredi */ 476f9f1180SMiklos Szeredi 486f9f1180SMiklos Szeredi /* 496f9f1180SMiklos Szeredi * Calculate the time in jiffies until a dentry/attributes are valid 506f9f1180SMiklos Szeredi */ 51bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec) 52e5e5558eSMiklos Szeredi { 53685d16ddSMiklos Szeredi if (sec || nsec) { 54bcb6f6d2SMiklos Szeredi struct timespec64 ts = { 55bcb6f6d2SMiklos Szeredi sec, 5621067527SDavid Sheets min_t(u32, nsec, NSEC_PER_SEC - 1) 57bcb6f6d2SMiklos Szeredi }; 58bcb6f6d2SMiklos Szeredi 59bcb6f6d2SMiklos Szeredi return get_jiffies_64() + timespec64_to_jiffies(&ts); 60685d16ddSMiklos Szeredi } else 610a0898cfSMiklos Szeredi return 0; 62e5e5558eSMiklos Szeredi } 63e5e5558eSMiklos Szeredi 646f9f1180SMiklos Szeredi /* 656f9f1180SMiklos Szeredi * Set dentry and possibly attribute timeouts from the lookup/mk* 666f9f1180SMiklos Szeredi * replies 676f9f1180SMiklos Szeredi */ 68d123d8e1SMiklos Szeredi void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o) 690aa7c699SMiklos Szeredi { 700a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 710a0898cfSMiklos Szeredi time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 721fb69e78SMiklos Szeredi } 731fb69e78SMiklos Szeredi 741fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o) 751fb69e78SMiklos Szeredi { 761fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 771fb69e78SMiklos Szeredi } 781fb69e78SMiklos Szeredi 79d123d8e1SMiklos Szeredi u64 entry_attr_timeout(struct fuse_entry_out *o) 801fb69e78SMiklos Szeredi { 811fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 828cbdf1e6SMiklos Szeredi } 838cbdf1e6SMiklos Szeredi 842f1e8196SMiklos Szeredi static void fuse_invalidate_attr_mask(struct inode *inode, u32 mask) 852f1e8196SMiklos Szeredi { 862f1e8196SMiklos Szeredi set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask); 872f1e8196SMiklos Szeredi } 882f1e8196SMiklos Szeredi 896f9f1180SMiklos Szeredi /* 906f9f1180SMiklos Szeredi * Mark the attributes as stale, so that at the next call to 916f9f1180SMiklos Szeredi * ->getattr() they will be fetched from userspace 926f9f1180SMiklos Szeredi */ 938cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode) 948cbdf1e6SMiklos Szeredi { 952f1e8196SMiklos Szeredi fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS); 968cbdf1e6SMiklos Szeredi } 978cbdf1e6SMiklos Szeredi 98261aaba7SMiklos Szeredi static void fuse_dir_changed(struct inode *dir) 99261aaba7SMiklos Szeredi { 100261aaba7SMiklos Szeredi fuse_invalidate_attr(dir); 101261aaba7SMiklos Szeredi inode_maybe_inc_iversion(dir, false); 102261aaba7SMiklos Szeredi } 103261aaba7SMiklos Szeredi 104451418fcSAndrew Gallagher /** 105451418fcSAndrew Gallagher * Mark the attributes as stale due to an atime change. Avoid the invalidate if 106451418fcSAndrew Gallagher * atime is not used. 107451418fcSAndrew Gallagher */ 108451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode) 109451418fcSAndrew Gallagher { 110451418fcSAndrew Gallagher if (!IS_RDONLY(inode)) 1112f1e8196SMiklos Szeredi fuse_invalidate_attr_mask(inode, STATX_ATIME); 112451418fcSAndrew Gallagher } 113451418fcSAndrew Gallagher 1146f9f1180SMiklos Szeredi /* 1156f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 1166f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 1176f9f1180SMiklos Szeredi * 1186f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 1196f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 1206f9f1180SMiklos Szeredi * lookup) 1216f9f1180SMiklos Szeredi */ 122dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry) 1238cbdf1e6SMiklos Szeredi { 1240a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 1258cbdf1e6SMiklos Szeredi } 1268cbdf1e6SMiklos Szeredi 1276f9f1180SMiklos Szeredi /* 1286f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 1296f9f1180SMiklos Szeredi * dentry from the hash 1306f9f1180SMiklos Szeredi */ 1318cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1328cbdf1e6SMiklos Szeredi { 1338cbdf1e6SMiklos Szeredi d_invalidate(entry); 1348cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1350aa7c699SMiklos Szeredi } 1360aa7c699SMiklos Szeredi 1377078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, 13813983d06SAl Viro u64 nodeid, const struct qstr *name, 139e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 140e5e5558eSMiklos Szeredi { 1410e9663eeSMiklos Szeredi memset(outarg, 0, sizeof(struct fuse_entry_out)); 1427078187aSMiklos Szeredi args->in.h.opcode = FUSE_LOOKUP; 1437078187aSMiklos Szeredi args->in.h.nodeid = nodeid; 1447078187aSMiklos Szeredi args->in.numargs = 1; 1457078187aSMiklos Szeredi args->in.args[0].size = name->len + 1; 1467078187aSMiklos Szeredi args->in.args[0].value = name->name; 1477078187aSMiklos Szeredi args->out.numargs = 1; 1487078187aSMiklos Szeredi args->out.args[0].size = sizeof(struct fuse_entry_out); 1497078187aSMiklos Szeredi args->out.args[0].value = outarg; 150e5e5558eSMiklos Szeredi } 151e5e5558eSMiklos Szeredi 1525c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc) 1537dca9fd3SMiklos Szeredi { 1547dca9fd3SMiklos Szeredi u64 curr_version; 1557dca9fd3SMiklos Szeredi 1567dca9fd3SMiklos Szeredi /* 1577dca9fd3SMiklos Szeredi * The spin lock isn't actually needed on 64bit archs, but we 1587dca9fd3SMiklos Szeredi * don't yet care too much about such optimizations. 1597dca9fd3SMiklos Szeredi */ 1607dca9fd3SMiklos Szeredi spin_lock(&fc->lock); 1617dca9fd3SMiklos Szeredi curr_version = fc->attr_version; 1627dca9fd3SMiklos Szeredi spin_unlock(&fc->lock); 1637dca9fd3SMiklos Szeredi 1647dca9fd3SMiklos Szeredi return curr_version; 1657dca9fd3SMiklos Szeredi } 1667dca9fd3SMiklos Szeredi 1676f9f1180SMiklos Szeredi /* 1686f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1696f9f1180SMiklos Szeredi * 1706f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 1716f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 1726f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 1736f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 1746f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 1756f9f1180SMiklos Szeredi */ 1760b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) 177e5e5558eSMiklos Szeredi { 17834286d66SNick Piggin struct inode *inode; 17928420dadSMiklos Szeredi struct dentry *parent; 18028420dadSMiklos Szeredi struct fuse_conn *fc; 1816314efeeSMiklos Szeredi struct fuse_inode *fi; 182e2a6b952SMiklos Szeredi int ret; 1838cbdf1e6SMiklos Szeredi 1842b0143b5SDavid Howells inode = d_inode_rcu(entry); 1858cbdf1e6SMiklos Szeredi if (inode && is_bad_inode(inode)) 186e2a6b952SMiklos Szeredi goto invalid; 187154210ccSAnand Avati else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || 188154210ccSAnand Avati (flags & LOOKUP_REVAL)) { 189e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 1907078187aSMiklos Szeredi FUSE_ARGS(args); 19107e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 1921fb69e78SMiklos Szeredi u64 attr_version; 1938cbdf1e6SMiklos Szeredi 19450322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 1958cbdf1e6SMiklos Szeredi if (!inode) 196e2a6b952SMiklos Szeredi goto invalid; 1978cbdf1e6SMiklos Szeredi 198e2a6b952SMiklos Szeredi ret = -ECHILD; 1990b728e19SAl Viro if (flags & LOOKUP_RCU) 200e2a6b952SMiklos Szeredi goto out; 201e7c0a167SMiklos Szeredi 2028cbdf1e6SMiklos Szeredi fc = get_fuse_conn(inode); 203e5e5558eSMiklos Szeredi 20407e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 205e2a6b952SMiklos Szeredi ret = -ENOMEM; 2067078187aSMiklos Szeredi if (!forget) 207e2a6b952SMiklos Szeredi goto out; 2082d51013eSMiklos Szeredi 2097dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 2101fb69e78SMiklos Szeredi 211e956edd0SMiklos Szeredi parent = dget_parent(entry); 2122b0143b5SDavid Howells fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)), 213c180eebeSMiklos Szeredi &entry->d_name, &outarg); 2147078187aSMiklos Szeredi ret = fuse_simple_request(fc, &args); 215e956edd0SMiklos Szeredi dput(parent); 21650322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 2177078187aSMiklos Szeredi if (!ret && !outarg.nodeid) 2187078187aSMiklos Szeredi ret = -ENOENT; 2197078187aSMiklos Szeredi if (!ret) { 2206314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2219e6268dbSMiklos Szeredi if (outarg.nodeid != get_node_id(inode)) { 22207e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 223e2a6b952SMiklos Szeredi goto invalid; 2249e6268dbSMiklos Szeredi } 2258da5ff23SMiklos Szeredi spin_lock(&fc->lock); 2269e6268dbSMiklos Szeredi fi->nlookup++; 2278da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 2289e6268dbSMiklos Szeredi } 22907e77dcaSMiklos Szeredi kfree(forget); 2307078187aSMiklos Szeredi if (ret == -ENOMEM) 2317078187aSMiklos Szeredi goto out; 2327078187aSMiklos Szeredi if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 233e2a6b952SMiklos Szeredi goto invalid; 234e5e5558eSMiklos Szeredi 23560bcc88aSSeth Forshee forget_all_cached_acls(inode); 2361fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2371fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2381fb69e78SMiklos Szeredi attr_version); 2391fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 24028420dadSMiklos Szeredi } else if (inode) { 2416314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2426314efeeSMiklos Szeredi if (flags & LOOKUP_RCU) { 2436314efeeSMiklos Szeredi if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) 2446314efeeSMiklos Szeredi return -ECHILD; 2456314efeeSMiklos Szeredi } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { 24628420dadSMiklos Szeredi parent = dget_parent(entry); 2472b0143b5SDavid Howells fuse_advise_use_readdirplus(d_inode(parent)); 24828420dadSMiklos Szeredi dput(parent); 249e5e5558eSMiklos Szeredi } 25028420dadSMiklos Szeredi } 251e2a6b952SMiklos Szeredi ret = 1; 252e2a6b952SMiklos Szeredi out: 253e2a6b952SMiklos Szeredi return ret; 254e2a6b952SMiklos Szeredi 255e2a6b952SMiklos Szeredi invalid: 256e2a6b952SMiklos Szeredi ret = 0; 257e2a6b952SMiklos Szeredi goto out; 258e5e5558eSMiklos Szeredi } 259e5e5558eSMiklos Szeredi 260f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry) 261f75fdf22SMiklos Szeredi { 262f75fdf22SMiklos Szeredi dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), GFP_KERNEL); 263f75fdf22SMiklos Szeredi 264f75fdf22SMiklos Szeredi return dentry->d_fsdata ? 0 : -ENOMEM; 265f75fdf22SMiklos Szeredi } 266f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry) 267f75fdf22SMiklos Szeredi { 268f75fdf22SMiklos Szeredi union fuse_dentry *fd = dentry->d_fsdata; 269f75fdf22SMiklos Szeredi 270f75fdf22SMiklos Szeredi kfree_rcu(fd, rcu); 271f75fdf22SMiklos Szeredi } 272f75fdf22SMiklos Szeredi 2734269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 274e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 275f75fdf22SMiklos Szeredi .d_init = fuse_dentry_init, 276f75fdf22SMiklos Szeredi .d_release = fuse_dentry_release, 277e5e5558eSMiklos Szeredi }; 278e5e5558eSMiklos Szeredi 2790ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = { 2800ce267ffSMiklos Szeredi .d_init = fuse_dentry_init, 2810ce267ffSMiklos Szeredi .d_release = fuse_dentry_release, 2820ce267ffSMiklos Szeredi }; 2830ce267ffSMiklos Szeredi 284a5bfffacSTimo Savola int fuse_valid_type(int m) 28539ee059aSMiklos Szeredi { 28639ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 28739ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 28839ee059aSMiklos Szeredi } 28939ee059aSMiklos Szeredi 29013983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, 291c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 292c180eebeSMiklos Szeredi { 293c180eebeSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 2947078187aSMiklos Szeredi FUSE_ARGS(args); 29507e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 296c180eebeSMiklos Szeredi u64 attr_version; 297c180eebeSMiklos Szeredi int err; 298c180eebeSMiklos Szeredi 299c180eebeSMiklos Szeredi *inode = NULL; 300c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 301c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 302c180eebeSMiklos Szeredi goto out; 303c180eebeSMiklos Szeredi 304c180eebeSMiklos Szeredi 30507e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 30607e77dcaSMiklos Szeredi err = -ENOMEM; 3077078187aSMiklos Szeredi if (!forget) 308c180eebeSMiklos Szeredi goto out; 309c180eebeSMiklos Szeredi 310c180eebeSMiklos Szeredi attr_version = fuse_get_attr_version(fc); 311c180eebeSMiklos Szeredi 3127078187aSMiklos Szeredi fuse_lookup_init(fc, &args, nodeid, name, outarg); 3137078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 314c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 315c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 316c180eebeSMiklos Szeredi goto out_put_forget; 317c180eebeSMiklos Szeredi 318c180eebeSMiklos Szeredi err = -EIO; 319c180eebeSMiklos Szeredi if (!outarg->nodeid) 320c180eebeSMiklos Szeredi goto out_put_forget; 321c180eebeSMiklos Szeredi if (!fuse_valid_type(outarg->attr.mode)) 322c180eebeSMiklos Szeredi goto out_put_forget; 323c180eebeSMiklos Szeredi 324c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 325c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 326c180eebeSMiklos Szeredi attr_version); 327c180eebeSMiklos Szeredi err = -ENOMEM; 328c180eebeSMiklos Szeredi if (!*inode) { 32907e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg->nodeid, 1); 330c180eebeSMiklos Szeredi goto out; 331c180eebeSMiklos Szeredi } 332c180eebeSMiklos Szeredi err = 0; 333c180eebeSMiklos Szeredi 334c180eebeSMiklos Szeredi out_put_forget: 33507e77dcaSMiklos Szeredi kfree(forget); 336c180eebeSMiklos Szeredi out: 337c180eebeSMiklos Szeredi return err; 338c180eebeSMiklos Szeredi } 339c180eebeSMiklos Szeredi 3400aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 34100cd8dd3SAl Viro unsigned int flags) 342e5e5558eSMiklos Szeredi { 343e5e5558eSMiklos Szeredi int err; 344e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 345c180eebeSMiklos Szeredi struct inode *inode; 3460de6256dSMiklos Szeredi struct dentry *newent; 347c180eebeSMiklos Szeredi bool outarg_valid = true; 34863576c13SMiklos Szeredi bool locked; 349e5e5558eSMiklos Szeredi 35063576c13SMiklos Szeredi locked = fuse_lock_inode(dir); 351c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 352c180eebeSMiklos Szeredi &outarg, &inode); 35363576c13SMiklos Szeredi fuse_unlock_inode(dir, locked); 354c180eebeSMiklos Szeredi if (err == -ENOENT) { 355c180eebeSMiklos Szeredi outarg_valid = false; 356c180eebeSMiklos Szeredi err = 0; 3572d51013eSMiklos Szeredi } 358c180eebeSMiklos Szeredi if (err) 359c180eebeSMiklos Szeredi goto out_err; 3602d51013eSMiklos Szeredi 361ee4e5271SMiklos Szeredi err = -EIO; 362c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 363c180eebeSMiklos Szeredi goto out_iput; 364e5e5558eSMiklos Szeredi 36541d28bcaSAl Viro newent = d_splice_alias(inode, entry); 366c180eebeSMiklos Szeredi err = PTR_ERR(newent); 367c180eebeSMiklos Szeredi if (IS_ERR(newent)) 3685835f339SMiklos Szeredi goto out_err; 369d2a85164SMiklos Szeredi 3700de6256dSMiklos Szeredi entry = newent ? newent : entry; 371c180eebeSMiklos Szeredi if (outarg_valid) 3721fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 3738cbdf1e6SMiklos Szeredi else 3748cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 375c180eebeSMiklos Szeredi 3764582a4abSFeng Shuo fuse_advise_use_readdirplus(dir); 3770de6256dSMiklos Szeredi return newent; 378c180eebeSMiklos Szeredi 379c180eebeSMiklos Szeredi out_iput: 380c180eebeSMiklos Szeredi iput(inode); 381c180eebeSMiklos Szeredi out_err: 382c180eebeSMiklos Szeredi return ERR_PTR(err); 383e5e5558eSMiklos Szeredi } 384e5e5558eSMiklos Szeredi 3856f9f1180SMiklos Szeredi /* 3866f9f1180SMiklos Szeredi * Atomic create+open operation 3876f9f1180SMiklos Szeredi * 3886f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 3896f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 3906f9f1180SMiklos Szeredi */ 391d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 39230d90494SAl Viro struct file *file, unsigned flags, 393b452a458SAl Viro umode_t mode) 394fd72faacSMiklos Szeredi { 395fd72faacSMiklos Szeredi int err; 396fd72faacSMiklos Szeredi struct inode *inode; 397fd72faacSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 3987078187aSMiklos Szeredi FUSE_ARGS(args); 39907e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 400e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 401fd72faacSMiklos Szeredi struct fuse_open_out outopen; 402fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 403fd72faacSMiklos Szeredi struct fuse_file *ff; 404fd72faacSMiklos Szeredi 405af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 406af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 407af109bcaSMiklos Szeredi 40807e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 409c8ccbe03SMiklos Szeredi err = -ENOMEM; 41007e77dcaSMiklos Szeredi if (!forget) 411c8ccbe03SMiklos Szeredi goto out_err; 41251eb01e7SMiklos Szeredi 413ce1d5a49SMiklos Szeredi err = -ENOMEM; 414acf99433STejun Heo ff = fuse_file_alloc(fc); 415fd72faacSMiklos Szeredi if (!ff) 4167078187aSMiklos Szeredi goto out_put_forget_req; 417fd72faacSMiklos Szeredi 418e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 419e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 420e0a43ddcSMiklos Szeredi 421fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 422fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4230e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 424fd72faacSMiklos Szeredi inarg.flags = flags; 425fd72faacSMiklos Szeredi inarg.mode = mode; 426e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 4277078187aSMiklos Szeredi args.in.h.opcode = FUSE_CREATE; 4287078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(dir); 4297078187aSMiklos Szeredi args.in.numargs = 2; 43021f62174SMiklos Szeredi args.in.args[0].size = sizeof(inarg); 4317078187aSMiklos Szeredi args.in.args[0].value = &inarg; 4327078187aSMiklos Szeredi args.in.args[1].size = entry->d_name.len + 1; 4337078187aSMiklos Szeredi args.in.args[1].value = entry->d_name.name; 4347078187aSMiklos Szeredi args.out.numargs = 2; 4357078187aSMiklos Szeredi args.out.args[0].size = sizeof(outentry); 4367078187aSMiklos Szeredi args.out.args[0].value = &outentry; 4377078187aSMiklos Szeredi args.out.args[1].size = sizeof(outopen); 4387078187aSMiklos Szeredi args.out.args[1].value = &outopen; 4397078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 440c8ccbe03SMiklos Szeredi if (err) 441fd72faacSMiklos Szeredi goto out_free_ff; 442fd72faacSMiklos Szeredi 443fd72faacSMiklos Szeredi err = -EIO; 4442827d0b2SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 445fd72faacSMiklos Szeredi goto out_free_ff; 446fd72faacSMiklos Szeredi 447c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 448c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 449c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 450fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 4511fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 452fd72faacSMiklos Szeredi if (!inode) { 453fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 4548b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 45507e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outentry.nodeid, 1); 456c8ccbe03SMiklos Szeredi err = -ENOMEM; 457c8ccbe03SMiklos Szeredi goto out_err; 458fd72faacSMiklos Szeredi } 45907e77dcaSMiklos Szeredi kfree(forget); 460fd72faacSMiklos Szeredi d_instantiate(entry, inode); 4611fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 462261aaba7SMiklos Szeredi fuse_dir_changed(dir); 463be12af3eSAl Viro err = finish_open(file, entry, generic_file_open); 46430d90494SAl Viro if (err) { 4658b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 466c8ccbe03SMiklos Szeredi } else { 467267d8444SMiklos Szeredi file->private_data = ff; 468c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 469c8ccbe03SMiklos Szeredi } 470d9585277SAl Viro return err; 471fd72faacSMiklos Szeredi 472fd72faacSMiklos Szeredi out_free_ff: 473fd72faacSMiklos Szeredi fuse_file_free(ff); 47451eb01e7SMiklos Szeredi out_put_forget_req: 47507e77dcaSMiklos Szeredi kfree(forget); 476c8ccbe03SMiklos Szeredi out_err: 477d9585277SAl Viro return err; 478c8ccbe03SMiklos Szeredi } 479c8ccbe03SMiklos Szeredi 480c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); 481d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 48230d90494SAl Viro struct file *file, unsigned flags, 48344907d79SAl Viro umode_t mode) 484c8ccbe03SMiklos Szeredi { 485c8ccbe03SMiklos Szeredi int err; 486c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 487c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 488c8ccbe03SMiklos Szeredi 48900699ad8SAl Viro if (d_in_lookup(entry)) { 49000cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 491c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 492d9585277SAl Viro return PTR_ERR(res); 493c8ccbe03SMiklos Szeredi 494c8ccbe03SMiklos Szeredi if (res) 495c8ccbe03SMiklos Szeredi entry = res; 496c8ccbe03SMiklos Szeredi } 497c8ccbe03SMiklos Szeredi 4982b0143b5SDavid Howells if (!(flags & O_CREAT) || d_really_is_positive(entry)) 499c8ccbe03SMiklos Szeredi goto no_open; 500c8ccbe03SMiklos Szeredi 501c8ccbe03SMiklos Szeredi /* Only creates */ 50273a09dd9SAl Viro file->f_mode |= FMODE_CREATED; 503c8ccbe03SMiklos Szeredi 504c8ccbe03SMiklos Szeredi if (fc->no_create) 505c8ccbe03SMiklos Szeredi goto mknod; 506c8ccbe03SMiklos Szeredi 507b452a458SAl Viro err = fuse_create_open(dir, entry, file, flags, mode); 508d9585277SAl Viro if (err == -ENOSYS) { 509c8ccbe03SMiklos Szeredi fc->no_create = 1; 510c8ccbe03SMiklos Szeredi goto mknod; 511c8ccbe03SMiklos Szeredi } 512c8ccbe03SMiklos Szeredi out_dput: 513c8ccbe03SMiklos Szeredi dput(res); 514d9585277SAl Viro return err; 515c8ccbe03SMiklos Szeredi 516c8ccbe03SMiklos Szeredi mknod: 517c8ccbe03SMiklos Szeredi err = fuse_mknod(dir, entry, mode, 0); 518d9585277SAl Viro if (err) 519c8ccbe03SMiklos Szeredi goto out_dput; 520c8ccbe03SMiklos Szeredi no_open: 521e45198a6SAl Viro return finish_no_open(file, res); 522fd72faacSMiklos Szeredi } 523fd72faacSMiklos Szeredi 5246f9f1180SMiklos Szeredi /* 5256f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 5266f9f1180SMiklos Szeredi */ 5277078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, 5289e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 529541af6a0SAl Viro umode_t mode) 5309e6268dbSMiklos Szeredi { 5319e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 5329e6268dbSMiklos Szeredi struct inode *inode; 533c971e6a0SAl Viro struct dentry *d; 5349e6268dbSMiklos Szeredi int err; 53507e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 5362d51013eSMiklos Szeredi 53707e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 5387078187aSMiklos Szeredi if (!forget) 53907e77dcaSMiklos Szeredi return -ENOMEM; 5409e6268dbSMiklos Szeredi 5410e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 5427078187aSMiklos Szeredi args->in.h.nodeid = get_node_id(dir); 5437078187aSMiklos Szeredi args->out.numargs = 1; 5447078187aSMiklos Szeredi args->out.args[0].size = sizeof(outarg); 5457078187aSMiklos Szeredi args->out.args[0].value = &outarg; 5467078187aSMiklos Szeredi err = fuse_simple_request(fc, args); 5472d51013eSMiklos Szeredi if (err) 5482d51013eSMiklos Szeredi goto out_put_forget_req; 5492d51013eSMiklos Szeredi 55039ee059aSMiklos Szeredi err = -EIO; 55139ee059aSMiklos Szeredi if (invalid_nodeid(outarg.nodeid)) 5522d51013eSMiklos Szeredi goto out_put_forget_req; 55339ee059aSMiklos Szeredi 55439ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 5552d51013eSMiklos Szeredi goto out_put_forget_req; 55639ee059aSMiklos Szeredi 5579e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 5581fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 5599e6268dbSMiklos Szeredi if (!inode) { 56007e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 5619e6268dbSMiklos Szeredi return -ENOMEM; 5629e6268dbSMiklos Szeredi } 56307e77dcaSMiklos Szeredi kfree(forget); 5649e6268dbSMiklos Szeredi 565c971e6a0SAl Viro d_drop(entry); 566c971e6a0SAl Viro d = d_splice_alias(inode, entry); 567c971e6a0SAl Viro if (IS_ERR(d)) 568c971e6a0SAl Viro return PTR_ERR(d); 569d2a85164SMiklos Szeredi 570c971e6a0SAl Viro if (d) { 571c971e6a0SAl Viro fuse_change_entry_timeout(d, &outarg); 572c971e6a0SAl Viro dput(d); 573c971e6a0SAl Viro } else { 5741fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 575c971e6a0SAl Viro } 576261aaba7SMiklos Szeredi fuse_dir_changed(dir); 5779e6268dbSMiklos Szeredi return 0; 57839ee059aSMiklos Szeredi 5792d51013eSMiklos Szeredi out_put_forget_req: 58007e77dcaSMiklos Szeredi kfree(forget); 58139ee059aSMiklos Szeredi return err; 5829e6268dbSMiklos Szeredi } 5839e6268dbSMiklos Szeredi 5841a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, 5859e6268dbSMiklos Szeredi dev_t rdev) 5869e6268dbSMiklos Szeredi { 5879e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 5889e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 5897078187aSMiklos Szeredi FUSE_ARGS(args); 5909e6268dbSMiklos Szeredi 591e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 592e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 593e0a43ddcSMiklos Szeredi 5949e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 5959e6268dbSMiklos Szeredi inarg.mode = mode; 5969e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 597e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 5987078187aSMiklos Szeredi args.in.h.opcode = FUSE_MKNOD; 5997078187aSMiklos Szeredi args.in.numargs = 2; 60021f62174SMiklos Szeredi args.in.args[0].size = sizeof(inarg); 6017078187aSMiklos Szeredi args.in.args[0].value = &inarg; 6027078187aSMiklos Szeredi args.in.args[1].size = entry->d_name.len + 1; 6037078187aSMiklos Szeredi args.in.args[1].value = entry->d_name.name; 6047078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, mode); 6059e6268dbSMiklos Szeredi } 6069e6268dbSMiklos Szeredi 6074acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, 608ebfc3b49SAl Viro bool excl) 6099e6268dbSMiklos Szeredi { 6109e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 6119e6268dbSMiklos Szeredi } 6129e6268dbSMiklos Szeredi 61318bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) 6149e6268dbSMiklos Szeredi { 6159e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 6169e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6177078187aSMiklos Szeredi FUSE_ARGS(args); 6189e6268dbSMiklos Szeredi 619e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 620e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 621e0a43ddcSMiklos Szeredi 6229e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6239e6268dbSMiklos Szeredi inarg.mode = mode; 624e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6257078187aSMiklos Szeredi args.in.h.opcode = FUSE_MKDIR; 6267078187aSMiklos Szeredi args.in.numargs = 2; 6277078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 6287078187aSMiklos Szeredi args.in.args[0].value = &inarg; 6297078187aSMiklos Szeredi args.in.args[1].size = entry->d_name.len + 1; 6307078187aSMiklos Szeredi args.in.args[1].value = entry->d_name.name; 6317078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, S_IFDIR); 6329e6268dbSMiklos Szeredi } 6339e6268dbSMiklos Szeredi 6349e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 6359e6268dbSMiklos Szeredi const char *link) 6369e6268dbSMiklos Szeredi { 6379e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6389e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 6397078187aSMiklos Szeredi FUSE_ARGS(args); 6409e6268dbSMiklos Szeredi 6417078187aSMiklos Szeredi args.in.h.opcode = FUSE_SYMLINK; 6427078187aSMiklos Szeredi args.in.numargs = 2; 6437078187aSMiklos Szeredi args.in.args[0].size = entry->d_name.len + 1; 6447078187aSMiklos Szeredi args.in.args[0].value = entry->d_name.name; 6457078187aSMiklos Szeredi args.in.args[1].size = len; 6467078187aSMiklos Szeredi args.in.args[1].value = link; 6477078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, S_IFLNK); 6489e6268dbSMiklos Szeredi } 6499e6268dbSMiklos Szeredi 650703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode) 65131f3267bSMaxim Patlasov { 65231f3267bSMaxim Patlasov if (!IS_NOCMTIME(inode)) { 653c2050a45SDeepa Dinamani inode->i_ctime = current_time(inode); 65431f3267bSMaxim Patlasov mark_inode_dirty_sync(inode); 65531f3267bSMaxim Patlasov } 65631f3267bSMaxim Patlasov } 65731f3267bSMaxim Patlasov 6589e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 6599e6268dbSMiklos Szeredi { 6609e6268dbSMiklos Szeredi int err; 6619e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6627078187aSMiklos Szeredi FUSE_ARGS(args); 6639e6268dbSMiklos Szeredi 6647078187aSMiklos Szeredi args.in.h.opcode = FUSE_UNLINK; 6657078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(dir); 6667078187aSMiklos Szeredi args.in.numargs = 1; 6677078187aSMiklos Szeredi args.in.args[0].size = entry->d_name.len + 1; 6687078187aSMiklos Szeredi args.in.args[0].value = entry->d_name.name; 6697078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 6709e6268dbSMiklos Szeredi if (!err) { 6712b0143b5SDavid Howells struct inode *inode = d_inode(entry); 672ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 6739e6268dbSMiklos Szeredi 674ac45d613SMiklos Szeredi spin_lock(&fc->lock); 675ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 676dfca7cebSMiklos Szeredi /* 677dfca7cebSMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 678dfca7cebSMiklos Szeredi * happen if userspace filesystem is careless. It would be 679dfca7cebSMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 680dfca7cebSMiklos Szeredi * condition here 681dfca7cebSMiklos Szeredi */ 682dfca7cebSMiklos Szeredi if (inode->i_nlink > 0) 683ac45d613SMiklos Szeredi drop_nlink(inode); 684ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 6859e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 686261aaba7SMiklos Szeredi fuse_dir_changed(dir); 6878cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 68831f3267bSMaxim Patlasov fuse_update_ctime(inode); 6899e6268dbSMiklos Szeredi } else if (err == -EINTR) 6909e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 6919e6268dbSMiklos Szeredi return err; 6929e6268dbSMiklos Szeredi } 6939e6268dbSMiklos Szeredi 6949e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 6959e6268dbSMiklos Szeredi { 6969e6268dbSMiklos Szeredi int err; 6979e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6987078187aSMiklos Szeredi FUSE_ARGS(args); 6999e6268dbSMiklos Szeredi 7007078187aSMiklos Szeredi args.in.h.opcode = FUSE_RMDIR; 7017078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(dir); 7027078187aSMiklos Szeredi args.in.numargs = 1; 7037078187aSMiklos Szeredi args.in.args[0].size = entry->d_name.len + 1; 7047078187aSMiklos Szeredi args.in.args[0].value = entry->d_name.name; 7057078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 7069e6268dbSMiklos Szeredi if (!err) { 7072b0143b5SDavid Howells clear_nlink(d_inode(entry)); 708261aaba7SMiklos Szeredi fuse_dir_changed(dir); 7098cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 7109e6268dbSMiklos Szeredi } else if (err == -EINTR) 7119e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7129e6268dbSMiklos Szeredi return err; 7139e6268dbSMiklos Szeredi } 7149e6268dbSMiklos Szeredi 7151560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, 7161560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 7171560c974SMiklos Szeredi unsigned int flags, int opcode, size_t argsize) 7189e6268dbSMiklos Szeredi { 7199e6268dbSMiklos Szeredi int err; 7201560c974SMiklos Szeredi struct fuse_rename2_in inarg; 7219e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 7227078187aSMiklos Szeredi FUSE_ARGS(args); 7239e6268dbSMiklos Szeredi 7241560c974SMiklos Szeredi memset(&inarg, 0, argsize); 7259e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 7261560c974SMiklos Szeredi inarg.flags = flags; 7277078187aSMiklos Szeredi args.in.h.opcode = opcode; 7287078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(olddir); 7297078187aSMiklos Szeredi args.in.numargs = 3; 7307078187aSMiklos Szeredi args.in.args[0].size = argsize; 7317078187aSMiklos Szeredi args.in.args[0].value = &inarg; 7327078187aSMiklos Szeredi args.in.args[1].size = oldent->d_name.len + 1; 7337078187aSMiklos Szeredi args.in.args[1].value = oldent->d_name.name; 7347078187aSMiklos Szeredi args.in.args[2].size = newent->d_name.len + 1; 7357078187aSMiklos Szeredi args.in.args[2].value = newent->d_name.name; 7367078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 7379e6268dbSMiklos Szeredi if (!err) { 73808b63307SMiklos Szeredi /* ctime changes */ 7392b0143b5SDavid Howells fuse_invalidate_attr(d_inode(oldent)); 7402b0143b5SDavid Howells fuse_update_ctime(d_inode(oldent)); 74108b63307SMiklos Szeredi 7421560c974SMiklos Szeredi if (flags & RENAME_EXCHANGE) { 7432b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 7442b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 7451560c974SMiklos Szeredi } 7461560c974SMiklos Szeredi 747261aaba7SMiklos Szeredi fuse_dir_changed(olddir); 7489e6268dbSMiklos Szeredi if (olddir != newdir) 749261aaba7SMiklos Szeredi fuse_dir_changed(newdir); 7508cbdf1e6SMiklos Szeredi 7518cbdf1e6SMiklos Szeredi /* newent will end up negative */ 7522b0143b5SDavid Howells if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { 7532b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 7548cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 7552b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 7565219f346SMiklos Szeredi } 7579e6268dbSMiklos Szeredi } else if (err == -EINTR) { 7589e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 7599e6268dbSMiklos Szeredi rename actually took place. If the invalidation 7609e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 7619e6268dbSMiklos Szeredi directory), then there can be inconsistency between 7629e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 7639e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 7642b0143b5SDavid Howells if (d_really_is_positive(newent)) 7659e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 7669e6268dbSMiklos Szeredi } 7679e6268dbSMiklos Szeredi 7689e6268dbSMiklos Szeredi return err; 7699e6268dbSMiklos Szeredi } 7709e6268dbSMiklos Szeredi 7711560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent, 7721560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 7731560c974SMiklos Szeredi unsigned int flags) 7741560c974SMiklos Szeredi { 7751560c974SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 7761560c974SMiklos Szeredi int err; 7771560c974SMiklos Szeredi 7781560c974SMiklos Szeredi if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) 7791560c974SMiklos Szeredi return -EINVAL; 7801560c974SMiklos Szeredi 7814237ba43SMiklos Szeredi if (flags) { 7821560c974SMiklos Szeredi if (fc->no_rename2 || fc->minor < 23) 7831560c974SMiklos Szeredi return -EINVAL; 7841560c974SMiklos Szeredi 7851560c974SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, flags, 7864237ba43SMiklos Szeredi FUSE_RENAME2, 7874237ba43SMiklos Szeredi sizeof(struct fuse_rename2_in)); 7881560c974SMiklos Szeredi if (err == -ENOSYS) { 7891560c974SMiklos Szeredi fc->no_rename2 = 1; 7901560c974SMiklos Szeredi err = -EINVAL; 7911560c974SMiklos Szeredi } 7924237ba43SMiklos Szeredi } else { 7934237ba43SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, 0, 7944237ba43SMiklos Szeredi FUSE_RENAME, 7954237ba43SMiklos Szeredi sizeof(struct fuse_rename_in)); 7964237ba43SMiklos Szeredi } 7971560c974SMiklos Szeredi 7984237ba43SMiklos Szeredi return err; 7994237ba43SMiklos Szeredi } 8004237ba43SMiklos Szeredi 8019e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 8029e6268dbSMiklos Szeredi struct dentry *newent) 8039e6268dbSMiklos Szeredi { 8049e6268dbSMiklos Szeredi int err; 8059e6268dbSMiklos Szeredi struct fuse_link_in inarg; 8062b0143b5SDavid Howells struct inode *inode = d_inode(entry); 8079e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 8087078187aSMiklos Szeredi FUSE_ARGS(args); 8099e6268dbSMiklos Szeredi 8109e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8119e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 8127078187aSMiklos Szeredi args.in.h.opcode = FUSE_LINK; 8137078187aSMiklos Szeredi args.in.numargs = 2; 8147078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 8157078187aSMiklos Szeredi args.in.args[0].value = &inarg; 8167078187aSMiklos Szeredi args.in.args[1].size = newent->d_name.len + 1; 8177078187aSMiklos Szeredi args.in.args[1].value = newent->d_name.name; 8187078187aSMiklos Szeredi err = create_new_entry(fc, &args, newdir, newent, inode->i_mode); 8199e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 8209e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 8219e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 8229e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 8239e6268dbSMiklos Szeredi etc.) 8249e6268dbSMiklos Szeredi */ 825ac45d613SMiklos Szeredi if (!err) { 826ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 827ac45d613SMiklos Szeredi 828ac45d613SMiklos Szeredi spin_lock(&fc->lock); 829ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 830ac45d613SMiklos Szeredi inc_nlink(inode); 831ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 8329e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 83331f3267bSMaxim Patlasov fuse_update_ctime(inode); 834ac45d613SMiklos Szeredi } else if (err == -EINTR) { 835ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 836ac45d613SMiklos Szeredi } 8379e6268dbSMiklos Szeredi return err; 8389e6268dbSMiklos Szeredi } 8399e6268dbSMiklos Szeredi 8401fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 8411fb69e78SMiklos Szeredi struct kstat *stat) 8421fb69e78SMiklos Szeredi { 843203627bbSMiklos Szeredi unsigned int blkbits; 8448373200bSPavel Emelyanov struct fuse_conn *fc = get_fuse_conn(inode); 8458373200bSPavel Emelyanov 8468373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 847b0aa7606SMaxim Patlasov if (fc->writeback_cache && S_ISREG(inode->i_mode)) { 8488373200bSPavel Emelyanov attr->size = i_size_read(inode); 849b0aa7606SMaxim Patlasov attr->mtime = inode->i_mtime.tv_sec; 850b0aa7606SMaxim Patlasov attr->mtimensec = inode->i_mtime.tv_nsec; 85131f3267bSMaxim Patlasov attr->ctime = inode->i_ctime.tv_sec; 85231f3267bSMaxim Patlasov attr->ctimensec = inode->i_ctime.tv_nsec; 853b0aa7606SMaxim Patlasov } 854203627bbSMiklos Szeredi 8551fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 8561fb69e78SMiklos Szeredi stat->ino = attr->ino; 8571fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 8581fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 8598cb08329SEric W. Biederman stat->uid = make_kuid(fc->user_ns, attr->uid); 8608cb08329SEric W. Biederman stat->gid = make_kgid(fc->user_ns, attr->gid); 8611fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 8621fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 8631fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 8641fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 8651fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 8661fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 8671fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 8681fb69e78SMiklos Szeredi stat->size = attr->size; 8691fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 870203627bbSMiklos Szeredi 871203627bbSMiklos Szeredi if (attr->blksize != 0) 872203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 873203627bbSMiklos Szeredi else 874203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 875203627bbSMiklos Szeredi 876203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 8771fb69e78SMiklos Szeredi } 8781fb69e78SMiklos Szeredi 879c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 880c79e322fSMiklos Szeredi struct file *file) 881e5e5558eSMiklos Szeredi { 882e5e5558eSMiklos Szeredi int err; 883c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 884c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 885e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 8867078187aSMiklos Szeredi FUSE_ARGS(args); 8871fb69e78SMiklos Szeredi u64 attr_version; 8881fb69e78SMiklos Szeredi 8897dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 8901fb69e78SMiklos Szeredi 891c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8920e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 893c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 894c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 895c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 896c79e322fSMiklos Szeredi 897c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 898c79e322fSMiklos Szeredi inarg.fh = ff->fh; 899c79e322fSMiklos Szeredi } 9007078187aSMiklos Szeredi args.in.h.opcode = FUSE_GETATTR; 9017078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 9027078187aSMiklos Szeredi args.in.numargs = 1; 9037078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 9047078187aSMiklos Szeredi args.in.args[0].value = &inarg; 9057078187aSMiklos Szeredi args.out.numargs = 1; 9067078187aSMiklos Szeredi args.out.args[0].size = sizeof(outarg); 9077078187aSMiklos Szeredi args.out.args[0].value = &outarg; 9087078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 909e5e5558eSMiklos Szeredi if (!err) { 910c79e322fSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 911e5e5558eSMiklos Szeredi make_bad_inode(inode); 912e5e5558eSMiklos Szeredi err = -EIO; 913e5e5558eSMiklos Szeredi } else { 914c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 915c79e322fSMiklos Szeredi attr_timeout(&outarg), 9161fb69e78SMiklos Szeredi attr_version); 9171fb69e78SMiklos Szeredi if (stat) 918c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 919e5e5558eSMiklos Szeredi } 920e5e5558eSMiklos Szeredi } 921e5e5558eSMiklos Szeredi return err; 922e5e5558eSMiklos Szeredi } 923e5e5558eSMiklos Szeredi 9245b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file, 9252f1e8196SMiklos Szeredi struct kstat *stat, u32 request_mask, 9262f1e8196SMiklos Szeredi unsigned int flags) 927bcb4be80SMiklos Szeredi { 928bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 9295b97eeacSMiklos Szeredi int err = 0; 930bf5c1898SMiklos Szeredi bool sync; 931bcb4be80SMiklos Szeredi 932bf5c1898SMiklos Szeredi if (flags & AT_STATX_FORCE_SYNC) 933bf5c1898SMiklos Szeredi sync = true; 934bf5c1898SMiklos Szeredi else if (flags & AT_STATX_DONT_SYNC) 935bf5c1898SMiklos Szeredi sync = false; 9362f1e8196SMiklos Szeredi else if (request_mask & READ_ONCE(fi->inval_mask)) 9372f1e8196SMiklos Szeredi sync = true; 938bf5c1898SMiklos Szeredi else 939bf5c1898SMiklos Szeredi sync = time_before64(fi->i_time, get_jiffies_64()); 940bf5c1898SMiklos Szeredi 941bf5c1898SMiklos Szeredi if (sync) { 94260bcc88aSSeth Forshee forget_all_cached_acls(inode); 943bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 9445b97eeacSMiklos Szeredi } else if (stat) { 945bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 946bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 94745c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 948bcb4be80SMiklos Szeredi } 949bcb4be80SMiklos Szeredi 950bcb4be80SMiklos Szeredi return err; 951bcb4be80SMiklos Szeredi } 952bcb4be80SMiklos Szeredi 9535b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file) 9545b97eeacSMiklos Szeredi { 955*802dc049SMiklos Szeredi /* Do *not* need to get atime for internal purposes */ 956*802dc049SMiklos Szeredi return fuse_update_get_attr(inode, file, NULL, 957*802dc049SMiklos Szeredi STATX_BASIC_STATS & ~STATX_ATIME, 0); 9585b97eeacSMiklos Szeredi } 9595b97eeacSMiklos Szeredi 9603b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 961451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 9623b463ae0SJohn Muir { 9633b463ae0SJohn Muir int err = -ENOTDIR; 9643b463ae0SJohn Muir struct inode *parent; 9653b463ae0SJohn Muir struct dentry *dir; 9663b463ae0SJohn Muir struct dentry *entry; 9673b463ae0SJohn Muir 9683b463ae0SJohn Muir parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); 9693b463ae0SJohn Muir if (!parent) 9703b463ae0SJohn Muir return -ENOENT; 9713b463ae0SJohn Muir 9725955102cSAl Viro inode_lock(parent); 9733b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 9743b463ae0SJohn Muir goto unlock; 9753b463ae0SJohn Muir 9763b463ae0SJohn Muir err = -ENOENT; 9773b463ae0SJohn Muir dir = d_find_alias(parent); 9783b463ae0SJohn Muir if (!dir) 9793b463ae0SJohn Muir goto unlock; 9803b463ae0SJohn Muir 9818387ff25SLinus Torvalds name->hash = full_name_hash(dir, name->name, name->len); 9823b463ae0SJohn Muir entry = d_lookup(dir, name); 9833b463ae0SJohn Muir dput(dir); 9843b463ae0SJohn Muir if (!entry) 9853b463ae0SJohn Muir goto unlock; 9863b463ae0SJohn Muir 987261aaba7SMiklos Szeredi fuse_dir_changed(parent); 9883b463ae0SJohn Muir fuse_invalidate_entry(entry); 989451d0f59SJohn Muir 9902b0143b5SDavid Howells if (child_nodeid != 0 && d_really_is_positive(entry)) { 9915955102cSAl Viro inode_lock(d_inode(entry)); 9922b0143b5SDavid Howells if (get_node_id(d_inode(entry)) != child_nodeid) { 993451d0f59SJohn Muir err = -ENOENT; 994451d0f59SJohn Muir goto badentry; 995451d0f59SJohn Muir } 996451d0f59SJohn Muir if (d_mountpoint(entry)) { 997451d0f59SJohn Muir err = -EBUSY; 998451d0f59SJohn Muir goto badentry; 999451d0f59SJohn Muir } 1000e36cb0b8SDavid Howells if (d_is_dir(entry)) { 1001451d0f59SJohn Muir shrink_dcache_parent(entry); 1002451d0f59SJohn Muir if (!simple_empty(entry)) { 1003451d0f59SJohn Muir err = -ENOTEMPTY; 1004451d0f59SJohn Muir goto badentry; 1005451d0f59SJohn Muir } 10062b0143b5SDavid Howells d_inode(entry)->i_flags |= S_DEAD; 1007451d0f59SJohn Muir } 1008451d0f59SJohn Muir dont_mount(entry); 10092b0143b5SDavid Howells clear_nlink(d_inode(entry)); 10103b463ae0SJohn Muir err = 0; 1011451d0f59SJohn Muir badentry: 10125955102cSAl Viro inode_unlock(d_inode(entry)); 1013451d0f59SJohn Muir if (!err) 1014451d0f59SJohn Muir d_delete(entry); 1015451d0f59SJohn Muir } else { 1016451d0f59SJohn Muir err = 0; 1017451d0f59SJohn Muir } 1018451d0f59SJohn Muir dput(entry); 10193b463ae0SJohn Muir 10203b463ae0SJohn Muir unlock: 10215955102cSAl Viro inode_unlock(parent); 10223b463ae0SJohn Muir iput(parent); 10233b463ae0SJohn Muir return err; 10243b463ae0SJohn Muir } 10253b463ae0SJohn Muir 102687729a55SMiklos Szeredi /* 102787729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1028c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 102987729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 103087729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 103187729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 103287729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 103387729a55SMiklos Szeredi * DoS against the requester. 103487729a55SMiklos Szeredi * 103587729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 103687729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 103787729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 103887729a55SMiklos Szeredi */ 1039c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc) 104087729a55SMiklos Szeredi { 1041c69e8d9cSDavid Howells const struct cred *cred; 1042c69e8d9cSDavid Howells 104329433a29SMiklos Szeredi if (fc->allow_other) 104473f03c2bSSeth Forshee return current_in_userns(fc->user_ns); 104587729a55SMiklos Szeredi 1046c2132c1bSAnatol Pomozov cred = current_cred(); 1047499dcf20SEric W. Biederman if (uid_eq(cred->euid, fc->user_id) && 1048499dcf20SEric W. Biederman uid_eq(cred->suid, fc->user_id) && 1049499dcf20SEric W. Biederman uid_eq(cred->uid, fc->user_id) && 1050499dcf20SEric W. Biederman gid_eq(cred->egid, fc->group_id) && 1051499dcf20SEric W. Biederman gid_eq(cred->sgid, fc->group_id) && 1052499dcf20SEric W. Biederman gid_eq(cred->gid, fc->group_id)) 1053c2132c1bSAnatol Pomozov return 1; 105487729a55SMiklos Szeredi 1055c2132c1bSAnatol Pomozov return 0; 105687729a55SMiklos Szeredi } 105787729a55SMiklos Szeredi 105831d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 105931d40d74SMiklos Szeredi { 106031d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 10617078187aSMiklos Szeredi FUSE_ARGS(args); 106231d40d74SMiklos Szeredi struct fuse_access_in inarg; 106331d40d74SMiklos Szeredi int err; 106431d40d74SMiklos Szeredi 1065698fa1d1SMiklos Szeredi BUG_ON(mask & MAY_NOT_BLOCK); 1066698fa1d1SMiklos Szeredi 106731d40d74SMiklos Szeredi if (fc->no_access) 106831d40d74SMiklos Szeredi return 0; 106931d40d74SMiklos Szeredi 107031d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1071e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 10727078187aSMiklos Szeredi args.in.h.opcode = FUSE_ACCESS; 10737078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 10747078187aSMiklos Szeredi args.in.numargs = 1; 10757078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 10767078187aSMiklos Szeredi args.in.args[0].value = &inarg; 10777078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 107831d40d74SMiklos Szeredi if (err == -ENOSYS) { 107931d40d74SMiklos Szeredi fc->no_access = 1; 108031d40d74SMiklos Szeredi err = 0; 108131d40d74SMiklos Szeredi } 108231d40d74SMiklos Szeredi return err; 108331d40d74SMiklos Szeredi } 108431d40d74SMiklos Szeredi 108510556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 108619690ddbSMiklos Szeredi { 108710556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 108819690ddbSMiklos Szeredi return -ECHILD; 108919690ddbSMiklos Szeredi 109060bcc88aSSeth Forshee forget_all_cached_acls(inode); 109119690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 109219690ddbSMiklos Szeredi } 109319690ddbSMiklos Szeredi 10946f9f1180SMiklos Szeredi /* 10956f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 10966f9f1180SMiklos Szeredi * 10976f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 10986f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 10996f9f1180SMiklos Szeredi * modell. 11006f9f1180SMiklos Szeredi * 11016f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 11026f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 11036f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 11046f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 11056f9f1180SMiklos Szeredi * locally based on file mode. 11066f9f1180SMiklos Szeredi */ 110710556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask) 1108e5e5558eSMiklos Szeredi { 1109e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1110244f6385SMiklos Szeredi bool refreshed = false; 1111244f6385SMiklos Szeredi int err = 0; 1112e5e5558eSMiklos Szeredi 1113c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1114e5e5558eSMiklos Szeredi return -EACCES; 1115244f6385SMiklos Szeredi 1116244f6385SMiklos Szeredi /* 1117e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1118244f6385SMiklos Szeredi */ 111929433a29SMiklos Szeredi if (fc->default_permissions || 1120e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 112119690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 112219690ddbSMiklos Szeredi 1123126b9d43SMiklos Szeredi if (time_before64(fi->i_time, get_jiffies_64())) { 112419690ddbSMiklos Szeredi refreshed = true; 112519690ddbSMiklos Szeredi 112610556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1127244f6385SMiklos Szeredi if (err) 1128244f6385SMiklos Szeredi return err; 11291fb69e78SMiklos Szeredi } 113019690ddbSMiklos Szeredi } 1131244f6385SMiklos Szeredi 113229433a29SMiklos Szeredi if (fc->default_permissions) { 11332830ba7fSAl Viro err = generic_permission(inode, mask); 11341e9a4ed9SMiklos Szeredi 11351e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 11361e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 11371e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1138244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 113910556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 11401e9a4ed9SMiklos Szeredi if (!err) 11412830ba7fSAl Viro err = generic_permission(inode, mask); 11421e9a4ed9SMiklos Szeredi } 11431e9a4ed9SMiklos Szeredi 11446f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 11456f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 11466f9f1180SMiklos Szeredi noticed immediately, only after the attribute 11476f9f1180SMiklos Szeredi timeout has expired */ 11489cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1149e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1150e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1151e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1152e8e96157SMiklos Szeredi if (refreshed) 1153e5e5558eSMiklos Szeredi return -EACCES; 115431d40d74SMiklos Szeredi 115510556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1156e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1157e8e96157SMiklos Szeredi return -EACCES; 1158e8e96157SMiklos Szeredi } 1159e5e5558eSMiklos Szeredi } 1160244f6385SMiklos Szeredi return err; 1161e5e5558eSMiklos Szeredi } 1162e5e5558eSMiklos Szeredi 11636b255391SAl Viro static const char *fuse_get_link(struct dentry *dentry, 1164fceef393SAl Viro struct inode *inode, 1165fceef393SAl Viro struct delayed_call *done) 1166e5e5558eSMiklos Szeredi { 1167e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 11687078187aSMiklos Szeredi FUSE_ARGS(args); 1169e5e5558eSMiklos Szeredi char *link; 11707078187aSMiklos Szeredi ssize_t ret; 1171e5e5558eSMiklos Szeredi 11726b255391SAl Viro if (!dentry) 11736b255391SAl Viro return ERR_PTR(-ECHILD); 11746b255391SAl Viro 1175cd3417c8SAl Viro link = kmalloc(PAGE_SIZE, GFP_KERNEL); 11767078187aSMiklos Szeredi if (!link) 11777078187aSMiklos Szeredi return ERR_PTR(-ENOMEM); 11787078187aSMiklos Szeredi 11797078187aSMiklos Szeredi args.in.h.opcode = FUSE_READLINK; 11807078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 11817078187aSMiklos Szeredi args.out.argvar = 1; 11827078187aSMiklos Szeredi args.out.numargs = 1; 11837078187aSMiklos Szeredi args.out.args[0].size = PAGE_SIZE - 1; 11847078187aSMiklos Szeredi args.out.args[0].value = link; 11857078187aSMiklos Szeredi ret = fuse_simple_request(fc, &args); 11867078187aSMiklos Szeredi if (ret < 0) { 1187cd3417c8SAl Viro kfree(link); 11887078187aSMiklos Szeredi link = ERR_PTR(ret); 11897078187aSMiklos Szeredi } else { 11907078187aSMiklos Szeredi link[ret] = '\0'; 1191fceef393SAl Viro set_delayed_call(done, kfree_link, link); 11927078187aSMiklos Szeredi } 1193451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 1194e5e5558eSMiklos Szeredi return link; 1195e5e5558eSMiklos Szeredi } 1196e5e5558eSMiklos Szeredi 1197e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1198e5e5558eSMiklos Szeredi { 119991fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1200e5e5558eSMiklos Szeredi } 1201e5e5558eSMiklos Szeredi 1202e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1203e5e5558eSMiklos Szeredi { 12048b0797a4SMiklos Szeredi fuse_release_common(file, FUSE_RELEASEDIR); 12058b0797a4SMiklos Szeredi 12068b0797a4SMiklos Szeredi return 0; 1207e5e5558eSMiklos Szeredi } 1208e5e5558eSMiklos Szeredi 120902c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 121002c24a82SJosef Bacik int datasync) 121182547981SMiklos Szeredi { 121202c24a82SJosef Bacik return fuse_fsync_common(file, start, end, datasync, 1); 121382547981SMiklos Szeredi } 121482547981SMiklos Szeredi 1215b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1216b18da0c5SMiklos Szeredi unsigned long arg) 1217b18da0c5SMiklos Szeredi { 1218b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1219b18da0c5SMiklos Szeredi 1220b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1221b18da0c5SMiklos Szeredi if (fc->minor < 18) 1222b18da0c5SMiklos Szeredi return -ENOTTY; 1223b18da0c5SMiklos Szeredi 1224b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1225b18da0c5SMiklos Szeredi } 1226b18da0c5SMiklos Szeredi 1227b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1228b18da0c5SMiklos Szeredi unsigned long arg) 1229b18da0c5SMiklos Szeredi { 1230b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1231b18da0c5SMiklos Szeredi 1232b18da0c5SMiklos Szeredi if (fc->minor < 18) 1233b18da0c5SMiklos Szeredi return -ENOTTY; 1234b18da0c5SMiklos Szeredi 1235b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1236b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1237b18da0c5SMiklos Szeredi } 1238b18da0c5SMiklos Szeredi 1239b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime) 124017637cbaSMiklos Szeredi { 124117637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 124217637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 124317637cbaSMiklos Szeredi return true; 124417637cbaSMiklos Szeredi 1245b0aa7606SMaxim Patlasov /* Or if kernel i_mtime is the official one */ 1246b0aa7606SMaxim Patlasov if (trust_local_mtime) 1247b0aa7606SMaxim Patlasov return true; 1248b0aa7606SMaxim Patlasov 124917637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 125017637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 125117637cbaSMiklos Szeredi return false; 125217637cbaSMiklos Szeredi 125317637cbaSMiklos Szeredi /* In all other cases update */ 125417637cbaSMiklos Szeredi return true; 125517637cbaSMiklos Szeredi } 125617637cbaSMiklos Szeredi 12578cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr, 12588cb08329SEric W. Biederman struct fuse_setattr_in *arg, bool trust_local_cmtime) 12599e6268dbSMiklos Szeredi { 12609e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 12619e6268dbSMiklos Szeredi 12629e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1263befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 12649e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 12658cb08329SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid); 12669e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 12678cb08329SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid); 12689e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1269befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 127017637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 127117637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1272befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 127317637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 127417637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 127517637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 127617637cbaSMiklos Szeredi } 12773ad22c62SMaxim Patlasov if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) { 127817637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1279befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 128017637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 12813ad22c62SMaxim Patlasov if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime) 128217637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 12839e6268dbSMiklos Szeredi } 12843ad22c62SMaxim Patlasov if ((ivalid & ATTR_CTIME) && trust_local_cmtime) { 12853ad22c62SMaxim Patlasov arg->valid |= FATTR_CTIME; 12863ad22c62SMaxim Patlasov arg->ctime = iattr->ia_ctime.tv_sec; 12873ad22c62SMaxim Patlasov arg->ctimensec = iattr->ia_ctime.tv_nsec; 12883ad22c62SMaxim Patlasov } 12899e6268dbSMiklos Szeredi } 12909e6268dbSMiklos Szeredi 12916f9f1180SMiklos Szeredi /* 12923be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 12933be5a52bSMiklos Szeredi * 12943be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 12953be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 12963be5a52bSMiklos Szeredi */ 12973be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 12983be5a52bSMiklos Szeredi { 12993be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 13003be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 13013be5a52bSMiklos Szeredi 13025955102cSAl Viro BUG_ON(!inode_is_locked(inode)); 13033be5a52bSMiklos Szeredi 13043be5a52bSMiklos Szeredi spin_lock(&fc->lock); 13053be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 13063be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 13073be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 13083be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 13093be5a52bSMiklos Szeredi } 13103be5a52bSMiklos Szeredi 13113be5a52bSMiklos Szeredi /* 13123be5a52bSMiklos Szeredi * Allow writepages on inode 13133be5a52bSMiklos Szeredi * 13143be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 13153be5a52bSMiklos Szeredi * writepages. 13163be5a52bSMiklos Szeredi */ 13173be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 13183be5a52bSMiklos Szeredi { 13193be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 13203be5a52bSMiklos Szeredi 13213be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 13223be5a52bSMiklos Szeredi fi->writectr = 0; 13233be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 13243be5a52bSMiklos Szeredi } 13253be5a52bSMiklos Szeredi 13263be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 13273be5a52bSMiklos Szeredi { 13283be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 13293be5a52bSMiklos Szeredi 13303be5a52bSMiklos Szeredi spin_lock(&fc->lock); 13313be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 13323be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 13333be5a52bSMiklos Szeredi } 13343be5a52bSMiklos Szeredi 13357078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, 1336b0aa7606SMaxim Patlasov struct inode *inode, 1337b0aa7606SMaxim Patlasov struct fuse_setattr_in *inarg_p, 1338b0aa7606SMaxim Patlasov struct fuse_attr_out *outarg_p) 1339b0aa7606SMaxim Patlasov { 13407078187aSMiklos Szeredi args->in.h.opcode = FUSE_SETATTR; 13417078187aSMiklos Szeredi args->in.h.nodeid = get_node_id(inode); 13427078187aSMiklos Szeredi args->in.numargs = 1; 13437078187aSMiklos Szeredi args->in.args[0].size = sizeof(*inarg_p); 13447078187aSMiklos Szeredi args->in.args[0].value = inarg_p; 13457078187aSMiklos Szeredi args->out.numargs = 1; 13467078187aSMiklos Szeredi args->out.args[0].size = sizeof(*outarg_p); 13477078187aSMiklos Szeredi args->out.args[0].value = outarg_p; 1348b0aa7606SMaxim Patlasov } 1349b0aa7606SMaxim Patlasov 1350b0aa7606SMaxim Patlasov /* 1351b0aa7606SMaxim Patlasov * Flush inode->i_mtime to the server 1352b0aa7606SMaxim Patlasov */ 1353ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff) 1354b0aa7606SMaxim Patlasov { 1355b0aa7606SMaxim Patlasov struct fuse_conn *fc = get_fuse_conn(inode); 13567078187aSMiklos Szeredi FUSE_ARGS(args); 1357b0aa7606SMaxim Patlasov struct fuse_setattr_in inarg; 1358b0aa7606SMaxim Patlasov struct fuse_attr_out outarg; 1359b0aa7606SMaxim Patlasov 1360b0aa7606SMaxim Patlasov memset(&inarg, 0, sizeof(inarg)); 1361b0aa7606SMaxim Patlasov memset(&outarg, 0, sizeof(outarg)); 1362b0aa7606SMaxim Patlasov 1363ab9e13f7SMaxim Patlasov inarg.valid = FATTR_MTIME; 1364b0aa7606SMaxim Patlasov inarg.mtime = inode->i_mtime.tv_sec; 1365b0aa7606SMaxim Patlasov inarg.mtimensec = inode->i_mtime.tv_nsec; 1366ab9e13f7SMaxim Patlasov if (fc->minor >= 23) { 1367ab9e13f7SMaxim Patlasov inarg.valid |= FATTR_CTIME; 1368ab9e13f7SMaxim Patlasov inarg.ctime = inode->i_ctime.tv_sec; 1369ab9e13f7SMaxim Patlasov inarg.ctimensec = inode->i_ctime.tv_nsec; 1370ab9e13f7SMaxim Patlasov } 13711e18bda8SMiklos Szeredi if (ff) { 13721e18bda8SMiklos Szeredi inarg.valid |= FATTR_FH; 13731e18bda8SMiklos Szeredi inarg.fh = ff->fh; 13741e18bda8SMiklos Szeredi } 13757078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 1376b0aa7606SMaxim Patlasov 13777078187aSMiklos Szeredi return fuse_simple_request(fc, &args); 1378b0aa7606SMaxim Patlasov } 1379b0aa7606SMaxim Patlasov 13803be5a52bSMiklos Szeredi /* 13816f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 13826f9f1180SMiklos Szeredi * 13836f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 13846f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 13859ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 13869ffbb916SMiklos Szeredi * and the actual truncation by hand. 13876f9f1180SMiklos Szeredi */ 138862490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, 138949d4914fSMiklos Szeredi struct file *file) 13909e6268dbSMiklos Szeredi { 139162490330SJan Kara struct inode *inode = d_inode(dentry); 13929e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 139306a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 13947078187aSMiklos Szeredi FUSE_ARGS(args); 13959e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 13969e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 13973be5a52bSMiklos Szeredi bool is_truncate = false; 13988373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 13993be5a52bSMiklos Szeredi loff_t oldsize; 14009e6268dbSMiklos Szeredi int err; 14013ad22c62SMaxim Patlasov bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode); 14029e6268dbSMiklos Szeredi 140329433a29SMiklos Szeredi if (!fc->default_permissions) 1404db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1405db78b877SChristoph Hellwig 140631051c85SJan Kara err = setattr_prepare(dentry, attr); 14071e9a4ed9SMiklos Szeredi if (err) 14081e9a4ed9SMiklos Szeredi return err; 14091e9a4ed9SMiklos Szeredi 14108d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 1411df0e91d4SMiklos Szeredi /* This is coming from open(..., ... | O_TRUNC); */ 1412df0e91d4SMiklos Szeredi WARN_ON(!(attr->ia_valid & ATTR_SIZE)); 1413df0e91d4SMiklos Szeredi WARN_ON(attr->ia_size != 0); 1414df0e91d4SMiklos Szeredi if (fc->atomic_o_trunc) { 1415df0e91d4SMiklos Szeredi /* 1416df0e91d4SMiklos Szeredi * No need to send request to userspace, since actual 1417df0e91d4SMiklos Szeredi * truncation has already been done by OPEN. But still 1418df0e91d4SMiklos Szeredi * need to truncate page cache. 1419df0e91d4SMiklos Szeredi */ 1420df0e91d4SMiklos Szeredi i_size_write(inode, 0); 1421df0e91d4SMiklos Szeredi truncate_pagecache(inode, 0); 14226ff958edSMiklos Szeredi return 0; 1423df0e91d4SMiklos Szeredi } 14248d56adddSMiklos Szeredi file = NULL; 14258d56adddSMiklos Szeredi } 14266ff958edSMiklos Szeredi 1427ab2257e9SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1428ab2257e9SMiklos Szeredi if (WARN_ON(!S_ISREG(inode->i_mode))) 1429ab2257e9SMiklos Szeredi return -EIO; 14303be5a52bSMiklos Szeredi is_truncate = true; 1431ab2257e9SMiklos Szeredi } 14329e6268dbSMiklos Szeredi 143306a7c3c2SMaxim Patlasov if (is_truncate) { 14343be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 143506a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 14363ad22c62SMaxim Patlasov if (trust_local_cmtime && attr->ia_size != inode->i_size) 14373ad22c62SMaxim Patlasov attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; 143806a7c3c2SMaxim Patlasov } 14393be5a52bSMiklos Szeredi 14409e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 14410e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 14428cb08329SEric W. Biederman iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime); 144349d4914fSMiklos Szeredi if (file) { 144449d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 144549d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 144649d4914fSMiklos Szeredi inarg.fh = ff->fh; 144749d4914fSMiklos Szeredi } 1448f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1449f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1450f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1451f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 1452f3332114SMiklos Szeredi } 14537078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 14547078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 1455e00d2c2dSMiklos Szeredi if (err) { 1456e00d2c2dSMiklos Szeredi if (err == -EINTR) 1457e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 14583be5a52bSMiklos Szeredi goto error; 1459e00d2c2dSMiklos Szeredi } 1460e00d2c2dSMiklos Szeredi 14619e6268dbSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 14629e6268dbSMiklos Szeredi make_bad_inode(inode); 14633be5a52bSMiklos Szeredi err = -EIO; 14643be5a52bSMiklos Szeredi goto error; 14659e6268dbSMiklos Szeredi } 14669e6268dbSMiklos Szeredi 14673be5a52bSMiklos Szeredi spin_lock(&fc->lock); 1468b0aa7606SMaxim Patlasov /* the kernel maintains i_mtime locally */ 14693ad22c62SMaxim Patlasov if (trust_local_cmtime) { 14703ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_MTIME) 1471b0aa7606SMaxim Patlasov inode->i_mtime = attr->ia_mtime; 14723ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_CTIME) 14733ad22c62SMaxim Patlasov inode->i_ctime = attr->ia_ctime; 14741e18bda8SMiklos Szeredi /* FIXME: clear I_DIRTY_SYNC? */ 1475b0aa7606SMaxim Patlasov } 1476b0aa7606SMaxim Patlasov 14773be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 14783be5a52bSMiklos Szeredi attr_timeout(&outarg)); 14793be5a52bSMiklos Szeredi oldsize = inode->i_size; 14808373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 14818373200bSPavel Emelyanov if (!is_wb || is_truncate || !S_ISREG(inode->i_mode)) 14823be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 14833be5a52bSMiklos Szeredi 14843be5a52bSMiklos Szeredi if (is_truncate) { 14853be5a52bSMiklos Szeredi /* NOTE: this may release/reacquire fc->lock */ 14863be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 14873be5a52bSMiklos Szeredi } 14883be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 14893be5a52bSMiklos Szeredi 14903be5a52bSMiklos Szeredi /* 14913be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 14923be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 14933be5a52bSMiklos Szeredi */ 14948373200bSPavel Emelyanov if ((is_truncate || !is_wb) && 14958373200bSPavel Emelyanov S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 14967caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 14973be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 14983be5a52bSMiklos Szeredi } 14993be5a52bSMiklos Szeredi 150006a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 1501e00d2c2dSMiklos Szeredi return 0; 15023be5a52bSMiklos Szeredi 15033be5a52bSMiklos Szeredi error: 15043be5a52bSMiklos Szeredi if (is_truncate) 15053be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 15063be5a52bSMiklos Szeredi 150706a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 15083be5a52bSMiklos Szeredi return err; 15099e6268dbSMiklos Szeredi } 15109e6268dbSMiklos Szeredi 151149d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 151249d4914fSMiklos Szeredi { 15132b0143b5SDavid Howells struct inode *inode = d_inode(entry); 15145e940c1dSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1515a09f99edSMiklos Szeredi struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL; 15165e2b8828SMiklos Szeredi int ret; 1517efb9fa9eSMaxim Patlasov 1518efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1519efb9fa9eSMaxim Patlasov return -EACCES; 1520efb9fa9eSMaxim Patlasov 1521a09f99edSMiklos Szeredi if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) { 1522a09f99edSMiklos Szeredi attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | 1523a09f99edSMiklos Szeredi ATTR_MODE); 15245e940c1dSMiklos Szeredi 1525a09f99edSMiklos Szeredi /* 15265e940c1dSMiklos Szeredi * The only sane way to reliably kill suid/sgid is to do it in 15275e940c1dSMiklos Szeredi * the userspace filesystem 15285e940c1dSMiklos Szeredi * 15295e940c1dSMiklos Szeredi * This should be done on write(), truncate() and chown(). 15305e940c1dSMiklos Szeredi */ 15315e940c1dSMiklos Szeredi if (!fc->handle_killpriv) { 15325e940c1dSMiklos Szeredi /* 15335e940c1dSMiklos Szeredi * ia_mode calculation may have used stale i_mode. 15345e940c1dSMiklos Szeredi * Refresh and recalculate. 1535a09f99edSMiklos Szeredi */ 1536a09f99edSMiklos Szeredi ret = fuse_do_getattr(inode, NULL, file); 1537a09f99edSMiklos Szeredi if (ret) 1538a09f99edSMiklos Szeredi return ret; 1539a09f99edSMiklos Szeredi 1540a09f99edSMiklos Szeredi attr->ia_mode = inode->i_mode; 1541c01638f5SMiklos Szeredi if (inode->i_mode & S_ISUID) { 1542a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1543a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISUID; 1544a09f99edSMiklos Szeredi } 1545c01638f5SMiklos Szeredi if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 1546a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1547a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISGID; 1548a09f99edSMiklos Szeredi } 1549a09f99edSMiklos Szeredi } 15505e940c1dSMiklos Szeredi } 1551a09f99edSMiklos Szeredi if (!attr->ia_valid) 1552a09f99edSMiklos Szeredi return 0; 1553a09f99edSMiklos Szeredi 1554abb5a14fSLinus Torvalds ret = fuse_do_setattr(entry, attr, file); 15555e2b8828SMiklos Szeredi if (!ret) { 155660bcc88aSSeth Forshee /* 155760bcc88aSSeth Forshee * If filesystem supports acls it may have updated acl xattrs in 155860bcc88aSSeth Forshee * the filesystem, so forget cached acls for the inode. 155960bcc88aSSeth Forshee */ 156060bcc88aSSeth Forshee if (fc->posix_acl) 156160bcc88aSSeth Forshee forget_all_cached_acls(inode); 156260bcc88aSSeth Forshee 15635e2b8828SMiklos Szeredi /* Directory mode changed, may need to revalidate access */ 15645e2b8828SMiklos Szeredi if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE)) 15655e2b8828SMiklos Szeredi fuse_invalidate_entry_cache(entry); 15665e2b8828SMiklos Szeredi } 15675e2b8828SMiklos Szeredi return ret; 156849d4914fSMiklos Szeredi } 156949d4914fSMiklos Szeredi 1570a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat, 1571a528d35eSDavid Howells u32 request_mask, unsigned int flags) 1572e5e5558eSMiklos Szeredi { 1573a528d35eSDavid Howells struct inode *inode = d_inode(path->dentry); 1574244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1575244f6385SMiklos Szeredi 1576c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1577244f6385SMiklos Szeredi return -EACCES; 1578244f6385SMiklos Szeredi 15792f1e8196SMiklos Szeredi return fuse_update_get_attr(inode, NULL, stat, request_mask, flags); 1580e5e5558eSMiklos Szeredi } 1581e5e5558eSMiklos Szeredi 1582754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1583e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 15849e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 15859e6268dbSMiklos Szeredi .symlink = fuse_symlink, 15869e6268dbSMiklos Szeredi .unlink = fuse_unlink, 15879e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 15882773bf00SMiklos Szeredi .rename = fuse_rename2, 15899e6268dbSMiklos Szeredi .link = fuse_link, 15909e6268dbSMiklos Szeredi .setattr = fuse_setattr, 15919e6268dbSMiklos Szeredi .create = fuse_create, 1592c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 15939e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1594e5e5558eSMiklos Szeredi .permission = fuse_permission, 1595e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 159692a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 159760bcc88aSSeth Forshee .get_acl = fuse_get_acl, 159860bcc88aSSeth Forshee .set_acl = fuse_set_acl, 1599e5e5558eSMiklos Szeredi }; 1600e5e5558eSMiklos Szeredi 16014b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1602b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1603e5e5558eSMiklos Szeredi .read = generic_read_dir, 1604d9b3dbdcSAl Viro .iterate_shared = fuse_readdir, 1605e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1606e5e5558eSMiklos Szeredi .release = fuse_dir_release, 160782547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1608b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 1609b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 1610e5e5558eSMiklos Szeredi }; 1611e5e5558eSMiklos Szeredi 1612754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 16139e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1614e5e5558eSMiklos Szeredi .permission = fuse_permission, 1615e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 161692a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 161760bcc88aSSeth Forshee .get_acl = fuse_get_acl, 161860bcc88aSSeth Forshee .set_acl = fuse_set_acl, 1619e5e5558eSMiklos Szeredi }; 1620e5e5558eSMiklos Szeredi 1621754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 16229e6268dbSMiklos Szeredi .setattr = fuse_setattr, 16236b255391SAl Viro .get_link = fuse_get_link, 1624e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 162592a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 1626e5e5558eSMiklos Szeredi }; 1627e5e5558eSMiklos Szeredi 1628e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1629e5e5558eSMiklos Szeredi { 1630e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1631e5e5558eSMiklos Szeredi } 1632e5e5558eSMiklos Szeredi 1633e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1634e5e5558eSMiklos Szeredi { 1635ab2257e9SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1636ab2257e9SMiklos Szeredi 1637e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1638e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1639ab2257e9SMiklos Szeredi 1640ab2257e9SMiklos Szeredi spin_lock_init(&fi->rdc.lock); 1641ab2257e9SMiklos Szeredi fi->rdc.cached = false; 1642ab2257e9SMiklos Szeredi fi->rdc.size = 0; 1643ab2257e9SMiklos Szeredi fi->rdc.pos = 0; 1644ab2257e9SMiklos Szeredi fi->rdc.version = 0; 1645e5e5558eSMiklos Szeredi } 1646e5e5558eSMiklos Szeredi 1647e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1648e5e5558eSMiklos Szeredi { 1649e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 1650e5e5558eSMiklos Szeredi } 1651