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> 1760bcc88aSSeth Forshee #include <linux/posix_acl.h> 18e5e5558eSMiklos Szeredi 198d3af7f3SAl Viro static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx) 204582a4abSFeng Shuo { 214582a4abSFeng Shuo struct fuse_conn *fc = get_fuse_conn(dir); 224582a4abSFeng Shuo struct fuse_inode *fi = get_fuse_inode(dir); 234582a4abSFeng Shuo 244582a4abSFeng Shuo if (!fc->do_readdirplus) 254582a4abSFeng Shuo return false; 26634734b6SEric Wong if (!fc->readdirplus_auto) 27634734b6SEric Wong return true; 284582a4abSFeng Shuo if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state)) 294582a4abSFeng Shuo return true; 308d3af7f3SAl Viro if (ctx->pos == 0) 314582a4abSFeng Shuo return true; 324582a4abSFeng Shuo return false; 334582a4abSFeng Shuo } 344582a4abSFeng Shuo 354582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir) 364582a4abSFeng Shuo { 374582a4abSFeng Shuo struct fuse_inode *fi = get_fuse_inode(dir); 384582a4abSFeng Shuo 394582a4abSFeng Shuo set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state); 404582a4abSFeng Shuo } 414582a4abSFeng Shuo 42f75fdf22SMiklos Szeredi union fuse_dentry { 43f75fdf22SMiklos Szeredi u64 time; 44f75fdf22SMiklos Szeredi struct rcu_head rcu; 45f75fdf22SMiklos Szeredi }; 46f75fdf22SMiklos Szeredi 470a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time) 480a0898cfSMiklos Szeredi { 49f75fdf22SMiklos Szeredi ((union fuse_dentry *) entry->d_fsdata)->time = time; 500a0898cfSMiklos Szeredi } 510a0898cfSMiklos Szeredi 520a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry) 530a0898cfSMiklos Szeredi { 54f75fdf22SMiklos Szeredi return ((union fuse_dentry *) entry->d_fsdata)->time; 550a0898cfSMiklos Szeredi } 560a0898cfSMiklos Szeredi 576f9f1180SMiklos Szeredi /* 586f9f1180SMiklos Szeredi * FUSE caches dentries and attributes with separate timeout. The 596f9f1180SMiklos Szeredi * time in jiffies until the dentry/attributes are valid is stored in 60f75fdf22SMiklos Szeredi * dentry->d_fsdata and fuse_inode->i_time respectively. 616f9f1180SMiklos Szeredi */ 626f9f1180SMiklos Szeredi 636f9f1180SMiklos Szeredi /* 646f9f1180SMiklos Szeredi * Calculate the time in jiffies until a dentry/attributes are valid 656f9f1180SMiklos Szeredi */ 66bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec) 67e5e5558eSMiklos Szeredi { 68685d16ddSMiklos Szeredi if (sec || nsec) { 69bcb6f6d2SMiklos Szeredi struct timespec64 ts = { 70bcb6f6d2SMiklos Szeredi sec, 7121067527SDavid Sheets min_t(u32, nsec, NSEC_PER_SEC - 1) 72bcb6f6d2SMiklos Szeredi }; 73bcb6f6d2SMiklos Szeredi 74bcb6f6d2SMiklos Szeredi return get_jiffies_64() + timespec64_to_jiffies(&ts); 75685d16ddSMiklos Szeredi } else 760a0898cfSMiklos Szeredi return 0; 77e5e5558eSMiklos Szeredi } 78e5e5558eSMiklos Szeredi 796f9f1180SMiklos Szeredi /* 806f9f1180SMiklos Szeredi * Set dentry and possibly attribute timeouts from the lookup/mk* 816f9f1180SMiklos Szeredi * replies 826f9f1180SMiklos Szeredi */ 831fb69e78SMiklos Szeredi static void fuse_change_entry_timeout(struct dentry *entry, 841fb69e78SMiklos Szeredi struct fuse_entry_out *o) 850aa7c699SMiklos Szeredi { 860a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 870a0898cfSMiklos Szeredi time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 881fb69e78SMiklos Szeredi } 891fb69e78SMiklos Szeredi 901fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o) 911fb69e78SMiklos Szeredi { 921fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 931fb69e78SMiklos Szeredi } 941fb69e78SMiklos Szeredi 951fb69e78SMiklos Szeredi static u64 entry_attr_timeout(struct fuse_entry_out *o) 961fb69e78SMiklos Szeredi { 971fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 988cbdf1e6SMiklos Szeredi } 998cbdf1e6SMiklos Szeredi 1006f9f1180SMiklos Szeredi /* 1016f9f1180SMiklos Szeredi * Mark the attributes as stale, so that at the next call to 1026f9f1180SMiklos Szeredi * ->getattr() they will be fetched from userspace 1036f9f1180SMiklos Szeredi */ 1048cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode) 1058cbdf1e6SMiklos Szeredi { 1060a0898cfSMiklos Szeredi get_fuse_inode(inode)->i_time = 0; 1078cbdf1e6SMiklos Szeredi } 1088cbdf1e6SMiklos Szeredi 109451418fcSAndrew Gallagher /** 110451418fcSAndrew Gallagher * Mark the attributes as stale due to an atime change. Avoid the invalidate if 111451418fcSAndrew Gallagher * atime is not used. 112451418fcSAndrew Gallagher */ 113451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode) 114451418fcSAndrew Gallagher { 115451418fcSAndrew Gallagher if (!IS_RDONLY(inode)) 116451418fcSAndrew Gallagher fuse_invalidate_attr(inode); 117451418fcSAndrew Gallagher } 118451418fcSAndrew Gallagher 1196f9f1180SMiklos Szeredi /* 1206f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 1216f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 1226f9f1180SMiklos Szeredi * 1236f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 1246f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 1256f9f1180SMiklos Szeredi * lookup) 1266f9f1180SMiklos Szeredi */ 127dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry) 1288cbdf1e6SMiklos Szeredi { 1290a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 1308cbdf1e6SMiklos Szeredi } 1318cbdf1e6SMiklos Szeredi 1326f9f1180SMiklos Szeredi /* 1336f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 1346f9f1180SMiklos Szeredi * dentry from the hash 1356f9f1180SMiklos Szeredi */ 1368cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1378cbdf1e6SMiklos Szeredi { 1388cbdf1e6SMiklos Szeredi d_invalidate(entry); 1398cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1400aa7c699SMiklos Szeredi } 1410aa7c699SMiklos Szeredi 1427078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, 14313983d06SAl Viro u64 nodeid, const struct qstr *name, 144e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 145e5e5558eSMiklos Szeredi { 1460e9663eeSMiklos Szeredi memset(outarg, 0, sizeof(struct fuse_entry_out)); 1477078187aSMiklos Szeredi args->in.h.opcode = FUSE_LOOKUP; 1487078187aSMiklos Szeredi args->in.h.nodeid = nodeid; 1497078187aSMiklos Szeredi args->in.numargs = 1; 1507078187aSMiklos Szeredi args->in.args[0].size = name->len + 1; 1517078187aSMiklos Szeredi args->in.args[0].value = name->name; 1527078187aSMiklos Szeredi args->out.numargs = 1; 1537078187aSMiklos Szeredi args->out.args[0].size = sizeof(struct fuse_entry_out); 1547078187aSMiklos Szeredi args->out.args[0].value = outarg; 155e5e5558eSMiklos Szeredi } 156e5e5558eSMiklos Szeredi 1575c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc) 1587dca9fd3SMiklos Szeredi { 1597dca9fd3SMiklos Szeredi u64 curr_version; 1607dca9fd3SMiklos Szeredi 1617dca9fd3SMiklos Szeredi /* 1627dca9fd3SMiklos Szeredi * The spin lock isn't actually needed on 64bit archs, but we 1637dca9fd3SMiklos Szeredi * don't yet care too much about such optimizations. 1647dca9fd3SMiklos Szeredi */ 1657dca9fd3SMiklos Szeredi spin_lock(&fc->lock); 1667dca9fd3SMiklos Szeredi curr_version = fc->attr_version; 1677dca9fd3SMiklos Szeredi spin_unlock(&fc->lock); 1687dca9fd3SMiklos Szeredi 1697dca9fd3SMiklos Szeredi return curr_version; 1707dca9fd3SMiklos Szeredi } 1717dca9fd3SMiklos Szeredi 1726f9f1180SMiklos Szeredi /* 1736f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1746f9f1180SMiklos Szeredi * 1756f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 1766f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 1776f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 1786f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 1796f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 1806f9f1180SMiklos Szeredi */ 1810b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) 182e5e5558eSMiklos Szeredi { 18334286d66SNick Piggin struct inode *inode; 18428420dadSMiklos Szeredi struct dentry *parent; 18528420dadSMiklos Szeredi struct fuse_conn *fc; 1866314efeeSMiklos Szeredi struct fuse_inode *fi; 187e2a6b952SMiklos Szeredi int ret; 1888cbdf1e6SMiklos Szeredi 1892b0143b5SDavid Howells inode = d_inode_rcu(entry); 1908cbdf1e6SMiklos Szeredi if (inode && is_bad_inode(inode)) 191e2a6b952SMiklos Szeredi goto invalid; 192154210ccSAnand Avati else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || 193154210ccSAnand Avati (flags & LOOKUP_REVAL)) { 194e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 1957078187aSMiklos Szeredi FUSE_ARGS(args); 19607e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 1971fb69e78SMiklos Szeredi u64 attr_version; 1988cbdf1e6SMiklos Szeredi 19950322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 2008cbdf1e6SMiklos Szeredi if (!inode) 201e2a6b952SMiklos Szeredi goto invalid; 2028cbdf1e6SMiklos Szeredi 203e2a6b952SMiklos Szeredi ret = -ECHILD; 2040b728e19SAl Viro if (flags & LOOKUP_RCU) 205e2a6b952SMiklos Szeredi goto out; 206e7c0a167SMiklos Szeredi 2078cbdf1e6SMiklos Szeredi fc = get_fuse_conn(inode); 208e5e5558eSMiklos Szeredi 20907e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 210e2a6b952SMiklos Szeredi ret = -ENOMEM; 2117078187aSMiklos Szeredi if (!forget) 212e2a6b952SMiklos Szeredi goto out; 2132d51013eSMiklos Szeredi 2147dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 2151fb69e78SMiklos Szeredi 216e956edd0SMiklos Szeredi parent = dget_parent(entry); 2172b0143b5SDavid Howells fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)), 218c180eebeSMiklos Szeredi &entry->d_name, &outarg); 2197078187aSMiklos Szeredi ret = fuse_simple_request(fc, &args); 220e956edd0SMiklos Szeredi dput(parent); 22150322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 2227078187aSMiklos Szeredi if (!ret && !outarg.nodeid) 2237078187aSMiklos Szeredi ret = -ENOENT; 2247078187aSMiklos Szeredi if (!ret) { 2256314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2269e6268dbSMiklos Szeredi if (outarg.nodeid != get_node_id(inode)) { 22707e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 228e2a6b952SMiklos Szeredi goto invalid; 2299e6268dbSMiklos Szeredi } 2308da5ff23SMiklos Szeredi spin_lock(&fc->lock); 2319e6268dbSMiklos Szeredi fi->nlookup++; 2328da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 2339e6268dbSMiklos Szeredi } 23407e77dcaSMiklos Szeredi kfree(forget); 2357078187aSMiklos Szeredi if (ret == -ENOMEM) 2367078187aSMiklos Szeredi goto out; 2377078187aSMiklos Szeredi if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 238e2a6b952SMiklos Szeredi goto invalid; 239e5e5558eSMiklos Szeredi 24060bcc88aSSeth Forshee forget_all_cached_acls(inode); 2411fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2421fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2431fb69e78SMiklos Szeredi attr_version); 2441fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 24528420dadSMiklos Szeredi } else if (inode) { 2466314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2476314efeeSMiklos Szeredi if (flags & LOOKUP_RCU) { 2486314efeeSMiklos Szeredi if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) 2496314efeeSMiklos Szeredi return -ECHILD; 2506314efeeSMiklos Szeredi } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { 25128420dadSMiklos Szeredi parent = dget_parent(entry); 2522b0143b5SDavid Howells fuse_advise_use_readdirplus(d_inode(parent)); 25328420dadSMiklos Szeredi dput(parent); 254e5e5558eSMiklos Szeredi } 25528420dadSMiklos Szeredi } 256e2a6b952SMiklos Szeredi ret = 1; 257e2a6b952SMiklos Szeredi out: 258e2a6b952SMiklos Szeredi return ret; 259e2a6b952SMiklos Szeredi 260e2a6b952SMiklos Szeredi invalid: 261e2a6b952SMiklos Szeredi ret = 0; 262e2a6b952SMiklos Szeredi goto out; 263e5e5558eSMiklos Szeredi } 264e5e5558eSMiklos Szeredi 2658bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid) 2662827d0b2SMiklos Szeredi { 2672827d0b2SMiklos Szeredi return !nodeid || nodeid == FUSE_ROOT_ID; 2682827d0b2SMiklos Szeredi } 2692827d0b2SMiklos Szeredi 270f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry) 271f75fdf22SMiklos Szeredi { 272f75fdf22SMiklos Szeredi dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), GFP_KERNEL); 273f75fdf22SMiklos Szeredi 274f75fdf22SMiklos Szeredi return dentry->d_fsdata ? 0 : -ENOMEM; 275f75fdf22SMiklos Szeredi } 276f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry) 277f75fdf22SMiklos Szeredi { 278f75fdf22SMiklos Szeredi union fuse_dentry *fd = dentry->d_fsdata; 279f75fdf22SMiklos Szeredi 280f75fdf22SMiklos Szeredi kfree_rcu(fd, rcu); 281f75fdf22SMiklos Szeredi } 282f75fdf22SMiklos Szeredi 2834269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 284e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 285f75fdf22SMiklos Szeredi .d_init = fuse_dentry_init, 286f75fdf22SMiklos Szeredi .d_release = fuse_dentry_release, 287e5e5558eSMiklos Szeredi }; 288e5e5558eSMiklos Szeredi 2890ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = { 2900ce267ffSMiklos Szeredi .d_init = fuse_dentry_init, 2910ce267ffSMiklos Szeredi .d_release = fuse_dentry_release, 2920ce267ffSMiklos Szeredi }; 2930ce267ffSMiklos Szeredi 294a5bfffacSTimo Savola int fuse_valid_type(int m) 29539ee059aSMiklos Szeredi { 29639ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 29739ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 29839ee059aSMiklos Szeredi } 29939ee059aSMiklos Szeredi 30013983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, 301c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 302c180eebeSMiklos Szeredi { 303c180eebeSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 3047078187aSMiklos Szeredi FUSE_ARGS(args); 30507e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 306c180eebeSMiklos Szeredi u64 attr_version; 307c180eebeSMiklos Szeredi int err; 308c180eebeSMiklos Szeredi 309c180eebeSMiklos Szeredi *inode = NULL; 310c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 311c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 312c180eebeSMiklos Szeredi goto out; 313c180eebeSMiklos Szeredi 314c180eebeSMiklos Szeredi 31507e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 31607e77dcaSMiklos Szeredi err = -ENOMEM; 3177078187aSMiklos Szeredi if (!forget) 318c180eebeSMiklos Szeredi goto out; 319c180eebeSMiklos Szeredi 320c180eebeSMiklos Szeredi attr_version = fuse_get_attr_version(fc); 321c180eebeSMiklos Szeredi 3227078187aSMiklos Szeredi fuse_lookup_init(fc, &args, nodeid, name, outarg); 3237078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 324c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 325c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 326c180eebeSMiklos Szeredi goto out_put_forget; 327c180eebeSMiklos Szeredi 328c180eebeSMiklos Szeredi err = -EIO; 329c180eebeSMiklos Szeredi if (!outarg->nodeid) 330c180eebeSMiklos Szeredi goto out_put_forget; 331c180eebeSMiklos Szeredi if (!fuse_valid_type(outarg->attr.mode)) 332c180eebeSMiklos Szeredi goto out_put_forget; 333c180eebeSMiklos Szeredi 334c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 335c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 336c180eebeSMiklos Szeredi attr_version); 337c180eebeSMiklos Szeredi err = -ENOMEM; 338c180eebeSMiklos Szeredi if (!*inode) { 33907e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg->nodeid, 1); 340c180eebeSMiklos Szeredi goto out; 341c180eebeSMiklos Szeredi } 342c180eebeSMiklos Szeredi err = 0; 343c180eebeSMiklos Szeredi 344c180eebeSMiklos Szeredi out_put_forget: 34507e77dcaSMiklos Szeredi kfree(forget); 346c180eebeSMiklos Szeredi out: 347c180eebeSMiklos Szeredi return err; 348c180eebeSMiklos Szeredi } 349c180eebeSMiklos Szeredi 3500aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 35100cd8dd3SAl Viro unsigned int flags) 352e5e5558eSMiklos Szeredi { 353e5e5558eSMiklos Szeredi int err; 354e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 355c180eebeSMiklos Szeredi struct inode *inode; 3560de6256dSMiklos Szeredi struct dentry *newent; 357c180eebeSMiklos Szeredi bool outarg_valid = true; 358e5e5558eSMiklos Szeredi 3595c672ab3SMiklos Szeredi fuse_lock_inode(dir); 360c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 361c180eebeSMiklos Szeredi &outarg, &inode); 3625c672ab3SMiklos Szeredi fuse_unlock_inode(dir); 363c180eebeSMiklos Szeredi if (err == -ENOENT) { 364c180eebeSMiklos Szeredi outarg_valid = false; 365c180eebeSMiklos Szeredi err = 0; 3662d51013eSMiklos Szeredi } 367c180eebeSMiklos Szeredi if (err) 368c180eebeSMiklos Szeredi goto out_err; 3692d51013eSMiklos Szeredi 370ee4e5271SMiklos Szeredi err = -EIO; 371c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 372c180eebeSMiklos Szeredi goto out_iput; 373e5e5558eSMiklos Szeredi 37441d28bcaSAl Viro newent = d_splice_alias(inode, entry); 375c180eebeSMiklos Szeredi err = PTR_ERR(newent); 376c180eebeSMiklos Szeredi if (IS_ERR(newent)) 3775835f339SMiklos Szeredi goto out_err; 378d2a85164SMiklos Szeredi 3790de6256dSMiklos Szeredi entry = newent ? newent : entry; 380c180eebeSMiklos Szeredi if (outarg_valid) 3811fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 3828cbdf1e6SMiklos Szeredi else 3838cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 384c180eebeSMiklos Szeredi 3854582a4abSFeng Shuo fuse_advise_use_readdirplus(dir); 3860de6256dSMiklos Szeredi return newent; 387c180eebeSMiklos Szeredi 388c180eebeSMiklos Szeredi out_iput: 389c180eebeSMiklos Szeredi iput(inode); 390c180eebeSMiklos Szeredi out_err: 391c180eebeSMiklos Szeredi return ERR_PTR(err); 392e5e5558eSMiklos Szeredi } 393e5e5558eSMiklos Szeredi 3946f9f1180SMiklos Szeredi /* 3956f9f1180SMiklos Szeredi * Atomic create+open operation 3966f9f1180SMiklos Szeredi * 3976f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 3986f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 3996f9f1180SMiklos Szeredi */ 400d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 40130d90494SAl Viro struct file *file, unsigned flags, 40247237687SAl Viro umode_t mode, int *opened) 403fd72faacSMiklos Szeredi { 404fd72faacSMiklos Szeredi int err; 405fd72faacSMiklos Szeredi struct inode *inode; 406fd72faacSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 4077078187aSMiklos Szeredi FUSE_ARGS(args); 40807e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 409e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 410fd72faacSMiklos Szeredi struct fuse_open_out outopen; 411fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 412fd72faacSMiklos Szeredi struct fuse_file *ff; 413fd72faacSMiklos Szeredi 414af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 415af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 416af109bcaSMiklos Szeredi 41707e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 418c8ccbe03SMiklos Szeredi err = -ENOMEM; 41907e77dcaSMiklos Szeredi if (!forget) 420c8ccbe03SMiklos Szeredi goto out_err; 42151eb01e7SMiklos Szeredi 422ce1d5a49SMiklos Szeredi err = -ENOMEM; 423acf99433STejun Heo ff = fuse_file_alloc(fc); 424fd72faacSMiklos Szeredi if (!ff) 4257078187aSMiklos Szeredi goto out_put_forget_req; 426fd72faacSMiklos Szeredi 427e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 428e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 429e0a43ddcSMiklos Szeredi 430fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 431fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4320e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 433fd72faacSMiklos Szeredi inarg.flags = flags; 434fd72faacSMiklos Szeredi inarg.mode = mode; 435e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 4367078187aSMiklos Szeredi args.in.h.opcode = FUSE_CREATE; 4377078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(dir); 4387078187aSMiklos Szeredi args.in.numargs = 2; 43921f62174SMiklos Szeredi args.in.args[0].size = sizeof(inarg); 4407078187aSMiklos Szeredi args.in.args[0].value = &inarg; 4417078187aSMiklos Szeredi args.in.args[1].size = entry->d_name.len + 1; 4427078187aSMiklos Szeredi args.in.args[1].value = entry->d_name.name; 4437078187aSMiklos Szeredi args.out.numargs = 2; 4447078187aSMiklos Szeredi args.out.args[0].size = sizeof(outentry); 4457078187aSMiklos Szeredi args.out.args[0].value = &outentry; 4467078187aSMiklos Szeredi args.out.args[1].size = sizeof(outopen); 4477078187aSMiklos Szeredi args.out.args[1].value = &outopen; 4487078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 449c8ccbe03SMiklos Szeredi if (err) 450fd72faacSMiklos Szeredi goto out_free_ff; 451fd72faacSMiklos Szeredi 452fd72faacSMiklos Szeredi err = -EIO; 4532827d0b2SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 454fd72faacSMiklos Szeredi goto out_free_ff; 455fd72faacSMiklos Szeredi 456c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 457c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 458c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 459fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 4601fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 461fd72faacSMiklos Szeredi if (!inode) { 462fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 4638b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 46407e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outentry.nodeid, 1); 465c8ccbe03SMiklos Szeredi err = -ENOMEM; 466c8ccbe03SMiklos Szeredi goto out_err; 467fd72faacSMiklos Szeredi } 46807e77dcaSMiklos Szeredi kfree(forget); 469fd72faacSMiklos Szeredi d_instantiate(entry, inode); 4701fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 4710952b2a4SMiklos Szeredi fuse_invalidate_attr(dir); 472*be12af3eSAl Viro err = finish_open(file, entry, generic_file_open); 47330d90494SAl Viro if (err) { 4748b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 475c8ccbe03SMiklos Szeredi } else { 476267d8444SMiklos Szeredi file->private_data = ff; 477c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 478c8ccbe03SMiklos Szeredi } 479d9585277SAl Viro return err; 480fd72faacSMiklos Szeredi 481fd72faacSMiklos Szeredi out_free_ff: 482fd72faacSMiklos Szeredi fuse_file_free(ff); 48351eb01e7SMiklos Szeredi out_put_forget_req: 48407e77dcaSMiklos Szeredi kfree(forget); 485c8ccbe03SMiklos Szeredi out_err: 486d9585277SAl Viro return err; 487c8ccbe03SMiklos Szeredi } 488c8ccbe03SMiklos Szeredi 489c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); 490d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 49130d90494SAl Viro struct file *file, unsigned flags, 49247237687SAl Viro umode_t mode, int *opened) 493c8ccbe03SMiklos Szeredi { 494c8ccbe03SMiklos Szeredi int err; 495c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 496c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 497c8ccbe03SMiklos Szeredi 49800699ad8SAl Viro if (d_in_lookup(entry)) { 49900cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 500c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 501d9585277SAl Viro return PTR_ERR(res); 502c8ccbe03SMiklos Szeredi 503c8ccbe03SMiklos Szeredi if (res) 504c8ccbe03SMiklos Szeredi entry = res; 505c8ccbe03SMiklos Szeredi } 506c8ccbe03SMiklos Szeredi 5072b0143b5SDavid Howells if (!(flags & O_CREAT) || d_really_is_positive(entry)) 508c8ccbe03SMiklos Szeredi goto no_open; 509c8ccbe03SMiklos Szeredi 510c8ccbe03SMiklos Szeredi /* Only creates */ 51173a09dd9SAl Viro file->f_mode |= FMODE_CREATED; 512c8ccbe03SMiklos Szeredi 513c8ccbe03SMiklos Szeredi if (fc->no_create) 514c8ccbe03SMiklos Szeredi goto mknod; 515c8ccbe03SMiklos Szeredi 51630d90494SAl Viro err = fuse_create_open(dir, entry, file, flags, mode, opened); 517d9585277SAl Viro if (err == -ENOSYS) { 518c8ccbe03SMiklos Szeredi fc->no_create = 1; 519c8ccbe03SMiklos Szeredi goto mknod; 520c8ccbe03SMiklos Szeredi } 521c8ccbe03SMiklos Szeredi out_dput: 522c8ccbe03SMiklos Szeredi dput(res); 523d9585277SAl Viro return err; 524c8ccbe03SMiklos Szeredi 525c8ccbe03SMiklos Szeredi mknod: 526c8ccbe03SMiklos Szeredi err = fuse_mknod(dir, entry, mode, 0); 527d9585277SAl Viro if (err) 528c8ccbe03SMiklos Szeredi goto out_dput; 529c8ccbe03SMiklos Szeredi no_open: 530e45198a6SAl Viro return finish_no_open(file, res); 531fd72faacSMiklos Szeredi } 532fd72faacSMiklos Szeredi 5336f9f1180SMiklos Szeredi /* 5346f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 5356f9f1180SMiklos Szeredi */ 5367078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, 5379e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 538541af6a0SAl Viro umode_t mode) 5399e6268dbSMiklos Szeredi { 5409e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 5419e6268dbSMiklos Szeredi struct inode *inode; 5429e6268dbSMiklos Szeredi int err; 54307e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 5442d51013eSMiklos Szeredi 54507e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 5467078187aSMiklos Szeredi if (!forget) 54707e77dcaSMiklos Szeredi return -ENOMEM; 5489e6268dbSMiklos Szeredi 5490e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 5507078187aSMiklos Szeredi args->in.h.nodeid = get_node_id(dir); 5517078187aSMiklos Szeredi args->out.numargs = 1; 5527078187aSMiklos Szeredi args->out.args[0].size = sizeof(outarg); 5537078187aSMiklos Szeredi args->out.args[0].value = &outarg; 5547078187aSMiklos Szeredi err = fuse_simple_request(fc, args); 5552d51013eSMiklos Szeredi if (err) 5562d51013eSMiklos Szeredi goto out_put_forget_req; 5572d51013eSMiklos Szeredi 55839ee059aSMiklos Szeredi err = -EIO; 55939ee059aSMiklos Szeredi if (invalid_nodeid(outarg.nodeid)) 5602d51013eSMiklos Szeredi goto out_put_forget_req; 56139ee059aSMiklos Szeredi 56239ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 5632d51013eSMiklos Szeredi goto out_put_forget_req; 56439ee059aSMiklos Szeredi 5659e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 5661fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 5679e6268dbSMiklos Szeredi if (!inode) { 56807e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 5699e6268dbSMiklos Szeredi return -ENOMEM; 5709e6268dbSMiklos Szeredi } 57107e77dcaSMiklos Szeredi kfree(forget); 5729e6268dbSMiklos Szeredi 573b70a80e7SMiklos Szeredi err = d_instantiate_no_diralias(entry, inode); 574b70a80e7SMiklos Szeredi if (err) 575b70a80e7SMiklos Szeredi return err; 576d2a85164SMiklos Szeredi 5771fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 5789e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 5799e6268dbSMiklos Szeredi return 0; 58039ee059aSMiklos Szeredi 5812d51013eSMiklos Szeredi out_put_forget_req: 58207e77dcaSMiklos Szeredi kfree(forget); 58339ee059aSMiklos Szeredi return err; 5849e6268dbSMiklos Szeredi } 5859e6268dbSMiklos Szeredi 5861a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, 5879e6268dbSMiklos Szeredi dev_t rdev) 5889e6268dbSMiklos Szeredi { 5899e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 5909e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 5917078187aSMiklos Szeredi FUSE_ARGS(args); 5929e6268dbSMiklos Szeredi 593e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 594e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 595e0a43ddcSMiklos Szeredi 5969e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 5979e6268dbSMiklos Szeredi inarg.mode = mode; 5989e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 599e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6007078187aSMiklos Szeredi args.in.h.opcode = FUSE_MKNOD; 6017078187aSMiklos Szeredi args.in.numargs = 2; 60221f62174SMiklos Szeredi args.in.args[0].size = sizeof(inarg); 6037078187aSMiklos Szeredi args.in.args[0].value = &inarg; 6047078187aSMiklos Szeredi args.in.args[1].size = entry->d_name.len + 1; 6057078187aSMiklos Szeredi args.in.args[1].value = entry->d_name.name; 6067078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, mode); 6079e6268dbSMiklos Szeredi } 6089e6268dbSMiklos Szeredi 6094acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, 610ebfc3b49SAl Viro bool excl) 6119e6268dbSMiklos Szeredi { 6129e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 6139e6268dbSMiklos Szeredi } 6149e6268dbSMiklos Szeredi 61518bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) 6169e6268dbSMiklos Szeredi { 6179e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 6189e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6197078187aSMiklos Szeredi FUSE_ARGS(args); 6209e6268dbSMiklos Szeredi 621e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 622e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 623e0a43ddcSMiklos Szeredi 6249e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6259e6268dbSMiklos Szeredi inarg.mode = mode; 626e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6277078187aSMiklos Szeredi args.in.h.opcode = FUSE_MKDIR; 6287078187aSMiklos Szeredi args.in.numargs = 2; 6297078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 6307078187aSMiklos Szeredi args.in.args[0].value = &inarg; 6317078187aSMiklos Szeredi args.in.args[1].size = entry->d_name.len + 1; 6327078187aSMiklos Szeredi args.in.args[1].value = entry->d_name.name; 6337078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, S_IFDIR); 6349e6268dbSMiklos Szeredi } 6359e6268dbSMiklos Szeredi 6369e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 6379e6268dbSMiklos Szeredi const char *link) 6389e6268dbSMiklos Szeredi { 6399e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6409e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 6417078187aSMiklos Szeredi FUSE_ARGS(args); 6429e6268dbSMiklos Szeredi 6437078187aSMiklos Szeredi args.in.h.opcode = FUSE_SYMLINK; 6447078187aSMiklos Szeredi args.in.numargs = 2; 6457078187aSMiklos Szeredi args.in.args[0].size = entry->d_name.len + 1; 6467078187aSMiklos Szeredi args.in.args[0].value = entry->d_name.name; 6477078187aSMiklos Szeredi args.in.args[1].size = len; 6487078187aSMiklos Szeredi args.in.args[1].value = link; 6497078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, S_IFLNK); 6509e6268dbSMiklos Szeredi } 6519e6268dbSMiklos Szeredi 652703c7362SSeth Forshee void fuse_update_ctime(struct inode *inode) 65331f3267bSMaxim Patlasov { 65431f3267bSMaxim Patlasov if (!IS_NOCMTIME(inode)) { 655c2050a45SDeepa Dinamani inode->i_ctime = current_time(inode); 65631f3267bSMaxim Patlasov mark_inode_dirty_sync(inode); 65731f3267bSMaxim Patlasov } 65831f3267bSMaxim Patlasov } 65931f3267bSMaxim Patlasov 6609e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 6619e6268dbSMiklos Szeredi { 6629e6268dbSMiklos Szeredi int err; 6639e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6647078187aSMiklos Szeredi FUSE_ARGS(args); 6659e6268dbSMiklos Szeredi 6667078187aSMiklos Szeredi args.in.h.opcode = FUSE_UNLINK; 6677078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(dir); 6687078187aSMiklos Szeredi args.in.numargs = 1; 6697078187aSMiklos Szeredi args.in.args[0].size = entry->d_name.len + 1; 6707078187aSMiklos Szeredi args.in.args[0].value = entry->d_name.name; 6717078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 6729e6268dbSMiklos Szeredi if (!err) { 6732b0143b5SDavid Howells struct inode *inode = d_inode(entry); 674ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 6759e6268dbSMiklos Szeredi 676ac45d613SMiklos Szeredi spin_lock(&fc->lock); 677ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 678dfca7cebSMiklos Szeredi /* 679dfca7cebSMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 680dfca7cebSMiklos Szeredi * happen if userspace filesystem is careless. It would be 681dfca7cebSMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 682dfca7cebSMiklos Szeredi * condition here 683dfca7cebSMiklos Szeredi */ 684dfca7cebSMiklos Szeredi if (inode->i_nlink > 0) 685ac45d613SMiklos Szeredi drop_nlink(inode); 686ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 6879e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 6889e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 6898cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 69031f3267bSMaxim Patlasov fuse_update_ctime(inode); 6919e6268dbSMiklos Szeredi } else if (err == -EINTR) 6929e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 6939e6268dbSMiklos Szeredi return err; 6949e6268dbSMiklos Szeredi } 6959e6268dbSMiklos Szeredi 6969e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 6979e6268dbSMiklos Szeredi { 6989e6268dbSMiklos Szeredi int err; 6999e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 7007078187aSMiklos Szeredi FUSE_ARGS(args); 7019e6268dbSMiklos Szeredi 7027078187aSMiklos Szeredi args.in.h.opcode = FUSE_RMDIR; 7037078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(dir); 7047078187aSMiklos Szeredi args.in.numargs = 1; 7057078187aSMiklos Szeredi args.in.args[0].size = entry->d_name.len + 1; 7067078187aSMiklos Szeredi args.in.args[0].value = entry->d_name.name; 7077078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 7089e6268dbSMiklos Szeredi if (!err) { 7092b0143b5SDavid Howells clear_nlink(d_inode(entry)); 7109e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 7118cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 7129e6268dbSMiklos Szeredi } else if (err == -EINTR) 7139e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7149e6268dbSMiklos Szeredi return err; 7159e6268dbSMiklos Szeredi } 7169e6268dbSMiklos Szeredi 7171560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, 7181560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 7191560c974SMiklos Szeredi unsigned int flags, int opcode, size_t argsize) 7209e6268dbSMiklos Szeredi { 7219e6268dbSMiklos Szeredi int err; 7221560c974SMiklos Szeredi struct fuse_rename2_in inarg; 7239e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 7247078187aSMiklos Szeredi FUSE_ARGS(args); 7259e6268dbSMiklos Szeredi 7261560c974SMiklos Szeredi memset(&inarg, 0, argsize); 7279e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 7281560c974SMiklos Szeredi inarg.flags = flags; 7297078187aSMiklos Szeredi args.in.h.opcode = opcode; 7307078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(olddir); 7317078187aSMiklos Szeredi args.in.numargs = 3; 7327078187aSMiklos Szeredi args.in.args[0].size = argsize; 7337078187aSMiklos Szeredi args.in.args[0].value = &inarg; 7347078187aSMiklos Szeredi args.in.args[1].size = oldent->d_name.len + 1; 7357078187aSMiklos Szeredi args.in.args[1].value = oldent->d_name.name; 7367078187aSMiklos Szeredi args.in.args[2].size = newent->d_name.len + 1; 7377078187aSMiklos Szeredi args.in.args[2].value = newent->d_name.name; 7387078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 7399e6268dbSMiklos Szeredi if (!err) { 74008b63307SMiklos Szeredi /* ctime changes */ 7412b0143b5SDavid Howells fuse_invalidate_attr(d_inode(oldent)); 7422b0143b5SDavid Howells fuse_update_ctime(d_inode(oldent)); 74308b63307SMiklos Szeredi 7441560c974SMiklos Szeredi if (flags & RENAME_EXCHANGE) { 7452b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 7462b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 7471560c974SMiklos Szeredi } 7481560c974SMiklos Szeredi 7499e6268dbSMiklos Szeredi fuse_invalidate_attr(olddir); 7509e6268dbSMiklos Szeredi if (olddir != newdir) 7519e6268dbSMiklos Szeredi fuse_invalidate_attr(newdir); 7528cbdf1e6SMiklos Szeredi 7538cbdf1e6SMiklos Szeredi /* newent will end up negative */ 7542b0143b5SDavid Howells if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { 7552b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 7568cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 7572b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 7585219f346SMiklos Szeredi } 7599e6268dbSMiklos Szeredi } else if (err == -EINTR) { 7609e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 7619e6268dbSMiklos Szeredi rename actually took place. If the invalidation 7629e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 7639e6268dbSMiklos Szeredi directory), then there can be inconsistency between 7649e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 7659e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 7662b0143b5SDavid Howells if (d_really_is_positive(newent)) 7679e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 7689e6268dbSMiklos Szeredi } 7699e6268dbSMiklos Szeredi 7709e6268dbSMiklos Szeredi return err; 7719e6268dbSMiklos Szeredi } 7729e6268dbSMiklos Szeredi 7731560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent, 7741560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 7751560c974SMiklos Szeredi unsigned int flags) 7761560c974SMiklos Szeredi { 7771560c974SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 7781560c974SMiklos Szeredi int err; 7791560c974SMiklos Szeredi 7801560c974SMiklos Szeredi if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) 7811560c974SMiklos Szeredi return -EINVAL; 7821560c974SMiklos Szeredi 7834237ba43SMiklos Szeredi if (flags) { 7841560c974SMiklos Szeredi if (fc->no_rename2 || fc->minor < 23) 7851560c974SMiklos Szeredi return -EINVAL; 7861560c974SMiklos Szeredi 7871560c974SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, flags, 7884237ba43SMiklos Szeredi FUSE_RENAME2, 7894237ba43SMiklos Szeredi sizeof(struct fuse_rename2_in)); 7901560c974SMiklos Szeredi if (err == -ENOSYS) { 7911560c974SMiklos Szeredi fc->no_rename2 = 1; 7921560c974SMiklos Szeredi err = -EINVAL; 7931560c974SMiklos Szeredi } 7944237ba43SMiklos Szeredi } else { 7954237ba43SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, 0, 7964237ba43SMiklos Szeredi FUSE_RENAME, 7974237ba43SMiklos Szeredi sizeof(struct fuse_rename_in)); 7984237ba43SMiklos Szeredi } 7991560c974SMiklos Szeredi 8004237ba43SMiklos Szeredi return err; 8014237ba43SMiklos Szeredi } 8024237ba43SMiklos Szeredi 8039e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 8049e6268dbSMiklos Szeredi struct dentry *newent) 8059e6268dbSMiklos Szeredi { 8069e6268dbSMiklos Szeredi int err; 8079e6268dbSMiklos Szeredi struct fuse_link_in inarg; 8082b0143b5SDavid Howells struct inode *inode = d_inode(entry); 8099e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 8107078187aSMiklos Szeredi FUSE_ARGS(args); 8119e6268dbSMiklos Szeredi 8129e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8139e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 8147078187aSMiklos Szeredi args.in.h.opcode = FUSE_LINK; 8157078187aSMiklos Szeredi args.in.numargs = 2; 8167078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 8177078187aSMiklos Szeredi args.in.args[0].value = &inarg; 8187078187aSMiklos Szeredi args.in.args[1].size = newent->d_name.len + 1; 8197078187aSMiklos Szeredi args.in.args[1].value = newent->d_name.name; 8207078187aSMiklos Szeredi err = create_new_entry(fc, &args, newdir, newent, inode->i_mode); 8219e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 8229e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 8239e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 8249e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 8259e6268dbSMiklos Szeredi etc.) 8269e6268dbSMiklos Szeredi */ 827ac45d613SMiklos Szeredi if (!err) { 828ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 829ac45d613SMiklos Szeredi 830ac45d613SMiklos Szeredi spin_lock(&fc->lock); 831ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 832ac45d613SMiklos Szeredi inc_nlink(inode); 833ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 8349e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 83531f3267bSMaxim Patlasov fuse_update_ctime(inode); 836ac45d613SMiklos Szeredi } else if (err == -EINTR) { 837ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 838ac45d613SMiklos Szeredi } 8399e6268dbSMiklos Szeredi return err; 8409e6268dbSMiklos Szeredi } 8419e6268dbSMiklos Szeredi 8421fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 8431fb69e78SMiklos Szeredi struct kstat *stat) 8441fb69e78SMiklos Szeredi { 845203627bbSMiklos Szeredi unsigned int blkbits; 8468373200bSPavel Emelyanov struct fuse_conn *fc = get_fuse_conn(inode); 8478373200bSPavel Emelyanov 8488373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 849b0aa7606SMaxim Patlasov if (fc->writeback_cache && S_ISREG(inode->i_mode)) { 8508373200bSPavel Emelyanov attr->size = i_size_read(inode); 851b0aa7606SMaxim Patlasov attr->mtime = inode->i_mtime.tv_sec; 852b0aa7606SMaxim Patlasov attr->mtimensec = inode->i_mtime.tv_nsec; 85331f3267bSMaxim Patlasov attr->ctime = inode->i_ctime.tv_sec; 85431f3267bSMaxim Patlasov attr->ctimensec = inode->i_ctime.tv_nsec; 855b0aa7606SMaxim Patlasov } 856203627bbSMiklos Szeredi 8571fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 8581fb69e78SMiklos Szeredi stat->ino = attr->ino; 8591fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 8601fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 8618cb08329SEric W. Biederman stat->uid = make_kuid(fc->user_ns, attr->uid); 8628cb08329SEric W. Biederman stat->gid = make_kgid(fc->user_ns, attr->gid); 8631fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 8641fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 8651fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 8661fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 8671fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 8681fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 8691fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 8701fb69e78SMiklos Szeredi stat->size = attr->size; 8711fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 872203627bbSMiklos Szeredi 873203627bbSMiklos Szeredi if (attr->blksize != 0) 874203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 875203627bbSMiklos Szeredi else 876203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 877203627bbSMiklos Szeredi 878203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 8791fb69e78SMiklos Szeredi } 8801fb69e78SMiklos Szeredi 881c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 882c79e322fSMiklos Szeredi struct file *file) 883e5e5558eSMiklos Szeredi { 884e5e5558eSMiklos Szeredi int err; 885c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 886c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 887e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 8887078187aSMiklos Szeredi FUSE_ARGS(args); 8891fb69e78SMiklos Szeredi u64 attr_version; 8901fb69e78SMiklos Szeredi 8917dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 8921fb69e78SMiklos Szeredi 893c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8940e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 895c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 896c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 897c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 898c79e322fSMiklos Szeredi 899c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 900c79e322fSMiklos Szeredi inarg.fh = ff->fh; 901c79e322fSMiklos Szeredi } 9027078187aSMiklos Szeredi args.in.h.opcode = FUSE_GETATTR; 9037078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 9047078187aSMiklos Szeredi args.in.numargs = 1; 9057078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 9067078187aSMiklos Szeredi args.in.args[0].value = &inarg; 9077078187aSMiklos Szeredi args.out.numargs = 1; 9087078187aSMiklos Szeredi args.out.args[0].size = sizeof(outarg); 9097078187aSMiklos Szeredi args.out.args[0].value = &outarg; 9107078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 911e5e5558eSMiklos Szeredi if (!err) { 912c79e322fSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 913e5e5558eSMiklos Szeredi make_bad_inode(inode); 914e5e5558eSMiklos Szeredi err = -EIO; 915e5e5558eSMiklos Szeredi } else { 916c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 917c79e322fSMiklos Szeredi attr_timeout(&outarg), 9181fb69e78SMiklos Szeredi attr_version); 9191fb69e78SMiklos Szeredi if (stat) 920c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 921e5e5558eSMiklos Szeredi } 922e5e5558eSMiklos Szeredi } 923e5e5558eSMiklos Szeredi return err; 924e5e5558eSMiklos Szeredi } 925e5e5558eSMiklos Szeredi 9265b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file, 927ff1b89f3SMiklos Szeredi struct kstat *stat, unsigned int flags) 928bcb4be80SMiklos Szeredi { 929bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 9305b97eeacSMiklos Szeredi int err = 0; 931bf5c1898SMiklos Szeredi bool sync; 932bcb4be80SMiklos Szeredi 933bf5c1898SMiklos Szeredi if (flags & AT_STATX_FORCE_SYNC) 934bf5c1898SMiklos Szeredi sync = true; 935bf5c1898SMiklos Szeredi else if (flags & AT_STATX_DONT_SYNC) 936bf5c1898SMiklos Szeredi sync = false; 937bf5c1898SMiklos Szeredi else 938bf5c1898SMiklos Szeredi sync = time_before64(fi->i_time, get_jiffies_64()); 939bf5c1898SMiklos Szeredi 940bf5c1898SMiklos Szeredi if (sync) { 94160bcc88aSSeth Forshee forget_all_cached_acls(inode); 942bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 9435b97eeacSMiklos Szeredi } else if (stat) { 944bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 945bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 94645c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 947bcb4be80SMiklos Szeredi } 948bcb4be80SMiklos Szeredi 949bcb4be80SMiklos Szeredi return err; 950bcb4be80SMiklos Szeredi } 951bcb4be80SMiklos Szeredi 9525b97eeacSMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file) 9535b97eeacSMiklos Szeredi { 954ff1b89f3SMiklos Szeredi return fuse_update_get_attr(inode, file, NULL, 0); 9555b97eeacSMiklos Szeredi } 9565b97eeacSMiklos Szeredi 9573b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 958451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 9593b463ae0SJohn Muir { 9603b463ae0SJohn Muir int err = -ENOTDIR; 9613b463ae0SJohn Muir struct inode *parent; 9623b463ae0SJohn Muir struct dentry *dir; 9633b463ae0SJohn Muir struct dentry *entry; 9643b463ae0SJohn Muir 9653b463ae0SJohn Muir parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); 9663b463ae0SJohn Muir if (!parent) 9673b463ae0SJohn Muir return -ENOENT; 9683b463ae0SJohn Muir 9695955102cSAl Viro inode_lock(parent); 9703b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 9713b463ae0SJohn Muir goto unlock; 9723b463ae0SJohn Muir 9733b463ae0SJohn Muir err = -ENOENT; 9743b463ae0SJohn Muir dir = d_find_alias(parent); 9753b463ae0SJohn Muir if (!dir) 9763b463ae0SJohn Muir goto unlock; 9773b463ae0SJohn Muir 9788387ff25SLinus Torvalds name->hash = full_name_hash(dir, name->name, name->len); 9793b463ae0SJohn Muir entry = d_lookup(dir, name); 9803b463ae0SJohn Muir dput(dir); 9813b463ae0SJohn Muir if (!entry) 9823b463ae0SJohn Muir goto unlock; 9833b463ae0SJohn Muir 9843b463ae0SJohn Muir fuse_invalidate_attr(parent); 9853b463ae0SJohn Muir fuse_invalidate_entry(entry); 986451d0f59SJohn Muir 9872b0143b5SDavid Howells if (child_nodeid != 0 && d_really_is_positive(entry)) { 9885955102cSAl Viro inode_lock(d_inode(entry)); 9892b0143b5SDavid Howells if (get_node_id(d_inode(entry)) != child_nodeid) { 990451d0f59SJohn Muir err = -ENOENT; 991451d0f59SJohn Muir goto badentry; 992451d0f59SJohn Muir } 993451d0f59SJohn Muir if (d_mountpoint(entry)) { 994451d0f59SJohn Muir err = -EBUSY; 995451d0f59SJohn Muir goto badentry; 996451d0f59SJohn Muir } 997e36cb0b8SDavid Howells if (d_is_dir(entry)) { 998451d0f59SJohn Muir shrink_dcache_parent(entry); 999451d0f59SJohn Muir if (!simple_empty(entry)) { 1000451d0f59SJohn Muir err = -ENOTEMPTY; 1001451d0f59SJohn Muir goto badentry; 1002451d0f59SJohn Muir } 10032b0143b5SDavid Howells d_inode(entry)->i_flags |= S_DEAD; 1004451d0f59SJohn Muir } 1005451d0f59SJohn Muir dont_mount(entry); 10062b0143b5SDavid Howells clear_nlink(d_inode(entry)); 10073b463ae0SJohn Muir err = 0; 1008451d0f59SJohn Muir badentry: 10095955102cSAl Viro inode_unlock(d_inode(entry)); 1010451d0f59SJohn Muir if (!err) 1011451d0f59SJohn Muir d_delete(entry); 1012451d0f59SJohn Muir } else { 1013451d0f59SJohn Muir err = 0; 1014451d0f59SJohn Muir } 1015451d0f59SJohn Muir dput(entry); 10163b463ae0SJohn Muir 10173b463ae0SJohn Muir unlock: 10185955102cSAl Viro inode_unlock(parent); 10193b463ae0SJohn Muir iput(parent); 10203b463ae0SJohn Muir return err; 10213b463ae0SJohn Muir } 10223b463ae0SJohn Muir 102387729a55SMiklos Szeredi /* 102487729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1025c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 102687729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 102787729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 102887729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 102987729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 103087729a55SMiklos Szeredi * DoS against the requester. 103187729a55SMiklos Szeredi * 103287729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 103387729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 103487729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 103587729a55SMiklos Szeredi */ 1036c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc) 103787729a55SMiklos Szeredi { 1038c69e8d9cSDavid Howells const struct cred *cred; 1039c69e8d9cSDavid Howells 104029433a29SMiklos Szeredi if (fc->allow_other) 104173f03c2bSSeth Forshee return current_in_userns(fc->user_ns); 104287729a55SMiklos Szeredi 1043c2132c1bSAnatol Pomozov cred = current_cred(); 1044499dcf20SEric W. Biederman if (uid_eq(cred->euid, fc->user_id) && 1045499dcf20SEric W. Biederman uid_eq(cred->suid, fc->user_id) && 1046499dcf20SEric W. Biederman uid_eq(cred->uid, fc->user_id) && 1047499dcf20SEric W. Biederman gid_eq(cred->egid, fc->group_id) && 1048499dcf20SEric W. Biederman gid_eq(cred->sgid, fc->group_id) && 1049499dcf20SEric W. Biederman gid_eq(cred->gid, fc->group_id)) 1050c2132c1bSAnatol Pomozov return 1; 105187729a55SMiklos Szeredi 1052c2132c1bSAnatol Pomozov return 0; 105387729a55SMiklos Szeredi } 105487729a55SMiklos Szeredi 105531d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 105631d40d74SMiklos Szeredi { 105731d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 10587078187aSMiklos Szeredi FUSE_ARGS(args); 105931d40d74SMiklos Szeredi struct fuse_access_in inarg; 106031d40d74SMiklos Szeredi int err; 106131d40d74SMiklos Szeredi 1062698fa1d1SMiklos Szeredi BUG_ON(mask & MAY_NOT_BLOCK); 1063698fa1d1SMiklos Szeredi 106431d40d74SMiklos Szeredi if (fc->no_access) 106531d40d74SMiklos Szeredi return 0; 106631d40d74SMiklos Szeredi 106731d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1068e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 10697078187aSMiklos Szeredi args.in.h.opcode = FUSE_ACCESS; 10707078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 10717078187aSMiklos Szeredi args.in.numargs = 1; 10727078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 10737078187aSMiklos Szeredi args.in.args[0].value = &inarg; 10747078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 107531d40d74SMiklos Szeredi if (err == -ENOSYS) { 107631d40d74SMiklos Szeredi fc->no_access = 1; 107731d40d74SMiklos Szeredi err = 0; 107831d40d74SMiklos Szeredi } 107931d40d74SMiklos Szeredi return err; 108031d40d74SMiklos Szeredi } 108131d40d74SMiklos Szeredi 108210556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 108319690ddbSMiklos Szeredi { 108410556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 108519690ddbSMiklos Szeredi return -ECHILD; 108619690ddbSMiklos Szeredi 108760bcc88aSSeth Forshee forget_all_cached_acls(inode); 108819690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 108919690ddbSMiklos Szeredi } 109019690ddbSMiklos Szeredi 10916f9f1180SMiklos Szeredi /* 10926f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 10936f9f1180SMiklos Szeredi * 10946f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 10956f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 10966f9f1180SMiklos Szeredi * modell. 10976f9f1180SMiklos Szeredi * 10986f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 10996f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 11006f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 11016f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 11026f9f1180SMiklos Szeredi * locally based on file mode. 11036f9f1180SMiklos Szeredi */ 110410556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask) 1105e5e5558eSMiklos Szeredi { 1106e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1107244f6385SMiklos Szeredi bool refreshed = false; 1108244f6385SMiklos Szeredi int err = 0; 1109e5e5558eSMiklos Szeredi 1110c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1111e5e5558eSMiklos Szeredi return -EACCES; 1112244f6385SMiklos Szeredi 1113244f6385SMiklos Szeredi /* 1114e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1115244f6385SMiklos Szeredi */ 111629433a29SMiklos Szeredi if (fc->default_permissions || 1117e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 111819690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 111919690ddbSMiklos Szeredi 1120126b9d43SMiklos Szeredi if (time_before64(fi->i_time, get_jiffies_64())) { 112119690ddbSMiklos Szeredi refreshed = true; 112219690ddbSMiklos Szeredi 112310556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1124244f6385SMiklos Szeredi if (err) 1125244f6385SMiklos Szeredi return err; 11261fb69e78SMiklos Szeredi } 112719690ddbSMiklos Szeredi } 1128244f6385SMiklos Szeredi 112929433a29SMiklos Szeredi if (fc->default_permissions) { 11302830ba7fSAl Viro err = generic_permission(inode, mask); 11311e9a4ed9SMiklos Szeredi 11321e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 11331e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 11341e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1135244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 113610556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 11371e9a4ed9SMiklos Szeredi if (!err) 11382830ba7fSAl Viro err = generic_permission(inode, mask); 11391e9a4ed9SMiklos Szeredi } 11401e9a4ed9SMiklos Szeredi 11416f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 11426f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 11436f9f1180SMiklos Szeredi noticed immediately, only after the attribute 11446f9f1180SMiklos Szeredi timeout has expired */ 11459cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1146e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1147e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1148e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1149e8e96157SMiklos Szeredi if (refreshed) 1150e5e5558eSMiklos Szeredi return -EACCES; 115131d40d74SMiklos Szeredi 115210556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1153e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1154e8e96157SMiklos Szeredi return -EACCES; 1155e8e96157SMiklos Szeredi } 1156e5e5558eSMiklos Szeredi } 1157244f6385SMiklos Szeredi return err; 1158e5e5558eSMiklos Szeredi } 1159e5e5558eSMiklos Szeredi 1160e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file, 11618d3af7f3SAl Viro struct dir_context *ctx) 1162e5e5558eSMiklos Szeredi { 1163e5e5558eSMiklos Szeredi while (nbytes >= FUSE_NAME_OFFSET) { 1164e5e5558eSMiklos Szeredi struct fuse_dirent *dirent = (struct fuse_dirent *) buf; 1165e5e5558eSMiklos Szeredi size_t reclen = FUSE_DIRENT_SIZE(dirent); 1166e5e5558eSMiklos Szeredi if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 1167e5e5558eSMiklos Szeredi return -EIO; 1168e5e5558eSMiklos Szeredi if (reclen > nbytes) 1169e5e5558eSMiklos Szeredi break; 1170efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1171efeb9e60SMiklos Szeredi return -EIO; 1172e5e5558eSMiklos Szeredi 11738d3af7f3SAl Viro if (!dir_emit(ctx, dirent->name, dirent->namelen, 11748d3af7f3SAl Viro dirent->ino, dirent->type)) 1175e5e5558eSMiklos Szeredi break; 1176e5e5558eSMiklos Szeredi 1177e5e5558eSMiklos Szeredi buf += reclen; 1178e5e5558eSMiklos Szeredi nbytes -= reclen; 11798d3af7f3SAl Viro ctx->pos = dirent->off; 1180e5e5558eSMiklos Szeredi } 1181e5e5558eSMiklos Szeredi 1182e5e5558eSMiklos Szeredi return 0; 1183e5e5558eSMiklos Szeredi } 1184e5e5558eSMiklos Szeredi 11850b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file, 11860b05b183SAnand V. Avati struct fuse_direntplus *direntplus, 11870b05b183SAnand V. Avati u64 attr_version) 11880b05b183SAnand V. Avati { 11890b05b183SAnand V. Avati struct fuse_entry_out *o = &direntplus->entry_out; 11900b05b183SAnand V. Avati struct fuse_dirent *dirent = &direntplus->dirent; 11910b05b183SAnand V. Avati struct dentry *parent = file->f_path.dentry; 11920b05b183SAnand V. Avati struct qstr name = QSTR_INIT(dirent->name, dirent->namelen); 11930b05b183SAnand V. Avati struct dentry *dentry; 11940b05b183SAnand V. Avati struct dentry *alias; 11952b0143b5SDavid Howells struct inode *dir = d_inode(parent); 11960b05b183SAnand V. Avati struct fuse_conn *fc; 11970b05b183SAnand V. Avati struct inode *inode; 1198d9b3dbdcSAl Viro DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); 11990b05b183SAnand V. Avati 12000b05b183SAnand V. Avati if (!o->nodeid) { 12010b05b183SAnand V. Avati /* 12020b05b183SAnand V. Avati * Unlike in the case of fuse_lookup, zero nodeid does not mean 12030b05b183SAnand V. Avati * ENOENT. Instead, it only means the userspace filesystem did 12040b05b183SAnand V. Avati * not want to return attributes/handle for this entry. 12050b05b183SAnand V. Avati * 12060b05b183SAnand V. Avati * So do nothing. 12070b05b183SAnand V. Avati */ 12080b05b183SAnand V. Avati return 0; 12090b05b183SAnand V. Avati } 12100b05b183SAnand V. Avati 12110b05b183SAnand V. Avati if (name.name[0] == '.') { 12120b05b183SAnand V. Avati /* 12130b05b183SAnand V. Avati * We could potentially refresh the attributes of the directory 12140b05b183SAnand V. Avati * and its parent? 12150b05b183SAnand V. Avati */ 12160b05b183SAnand V. Avati if (name.len == 1) 12170b05b183SAnand V. Avati return 0; 12180b05b183SAnand V. Avati if (name.name[1] == '.' && name.len == 2) 12190b05b183SAnand V. Avati return 0; 12200b05b183SAnand V. Avati } 1221a28ef45cSMiklos Szeredi 1222a28ef45cSMiklos Szeredi if (invalid_nodeid(o->nodeid)) 1223a28ef45cSMiklos Szeredi return -EIO; 1224a28ef45cSMiklos Szeredi if (!fuse_valid_type(o->attr.mode)) 1225a28ef45cSMiklos Szeredi return -EIO; 1226a28ef45cSMiklos Szeredi 12270b05b183SAnand V. Avati fc = get_fuse_conn(dir); 12280b05b183SAnand V. Avati 12298387ff25SLinus Torvalds name.hash = full_name_hash(parent, name.name, name.len); 12300b05b183SAnand V. Avati dentry = d_lookup(parent, &name); 1231d9b3dbdcSAl Viro if (!dentry) { 1232d9b3dbdcSAl Viro retry: 1233d9b3dbdcSAl Viro dentry = d_alloc_parallel(parent, &name, &wq); 1234d9b3dbdcSAl Viro if (IS_ERR(dentry)) 1235d9b3dbdcSAl Viro return PTR_ERR(dentry); 1236d9b3dbdcSAl Viro } 1237d9b3dbdcSAl Viro if (!d_in_lookup(dentry)) { 1238d9b3dbdcSAl Viro struct fuse_inode *fi; 12392b0143b5SDavid Howells inode = d_inode(dentry); 1240d9b3dbdcSAl Viro if (!inode || 1241d9b3dbdcSAl Viro get_node_id(inode) != o->nodeid || 1242a28ef45cSMiklos Szeredi ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { 12435542aa2fSEric W. Biederman d_invalidate(dentry); 1244d9b3dbdcSAl Viro dput(dentry); 1245d9b3dbdcSAl Viro goto retry; 1246d9b3dbdcSAl Viro } 1247d9b3dbdcSAl Viro if (is_bad_inode(inode)) { 1248d9b3dbdcSAl Viro dput(dentry); 1249d9b3dbdcSAl Viro return -EIO; 1250d9b3dbdcSAl Viro } 1251d9b3dbdcSAl Viro 12520b05b183SAnand V. Avati fi = get_fuse_inode(inode); 12530b05b183SAnand V. Avati spin_lock(&fc->lock); 12540b05b183SAnand V. Avati fi->nlookup++; 12550b05b183SAnand V. Avati spin_unlock(&fc->lock); 12560b05b183SAnand V. Avati 125760bcc88aSSeth Forshee forget_all_cached_acls(inode); 1258fa2b7213SMiklos Szeredi fuse_change_attributes(inode, &o->attr, 1259fa2b7213SMiklos Szeredi entry_attr_timeout(o), 1260fa2b7213SMiklos Szeredi attr_version); 12610b05b183SAnand V. Avati /* 1262d9b3dbdcSAl Viro * The other branch comes via fuse_iget() 12630b05b183SAnand V. Avati * which bumps nlookup inside 12640b05b183SAnand V. Avati */ 1265d9b3dbdcSAl Viro } else { 12660b05b183SAnand V. Avati inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, 1267d9b3dbdcSAl Viro &o->attr, entry_attr_timeout(o), 1268d9b3dbdcSAl Viro attr_version); 12690b05b183SAnand V. Avati if (!inode) 1270d9b3dbdcSAl Viro inode = ERR_PTR(-ENOMEM); 12710b05b183SAnand V. Avati 127241d28bcaSAl Viro alias = d_splice_alias(inode, dentry); 1273d9b3dbdcSAl Viro d_lookup_done(dentry); 12740b05b183SAnand V. Avati if (alias) { 12750b05b183SAnand V. Avati dput(dentry); 12760b05b183SAnand V. Avati dentry = alias; 12770b05b183SAnand V. Avati } 1278d9b3dbdcSAl Viro if (IS_ERR(dentry)) 1279d9b3dbdcSAl Viro return PTR_ERR(dentry); 1280d9b3dbdcSAl Viro } 12816314efeeSMiklos Szeredi if (fc->readdirplus_auto) 12826314efeeSMiklos Szeredi set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); 12830b05b183SAnand V. Avati fuse_change_entry_timeout(dentry, o); 12840b05b183SAnand V. Avati 12850b05b183SAnand V. Avati dput(dentry); 1286d9b3dbdcSAl Viro return 0; 12870b05b183SAnand V. Avati } 12880b05b183SAnand V. Avati 12890b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, 12908d3af7f3SAl Viro struct dir_context *ctx, u64 attr_version) 12910b05b183SAnand V. Avati { 12920b05b183SAnand V. Avati struct fuse_direntplus *direntplus; 12930b05b183SAnand V. Avati struct fuse_dirent *dirent; 12940b05b183SAnand V. Avati size_t reclen; 12950b05b183SAnand V. Avati int over = 0; 12960b05b183SAnand V. Avati int ret; 12970b05b183SAnand V. Avati 12980b05b183SAnand V. Avati while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) { 12990b05b183SAnand V. Avati direntplus = (struct fuse_direntplus *) buf; 13000b05b183SAnand V. Avati dirent = &direntplus->dirent; 13010b05b183SAnand V. Avati reclen = FUSE_DIRENTPLUS_SIZE(direntplus); 13020b05b183SAnand V. Avati 13030b05b183SAnand V. Avati if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 13040b05b183SAnand V. Avati return -EIO; 13050b05b183SAnand V. Avati if (reclen > nbytes) 13060b05b183SAnand V. Avati break; 1307efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1308efeb9e60SMiklos Szeredi return -EIO; 13090b05b183SAnand V. Avati 13100b05b183SAnand V. Avati if (!over) { 13110b05b183SAnand V. Avati /* We fill entries into dstbuf only as much as 13120b05b183SAnand V. Avati it can hold. But we still continue iterating 13130b05b183SAnand V. Avati over remaining entries to link them. If not, 13140b05b183SAnand V. Avati we need to send a FORGET for each of those 13150b05b183SAnand V. Avati which we did not link. 13160b05b183SAnand V. Avati */ 13178d3af7f3SAl Viro over = !dir_emit(ctx, dirent->name, dirent->namelen, 13188d3af7f3SAl Viro dirent->ino, dirent->type); 1319c6cdd514SMiklos Szeredi if (!over) 13208d3af7f3SAl Viro ctx->pos = dirent->off; 13210b05b183SAnand V. Avati } 13220b05b183SAnand V. Avati 13230b05b183SAnand V. Avati buf += reclen; 13240b05b183SAnand V. Avati nbytes -= reclen; 13250b05b183SAnand V. Avati 13260b05b183SAnand V. Avati ret = fuse_direntplus_link(file, direntplus, attr_version); 13270b05b183SAnand V. Avati if (ret) 13280b05b183SAnand V. Avati fuse_force_forget(file, direntplus->entry_out.nodeid); 13290b05b183SAnand V. Avati } 13300b05b183SAnand V. Avati 13310b05b183SAnand V. Avati return 0; 13320b05b183SAnand V. Avati } 13330b05b183SAnand V. Avati 13348d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx) 1335e5e5558eSMiklos Szeredi { 13364582a4abSFeng Shuo int plus, err; 133704730fefSMiklos Szeredi size_t nbytes; 133804730fefSMiklos Szeredi struct page *page; 1339496ad9aaSAl Viro struct inode *inode = file_inode(file); 134004730fefSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1341248d86e8SMiklos Szeredi struct fuse_req *req; 13420b05b183SAnand V. Avati u64 attr_version = 0; 1343248d86e8SMiklos Szeredi 1344248d86e8SMiklos Szeredi if (is_bad_inode(inode)) 1345248d86e8SMiklos Szeredi return -EIO; 1346248d86e8SMiklos Szeredi 1347b111c8c0SMaxim Patlasov req = fuse_get_req(fc, 1); 1348ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1349ce1d5a49SMiklos Szeredi return PTR_ERR(req); 1350e5e5558eSMiklos Szeredi 135104730fefSMiklos Szeredi page = alloc_page(GFP_KERNEL); 135204730fefSMiklos Szeredi if (!page) { 135304730fefSMiklos Szeredi fuse_put_request(fc, req); 1354e5e5558eSMiklos Szeredi return -ENOMEM; 135504730fefSMiklos Szeredi } 13564582a4abSFeng Shuo 13578d3af7f3SAl Viro plus = fuse_use_readdirplus(inode, ctx); 1358f4975c67SMiklos Szeredi req->out.argpages = 1; 135904730fefSMiklos Szeredi req->num_pages = 1; 136004730fefSMiklos Szeredi req->pages[0] = page; 136185f40aecSMaxim Patlasov req->page_descs[0].length = PAGE_SIZE; 13624582a4abSFeng Shuo if (plus) { 13630b05b183SAnand V. Avati attr_version = fuse_get_attr_version(fc); 13648d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 13650b05b183SAnand V. Avati FUSE_READDIRPLUS); 13660b05b183SAnand V. Avati } else { 13678d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 13680b05b183SAnand V. Avati FUSE_READDIR); 13690b05b183SAnand V. Avati } 13705c672ab3SMiklos Szeredi fuse_lock_inode(inode); 1371b93f858aSTejun Heo fuse_request_send(fc, req); 13725c672ab3SMiklos Szeredi fuse_unlock_inode(inode); 1373361b1eb5SMiklos Szeredi nbytes = req->out.args[0].size; 137404730fefSMiklos Szeredi err = req->out.h.error; 137504730fefSMiklos Szeredi fuse_put_request(fc, req); 13760b05b183SAnand V. Avati if (!err) { 13774582a4abSFeng Shuo if (plus) { 13780b05b183SAnand V. Avati err = parse_dirplusfile(page_address(page), nbytes, 13798d3af7f3SAl Viro file, ctx, 13800b05b183SAnand V. Avati attr_version); 13810b05b183SAnand V. Avati } else { 13820b05b183SAnand V. Avati err = parse_dirfile(page_address(page), nbytes, file, 13838d3af7f3SAl Viro ctx); 13840b05b183SAnand V. Avati } 13850b05b183SAnand V. Avati } 1386e5e5558eSMiklos Szeredi 138704730fefSMiklos Szeredi __free_page(page); 1388451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 138904730fefSMiklos Szeredi return err; 1390e5e5558eSMiklos Szeredi } 1391e5e5558eSMiklos Szeredi 13926b255391SAl Viro static const char *fuse_get_link(struct dentry *dentry, 1393fceef393SAl Viro struct inode *inode, 1394fceef393SAl Viro struct delayed_call *done) 1395e5e5558eSMiklos Szeredi { 1396e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 13977078187aSMiklos Szeredi FUSE_ARGS(args); 1398e5e5558eSMiklos Szeredi char *link; 13997078187aSMiklos Szeredi ssize_t ret; 1400e5e5558eSMiklos Szeredi 14016b255391SAl Viro if (!dentry) 14026b255391SAl Viro return ERR_PTR(-ECHILD); 14036b255391SAl Viro 1404cd3417c8SAl Viro link = kmalloc(PAGE_SIZE, GFP_KERNEL); 14057078187aSMiklos Szeredi if (!link) 14067078187aSMiklos Szeredi return ERR_PTR(-ENOMEM); 14077078187aSMiklos Szeredi 14087078187aSMiklos Szeredi args.in.h.opcode = FUSE_READLINK; 14097078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 14107078187aSMiklos Szeredi args.out.argvar = 1; 14117078187aSMiklos Szeredi args.out.numargs = 1; 14127078187aSMiklos Szeredi args.out.args[0].size = PAGE_SIZE - 1; 14137078187aSMiklos Szeredi args.out.args[0].value = link; 14147078187aSMiklos Szeredi ret = fuse_simple_request(fc, &args); 14157078187aSMiklos Szeredi if (ret < 0) { 1416cd3417c8SAl Viro kfree(link); 14177078187aSMiklos Szeredi link = ERR_PTR(ret); 14187078187aSMiklos Szeredi } else { 14197078187aSMiklos Szeredi link[ret] = '\0'; 1420fceef393SAl Viro set_delayed_call(done, kfree_link, link); 14217078187aSMiklos Szeredi } 1422451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 1423e5e5558eSMiklos Szeredi return link; 1424e5e5558eSMiklos Szeredi } 1425e5e5558eSMiklos Szeredi 1426e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1427e5e5558eSMiklos Szeredi { 142891fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1429e5e5558eSMiklos Szeredi } 1430e5e5558eSMiklos Szeredi 1431e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1432e5e5558eSMiklos Szeredi { 14338b0797a4SMiklos Szeredi fuse_release_common(file, FUSE_RELEASEDIR); 14348b0797a4SMiklos Szeredi 14358b0797a4SMiklos Szeredi return 0; 1436e5e5558eSMiklos Szeredi } 1437e5e5558eSMiklos Szeredi 143802c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 143902c24a82SJosef Bacik int datasync) 144082547981SMiklos Szeredi { 144102c24a82SJosef Bacik return fuse_fsync_common(file, start, end, datasync, 1); 144282547981SMiklos Szeredi } 144382547981SMiklos Szeredi 1444b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1445b18da0c5SMiklos Szeredi unsigned long arg) 1446b18da0c5SMiklos Szeredi { 1447b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1448b18da0c5SMiklos Szeredi 1449b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1450b18da0c5SMiklos Szeredi if (fc->minor < 18) 1451b18da0c5SMiklos Szeredi return -ENOTTY; 1452b18da0c5SMiklos Szeredi 1453b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1454b18da0c5SMiklos Szeredi } 1455b18da0c5SMiklos Szeredi 1456b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1457b18da0c5SMiklos Szeredi unsigned long arg) 1458b18da0c5SMiklos Szeredi { 1459b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1460b18da0c5SMiklos Szeredi 1461b18da0c5SMiklos Szeredi if (fc->minor < 18) 1462b18da0c5SMiklos Szeredi return -ENOTTY; 1463b18da0c5SMiklos Szeredi 1464b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1465b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1466b18da0c5SMiklos Szeredi } 1467b18da0c5SMiklos Szeredi 1468b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime) 146917637cbaSMiklos Szeredi { 147017637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 147117637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 147217637cbaSMiklos Szeredi return true; 147317637cbaSMiklos Szeredi 1474b0aa7606SMaxim Patlasov /* Or if kernel i_mtime is the official one */ 1475b0aa7606SMaxim Patlasov if (trust_local_mtime) 1476b0aa7606SMaxim Patlasov return true; 1477b0aa7606SMaxim Patlasov 147817637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 147917637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 148017637cbaSMiklos Szeredi return false; 148117637cbaSMiklos Szeredi 148217637cbaSMiklos Szeredi /* In all other cases update */ 148317637cbaSMiklos Szeredi return true; 148417637cbaSMiklos Szeredi } 148517637cbaSMiklos Szeredi 14868cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr, 14878cb08329SEric W. Biederman struct fuse_setattr_in *arg, bool trust_local_cmtime) 14889e6268dbSMiklos Szeredi { 14899e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 14909e6268dbSMiklos Szeredi 14919e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1492befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 14939e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 14948cb08329SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid); 14959e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 14968cb08329SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid); 14979e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1498befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 149917637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 150017637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1501befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 150217637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 150317637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 150417637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 150517637cbaSMiklos Szeredi } 15063ad22c62SMaxim Patlasov if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) { 150717637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1508befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 150917637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 15103ad22c62SMaxim Patlasov if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime) 151117637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 15129e6268dbSMiklos Szeredi } 15133ad22c62SMaxim Patlasov if ((ivalid & ATTR_CTIME) && trust_local_cmtime) { 15143ad22c62SMaxim Patlasov arg->valid |= FATTR_CTIME; 15153ad22c62SMaxim Patlasov arg->ctime = iattr->ia_ctime.tv_sec; 15163ad22c62SMaxim Patlasov arg->ctimensec = iattr->ia_ctime.tv_nsec; 15173ad22c62SMaxim Patlasov } 15189e6268dbSMiklos Szeredi } 15199e6268dbSMiklos Szeredi 15206f9f1180SMiklos Szeredi /* 15213be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 15223be5a52bSMiklos Szeredi * 15233be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 15243be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 15253be5a52bSMiklos Szeredi */ 15263be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 15273be5a52bSMiklos Szeredi { 15283be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 15293be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15303be5a52bSMiklos Szeredi 15315955102cSAl Viro BUG_ON(!inode_is_locked(inode)); 15323be5a52bSMiklos Szeredi 15333be5a52bSMiklos Szeredi spin_lock(&fc->lock); 15343be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 15353be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 15363be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 15373be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 15383be5a52bSMiklos Szeredi } 15393be5a52bSMiklos Szeredi 15403be5a52bSMiklos Szeredi /* 15413be5a52bSMiklos Szeredi * Allow writepages on inode 15423be5a52bSMiklos Szeredi * 15433be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 15443be5a52bSMiklos Szeredi * writepages. 15453be5a52bSMiklos Szeredi */ 15463be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 15473be5a52bSMiklos Szeredi { 15483be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15493be5a52bSMiklos Szeredi 15503be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 15513be5a52bSMiklos Szeredi fi->writectr = 0; 15523be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 15533be5a52bSMiklos Szeredi } 15543be5a52bSMiklos Szeredi 15553be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 15563be5a52bSMiklos Szeredi { 15573be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 15583be5a52bSMiklos Szeredi 15593be5a52bSMiklos Szeredi spin_lock(&fc->lock); 15603be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 15613be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 15623be5a52bSMiklos Szeredi } 15633be5a52bSMiklos Szeredi 15647078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, 1565b0aa7606SMaxim Patlasov struct inode *inode, 1566b0aa7606SMaxim Patlasov struct fuse_setattr_in *inarg_p, 1567b0aa7606SMaxim Patlasov struct fuse_attr_out *outarg_p) 1568b0aa7606SMaxim Patlasov { 15697078187aSMiklos Szeredi args->in.h.opcode = FUSE_SETATTR; 15707078187aSMiklos Szeredi args->in.h.nodeid = get_node_id(inode); 15717078187aSMiklos Szeredi args->in.numargs = 1; 15727078187aSMiklos Szeredi args->in.args[0].size = sizeof(*inarg_p); 15737078187aSMiklos Szeredi args->in.args[0].value = inarg_p; 15747078187aSMiklos Szeredi args->out.numargs = 1; 15757078187aSMiklos Szeredi args->out.args[0].size = sizeof(*outarg_p); 15767078187aSMiklos Szeredi args->out.args[0].value = outarg_p; 1577b0aa7606SMaxim Patlasov } 1578b0aa7606SMaxim Patlasov 1579b0aa7606SMaxim Patlasov /* 1580b0aa7606SMaxim Patlasov * Flush inode->i_mtime to the server 1581b0aa7606SMaxim Patlasov */ 1582ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff) 1583b0aa7606SMaxim Patlasov { 1584b0aa7606SMaxim Patlasov struct fuse_conn *fc = get_fuse_conn(inode); 15857078187aSMiklos Szeredi FUSE_ARGS(args); 1586b0aa7606SMaxim Patlasov struct fuse_setattr_in inarg; 1587b0aa7606SMaxim Patlasov struct fuse_attr_out outarg; 1588b0aa7606SMaxim Patlasov 1589b0aa7606SMaxim Patlasov memset(&inarg, 0, sizeof(inarg)); 1590b0aa7606SMaxim Patlasov memset(&outarg, 0, sizeof(outarg)); 1591b0aa7606SMaxim Patlasov 1592ab9e13f7SMaxim Patlasov inarg.valid = FATTR_MTIME; 1593b0aa7606SMaxim Patlasov inarg.mtime = inode->i_mtime.tv_sec; 1594b0aa7606SMaxim Patlasov inarg.mtimensec = inode->i_mtime.tv_nsec; 1595ab9e13f7SMaxim Patlasov if (fc->minor >= 23) { 1596ab9e13f7SMaxim Patlasov inarg.valid |= FATTR_CTIME; 1597ab9e13f7SMaxim Patlasov inarg.ctime = inode->i_ctime.tv_sec; 1598ab9e13f7SMaxim Patlasov inarg.ctimensec = inode->i_ctime.tv_nsec; 1599ab9e13f7SMaxim Patlasov } 16001e18bda8SMiklos Szeredi if (ff) { 16011e18bda8SMiklos Szeredi inarg.valid |= FATTR_FH; 16021e18bda8SMiklos Szeredi inarg.fh = ff->fh; 16031e18bda8SMiklos Szeredi } 16047078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 1605b0aa7606SMaxim Patlasov 16067078187aSMiklos Szeredi return fuse_simple_request(fc, &args); 1607b0aa7606SMaxim Patlasov } 1608b0aa7606SMaxim Patlasov 16093be5a52bSMiklos Szeredi /* 16106f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 16116f9f1180SMiklos Szeredi * 16126f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 16136f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 16149ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 16159ffbb916SMiklos Szeredi * and the actual truncation by hand. 16166f9f1180SMiklos Szeredi */ 161762490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, 161849d4914fSMiklos Szeredi struct file *file) 16199e6268dbSMiklos Szeredi { 162062490330SJan Kara struct inode *inode = d_inode(dentry); 16219e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 162206a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 16237078187aSMiklos Szeredi FUSE_ARGS(args); 16249e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 16259e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 16263be5a52bSMiklos Szeredi bool is_truncate = false; 16278373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 16283be5a52bSMiklos Szeredi loff_t oldsize; 16299e6268dbSMiklos Szeredi int err; 16303ad22c62SMaxim Patlasov bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode); 16319e6268dbSMiklos Szeredi 163229433a29SMiklos Szeredi if (!fc->default_permissions) 1633db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1634db78b877SChristoph Hellwig 163531051c85SJan Kara err = setattr_prepare(dentry, attr); 16361e9a4ed9SMiklos Szeredi if (err) 16371e9a4ed9SMiklos Szeredi return err; 16381e9a4ed9SMiklos Szeredi 16398d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 1640df0e91d4SMiklos Szeredi /* This is coming from open(..., ... | O_TRUNC); */ 1641df0e91d4SMiklos Szeredi WARN_ON(!(attr->ia_valid & ATTR_SIZE)); 1642df0e91d4SMiklos Szeredi WARN_ON(attr->ia_size != 0); 1643df0e91d4SMiklos Szeredi if (fc->atomic_o_trunc) { 1644df0e91d4SMiklos Szeredi /* 1645df0e91d4SMiklos Szeredi * No need to send request to userspace, since actual 1646df0e91d4SMiklos Szeredi * truncation has already been done by OPEN. But still 1647df0e91d4SMiklos Szeredi * need to truncate page cache. 1648df0e91d4SMiklos Szeredi */ 1649df0e91d4SMiklos Szeredi i_size_write(inode, 0); 1650df0e91d4SMiklos Szeredi truncate_pagecache(inode, 0); 16516ff958edSMiklos Szeredi return 0; 1652df0e91d4SMiklos Szeredi } 16538d56adddSMiklos Szeredi file = NULL; 16548d56adddSMiklos Szeredi } 16556ff958edSMiklos Szeredi 16562c27c65eSChristoph Hellwig if (attr->ia_valid & ATTR_SIZE) 16573be5a52bSMiklos Szeredi is_truncate = true; 16589e6268dbSMiklos Szeredi 165906a7c3c2SMaxim Patlasov if (is_truncate) { 16603be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 166106a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 16623ad22c62SMaxim Patlasov if (trust_local_cmtime && attr->ia_size != inode->i_size) 16633ad22c62SMaxim Patlasov attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; 166406a7c3c2SMaxim Patlasov } 16653be5a52bSMiklos Szeredi 16669e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 16670e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 16688cb08329SEric W. Biederman iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime); 166949d4914fSMiklos Szeredi if (file) { 167049d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 167149d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 167249d4914fSMiklos Szeredi inarg.fh = ff->fh; 167349d4914fSMiklos Szeredi } 1674f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1675f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1676f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1677f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 1678f3332114SMiklos Szeredi } 16797078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 16807078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 1681e00d2c2dSMiklos Szeredi if (err) { 1682e00d2c2dSMiklos Szeredi if (err == -EINTR) 1683e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 16843be5a52bSMiklos Szeredi goto error; 1685e00d2c2dSMiklos Szeredi } 1686e00d2c2dSMiklos Szeredi 16879e6268dbSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 16889e6268dbSMiklos Szeredi make_bad_inode(inode); 16893be5a52bSMiklos Szeredi err = -EIO; 16903be5a52bSMiklos Szeredi goto error; 16919e6268dbSMiklos Szeredi } 16929e6268dbSMiklos Szeredi 16933be5a52bSMiklos Szeredi spin_lock(&fc->lock); 1694b0aa7606SMaxim Patlasov /* the kernel maintains i_mtime locally */ 16953ad22c62SMaxim Patlasov if (trust_local_cmtime) { 16963ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_MTIME) 1697b0aa7606SMaxim Patlasov inode->i_mtime = attr->ia_mtime; 16983ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_CTIME) 16993ad22c62SMaxim Patlasov inode->i_ctime = attr->ia_ctime; 17001e18bda8SMiklos Szeredi /* FIXME: clear I_DIRTY_SYNC? */ 1701b0aa7606SMaxim Patlasov } 1702b0aa7606SMaxim Patlasov 17033be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 17043be5a52bSMiklos Szeredi attr_timeout(&outarg)); 17053be5a52bSMiklos Szeredi oldsize = inode->i_size; 17068373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 17078373200bSPavel Emelyanov if (!is_wb || is_truncate || !S_ISREG(inode->i_mode)) 17083be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 17093be5a52bSMiklos Szeredi 17103be5a52bSMiklos Szeredi if (is_truncate) { 17113be5a52bSMiklos Szeredi /* NOTE: this may release/reacquire fc->lock */ 17123be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 17133be5a52bSMiklos Szeredi } 17143be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 17153be5a52bSMiklos Szeredi 17163be5a52bSMiklos Szeredi /* 17173be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 17183be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 17193be5a52bSMiklos Szeredi */ 17208373200bSPavel Emelyanov if ((is_truncate || !is_wb) && 17218373200bSPavel Emelyanov S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 17227caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 17233be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 17243be5a52bSMiklos Szeredi } 17253be5a52bSMiklos Szeredi 172606a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 1727e00d2c2dSMiklos Szeredi return 0; 17283be5a52bSMiklos Szeredi 17293be5a52bSMiklos Szeredi error: 17303be5a52bSMiklos Szeredi if (is_truncate) 17313be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 17323be5a52bSMiklos Szeredi 173306a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 17343be5a52bSMiklos Szeredi return err; 17359e6268dbSMiklos Szeredi } 17369e6268dbSMiklos Szeredi 173749d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 173849d4914fSMiklos Szeredi { 17392b0143b5SDavid Howells struct inode *inode = d_inode(entry); 17405e940c1dSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1741a09f99edSMiklos Szeredi struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL; 17425e2b8828SMiklos Szeredi int ret; 1743efb9fa9eSMaxim Patlasov 1744efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1745efb9fa9eSMaxim Patlasov return -EACCES; 1746efb9fa9eSMaxim Patlasov 1747a09f99edSMiklos Szeredi if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) { 1748a09f99edSMiklos Szeredi attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | 1749a09f99edSMiklos Szeredi ATTR_MODE); 17505e940c1dSMiklos Szeredi 1751a09f99edSMiklos Szeredi /* 17525e940c1dSMiklos Szeredi * The only sane way to reliably kill suid/sgid is to do it in 17535e940c1dSMiklos Szeredi * the userspace filesystem 17545e940c1dSMiklos Szeredi * 17555e940c1dSMiklos Szeredi * This should be done on write(), truncate() and chown(). 17565e940c1dSMiklos Szeredi */ 17575e940c1dSMiklos Szeredi if (!fc->handle_killpriv) { 17585e940c1dSMiklos Szeredi /* 17595e940c1dSMiklos Szeredi * ia_mode calculation may have used stale i_mode. 17605e940c1dSMiklos Szeredi * Refresh and recalculate. 1761a09f99edSMiklos Szeredi */ 1762a09f99edSMiklos Szeredi ret = fuse_do_getattr(inode, NULL, file); 1763a09f99edSMiklos Szeredi if (ret) 1764a09f99edSMiklos Szeredi return ret; 1765a09f99edSMiklos Szeredi 1766a09f99edSMiklos Szeredi attr->ia_mode = inode->i_mode; 1767c01638f5SMiklos Szeredi if (inode->i_mode & S_ISUID) { 1768a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1769a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISUID; 1770a09f99edSMiklos Szeredi } 1771c01638f5SMiklos Szeredi if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 1772a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1773a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISGID; 1774a09f99edSMiklos Szeredi } 1775a09f99edSMiklos Szeredi } 17765e940c1dSMiklos Szeredi } 1777a09f99edSMiklos Szeredi if (!attr->ia_valid) 1778a09f99edSMiklos Szeredi return 0; 1779a09f99edSMiklos Szeredi 1780abb5a14fSLinus Torvalds ret = fuse_do_setattr(entry, attr, file); 17815e2b8828SMiklos Szeredi if (!ret) { 178260bcc88aSSeth Forshee /* 178360bcc88aSSeth Forshee * If filesystem supports acls it may have updated acl xattrs in 178460bcc88aSSeth Forshee * the filesystem, so forget cached acls for the inode. 178560bcc88aSSeth Forshee */ 178660bcc88aSSeth Forshee if (fc->posix_acl) 178760bcc88aSSeth Forshee forget_all_cached_acls(inode); 178860bcc88aSSeth Forshee 17895e2b8828SMiklos Szeredi /* Directory mode changed, may need to revalidate access */ 17905e2b8828SMiklos Szeredi if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE)) 17915e2b8828SMiklos Szeredi fuse_invalidate_entry_cache(entry); 17925e2b8828SMiklos Szeredi } 17935e2b8828SMiklos Szeredi return ret; 179449d4914fSMiklos Szeredi } 179549d4914fSMiklos Szeredi 1796a528d35eSDavid Howells static int fuse_getattr(const struct path *path, struct kstat *stat, 1797a528d35eSDavid Howells u32 request_mask, unsigned int flags) 1798e5e5558eSMiklos Szeredi { 1799a528d35eSDavid Howells struct inode *inode = d_inode(path->dentry); 1800244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1801244f6385SMiklos Szeredi 1802c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1803244f6385SMiklos Szeredi return -EACCES; 1804244f6385SMiklos Szeredi 1805ff1b89f3SMiklos Szeredi return fuse_update_get_attr(inode, NULL, stat, flags); 1806e5e5558eSMiklos Szeredi } 1807e5e5558eSMiklos Szeredi 1808754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1809e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 18109e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 18119e6268dbSMiklos Szeredi .symlink = fuse_symlink, 18129e6268dbSMiklos Szeredi .unlink = fuse_unlink, 18139e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 18142773bf00SMiklos Szeredi .rename = fuse_rename2, 18159e6268dbSMiklos Szeredi .link = fuse_link, 18169e6268dbSMiklos Szeredi .setattr = fuse_setattr, 18179e6268dbSMiklos Szeredi .create = fuse_create, 1818c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 18199e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1820e5e5558eSMiklos Szeredi .permission = fuse_permission, 1821e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 182292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 182360bcc88aSSeth Forshee .get_acl = fuse_get_acl, 182460bcc88aSSeth Forshee .set_acl = fuse_set_acl, 1825e5e5558eSMiklos Szeredi }; 1826e5e5558eSMiklos Szeredi 18274b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1828b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1829e5e5558eSMiklos Szeredi .read = generic_read_dir, 1830d9b3dbdcSAl Viro .iterate_shared = fuse_readdir, 1831e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1832e5e5558eSMiklos Szeredi .release = fuse_dir_release, 183382547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1834b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 1835b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 1836e5e5558eSMiklos Szeredi }; 1837e5e5558eSMiklos Szeredi 1838754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 18399e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1840e5e5558eSMiklos Szeredi .permission = fuse_permission, 1841e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 184292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 184360bcc88aSSeth Forshee .get_acl = fuse_get_acl, 184460bcc88aSSeth Forshee .set_acl = fuse_set_acl, 1845e5e5558eSMiklos Szeredi }; 1846e5e5558eSMiklos Szeredi 1847754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 18489e6268dbSMiklos Szeredi .setattr = fuse_setattr, 18496b255391SAl Viro .get_link = fuse_get_link, 1850e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 185192a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 1852e5e5558eSMiklos Szeredi }; 1853e5e5558eSMiklos Szeredi 1854e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1855e5e5558eSMiklos Szeredi { 1856e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1857e5e5558eSMiklos Szeredi } 1858e5e5558eSMiklos Szeredi 1859e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1860e5e5558eSMiklos Szeredi { 1861e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1862e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1863e5e5558eSMiklos Szeredi } 1864e5e5558eSMiklos Szeredi 1865e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1866e5e5558eSMiklos Szeredi { 1867e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 1868e5e5558eSMiklos Szeredi } 1869