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/gfp.h> 14e5e5558eSMiklos Szeredi #include <linux/sched.h> 15e5e5558eSMiklos Szeredi #include <linux/namei.h> 16e5e5558eSMiklos Szeredi 170a0898cfSMiklos Szeredi #if BITS_PER_LONG >= 64 180a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time) 190a0898cfSMiklos Szeredi { 200a0898cfSMiklos Szeredi entry->d_time = time; 210a0898cfSMiklos Szeredi } 220a0898cfSMiklos Szeredi 230a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry) 240a0898cfSMiklos Szeredi { 250a0898cfSMiklos Szeredi return entry->d_time; 260a0898cfSMiklos Szeredi } 270a0898cfSMiklos Szeredi #else 280a0898cfSMiklos Szeredi /* 290a0898cfSMiklos Szeredi * On 32 bit archs store the high 32 bits of time in d_fsdata 300a0898cfSMiklos Szeredi */ 310a0898cfSMiklos Szeredi static void fuse_dentry_settime(struct dentry *entry, u64 time) 320a0898cfSMiklos Szeredi { 330a0898cfSMiklos Szeredi entry->d_time = time; 340a0898cfSMiklos Szeredi entry->d_fsdata = (void *) (unsigned long) (time >> 32); 350a0898cfSMiklos Szeredi } 360a0898cfSMiklos Szeredi 370a0898cfSMiklos Szeredi static u64 fuse_dentry_time(struct dentry *entry) 380a0898cfSMiklos Szeredi { 390a0898cfSMiklos Szeredi return (u64) entry->d_time + 400a0898cfSMiklos Szeredi ((u64) (unsigned long) entry->d_fsdata << 32); 410a0898cfSMiklos Szeredi } 420a0898cfSMiklos Szeredi #endif 430a0898cfSMiklos Szeredi 446f9f1180SMiklos Szeredi /* 456f9f1180SMiklos Szeredi * FUSE caches dentries and attributes with separate timeout. The 466f9f1180SMiklos Szeredi * time in jiffies until the dentry/attributes are valid is stored in 476f9f1180SMiklos Szeredi * dentry->d_time and fuse_inode->i_time respectively. 486f9f1180SMiklos Szeredi */ 496f9f1180SMiklos Szeredi 506f9f1180SMiklos Szeredi /* 516f9f1180SMiklos Szeredi * Calculate the time in jiffies until a dentry/attributes are valid 526f9f1180SMiklos Szeredi */ 530a0898cfSMiklos Szeredi static u64 time_to_jiffies(unsigned long sec, unsigned long nsec) 54e5e5558eSMiklos Szeredi { 55685d16ddSMiklos Szeredi if (sec || nsec) { 56e5e5558eSMiklos Szeredi struct timespec ts = {sec, nsec}; 570a0898cfSMiklos Szeredi return get_jiffies_64() + timespec_to_jiffies(&ts); 58685d16ddSMiklos Szeredi } else 590a0898cfSMiklos Szeredi return 0; 60e5e5558eSMiklos Szeredi } 61e5e5558eSMiklos Szeredi 626f9f1180SMiklos Szeredi /* 636f9f1180SMiklos Szeredi * Set dentry and possibly attribute timeouts from the lookup/mk* 646f9f1180SMiklos Szeredi * replies 656f9f1180SMiklos Szeredi */ 661fb69e78SMiklos Szeredi static void fuse_change_entry_timeout(struct dentry *entry, 671fb69e78SMiklos Szeredi struct fuse_entry_out *o) 680aa7c699SMiklos Szeredi { 690a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 700a0898cfSMiklos Szeredi time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 711fb69e78SMiklos Szeredi } 721fb69e78SMiklos Szeredi 731fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o) 741fb69e78SMiklos Szeredi { 751fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 761fb69e78SMiklos Szeredi } 771fb69e78SMiklos Szeredi 781fb69e78SMiklos Szeredi static u64 entry_attr_timeout(struct fuse_entry_out *o) 791fb69e78SMiklos Szeredi { 801fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 818cbdf1e6SMiklos Szeredi } 828cbdf1e6SMiklos Szeredi 836f9f1180SMiklos Szeredi /* 846f9f1180SMiklos Szeredi * Mark the attributes as stale, so that at the next call to 856f9f1180SMiklos Szeredi * ->getattr() they will be fetched from userspace 866f9f1180SMiklos Szeredi */ 878cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode) 888cbdf1e6SMiklos Szeredi { 890a0898cfSMiklos Szeredi get_fuse_inode(inode)->i_time = 0; 908cbdf1e6SMiklos Szeredi } 918cbdf1e6SMiklos Szeredi 926f9f1180SMiklos Szeredi /* 936f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 946f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 956f9f1180SMiklos Szeredi * 966f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 976f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 986f9f1180SMiklos Szeredi * lookup) 996f9f1180SMiklos Szeredi */ 100dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry) 1018cbdf1e6SMiklos Szeredi { 1020a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 1038cbdf1e6SMiklos Szeredi } 1048cbdf1e6SMiklos Szeredi 1056f9f1180SMiklos Szeredi /* 1066f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 1076f9f1180SMiklos Szeredi * dentry from the hash 1086f9f1180SMiklos Szeredi */ 1098cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1108cbdf1e6SMiklos Szeredi { 1118cbdf1e6SMiklos Szeredi d_invalidate(entry); 1128cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1130aa7c699SMiklos Szeredi } 1140aa7c699SMiklos Szeredi 115c180eebeSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req, 116c180eebeSMiklos Szeredi u64 nodeid, struct qstr *name, 117e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 118e5e5558eSMiklos Szeredi { 1190e9663eeSMiklos Szeredi memset(outarg, 0, sizeof(struct fuse_entry_out)); 120e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_LOOKUP; 121c180eebeSMiklos Szeredi req->in.h.nodeid = nodeid; 122e5e5558eSMiklos Szeredi req->in.numargs = 1; 123c180eebeSMiklos Szeredi req->in.args[0].size = name->len + 1; 124c180eebeSMiklos Szeredi req->in.args[0].value = name->name; 125e5e5558eSMiklos Szeredi req->out.numargs = 1; 1260e9663eeSMiklos Szeredi if (fc->minor < 9) 1270e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 1280e9663eeSMiklos Szeredi else 129e5e5558eSMiklos Szeredi req->out.args[0].size = sizeof(struct fuse_entry_out); 130e5e5558eSMiklos Szeredi req->out.args[0].value = outarg; 131e5e5558eSMiklos Szeredi } 132e5e5558eSMiklos Szeredi 1335c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc) 1347dca9fd3SMiklos Szeredi { 1357dca9fd3SMiklos Szeredi u64 curr_version; 1367dca9fd3SMiklos Szeredi 1377dca9fd3SMiklos Szeredi /* 1387dca9fd3SMiklos Szeredi * The spin lock isn't actually needed on 64bit archs, but we 1397dca9fd3SMiklos Szeredi * don't yet care too much about such optimizations. 1407dca9fd3SMiklos Szeredi */ 1417dca9fd3SMiklos Szeredi spin_lock(&fc->lock); 1427dca9fd3SMiklos Szeredi curr_version = fc->attr_version; 1437dca9fd3SMiklos Szeredi spin_unlock(&fc->lock); 1447dca9fd3SMiklos Szeredi 1457dca9fd3SMiklos Szeredi return curr_version; 1467dca9fd3SMiklos Szeredi } 1477dca9fd3SMiklos Szeredi 1486f9f1180SMiklos Szeredi /* 1496f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1506f9f1180SMiklos Szeredi * 1516f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 1526f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 1536f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 1546f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 1556f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 1566f9f1180SMiklos Szeredi */ 157e5e5558eSMiklos Szeredi static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) 158e5e5558eSMiklos Szeredi { 1598cbdf1e6SMiklos Szeredi struct inode *inode = entry->d_inode; 1608cbdf1e6SMiklos Szeredi 1618cbdf1e6SMiklos Szeredi if (inode && is_bad_inode(inode)) 162e5e5558eSMiklos Szeredi return 0; 1630a0898cfSMiklos Szeredi else if (fuse_dentry_time(entry) < get_jiffies_64()) { 164e5e5558eSMiklos Szeredi int err; 165e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 1668cbdf1e6SMiklos Szeredi struct fuse_conn *fc; 1678cbdf1e6SMiklos Szeredi struct fuse_req *req; 1682d51013eSMiklos Szeredi struct fuse_req *forget_req; 169e956edd0SMiklos Szeredi struct dentry *parent; 1701fb69e78SMiklos Szeredi u64 attr_version; 1718cbdf1e6SMiklos Szeredi 17250322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 1738cbdf1e6SMiklos Szeredi if (!inode) 1748cbdf1e6SMiklos Szeredi return 0; 1758cbdf1e6SMiklos Szeredi 1768cbdf1e6SMiklos Szeredi fc = get_fuse_conn(inode); 177ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 178ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 179e5e5558eSMiklos Szeredi return 0; 180e5e5558eSMiklos Szeredi 1812d51013eSMiklos Szeredi forget_req = fuse_get_req(fc); 1822d51013eSMiklos Szeredi if (IS_ERR(forget_req)) { 1832d51013eSMiklos Szeredi fuse_put_request(fc, req); 1842d51013eSMiklos Szeredi return 0; 1852d51013eSMiklos Szeredi } 1862d51013eSMiklos Szeredi 1877dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 1881fb69e78SMiklos Szeredi 189e956edd0SMiklos Szeredi parent = dget_parent(entry); 190c180eebeSMiklos Szeredi fuse_lookup_init(fc, req, get_node_id(parent->d_inode), 191c180eebeSMiklos Szeredi &entry->d_name, &outarg); 192b93f858aSTejun Heo fuse_request_send(fc, req); 193e956edd0SMiklos Szeredi dput(parent); 194e5e5558eSMiklos Szeredi err = req->out.h.error; 1952d51013eSMiklos Szeredi fuse_put_request(fc, req); 19650322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 19750322fe7SMiklos Szeredi if (!err && !outarg.nodeid) 19850322fe7SMiklos Szeredi err = -ENOENT; 1999e6268dbSMiklos Szeredi if (!err) { 2008cbdf1e6SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 2019e6268dbSMiklos Szeredi if (outarg.nodeid != get_node_id(inode)) { 2022d51013eSMiklos Szeredi fuse_send_forget(fc, forget_req, 2032d51013eSMiklos Szeredi outarg.nodeid, 1); 2049e6268dbSMiklos Szeredi return 0; 2059e6268dbSMiklos Szeredi } 2068da5ff23SMiklos Szeredi spin_lock(&fc->lock); 2079e6268dbSMiklos Szeredi fi->nlookup++; 2088da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 2099e6268dbSMiklos Szeredi } 2102d51013eSMiklos Szeredi fuse_put_request(fc, forget_req); 2119e6268dbSMiklos Szeredi if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 212e5e5558eSMiklos Szeredi return 0; 213e5e5558eSMiklos Szeredi 2141fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2151fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2161fb69e78SMiklos Szeredi attr_version); 2171fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 218e5e5558eSMiklos Szeredi } 219e5e5558eSMiklos Szeredi return 1; 220e5e5558eSMiklos Szeredi } 221e5e5558eSMiklos Szeredi 2228bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid) 2232827d0b2SMiklos Szeredi { 2242827d0b2SMiklos Szeredi return !nodeid || nodeid == FUSE_ROOT_ID; 2252827d0b2SMiklos Szeredi } 2262827d0b2SMiklos Szeredi 2274269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 228e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 229e5e5558eSMiklos Szeredi }; 230e5e5558eSMiklos Szeredi 231a5bfffacSTimo Savola int fuse_valid_type(int m) 23239ee059aSMiklos Szeredi { 23339ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 23439ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 23539ee059aSMiklos Szeredi } 23639ee059aSMiklos Szeredi 237d2a85164SMiklos Szeredi /* 238d2a85164SMiklos Szeredi * Add a directory inode to a dentry, ensuring that no other dentry 239d2a85164SMiklos Szeredi * refers to this inode. Called with fc->inst_mutex. 240d2a85164SMiklos Szeredi */ 2410de6256dSMiklos Szeredi static struct dentry *fuse_d_add_directory(struct dentry *entry, 2420de6256dSMiklos Szeredi struct inode *inode) 243d2a85164SMiklos Szeredi { 244d2a85164SMiklos Szeredi struct dentry *alias = d_find_alias(inode); 2450de6256dSMiklos Szeredi if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) { 246d2a85164SMiklos Szeredi /* This tries to shrink the subtree below alias */ 247d2a85164SMiklos Szeredi fuse_invalidate_entry(alias); 248d2a85164SMiklos Szeredi dput(alias); 249d2a85164SMiklos Szeredi if (!list_empty(&inode->i_dentry)) 2500de6256dSMiklos Szeredi return ERR_PTR(-EBUSY); 2510de6256dSMiklos Szeredi } else { 2520de6256dSMiklos Szeredi dput(alias); 253d2a85164SMiklos Szeredi } 2540de6256dSMiklos Szeredi return d_splice_alias(inode, entry); 255d2a85164SMiklos Szeredi } 256d2a85164SMiklos Szeredi 257c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, 258c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 259c180eebeSMiklos Szeredi { 260c180eebeSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 261c180eebeSMiklos Szeredi struct fuse_req *req; 262c180eebeSMiklos Szeredi struct fuse_req *forget_req; 263c180eebeSMiklos Szeredi u64 attr_version; 264c180eebeSMiklos Szeredi int err; 265c180eebeSMiklos Szeredi 266c180eebeSMiklos Szeredi *inode = NULL; 267c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 268c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 269c180eebeSMiklos Szeredi goto out; 270c180eebeSMiklos Szeredi 271c180eebeSMiklos Szeredi req = fuse_get_req(fc); 272c180eebeSMiklos Szeredi err = PTR_ERR(req); 273c180eebeSMiklos Szeredi if (IS_ERR(req)) 274c180eebeSMiklos Szeredi goto out; 275c180eebeSMiklos Szeredi 276c180eebeSMiklos Szeredi forget_req = fuse_get_req(fc); 277c180eebeSMiklos Szeredi err = PTR_ERR(forget_req); 278c180eebeSMiklos Szeredi if (IS_ERR(forget_req)) { 279c180eebeSMiklos Szeredi fuse_put_request(fc, req); 280c180eebeSMiklos Szeredi goto out; 281c180eebeSMiklos Szeredi } 282c180eebeSMiklos Szeredi 283c180eebeSMiklos Szeredi attr_version = fuse_get_attr_version(fc); 284c180eebeSMiklos Szeredi 285c180eebeSMiklos Szeredi fuse_lookup_init(fc, req, nodeid, name, outarg); 286b93f858aSTejun Heo fuse_request_send(fc, req); 287c180eebeSMiklos Szeredi err = req->out.h.error; 288c180eebeSMiklos Szeredi fuse_put_request(fc, req); 289c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 290c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 291c180eebeSMiklos Szeredi goto out_put_forget; 292c180eebeSMiklos Szeredi 293c180eebeSMiklos Szeredi err = -EIO; 294c180eebeSMiklos Szeredi if (!outarg->nodeid) 295c180eebeSMiklos Szeredi goto out_put_forget; 296c180eebeSMiklos Szeredi if (!fuse_valid_type(outarg->attr.mode)) 297c180eebeSMiklos Szeredi goto out_put_forget; 298c180eebeSMiklos Szeredi 299c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 300c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 301c180eebeSMiklos Szeredi attr_version); 302c180eebeSMiklos Szeredi err = -ENOMEM; 303c180eebeSMiklos Szeredi if (!*inode) { 304c180eebeSMiklos Szeredi fuse_send_forget(fc, forget_req, outarg->nodeid, 1); 305c180eebeSMiklos Szeredi goto out; 306c180eebeSMiklos Szeredi } 307c180eebeSMiklos Szeredi err = 0; 308c180eebeSMiklos Szeredi 309c180eebeSMiklos Szeredi out_put_forget: 310c180eebeSMiklos Szeredi fuse_put_request(fc, forget_req); 311c180eebeSMiklos Szeredi out: 312c180eebeSMiklos Szeredi return err; 313c180eebeSMiklos Szeredi } 314c180eebeSMiklos Szeredi 3150aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 3160aa7c699SMiklos Szeredi struct nameidata *nd) 317e5e5558eSMiklos Szeredi { 318e5e5558eSMiklos Szeredi int err; 319e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 320c180eebeSMiklos Szeredi struct inode *inode; 3210de6256dSMiklos Szeredi struct dentry *newent; 322e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 323c180eebeSMiklos Szeredi bool outarg_valid = true; 324e5e5558eSMiklos Szeredi 325c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 326c180eebeSMiklos Szeredi &outarg, &inode); 327c180eebeSMiklos Szeredi if (err == -ENOENT) { 328c180eebeSMiklos Szeredi outarg_valid = false; 329c180eebeSMiklos Szeredi err = 0; 3302d51013eSMiklos Szeredi } 331c180eebeSMiklos Szeredi if (err) 332c180eebeSMiklos Szeredi goto out_err; 3332d51013eSMiklos Szeredi 334ee4e5271SMiklos Szeredi err = -EIO; 335c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 336c180eebeSMiklos Szeredi goto out_iput; 337e5e5558eSMiklos Szeredi 338d2a85164SMiklos Szeredi if (inode && S_ISDIR(inode->i_mode)) { 339d2a85164SMiklos Szeredi mutex_lock(&fc->inst_mutex); 3400de6256dSMiklos Szeredi newent = fuse_d_add_directory(entry, inode); 341d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 342c180eebeSMiklos Szeredi err = PTR_ERR(newent); 343c180eebeSMiklos Szeredi if (IS_ERR(newent)) 344c180eebeSMiklos Szeredi goto out_iput; 345c180eebeSMiklos Szeredi } else { 3460de6256dSMiklos Szeredi newent = d_splice_alias(inode, entry); 347c180eebeSMiklos Szeredi } 348d2a85164SMiklos Szeredi 3490de6256dSMiklos Szeredi entry = newent ? newent : entry; 350e5e5558eSMiklos Szeredi entry->d_op = &fuse_dentry_operations; 351c180eebeSMiklos Szeredi if (outarg_valid) 3521fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 3538cbdf1e6SMiklos Szeredi else 3548cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 355c180eebeSMiklos Szeredi 3560de6256dSMiklos Szeredi return newent; 357c180eebeSMiklos Szeredi 358c180eebeSMiklos Szeredi out_iput: 359c180eebeSMiklos Szeredi iput(inode); 360c180eebeSMiklos Szeredi out_err: 361c180eebeSMiklos Szeredi return ERR_PTR(err); 362e5e5558eSMiklos Szeredi } 363e5e5558eSMiklos Szeredi 3646f9f1180SMiklos Szeredi /* 36551eb01e7SMiklos Szeredi * Synchronous release for the case when something goes wrong in CREATE_OPEN 36651eb01e7SMiklos Szeredi */ 36751eb01e7SMiklos Szeredi static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff, 36851eb01e7SMiklos Szeredi u64 nodeid, int flags) 36951eb01e7SMiklos Szeredi { 370c756e0a4SMiklos Szeredi fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE); 371c756e0a4SMiklos Szeredi ff->reserved_req->force = 1; 372b93f858aSTejun Heo fuse_request_send(fc, ff->reserved_req); 373c756e0a4SMiklos Szeredi fuse_put_request(fc, ff->reserved_req); 374c756e0a4SMiklos Szeredi kfree(ff); 37551eb01e7SMiklos Szeredi } 37651eb01e7SMiklos Szeredi 37751eb01e7SMiklos Szeredi /* 3786f9f1180SMiklos Szeredi * Atomic create+open operation 3796f9f1180SMiklos Szeredi * 3806f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 3816f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 3826f9f1180SMiklos Szeredi */ 383fd72faacSMiklos Szeredi static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, 384fd72faacSMiklos Szeredi struct nameidata *nd) 385fd72faacSMiklos Szeredi { 386fd72faacSMiklos Szeredi int err; 387fd72faacSMiklos Szeredi struct inode *inode; 388fd72faacSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 389fd72faacSMiklos Szeredi struct fuse_req *req; 39051eb01e7SMiklos Szeredi struct fuse_req *forget_req; 391fd72faacSMiklos Szeredi struct fuse_open_in inarg; 392fd72faacSMiklos Szeredi struct fuse_open_out outopen; 393fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 394fd72faacSMiklos Szeredi struct fuse_file *ff; 395fd72faacSMiklos Szeredi struct file *file; 396fd72faacSMiklos Szeredi int flags = nd->intent.open.flags - 1; 397fd72faacSMiklos Szeredi 398fd72faacSMiklos Szeredi if (fc->no_create) 399ce1d5a49SMiklos Szeredi return -ENOSYS; 400fd72faacSMiklos Szeredi 40151eb01e7SMiklos Szeredi forget_req = fuse_get_req(fc); 40251eb01e7SMiklos Szeredi if (IS_ERR(forget_req)) 40351eb01e7SMiklos Szeredi return PTR_ERR(forget_req); 40451eb01e7SMiklos Szeredi 405ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 40651eb01e7SMiklos Szeredi err = PTR_ERR(req); 407ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 40851eb01e7SMiklos Szeredi goto out_put_forget_req; 409fd72faacSMiklos Szeredi 410ce1d5a49SMiklos Szeredi err = -ENOMEM; 411acf99433STejun Heo ff = fuse_file_alloc(fc); 412fd72faacSMiklos Szeredi if (!ff) 413fd72faacSMiklos Szeredi goto out_put_request; 414fd72faacSMiklos Szeredi 415fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 416fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4170e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 418fd72faacSMiklos Szeredi inarg.flags = flags; 419fd72faacSMiklos Szeredi inarg.mode = mode; 420fd72faacSMiklos Szeredi req->in.h.opcode = FUSE_CREATE; 421fd72faacSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 422fd72faacSMiklos Szeredi req->in.numargs = 2; 423fd72faacSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 424fd72faacSMiklos Szeredi req->in.args[0].value = &inarg; 425fd72faacSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 426fd72faacSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 427fd72faacSMiklos Szeredi req->out.numargs = 2; 4280e9663eeSMiklos Szeredi if (fc->minor < 9) 4290e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 4300e9663eeSMiklos Szeredi else 431fd72faacSMiklos Szeredi req->out.args[0].size = sizeof(outentry); 432fd72faacSMiklos Szeredi req->out.args[0].value = &outentry; 433fd72faacSMiklos Szeredi req->out.args[1].size = sizeof(outopen); 434fd72faacSMiklos Szeredi req->out.args[1].value = &outopen; 435b93f858aSTejun Heo fuse_request_send(fc, req); 436fd72faacSMiklos Szeredi err = req->out.h.error; 437fd72faacSMiklos Szeredi if (err) { 438fd72faacSMiklos Szeredi if (err == -ENOSYS) 439fd72faacSMiklos Szeredi fc->no_create = 1; 440fd72faacSMiklos Szeredi goto out_free_ff; 441fd72faacSMiklos Szeredi } 442fd72faacSMiklos Szeredi 443fd72faacSMiklos Szeredi err = -EIO; 4442827d0b2SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 445fd72faacSMiklos Szeredi goto out_free_ff; 446fd72faacSMiklos Szeredi 44751eb01e7SMiklos Szeredi fuse_put_request(fc, req); 448fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 4491fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 450fd72faacSMiklos Szeredi if (!inode) { 451fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 452fd72faacSMiklos Szeredi ff->fh = outopen.fh; 45351eb01e7SMiklos Szeredi fuse_sync_release(fc, ff, outentry.nodeid, flags); 45451eb01e7SMiklos Szeredi fuse_send_forget(fc, forget_req, outentry.nodeid, 1); 45551eb01e7SMiklos Szeredi return -ENOMEM; 456fd72faacSMiklos Szeredi } 45751eb01e7SMiklos Szeredi fuse_put_request(fc, forget_req); 458fd72faacSMiklos Szeredi d_instantiate(entry, inode); 4591fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 4600952b2a4SMiklos Szeredi fuse_invalidate_attr(dir); 461fd72faacSMiklos Szeredi file = lookup_instantiate_filp(nd, entry, generic_file_open); 462fd72faacSMiklos Szeredi if (IS_ERR(file)) { 463fd72faacSMiklos Szeredi ff->fh = outopen.fh; 46451eb01e7SMiklos Szeredi fuse_sync_release(fc, ff, outentry.nodeid, flags); 465fd72faacSMiklos Szeredi return PTR_ERR(file); 466fd72faacSMiklos Szeredi } 467fd72faacSMiklos Szeredi fuse_finish_open(inode, file, ff, &outopen); 468fd72faacSMiklos Szeredi return 0; 469fd72faacSMiklos Szeredi 470fd72faacSMiklos Szeredi out_free_ff: 471fd72faacSMiklos Szeredi fuse_file_free(ff); 472fd72faacSMiklos Szeredi out_put_request: 473fd72faacSMiklos Szeredi fuse_put_request(fc, req); 47451eb01e7SMiklos Szeredi out_put_forget_req: 47551eb01e7SMiklos Szeredi fuse_put_request(fc, forget_req); 476fd72faacSMiklos Szeredi return err; 477fd72faacSMiklos Szeredi } 478fd72faacSMiklos Szeredi 4796f9f1180SMiklos Szeredi /* 4806f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 4816f9f1180SMiklos Szeredi */ 4829e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, 4839e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 4849e6268dbSMiklos Szeredi int mode) 4859e6268dbSMiklos Szeredi { 4869e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 4879e6268dbSMiklos Szeredi struct inode *inode; 4889e6268dbSMiklos Szeredi int err; 4892d51013eSMiklos Szeredi struct fuse_req *forget_req; 4902d51013eSMiklos Szeredi 4912d51013eSMiklos Szeredi forget_req = fuse_get_req(fc); 4922d51013eSMiklos Szeredi if (IS_ERR(forget_req)) { 4932d51013eSMiklos Szeredi fuse_put_request(fc, req); 4942d51013eSMiklos Szeredi return PTR_ERR(forget_req); 4952d51013eSMiklos Szeredi } 4969e6268dbSMiklos Szeredi 4970e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 4989e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 4999e6268dbSMiklos Szeredi req->out.numargs = 1; 5000e9663eeSMiklos Szeredi if (fc->minor < 9) 5010e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 5020e9663eeSMiklos Szeredi else 5039e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 5049e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 505b93f858aSTejun Heo fuse_request_send(fc, req); 5069e6268dbSMiklos Szeredi err = req->out.h.error; 5079e6268dbSMiklos Szeredi fuse_put_request(fc, req); 5082d51013eSMiklos Szeredi if (err) 5092d51013eSMiklos Szeredi goto out_put_forget_req; 5102d51013eSMiklos Szeredi 51139ee059aSMiklos Szeredi err = -EIO; 51239ee059aSMiklos Szeredi if (invalid_nodeid(outarg.nodeid)) 5132d51013eSMiklos Szeredi goto out_put_forget_req; 51439ee059aSMiklos Szeredi 51539ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 5162d51013eSMiklos Szeredi goto out_put_forget_req; 51739ee059aSMiklos Szeredi 5189e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 5191fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 5209e6268dbSMiklos Szeredi if (!inode) { 5212d51013eSMiklos Szeredi fuse_send_forget(fc, forget_req, outarg.nodeid, 1); 5229e6268dbSMiklos Szeredi return -ENOMEM; 5239e6268dbSMiklos Szeredi } 5242d51013eSMiklos Szeredi fuse_put_request(fc, forget_req); 5259e6268dbSMiklos Szeredi 526d2a85164SMiklos Szeredi if (S_ISDIR(inode->i_mode)) { 527d2a85164SMiklos Szeredi struct dentry *alias; 528d2a85164SMiklos Szeredi mutex_lock(&fc->inst_mutex); 529d2a85164SMiklos Szeredi alias = d_find_alias(inode); 530d2a85164SMiklos Szeredi if (alias) { 531d2a85164SMiklos Szeredi /* New directory must have moved since mkdir */ 532d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 533d2a85164SMiklos Szeredi dput(alias); 5349e6268dbSMiklos Szeredi iput(inode); 535d2a85164SMiklos Szeredi return -EBUSY; 5369e6268dbSMiklos Szeredi } 5379e6268dbSMiklos Szeredi d_instantiate(entry, inode); 538d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 539d2a85164SMiklos Szeredi } else 540d2a85164SMiklos Szeredi d_instantiate(entry, inode); 541d2a85164SMiklos Szeredi 5421fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 5439e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 5449e6268dbSMiklos Szeredi return 0; 54539ee059aSMiklos Szeredi 5462d51013eSMiklos Szeredi out_put_forget_req: 5472d51013eSMiklos Szeredi fuse_put_request(fc, forget_req); 54839ee059aSMiklos Szeredi return err; 5499e6268dbSMiklos Szeredi } 5509e6268dbSMiklos Szeredi 5519e6268dbSMiklos Szeredi static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, 5529e6268dbSMiklos Szeredi dev_t rdev) 5539e6268dbSMiklos Szeredi { 5549e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 5559e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 556ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 557ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 558ce1d5a49SMiklos Szeredi return PTR_ERR(req); 5599e6268dbSMiklos Szeredi 5609e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 5619e6268dbSMiklos Szeredi inarg.mode = mode; 5629e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 5639e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKNOD; 5649e6268dbSMiklos Szeredi req->in.numargs = 2; 5659e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 5669e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 5679e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 5689e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 5699e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, mode); 5709e6268dbSMiklos Szeredi } 5719e6268dbSMiklos Szeredi 5729e6268dbSMiklos Szeredi static int fuse_create(struct inode *dir, struct dentry *entry, int mode, 5739e6268dbSMiklos Szeredi struct nameidata *nd) 5749e6268dbSMiklos Szeredi { 575b9ba347fSMiklos Szeredi if (nd && (nd->flags & LOOKUP_OPEN)) { 576fd72faacSMiklos Szeredi int err = fuse_create_open(dir, entry, mode, nd); 577fd72faacSMiklos Szeredi if (err != -ENOSYS) 578fd72faacSMiklos Szeredi return err; 579fd72faacSMiklos Szeredi /* Fall back on mknod */ 580fd72faacSMiklos Szeredi } 5819e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 5829e6268dbSMiklos Szeredi } 5839e6268dbSMiklos Szeredi 5849e6268dbSMiklos Szeredi static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode) 5859e6268dbSMiklos Szeredi { 5869e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 5879e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 588ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 589ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 590ce1d5a49SMiklos Szeredi return PTR_ERR(req); 5919e6268dbSMiklos Szeredi 5929e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 5939e6268dbSMiklos Szeredi inarg.mode = mode; 5949e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKDIR; 5959e6268dbSMiklos Szeredi req->in.numargs = 2; 5969e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 5979e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 5989e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 5999e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 6009e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFDIR); 6019e6268dbSMiklos Szeredi } 6029e6268dbSMiklos Szeredi 6039e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 6049e6268dbSMiklos Szeredi const char *link) 6059e6268dbSMiklos Szeredi { 6069e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6079e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 608ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 609ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 610ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6119e6268dbSMiklos Szeredi 6129e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SYMLINK; 6139e6268dbSMiklos Szeredi req->in.numargs = 2; 6149e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 6159e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 6169e6268dbSMiklos Szeredi req->in.args[1].size = len; 6179e6268dbSMiklos Szeredi req->in.args[1].value = link; 6189e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFLNK); 6199e6268dbSMiklos Szeredi } 6209e6268dbSMiklos Szeredi 6219e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 6229e6268dbSMiklos Szeredi { 6239e6268dbSMiklos Szeredi int err; 6249e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 625ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 626ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 627ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6289e6268dbSMiklos Szeredi 6299e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_UNLINK; 6309e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 6319e6268dbSMiklos Szeredi req->in.numargs = 1; 6329e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 6339e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 634b93f858aSTejun Heo fuse_request_send(fc, req); 6359e6268dbSMiklos Szeredi err = req->out.h.error; 6369e6268dbSMiklos Szeredi fuse_put_request(fc, req); 6379e6268dbSMiklos Szeredi if (!err) { 6389e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 6399e6268dbSMiklos Szeredi 6401729a16cSMiklos Szeredi /* 6411729a16cSMiklos Szeredi * Set nlink to zero so the inode can be cleared, if the inode 6421729a16cSMiklos Szeredi * does have more links this will be discovered at the next 6431729a16cSMiklos Szeredi * lookup/getattr. 6441729a16cSMiklos Szeredi */ 645ce71ec36SDave Hansen clear_nlink(inode); 6469e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 6479e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 6488cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 6499e6268dbSMiklos Szeredi } else if (err == -EINTR) 6509e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 6519e6268dbSMiklos Szeredi return err; 6529e6268dbSMiklos Szeredi } 6539e6268dbSMiklos Szeredi 6549e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 6559e6268dbSMiklos Szeredi { 6569e6268dbSMiklos Szeredi int err; 6579e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 658ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 659ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 660ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6619e6268dbSMiklos Szeredi 6629e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RMDIR; 6639e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 6649e6268dbSMiklos Szeredi req->in.numargs = 1; 6659e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 6669e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 667b93f858aSTejun Heo fuse_request_send(fc, req); 6689e6268dbSMiklos Szeredi err = req->out.h.error; 6699e6268dbSMiklos Szeredi fuse_put_request(fc, req); 6709e6268dbSMiklos Szeredi if (!err) { 671ce71ec36SDave Hansen clear_nlink(entry->d_inode); 6729e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 6738cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 6749e6268dbSMiklos Szeredi } else if (err == -EINTR) 6759e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 6769e6268dbSMiklos Szeredi return err; 6779e6268dbSMiklos Szeredi } 6789e6268dbSMiklos Szeredi 6799e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent, 6809e6268dbSMiklos Szeredi struct inode *newdir, struct dentry *newent) 6819e6268dbSMiklos Szeredi { 6829e6268dbSMiklos Szeredi int err; 6839e6268dbSMiklos Szeredi struct fuse_rename_in inarg; 6849e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 685ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 686ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 687ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6889e6268dbSMiklos Szeredi 6899e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6909e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 6919e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RENAME; 6929e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(olddir); 6939e6268dbSMiklos Szeredi req->in.numargs = 3; 6949e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 6959e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 6969e6268dbSMiklos Szeredi req->in.args[1].size = oldent->d_name.len + 1; 6979e6268dbSMiklos Szeredi req->in.args[1].value = oldent->d_name.name; 6989e6268dbSMiklos Szeredi req->in.args[2].size = newent->d_name.len + 1; 6999e6268dbSMiklos Szeredi req->in.args[2].value = newent->d_name.name; 700b93f858aSTejun Heo fuse_request_send(fc, req); 7019e6268dbSMiklos Szeredi err = req->out.h.error; 7029e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7039e6268dbSMiklos Szeredi if (!err) { 70408b63307SMiklos Szeredi /* ctime changes */ 70508b63307SMiklos Szeredi fuse_invalidate_attr(oldent->d_inode); 70608b63307SMiklos Szeredi 7079e6268dbSMiklos Szeredi fuse_invalidate_attr(olddir); 7089e6268dbSMiklos Szeredi if (olddir != newdir) 7099e6268dbSMiklos Szeredi fuse_invalidate_attr(newdir); 7108cbdf1e6SMiklos Szeredi 7118cbdf1e6SMiklos Szeredi /* newent will end up negative */ 7128cbdf1e6SMiklos Szeredi if (newent->d_inode) 7138cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 7149e6268dbSMiklos Szeredi } else if (err == -EINTR) { 7159e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 7169e6268dbSMiklos Szeredi rename actually took place. If the invalidation 7179e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 7189e6268dbSMiklos Szeredi directory), then there can be inconsistency between 7199e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 7209e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 7219e6268dbSMiklos Szeredi if (newent->d_inode) 7229e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 7239e6268dbSMiklos Szeredi } 7249e6268dbSMiklos Szeredi 7259e6268dbSMiklos Szeredi return err; 7269e6268dbSMiklos Szeredi } 7279e6268dbSMiklos Szeredi 7289e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 7299e6268dbSMiklos Szeredi struct dentry *newent) 7309e6268dbSMiklos Szeredi { 7319e6268dbSMiklos Szeredi int err; 7329e6268dbSMiklos Szeredi struct fuse_link_in inarg; 7339e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 7349e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 735ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 736ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 737ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7389e6268dbSMiklos Szeredi 7399e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7409e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 7419e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_LINK; 7429e6268dbSMiklos Szeredi req->in.numargs = 2; 7439e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 7449e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 7459e6268dbSMiklos Szeredi req->in.args[1].size = newent->d_name.len + 1; 7469e6268dbSMiklos Szeredi req->in.args[1].value = newent->d_name.name; 7479e6268dbSMiklos Szeredi err = create_new_entry(fc, req, newdir, newent, inode->i_mode); 7489e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 7499e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 7509e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 7519e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 7529e6268dbSMiklos Szeredi etc.) 7539e6268dbSMiklos Szeredi */ 7549e6268dbSMiklos Szeredi if (!err || err == -EINTR) 7559e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 7569e6268dbSMiklos Szeredi return err; 7579e6268dbSMiklos Szeredi } 7589e6268dbSMiklos Szeredi 7591fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 7601fb69e78SMiklos Szeredi struct kstat *stat) 7611fb69e78SMiklos Szeredi { 7621fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 7631fb69e78SMiklos Szeredi stat->ino = attr->ino; 7641fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 7651fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 7661fb69e78SMiklos Szeredi stat->uid = attr->uid; 7671fb69e78SMiklos Szeredi stat->gid = attr->gid; 7681fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 7691fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 7701fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 7711fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 7721fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 7731fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 7741fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 7751fb69e78SMiklos Szeredi stat->size = attr->size; 7761fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 7771fb69e78SMiklos Szeredi stat->blksize = (1 << inode->i_blkbits); 7781fb69e78SMiklos Szeredi } 7791fb69e78SMiklos Szeredi 780c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 781c79e322fSMiklos Szeredi struct file *file) 782e5e5558eSMiklos Szeredi { 783e5e5558eSMiklos Szeredi int err; 784c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 785c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 786e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 7871fb69e78SMiklos Szeredi struct fuse_req *req; 7881fb69e78SMiklos Szeredi u64 attr_version; 7891fb69e78SMiklos Szeredi 7901fb69e78SMiklos Szeredi req = fuse_get_req(fc); 791ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 792ce1d5a49SMiklos Szeredi return PTR_ERR(req); 793e5e5558eSMiklos Szeredi 7947dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 7951fb69e78SMiklos Szeredi 796c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7970e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 798c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 799c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 800c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 801c79e322fSMiklos Szeredi 802c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 803c79e322fSMiklos Szeredi inarg.fh = ff->fh; 804c79e322fSMiklos Szeredi } 805e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_GETATTR; 806e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 807c79e322fSMiklos Szeredi req->in.numargs = 1; 808c79e322fSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 809c79e322fSMiklos Szeredi req->in.args[0].value = &inarg; 810e5e5558eSMiklos Szeredi req->out.numargs = 1; 8110e9663eeSMiklos Szeredi if (fc->minor < 9) 8120e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 8130e9663eeSMiklos Szeredi else 814c79e322fSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 815c79e322fSMiklos Szeredi req->out.args[0].value = &outarg; 816b93f858aSTejun Heo fuse_request_send(fc, req); 817e5e5558eSMiklos Szeredi err = req->out.h.error; 818e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 819e5e5558eSMiklos Szeredi if (!err) { 820c79e322fSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 821e5e5558eSMiklos Szeredi make_bad_inode(inode); 822e5e5558eSMiklos Szeredi err = -EIO; 823e5e5558eSMiklos Szeredi } else { 824c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 825c79e322fSMiklos Szeredi attr_timeout(&outarg), 8261fb69e78SMiklos Szeredi attr_version); 8271fb69e78SMiklos Szeredi if (stat) 828c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 829e5e5558eSMiklos Szeredi } 830e5e5558eSMiklos Szeredi } 831e5e5558eSMiklos Szeredi return err; 832e5e5558eSMiklos Szeredi } 833e5e5558eSMiklos Szeredi 834bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat, 835bcb4be80SMiklos Szeredi struct file *file, bool *refreshed) 836bcb4be80SMiklos Szeredi { 837bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 838bcb4be80SMiklos Szeredi int err; 839bcb4be80SMiklos Szeredi bool r; 840bcb4be80SMiklos Szeredi 841bcb4be80SMiklos Szeredi if (fi->i_time < get_jiffies_64()) { 842bcb4be80SMiklos Szeredi r = true; 843bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 844bcb4be80SMiklos Szeredi } else { 845bcb4be80SMiklos Szeredi r = false; 846bcb4be80SMiklos Szeredi err = 0; 847bcb4be80SMiklos Szeredi if (stat) { 848bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 849bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 850bcb4be80SMiklos Szeredi } 851bcb4be80SMiklos Szeredi } 852bcb4be80SMiklos Szeredi 853bcb4be80SMiklos Szeredi if (refreshed != NULL) 854bcb4be80SMiklos Szeredi *refreshed = r; 855bcb4be80SMiklos Szeredi 856bcb4be80SMiklos Szeredi return err; 857bcb4be80SMiklos Szeredi } 858bcb4be80SMiklos Szeredi 85987729a55SMiklos Szeredi /* 86087729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 86187729a55SMiklos Szeredi * daemon ptrace-like capabilities over the requester process. This 86287729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 86387729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 86487729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 86587729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 86687729a55SMiklos Szeredi * DoS against the requester. 86787729a55SMiklos Szeredi * 86887729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 86987729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 87087729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 87187729a55SMiklos Szeredi */ 872e57ac683SMiklos Szeredi int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) 87387729a55SMiklos Szeredi { 874c69e8d9cSDavid Howells const struct cred *cred; 875c69e8d9cSDavid Howells int ret; 876c69e8d9cSDavid Howells 87787729a55SMiklos Szeredi if (fc->flags & FUSE_ALLOW_OTHER) 87887729a55SMiklos Szeredi return 1; 87987729a55SMiklos Szeredi 880c69e8d9cSDavid Howells rcu_read_lock(); 881c69e8d9cSDavid Howells ret = 0; 882c69e8d9cSDavid Howells cred = __task_cred(task); 883c69e8d9cSDavid Howells if (cred->euid == fc->user_id && 884c69e8d9cSDavid Howells cred->suid == fc->user_id && 885c69e8d9cSDavid Howells cred->uid == fc->user_id && 886c69e8d9cSDavid Howells cred->egid == fc->group_id && 887c69e8d9cSDavid Howells cred->sgid == fc->group_id && 888c69e8d9cSDavid Howells cred->gid == fc->group_id) 889c69e8d9cSDavid Howells ret = 1; 890c69e8d9cSDavid Howells rcu_read_unlock(); 89187729a55SMiklos Szeredi 892c69e8d9cSDavid Howells return ret; 89387729a55SMiklos Szeredi } 89487729a55SMiklos Szeredi 89531d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 89631d40d74SMiklos Szeredi { 89731d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 89831d40d74SMiklos Szeredi struct fuse_req *req; 89931d40d74SMiklos Szeredi struct fuse_access_in inarg; 90031d40d74SMiklos Szeredi int err; 90131d40d74SMiklos Szeredi 90231d40d74SMiklos Szeredi if (fc->no_access) 90331d40d74SMiklos Szeredi return 0; 90431d40d74SMiklos Szeredi 905ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 906ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 907ce1d5a49SMiklos Szeredi return PTR_ERR(req); 90831d40d74SMiklos Szeredi 90931d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 910e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 91131d40d74SMiklos Szeredi req->in.h.opcode = FUSE_ACCESS; 91231d40d74SMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 91331d40d74SMiklos Szeredi req->in.numargs = 1; 91431d40d74SMiklos Szeredi req->in.args[0].size = sizeof(inarg); 91531d40d74SMiklos Szeredi req->in.args[0].value = &inarg; 916b93f858aSTejun Heo fuse_request_send(fc, req); 91731d40d74SMiklos Szeredi err = req->out.h.error; 91831d40d74SMiklos Szeredi fuse_put_request(fc, req); 91931d40d74SMiklos Szeredi if (err == -ENOSYS) { 92031d40d74SMiklos Szeredi fc->no_access = 1; 92131d40d74SMiklos Szeredi err = 0; 92231d40d74SMiklos Szeredi } 92331d40d74SMiklos Szeredi return err; 92431d40d74SMiklos Szeredi } 92531d40d74SMiklos Szeredi 9266f9f1180SMiklos Szeredi /* 9276f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 9286f9f1180SMiklos Szeredi * 9296f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 9306f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 9316f9f1180SMiklos Szeredi * modell. 9326f9f1180SMiklos Szeredi * 9336f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 9346f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 9356f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 9366f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 9376f9f1180SMiklos Szeredi * locally based on file mode. 9386f9f1180SMiklos Szeredi */ 939e6305c43SAl Viro static int fuse_permission(struct inode *inode, int mask) 940e5e5558eSMiklos Szeredi { 941e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 942244f6385SMiklos Szeredi bool refreshed = false; 943244f6385SMiklos Szeredi int err = 0; 944e5e5558eSMiklos Szeredi 94587729a55SMiklos Szeredi if (!fuse_allow_task(fc, current)) 946e5e5558eSMiklos Szeredi return -EACCES; 947244f6385SMiklos Szeredi 948244f6385SMiklos Szeredi /* 949e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 950244f6385SMiklos Szeredi */ 951e8e96157SMiklos Szeredi if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || 952e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 953bcb4be80SMiklos Szeredi err = fuse_update_attributes(inode, NULL, NULL, &refreshed); 954244f6385SMiklos Szeredi if (err) 955244f6385SMiklos Szeredi return err; 9561fb69e78SMiklos Szeredi } 957244f6385SMiklos Szeredi 958244f6385SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 9591a823ac9SMiklos Szeredi err = generic_permission(inode, mask, NULL); 9601e9a4ed9SMiklos Szeredi 9611e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 9621e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 9631e9a4ed9SMiklos Szeredi node will at first have no permissions */ 964244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 965c79e322fSMiklos Szeredi err = fuse_do_getattr(inode, NULL, NULL); 9661e9a4ed9SMiklos Szeredi if (!err) 9671e9a4ed9SMiklos Szeredi err = generic_permission(inode, mask, NULL); 9681e9a4ed9SMiklos Szeredi } 9691e9a4ed9SMiklos Szeredi 9706f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 9716f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 9726f9f1180SMiklos Szeredi noticed immediately, only after the attribute 9736f9f1180SMiklos Szeredi timeout has expired */ 974a110343fSAl Viro } else if (mask & MAY_ACCESS) { 975e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 976e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 977e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 978e8e96157SMiklos Szeredi if (refreshed) 979e5e5558eSMiklos Szeredi return -EACCES; 98031d40d74SMiklos Szeredi 981c79e322fSMiklos Szeredi err = fuse_do_getattr(inode, NULL, NULL); 982e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 983e8e96157SMiklos Szeredi return -EACCES; 984e8e96157SMiklos Szeredi } 985e5e5558eSMiklos Szeredi } 986244f6385SMiklos Szeredi return err; 987e5e5558eSMiklos Szeredi } 988e5e5558eSMiklos Szeredi 989e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file, 990e5e5558eSMiklos Szeredi void *dstbuf, filldir_t filldir) 991e5e5558eSMiklos Szeredi { 992e5e5558eSMiklos Szeredi while (nbytes >= FUSE_NAME_OFFSET) { 993e5e5558eSMiklos Szeredi struct fuse_dirent *dirent = (struct fuse_dirent *) buf; 994e5e5558eSMiklos Szeredi size_t reclen = FUSE_DIRENT_SIZE(dirent); 995e5e5558eSMiklos Szeredi int over; 996e5e5558eSMiklos Szeredi if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 997e5e5558eSMiklos Szeredi return -EIO; 998e5e5558eSMiklos Szeredi if (reclen > nbytes) 999e5e5558eSMiklos Szeredi break; 1000e5e5558eSMiklos Szeredi 1001e5e5558eSMiklos Szeredi over = filldir(dstbuf, dirent->name, dirent->namelen, 1002e5e5558eSMiklos Szeredi file->f_pos, dirent->ino, dirent->type); 1003e5e5558eSMiklos Szeredi if (over) 1004e5e5558eSMiklos Szeredi break; 1005e5e5558eSMiklos Szeredi 1006e5e5558eSMiklos Szeredi buf += reclen; 1007e5e5558eSMiklos Szeredi nbytes -= reclen; 1008e5e5558eSMiklos Szeredi file->f_pos = dirent->off; 1009e5e5558eSMiklos Szeredi } 1010e5e5558eSMiklos Szeredi 1011e5e5558eSMiklos Szeredi return 0; 1012e5e5558eSMiklos Szeredi } 1013e5e5558eSMiklos Szeredi 1014e5e5558eSMiklos Szeredi static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) 1015e5e5558eSMiklos Szeredi { 101604730fefSMiklos Szeredi int err; 101704730fefSMiklos Szeredi size_t nbytes; 101804730fefSMiklos Szeredi struct page *page; 10197706a9d6SJosef Sipek struct inode *inode = file->f_path.dentry->d_inode; 102004730fefSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1021248d86e8SMiklos Szeredi struct fuse_req *req; 1022248d86e8SMiklos Szeredi 1023248d86e8SMiklos Szeredi if (is_bad_inode(inode)) 1024248d86e8SMiklos Szeredi return -EIO; 1025248d86e8SMiklos Szeredi 1026ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1027ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1028ce1d5a49SMiklos Szeredi return PTR_ERR(req); 1029e5e5558eSMiklos Szeredi 103004730fefSMiklos Szeredi page = alloc_page(GFP_KERNEL); 103104730fefSMiklos Szeredi if (!page) { 103204730fefSMiklos Szeredi fuse_put_request(fc, req); 1033e5e5558eSMiklos Szeredi return -ENOMEM; 103404730fefSMiklos Szeredi } 1035f4975c67SMiklos Szeredi req->out.argpages = 1; 103604730fefSMiklos Szeredi req->num_pages = 1; 103704730fefSMiklos Szeredi req->pages[0] = page; 1038*2106cb18SMiklos Szeredi fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR); 1039b93f858aSTejun Heo fuse_request_send(fc, req); 1040361b1eb5SMiklos Szeredi nbytes = req->out.args[0].size; 104104730fefSMiklos Szeredi err = req->out.h.error; 104204730fefSMiklos Szeredi fuse_put_request(fc, req); 104304730fefSMiklos Szeredi if (!err) 104404730fefSMiklos Szeredi err = parse_dirfile(page_address(page), nbytes, file, dstbuf, 104504730fefSMiklos Szeredi filldir); 1046e5e5558eSMiklos Szeredi 104704730fefSMiklos Szeredi __free_page(page); 1048b36c31baSMiklos Szeredi fuse_invalidate_attr(inode); /* atime changed */ 104904730fefSMiklos Szeredi return err; 1050e5e5558eSMiklos Szeredi } 1051e5e5558eSMiklos Szeredi 1052e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry) 1053e5e5558eSMiklos Szeredi { 1054e5e5558eSMiklos Szeredi struct inode *inode = dentry->d_inode; 1055e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1056ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 1057e5e5558eSMiklos Szeredi char *link; 1058e5e5558eSMiklos Szeredi 1059ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1060e231c2eeSDavid Howells return ERR_CAST(req); 1061e5e5558eSMiklos Szeredi 1062e5e5558eSMiklos Szeredi link = (char *) __get_free_page(GFP_KERNEL); 1063e5e5558eSMiklos Szeredi if (!link) { 1064e5e5558eSMiklos Szeredi link = ERR_PTR(-ENOMEM); 1065e5e5558eSMiklos Szeredi goto out; 1066e5e5558eSMiklos Szeredi } 1067e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_READLINK; 1068e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 1069e5e5558eSMiklos Szeredi req->out.argvar = 1; 1070e5e5558eSMiklos Szeredi req->out.numargs = 1; 1071e5e5558eSMiklos Szeredi req->out.args[0].size = PAGE_SIZE - 1; 1072e5e5558eSMiklos Szeredi req->out.args[0].value = link; 1073b93f858aSTejun Heo fuse_request_send(fc, req); 1074e5e5558eSMiklos Szeredi if (req->out.h.error) { 1075e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1076e5e5558eSMiklos Szeredi link = ERR_PTR(req->out.h.error); 1077e5e5558eSMiklos Szeredi } else 1078e5e5558eSMiklos Szeredi link[req->out.args[0].size] = '\0'; 1079e5e5558eSMiklos Szeredi out: 1080e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 1081b36c31baSMiklos Szeredi fuse_invalidate_attr(inode); /* atime changed */ 1082e5e5558eSMiklos Szeredi return link; 1083e5e5558eSMiklos Szeredi } 1084e5e5558eSMiklos Szeredi 1085e5e5558eSMiklos Szeredi static void free_link(char *link) 1086e5e5558eSMiklos Szeredi { 1087e5e5558eSMiklos Szeredi if (!IS_ERR(link)) 1088e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1089e5e5558eSMiklos Szeredi } 1090e5e5558eSMiklos Szeredi 1091e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd) 1092e5e5558eSMiklos Szeredi { 1093e5e5558eSMiklos Szeredi nd_set_link(nd, read_link(dentry)); 1094e5e5558eSMiklos Szeredi return NULL; 1095e5e5558eSMiklos Szeredi } 1096e5e5558eSMiklos Szeredi 1097e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c) 1098e5e5558eSMiklos Szeredi { 1099e5e5558eSMiklos Szeredi free_link(nd_get_link(nd)); 1100e5e5558eSMiklos Szeredi } 1101e5e5558eSMiklos Szeredi 1102e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1103e5e5558eSMiklos Szeredi { 110404730fefSMiklos Szeredi return fuse_open_common(inode, file, 1); 1105e5e5558eSMiklos Szeredi } 1106e5e5558eSMiklos Szeredi 1107e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1108e5e5558eSMiklos Szeredi { 110904730fefSMiklos Szeredi return fuse_release_common(inode, file, 1); 1110e5e5558eSMiklos Szeredi } 1111e5e5558eSMiklos Szeredi 111282547981SMiklos Szeredi static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) 111382547981SMiklos Szeredi { 111482547981SMiklos Szeredi /* nfsd can call this with no file */ 111582547981SMiklos Szeredi return file ? fuse_fsync_common(file, de, datasync, 1) : 0; 111682547981SMiklos Szeredi } 111782547981SMiklos Szeredi 111817637cbaSMiklos Szeredi static bool update_mtime(unsigned ivalid) 111917637cbaSMiklos Szeredi { 112017637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 112117637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 112217637cbaSMiklos Szeredi return true; 112317637cbaSMiklos Szeredi 112417637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 112517637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 112617637cbaSMiklos Szeredi return false; 112717637cbaSMiklos Szeredi 112817637cbaSMiklos Szeredi /* In all other cases update */ 112917637cbaSMiklos Szeredi return true; 113017637cbaSMiklos Szeredi } 113117637cbaSMiklos Szeredi 1132befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) 11339e6268dbSMiklos Szeredi { 11349e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 11359e6268dbSMiklos Szeredi 11369e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1137befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 11389e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 1139befc649cSMiklos Szeredi arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid; 11409e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 1141befc649cSMiklos Szeredi arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid; 11429e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1143befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 114417637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 114517637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1146befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 114717637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 114817637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 114917637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 115017637cbaSMiklos Szeredi } 115117637cbaSMiklos Szeredi if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) { 115217637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1153befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 115417637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 115517637cbaSMiklos Szeredi if (!(ivalid & ATTR_MTIME_SET)) 115617637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 11579e6268dbSMiklos Szeredi } 11589e6268dbSMiklos Szeredi } 11599e6268dbSMiklos Szeredi 11606f9f1180SMiklos Szeredi /* 11613be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 11623be5a52bSMiklos Szeredi * 11633be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 11643be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 11653be5a52bSMiklos Szeredi */ 11663be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 11673be5a52bSMiklos Szeredi { 11683be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 11693be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 11703be5a52bSMiklos Szeredi 11713be5a52bSMiklos Szeredi BUG_ON(!mutex_is_locked(&inode->i_mutex)); 11723be5a52bSMiklos Szeredi 11733be5a52bSMiklos Szeredi spin_lock(&fc->lock); 11743be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 11753be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 11763be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 11773be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 11783be5a52bSMiklos Szeredi } 11793be5a52bSMiklos Szeredi 11803be5a52bSMiklos Szeredi /* 11813be5a52bSMiklos Szeredi * Allow writepages on inode 11823be5a52bSMiklos Szeredi * 11833be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 11843be5a52bSMiklos Szeredi * writepages. 11853be5a52bSMiklos Szeredi */ 11863be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 11873be5a52bSMiklos Szeredi { 11883be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 11893be5a52bSMiklos Szeredi 11903be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 11913be5a52bSMiklos Szeredi fi->writectr = 0; 11923be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 11933be5a52bSMiklos Szeredi } 11943be5a52bSMiklos Szeredi 11953be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 11963be5a52bSMiklos Szeredi { 11973be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 11983be5a52bSMiklos Szeredi 11993be5a52bSMiklos Szeredi spin_lock(&fc->lock); 12003be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 12013be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 12023be5a52bSMiklos Szeredi } 12033be5a52bSMiklos Szeredi 12043be5a52bSMiklos Szeredi /* 12056f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 12066f9f1180SMiklos Szeredi * 12076f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 12086f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 12099ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 12109ffbb916SMiklos Szeredi * and the actual truncation by hand. 12116f9f1180SMiklos Szeredi */ 121249d4914fSMiklos Szeredi static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, 121349d4914fSMiklos Szeredi struct file *file) 12149e6268dbSMiklos Szeredi { 12159e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 12169e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 12179e6268dbSMiklos Szeredi struct fuse_req *req; 12189e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 12199e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 12203be5a52bSMiklos Szeredi bool is_truncate = false; 12213be5a52bSMiklos Szeredi loff_t oldsize; 12229e6268dbSMiklos Szeredi int err; 12239e6268dbSMiklos Szeredi 1224e57ac683SMiklos Szeredi if (!fuse_allow_task(fc, current)) 1225e57ac683SMiklos Szeredi return -EACCES; 1226e57ac683SMiklos Szeredi 12271e9a4ed9SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 12281e9a4ed9SMiklos Szeredi err = inode_change_ok(inode, attr); 12291e9a4ed9SMiklos Szeredi if (err) 12301e9a4ed9SMiklos Szeredi return err; 12311e9a4ed9SMiklos Szeredi } 12321e9a4ed9SMiklos Szeredi 12336ff958edSMiklos Szeredi if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc) 12346ff958edSMiklos Szeredi return 0; 12356ff958edSMiklos Szeredi 12369e6268dbSMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 12379e6268dbSMiklos Szeredi unsigned long limit; 1238b2d2272fSMiklos Szeredi if (IS_SWAPFILE(inode)) 1239b2d2272fSMiklos Szeredi return -ETXTBSY; 12409e6268dbSMiklos Szeredi limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; 12419e6268dbSMiklos Szeredi if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) { 12429e6268dbSMiklos Szeredi send_sig(SIGXFSZ, current, 0); 12439e6268dbSMiklos Szeredi return -EFBIG; 12449e6268dbSMiklos Szeredi } 12453be5a52bSMiklos Szeredi is_truncate = true; 12469e6268dbSMiklos Szeredi } 12479e6268dbSMiklos Szeredi 1248ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1249ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1250ce1d5a49SMiklos Szeredi return PTR_ERR(req); 12519e6268dbSMiklos Szeredi 12523be5a52bSMiklos Szeredi if (is_truncate) 12533be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 12543be5a52bSMiklos Szeredi 12559e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 12560e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 1257befc649cSMiklos Szeredi iattr_to_fattr(attr, &inarg); 125849d4914fSMiklos Szeredi if (file) { 125949d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 126049d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 126149d4914fSMiklos Szeredi inarg.fh = ff->fh; 126249d4914fSMiklos Szeredi } 1263f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1264f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1265f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1266f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 1267f3332114SMiklos Szeredi } 12689e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SETATTR; 12699e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 12709e6268dbSMiklos Szeredi req->in.numargs = 1; 12719e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 12729e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 12739e6268dbSMiklos Szeredi req->out.numargs = 1; 12740e9663eeSMiklos Szeredi if (fc->minor < 9) 12750e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 12760e9663eeSMiklos Szeredi else 12779e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 12789e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 1279b93f858aSTejun Heo fuse_request_send(fc, req); 12809e6268dbSMiklos Szeredi err = req->out.h.error; 12819e6268dbSMiklos Szeredi fuse_put_request(fc, req); 1282e00d2c2dSMiklos Szeredi if (err) { 1283e00d2c2dSMiklos Szeredi if (err == -EINTR) 1284e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 12853be5a52bSMiklos Szeredi goto error; 1286e00d2c2dSMiklos Szeredi } 1287e00d2c2dSMiklos Szeredi 12889e6268dbSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 12899e6268dbSMiklos Szeredi make_bad_inode(inode); 12903be5a52bSMiklos Szeredi err = -EIO; 12913be5a52bSMiklos Szeredi goto error; 12929e6268dbSMiklos Szeredi } 12939e6268dbSMiklos Szeredi 12943be5a52bSMiklos Szeredi spin_lock(&fc->lock); 12953be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 12963be5a52bSMiklos Szeredi attr_timeout(&outarg)); 12973be5a52bSMiklos Szeredi oldsize = inode->i_size; 12983be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 12993be5a52bSMiklos Szeredi 13003be5a52bSMiklos Szeredi if (is_truncate) { 13013be5a52bSMiklos Szeredi /* NOTE: this may release/reacquire fc->lock */ 13023be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 13033be5a52bSMiklos Szeredi } 13043be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 13053be5a52bSMiklos Szeredi 13063be5a52bSMiklos Szeredi /* 13073be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 13083be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 13093be5a52bSMiklos Szeredi */ 13103be5a52bSMiklos Szeredi if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 13113be5a52bSMiklos Szeredi if (outarg.attr.size < oldsize) 13123be5a52bSMiklos Szeredi fuse_truncate(inode->i_mapping, outarg.attr.size); 13133be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 13143be5a52bSMiklos Szeredi } 13153be5a52bSMiklos Szeredi 1316e00d2c2dSMiklos Szeredi return 0; 13173be5a52bSMiklos Szeredi 13183be5a52bSMiklos Szeredi error: 13193be5a52bSMiklos Szeredi if (is_truncate) 13203be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 13213be5a52bSMiklos Szeredi 13223be5a52bSMiklos Szeredi return err; 13239e6268dbSMiklos Szeredi } 13249e6268dbSMiklos Szeredi 132549d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 132649d4914fSMiklos Szeredi { 132749d4914fSMiklos Szeredi if (attr->ia_valid & ATTR_FILE) 132849d4914fSMiklos Szeredi return fuse_do_setattr(entry, attr, attr->ia_file); 132949d4914fSMiklos Szeredi else 133049d4914fSMiklos Szeredi return fuse_do_setattr(entry, attr, NULL); 133149d4914fSMiklos Szeredi } 133249d4914fSMiklos Szeredi 1333e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, 1334e5e5558eSMiklos Szeredi struct kstat *stat) 1335e5e5558eSMiklos Szeredi { 1336e5e5558eSMiklos Szeredi struct inode *inode = entry->d_inode; 1337244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1338244f6385SMiklos Szeredi 1339244f6385SMiklos Szeredi if (!fuse_allow_task(fc, current)) 1340244f6385SMiklos Szeredi return -EACCES; 1341244f6385SMiklos Szeredi 1342bcb4be80SMiklos Szeredi return fuse_update_attributes(inode, stat, NULL, NULL); 1343e5e5558eSMiklos Szeredi } 1344e5e5558eSMiklos Szeredi 134592a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name, 134692a8780eSMiklos Szeredi const void *value, size_t size, int flags) 134792a8780eSMiklos Szeredi { 134892a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 134992a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 135092a8780eSMiklos Szeredi struct fuse_req *req; 135192a8780eSMiklos Szeredi struct fuse_setxattr_in inarg; 135292a8780eSMiklos Szeredi int err; 135392a8780eSMiklos Szeredi 135492a8780eSMiklos Szeredi if (fc->no_setxattr) 135592a8780eSMiklos Szeredi return -EOPNOTSUPP; 135692a8780eSMiklos Szeredi 1357ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1358ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1359ce1d5a49SMiklos Szeredi return PTR_ERR(req); 136092a8780eSMiklos Szeredi 136192a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 136292a8780eSMiklos Szeredi inarg.size = size; 136392a8780eSMiklos Szeredi inarg.flags = flags; 136492a8780eSMiklos Szeredi req->in.h.opcode = FUSE_SETXATTR; 136592a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 136692a8780eSMiklos Szeredi req->in.numargs = 3; 136792a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 136892a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 136992a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 137092a8780eSMiklos Szeredi req->in.args[1].value = name; 137192a8780eSMiklos Szeredi req->in.args[2].size = size; 137292a8780eSMiklos Szeredi req->in.args[2].value = value; 1373b93f858aSTejun Heo fuse_request_send(fc, req); 137492a8780eSMiklos Szeredi err = req->out.h.error; 137592a8780eSMiklos Szeredi fuse_put_request(fc, req); 137692a8780eSMiklos Szeredi if (err == -ENOSYS) { 137792a8780eSMiklos Szeredi fc->no_setxattr = 1; 137892a8780eSMiklos Szeredi err = -EOPNOTSUPP; 137992a8780eSMiklos Szeredi } 138092a8780eSMiklos Szeredi return err; 138192a8780eSMiklos Szeredi } 138292a8780eSMiklos Szeredi 138392a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name, 138492a8780eSMiklos Szeredi void *value, size_t size) 138592a8780eSMiklos Szeredi { 138692a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 138792a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 138892a8780eSMiklos Szeredi struct fuse_req *req; 138992a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 139092a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 139192a8780eSMiklos Szeredi ssize_t ret; 139292a8780eSMiklos Szeredi 139392a8780eSMiklos Szeredi if (fc->no_getxattr) 139492a8780eSMiklos Szeredi return -EOPNOTSUPP; 139592a8780eSMiklos Szeredi 1396ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1397ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1398ce1d5a49SMiklos Szeredi return PTR_ERR(req); 139992a8780eSMiklos Szeredi 140092a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 140192a8780eSMiklos Szeredi inarg.size = size; 140292a8780eSMiklos Szeredi req->in.h.opcode = FUSE_GETXATTR; 140392a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 140492a8780eSMiklos Szeredi req->in.numargs = 2; 140592a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 140692a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 140792a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 140892a8780eSMiklos Szeredi req->in.args[1].value = name; 140992a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 141092a8780eSMiklos Szeredi req->out.numargs = 1; 141192a8780eSMiklos Szeredi if (size) { 141292a8780eSMiklos Szeredi req->out.argvar = 1; 141392a8780eSMiklos Szeredi req->out.args[0].size = size; 141492a8780eSMiklos Szeredi req->out.args[0].value = value; 141592a8780eSMiklos Szeredi } else { 141692a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 141792a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 141892a8780eSMiklos Szeredi } 1419b93f858aSTejun Heo fuse_request_send(fc, req); 142092a8780eSMiklos Szeredi ret = req->out.h.error; 142192a8780eSMiklos Szeredi if (!ret) 142292a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 142392a8780eSMiklos Szeredi else { 142492a8780eSMiklos Szeredi if (ret == -ENOSYS) { 142592a8780eSMiklos Szeredi fc->no_getxattr = 1; 142692a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 142792a8780eSMiklos Szeredi } 142892a8780eSMiklos Szeredi } 142992a8780eSMiklos Szeredi fuse_put_request(fc, req); 143092a8780eSMiklos Szeredi return ret; 143192a8780eSMiklos Szeredi } 143292a8780eSMiklos Szeredi 143392a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) 143492a8780eSMiklos Szeredi { 143592a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 143692a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 143792a8780eSMiklos Szeredi struct fuse_req *req; 143892a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 143992a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 144092a8780eSMiklos Szeredi ssize_t ret; 144192a8780eSMiklos Szeredi 1442e57ac683SMiklos Szeredi if (!fuse_allow_task(fc, current)) 1443e57ac683SMiklos Szeredi return -EACCES; 1444e57ac683SMiklos Szeredi 144592a8780eSMiklos Szeredi if (fc->no_listxattr) 144692a8780eSMiklos Szeredi return -EOPNOTSUPP; 144792a8780eSMiklos Szeredi 1448ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1449ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1450ce1d5a49SMiklos Szeredi return PTR_ERR(req); 145192a8780eSMiklos Szeredi 145292a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 145392a8780eSMiklos Szeredi inarg.size = size; 145492a8780eSMiklos Szeredi req->in.h.opcode = FUSE_LISTXATTR; 145592a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 145692a8780eSMiklos Szeredi req->in.numargs = 1; 145792a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 145892a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 145992a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 146092a8780eSMiklos Szeredi req->out.numargs = 1; 146192a8780eSMiklos Szeredi if (size) { 146292a8780eSMiklos Szeredi req->out.argvar = 1; 146392a8780eSMiklos Szeredi req->out.args[0].size = size; 146492a8780eSMiklos Szeredi req->out.args[0].value = list; 146592a8780eSMiklos Szeredi } else { 146692a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 146792a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 146892a8780eSMiklos Szeredi } 1469b93f858aSTejun Heo fuse_request_send(fc, req); 147092a8780eSMiklos Szeredi ret = req->out.h.error; 147192a8780eSMiklos Szeredi if (!ret) 147292a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 147392a8780eSMiklos Szeredi else { 147492a8780eSMiklos Szeredi if (ret == -ENOSYS) { 147592a8780eSMiklos Szeredi fc->no_listxattr = 1; 147692a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 147792a8780eSMiklos Szeredi } 147892a8780eSMiklos Szeredi } 147992a8780eSMiklos Szeredi fuse_put_request(fc, req); 148092a8780eSMiklos Szeredi return ret; 148192a8780eSMiklos Szeredi } 148292a8780eSMiklos Szeredi 148392a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name) 148492a8780eSMiklos Szeredi { 148592a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 148692a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 148792a8780eSMiklos Szeredi struct fuse_req *req; 148892a8780eSMiklos Szeredi int err; 148992a8780eSMiklos Szeredi 149092a8780eSMiklos Szeredi if (fc->no_removexattr) 149192a8780eSMiklos Szeredi return -EOPNOTSUPP; 149292a8780eSMiklos Szeredi 1493ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1494ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1495ce1d5a49SMiklos Szeredi return PTR_ERR(req); 149692a8780eSMiklos Szeredi 149792a8780eSMiklos Szeredi req->in.h.opcode = FUSE_REMOVEXATTR; 149892a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 149992a8780eSMiklos Szeredi req->in.numargs = 1; 150092a8780eSMiklos Szeredi req->in.args[0].size = strlen(name) + 1; 150192a8780eSMiklos Szeredi req->in.args[0].value = name; 1502b93f858aSTejun Heo fuse_request_send(fc, req); 150392a8780eSMiklos Szeredi err = req->out.h.error; 150492a8780eSMiklos Szeredi fuse_put_request(fc, req); 150592a8780eSMiklos Szeredi if (err == -ENOSYS) { 150692a8780eSMiklos Szeredi fc->no_removexattr = 1; 150792a8780eSMiklos Szeredi err = -EOPNOTSUPP; 150892a8780eSMiklos Szeredi } 150992a8780eSMiklos Szeredi return err; 151092a8780eSMiklos Szeredi } 151192a8780eSMiklos Szeredi 1512754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1513e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 15149e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 15159e6268dbSMiklos Szeredi .symlink = fuse_symlink, 15169e6268dbSMiklos Szeredi .unlink = fuse_unlink, 15179e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 15189e6268dbSMiklos Szeredi .rename = fuse_rename, 15199e6268dbSMiklos Szeredi .link = fuse_link, 15209e6268dbSMiklos Szeredi .setattr = fuse_setattr, 15219e6268dbSMiklos Szeredi .create = fuse_create, 15229e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1523e5e5558eSMiklos Szeredi .permission = fuse_permission, 1524e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 152592a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 152692a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 152792a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 152892a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1529e5e5558eSMiklos Szeredi }; 1530e5e5558eSMiklos Szeredi 15314b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1532b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1533e5e5558eSMiklos Szeredi .read = generic_read_dir, 1534e5e5558eSMiklos Szeredi .readdir = fuse_readdir, 1535e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1536e5e5558eSMiklos Szeredi .release = fuse_dir_release, 153782547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1538e5e5558eSMiklos Szeredi }; 1539e5e5558eSMiklos Szeredi 1540754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 15419e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1542e5e5558eSMiklos Szeredi .permission = fuse_permission, 1543e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 154492a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 154592a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 154692a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 154792a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1548e5e5558eSMiklos Szeredi }; 1549e5e5558eSMiklos Szeredi 1550754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 15519e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1552e5e5558eSMiklos Szeredi .follow_link = fuse_follow_link, 1553e5e5558eSMiklos Szeredi .put_link = fuse_put_link, 1554e5e5558eSMiklos Szeredi .readlink = generic_readlink, 1555e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 155692a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 155792a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 155892a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 155992a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1560e5e5558eSMiklos Szeredi }; 1561e5e5558eSMiklos Szeredi 1562e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1563e5e5558eSMiklos Szeredi { 1564e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1565e5e5558eSMiklos Szeredi } 1566e5e5558eSMiklos Szeredi 1567e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1568e5e5558eSMiklos Szeredi { 1569e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1570e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1571e5e5558eSMiklos Szeredi } 1572e5e5558eSMiklos Szeredi 1573e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1574e5e5558eSMiklos Szeredi { 1575e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 1576e5e5558eSMiklos Szeredi } 1577