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> 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 */ 1570b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) 158e5e5558eSMiklos Szeredi { 15934286d66SNick Piggin struct inode *inode; 1608cbdf1e6SMiklos Szeredi 161e7c0a167SMiklos Szeredi inode = ACCESS_ONCE(entry->d_inode); 1628cbdf1e6SMiklos Szeredi if (inode && is_bad_inode(inode)) 163e5e5558eSMiklos Szeredi return 0; 1640a0898cfSMiklos Szeredi else if (fuse_dentry_time(entry) < get_jiffies_64()) { 165e5e5558eSMiklos Szeredi int err; 166e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 1678cbdf1e6SMiklos Szeredi struct fuse_conn *fc; 1688cbdf1e6SMiklos Szeredi struct fuse_req *req; 16907e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 170e956edd0SMiklos Szeredi struct dentry *parent; 1711fb69e78SMiklos Szeredi u64 attr_version; 1728cbdf1e6SMiklos Szeredi 17350322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 1748cbdf1e6SMiklos Szeredi if (!inode) 1758cbdf1e6SMiklos Szeredi return 0; 1768cbdf1e6SMiklos Szeredi 1770b728e19SAl Viro if (flags & LOOKUP_RCU) 178e7c0a167SMiklos Szeredi return -ECHILD; 179e7c0a167SMiklos Szeredi 1808cbdf1e6SMiklos Szeredi fc = get_fuse_conn(inode); 181ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 182ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 183e5e5558eSMiklos Szeredi return 0; 184e5e5558eSMiklos Szeredi 18507e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 18607e77dcaSMiklos Szeredi if (!forget) { 1872d51013eSMiklos Szeredi fuse_put_request(fc, req); 1882d51013eSMiklos Szeredi return 0; 1892d51013eSMiklos Szeredi } 1902d51013eSMiklos Szeredi 1917dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 1921fb69e78SMiklos Szeredi 193e956edd0SMiklos Szeredi parent = dget_parent(entry); 194c180eebeSMiklos Szeredi fuse_lookup_init(fc, req, get_node_id(parent->d_inode), 195c180eebeSMiklos Szeredi &entry->d_name, &outarg); 196b93f858aSTejun Heo fuse_request_send(fc, req); 197e956edd0SMiklos Szeredi dput(parent); 198e5e5558eSMiklos Szeredi err = req->out.h.error; 1992d51013eSMiklos Szeredi fuse_put_request(fc, req); 20050322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 20150322fe7SMiklos Szeredi if (!err && !outarg.nodeid) 20250322fe7SMiklos Szeredi err = -ENOENT; 2039e6268dbSMiklos Szeredi if (!err) { 2048cbdf1e6SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 2059e6268dbSMiklos Szeredi if (outarg.nodeid != get_node_id(inode)) { 20607e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 2079e6268dbSMiklos Szeredi return 0; 2089e6268dbSMiklos Szeredi } 2098da5ff23SMiklos Szeredi spin_lock(&fc->lock); 2109e6268dbSMiklos Szeredi fi->nlookup++; 2118da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 2129e6268dbSMiklos Szeredi } 21307e77dcaSMiklos Szeredi kfree(forget); 2149e6268dbSMiklos Szeredi if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 215e5e5558eSMiklos Szeredi return 0; 216e5e5558eSMiklos Szeredi 2171fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2181fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2191fb69e78SMiklos Szeredi attr_version); 2201fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 221e5e5558eSMiklos Szeredi } 222e5e5558eSMiklos Szeredi return 1; 223e5e5558eSMiklos Szeredi } 224e5e5558eSMiklos Szeredi 2258bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid) 2262827d0b2SMiklos Szeredi { 2272827d0b2SMiklos Szeredi return !nodeid || nodeid == FUSE_ROOT_ID; 2282827d0b2SMiklos Szeredi } 2292827d0b2SMiklos Szeredi 2304269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 231e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 232e5e5558eSMiklos Szeredi }; 233e5e5558eSMiklos Szeredi 234a5bfffacSTimo Savola int fuse_valid_type(int m) 23539ee059aSMiklos Szeredi { 23639ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 23739ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 23839ee059aSMiklos Szeredi } 23939ee059aSMiklos Szeredi 240d2a85164SMiklos Szeredi /* 241d2a85164SMiklos Szeredi * Add a directory inode to a dentry, ensuring that no other dentry 242d2a85164SMiklos Szeredi * refers to this inode. Called with fc->inst_mutex. 243d2a85164SMiklos Szeredi */ 2440de6256dSMiklos Szeredi static struct dentry *fuse_d_add_directory(struct dentry *entry, 2450de6256dSMiklos Szeredi struct inode *inode) 246d2a85164SMiklos Szeredi { 247d2a85164SMiklos Szeredi struct dentry *alias = d_find_alias(inode); 2480de6256dSMiklos Szeredi if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) { 249d2a85164SMiklos Szeredi /* This tries to shrink the subtree below alias */ 250d2a85164SMiklos Szeredi fuse_invalidate_entry(alias); 251d2a85164SMiklos Szeredi dput(alias); 252b3d9b7a3SAl Viro if (!hlist_empty(&inode->i_dentry)) 2530de6256dSMiklos Szeredi return ERR_PTR(-EBUSY); 2540de6256dSMiklos Szeredi } else { 2550de6256dSMiklos Szeredi dput(alias); 256d2a85164SMiklos Szeredi } 2570de6256dSMiklos Szeredi return d_splice_alias(inode, entry); 258d2a85164SMiklos Szeredi } 259d2a85164SMiklos Szeredi 260c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, 261c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 262c180eebeSMiklos Szeredi { 263c180eebeSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 264c180eebeSMiklos Szeredi struct fuse_req *req; 26507e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 266c180eebeSMiklos Szeredi u64 attr_version; 267c180eebeSMiklos Szeredi int err; 268c180eebeSMiklos Szeredi 269c180eebeSMiklos Szeredi *inode = NULL; 270c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 271c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 272c180eebeSMiklos Szeredi goto out; 273c180eebeSMiklos Szeredi 274c180eebeSMiklos Szeredi req = fuse_get_req(fc); 275c180eebeSMiklos Szeredi err = PTR_ERR(req); 276c180eebeSMiklos Szeredi if (IS_ERR(req)) 277c180eebeSMiklos Szeredi goto out; 278c180eebeSMiklos Szeredi 27907e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 28007e77dcaSMiklos Szeredi err = -ENOMEM; 28107e77dcaSMiklos Szeredi if (!forget) { 282c180eebeSMiklos Szeredi fuse_put_request(fc, req); 283c180eebeSMiklos Szeredi goto out; 284c180eebeSMiklos Szeredi } 285c180eebeSMiklos Szeredi 286c180eebeSMiklos Szeredi attr_version = fuse_get_attr_version(fc); 287c180eebeSMiklos Szeredi 288c180eebeSMiklos Szeredi fuse_lookup_init(fc, req, nodeid, name, outarg); 289b93f858aSTejun Heo fuse_request_send(fc, req); 290c180eebeSMiklos Szeredi err = req->out.h.error; 291c180eebeSMiklos Szeredi fuse_put_request(fc, req); 292c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 293c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 294c180eebeSMiklos Szeredi goto out_put_forget; 295c180eebeSMiklos Szeredi 296c180eebeSMiklos Szeredi err = -EIO; 297c180eebeSMiklos Szeredi if (!outarg->nodeid) 298c180eebeSMiklos Szeredi goto out_put_forget; 299c180eebeSMiklos Szeredi if (!fuse_valid_type(outarg->attr.mode)) 300c180eebeSMiklos Szeredi goto out_put_forget; 301c180eebeSMiklos Szeredi 302c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 303c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 304c180eebeSMiklos Szeredi attr_version); 305c180eebeSMiklos Szeredi err = -ENOMEM; 306c180eebeSMiklos Szeredi if (!*inode) { 30707e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg->nodeid, 1); 308c180eebeSMiklos Szeredi goto out; 309c180eebeSMiklos Szeredi } 310c180eebeSMiklos Szeredi err = 0; 311c180eebeSMiklos Szeredi 312c180eebeSMiklos Szeredi out_put_forget: 31307e77dcaSMiklos Szeredi kfree(forget); 314c180eebeSMiklos Szeredi out: 315c180eebeSMiklos Szeredi return err; 316c180eebeSMiklos Szeredi } 317c180eebeSMiklos Szeredi 3180aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 31900cd8dd3SAl Viro unsigned int flags) 320e5e5558eSMiklos Szeredi { 321e5e5558eSMiklos Szeredi int err; 322e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 323c180eebeSMiklos Szeredi struct inode *inode; 3240de6256dSMiklos Szeredi struct dentry *newent; 325e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 326c180eebeSMiklos Szeredi bool outarg_valid = true; 327e5e5558eSMiklos Szeredi 328c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 329c180eebeSMiklos Szeredi &outarg, &inode); 330c180eebeSMiklos Szeredi if (err == -ENOENT) { 331c180eebeSMiklos Szeredi outarg_valid = false; 332c180eebeSMiklos Szeredi err = 0; 3332d51013eSMiklos Szeredi } 334c180eebeSMiklos Szeredi if (err) 335c180eebeSMiklos Szeredi goto out_err; 3362d51013eSMiklos Szeredi 337ee4e5271SMiklos Szeredi err = -EIO; 338c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 339c180eebeSMiklos Szeredi goto out_iput; 340e5e5558eSMiklos Szeredi 341d2a85164SMiklos Szeredi if (inode && S_ISDIR(inode->i_mode)) { 342d2a85164SMiklos Szeredi mutex_lock(&fc->inst_mutex); 3430de6256dSMiklos Szeredi newent = fuse_d_add_directory(entry, inode); 344d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 345c180eebeSMiklos Szeredi err = PTR_ERR(newent); 346c180eebeSMiklos Szeredi if (IS_ERR(newent)) 347c180eebeSMiklos Szeredi goto out_iput; 348c180eebeSMiklos Szeredi } else { 3490de6256dSMiklos Szeredi newent = d_splice_alias(inode, entry); 350c180eebeSMiklos Szeredi } 351d2a85164SMiklos Szeredi 3520de6256dSMiklos Szeredi entry = newent ? newent : entry; 353c180eebeSMiklos Szeredi if (outarg_valid) 3541fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 3558cbdf1e6SMiklos Szeredi else 3568cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 357c180eebeSMiklos Szeredi 3580de6256dSMiklos Szeredi return newent; 359c180eebeSMiklos Szeredi 360c180eebeSMiklos Szeredi out_iput: 361c180eebeSMiklos Szeredi iput(inode); 362c180eebeSMiklos Szeredi out_err: 363c180eebeSMiklos Szeredi return ERR_PTR(err); 364e5e5558eSMiklos Szeredi } 365e5e5558eSMiklos Szeredi 3666f9f1180SMiklos Szeredi /* 3676f9f1180SMiklos Szeredi * Atomic create+open operation 3686f9f1180SMiklos Szeredi * 3696f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 3706f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 3716f9f1180SMiklos Szeredi */ 372d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 37330d90494SAl Viro struct file *file, unsigned flags, 37447237687SAl Viro umode_t mode, int *opened) 375fd72faacSMiklos Szeredi { 376fd72faacSMiklos Szeredi int err; 377fd72faacSMiklos Szeredi struct inode *inode; 378fd72faacSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 379fd72faacSMiklos Szeredi struct fuse_req *req; 38007e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 381e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 382fd72faacSMiklos Szeredi struct fuse_open_out outopen; 383fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 384fd72faacSMiklos Szeredi struct fuse_file *ff; 385fd72faacSMiklos Szeredi 386*af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 387*af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 388*af109bcaSMiklos Szeredi 38907e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 390c8ccbe03SMiklos Szeredi err = -ENOMEM; 39107e77dcaSMiklos Szeredi if (!forget) 392c8ccbe03SMiklos Szeredi goto out_err; 39351eb01e7SMiklos Szeredi 394ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 39551eb01e7SMiklos Szeredi err = PTR_ERR(req); 396ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 39751eb01e7SMiklos Szeredi goto out_put_forget_req; 398fd72faacSMiklos Szeredi 399ce1d5a49SMiklos Szeredi err = -ENOMEM; 400acf99433STejun Heo ff = fuse_file_alloc(fc); 401fd72faacSMiklos Szeredi if (!ff) 402fd72faacSMiklos Szeredi goto out_put_request; 403fd72faacSMiklos Szeredi 404e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 405e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 406e0a43ddcSMiklos Szeredi 407fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 408fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4090e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 410fd72faacSMiklos Szeredi inarg.flags = flags; 411fd72faacSMiklos Szeredi inarg.mode = mode; 412e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 413fd72faacSMiklos Szeredi req->in.h.opcode = FUSE_CREATE; 414fd72faacSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 415fd72faacSMiklos Szeredi req->in.numargs = 2; 416e0a43ddcSMiklos Szeredi req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) : 417e0a43ddcSMiklos Szeredi sizeof(inarg); 418fd72faacSMiklos Szeredi req->in.args[0].value = &inarg; 419fd72faacSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 420fd72faacSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 421fd72faacSMiklos Szeredi req->out.numargs = 2; 4220e9663eeSMiklos Szeredi if (fc->minor < 9) 4230e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 4240e9663eeSMiklos Szeredi else 425fd72faacSMiklos Szeredi req->out.args[0].size = sizeof(outentry); 426fd72faacSMiklos Szeredi req->out.args[0].value = &outentry; 427fd72faacSMiklos Szeredi req->out.args[1].size = sizeof(outopen); 428fd72faacSMiklos Szeredi req->out.args[1].value = &outopen; 429b93f858aSTejun Heo fuse_request_send(fc, req); 430fd72faacSMiklos Szeredi err = req->out.h.error; 431c8ccbe03SMiklos Szeredi if (err) 432fd72faacSMiklos Szeredi goto out_free_ff; 433fd72faacSMiklos Szeredi 434fd72faacSMiklos Szeredi err = -EIO; 4352827d0b2SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 436fd72faacSMiklos Szeredi goto out_free_ff; 437fd72faacSMiklos Szeredi 43851eb01e7SMiklos Szeredi fuse_put_request(fc, req); 439c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 440c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 441c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 442fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 4431fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 444fd72faacSMiklos Szeredi if (!inode) { 445fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 4468b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 44707e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outentry.nodeid, 1); 448c8ccbe03SMiklos Szeredi err = -ENOMEM; 449c8ccbe03SMiklos Szeredi goto out_err; 450fd72faacSMiklos Szeredi } 45107e77dcaSMiklos Szeredi kfree(forget); 452fd72faacSMiklos Szeredi d_instantiate(entry, inode); 4531fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 4540952b2a4SMiklos Szeredi fuse_invalidate_attr(dir); 45530d90494SAl Viro err = finish_open(file, entry, generic_file_open, opened); 45630d90494SAl Viro if (err) { 4578b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 458c8ccbe03SMiklos Szeredi } else { 459c7b7143cSMiklos Szeredi file->private_data = fuse_file_get(ff); 460c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 461c8ccbe03SMiklos Szeredi } 462d9585277SAl Viro return err; 463fd72faacSMiklos Szeredi 464fd72faacSMiklos Szeredi out_free_ff: 465fd72faacSMiklos Szeredi fuse_file_free(ff); 466fd72faacSMiklos Szeredi out_put_request: 467fd72faacSMiklos Szeredi fuse_put_request(fc, req); 46851eb01e7SMiklos Szeredi out_put_forget_req: 46907e77dcaSMiklos Szeredi kfree(forget); 470c8ccbe03SMiklos Szeredi out_err: 471d9585277SAl Viro return err; 472c8ccbe03SMiklos Szeredi } 473c8ccbe03SMiklos Szeredi 474c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); 475d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 47630d90494SAl Viro struct file *file, unsigned flags, 47747237687SAl Viro umode_t mode, int *opened) 478c8ccbe03SMiklos Szeredi { 479c8ccbe03SMiklos Szeredi int err; 480c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 481c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 482c8ccbe03SMiklos Szeredi 483c8ccbe03SMiklos Szeredi if (d_unhashed(entry)) { 48400cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 485c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 486d9585277SAl Viro return PTR_ERR(res); 487c8ccbe03SMiklos Szeredi 488c8ccbe03SMiklos Szeredi if (res) 489c8ccbe03SMiklos Szeredi entry = res; 490c8ccbe03SMiklos Szeredi } 491c8ccbe03SMiklos Szeredi 492c8ccbe03SMiklos Szeredi if (!(flags & O_CREAT) || entry->d_inode) 493c8ccbe03SMiklos Szeredi goto no_open; 494c8ccbe03SMiklos Szeredi 495c8ccbe03SMiklos Szeredi /* Only creates */ 49647237687SAl Viro *opened |= FILE_CREATED; 497c8ccbe03SMiklos Szeredi 498c8ccbe03SMiklos Szeredi if (fc->no_create) 499c8ccbe03SMiklos Szeredi goto mknod; 500c8ccbe03SMiklos Szeredi 50130d90494SAl Viro err = fuse_create_open(dir, entry, file, flags, mode, opened); 502d9585277SAl Viro if (err == -ENOSYS) { 503c8ccbe03SMiklos Szeredi fc->no_create = 1; 504c8ccbe03SMiklos Szeredi goto mknod; 505c8ccbe03SMiklos Szeredi } 506c8ccbe03SMiklos Szeredi out_dput: 507c8ccbe03SMiklos Szeredi dput(res); 508d9585277SAl Viro return err; 509c8ccbe03SMiklos Szeredi 510c8ccbe03SMiklos Szeredi mknod: 511c8ccbe03SMiklos Szeredi err = fuse_mknod(dir, entry, mode, 0); 512d9585277SAl Viro if (err) 513c8ccbe03SMiklos Szeredi goto out_dput; 514c8ccbe03SMiklos Szeredi no_open: 515e45198a6SAl Viro return finish_no_open(file, res); 516fd72faacSMiklos Szeredi } 517fd72faacSMiklos Szeredi 5186f9f1180SMiklos Szeredi /* 5196f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 5206f9f1180SMiklos Szeredi */ 5219e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, 5229e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 523541af6a0SAl Viro umode_t mode) 5249e6268dbSMiklos Szeredi { 5259e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 5269e6268dbSMiklos Szeredi struct inode *inode; 5279e6268dbSMiklos Szeredi int err; 52807e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 5292d51013eSMiklos Szeredi 53007e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 53107e77dcaSMiklos Szeredi if (!forget) { 5322d51013eSMiklos Szeredi fuse_put_request(fc, req); 53307e77dcaSMiklos Szeredi return -ENOMEM; 5342d51013eSMiklos Szeredi } 5359e6268dbSMiklos Szeredi 5360e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 5379e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 5389e6268dbSMiklos Szeredi req->out.numargs = 1; 5390e9663eeSMiklos Szeredi if (fc->minor < 9) 5400e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 5410e9663eeSMiklos Szeredi else 5429e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 5439e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 544b93f858aSTejun Heo fuse_request_send(fc, req); 5459e6268dbSMiklos Szeredi err = req->out.h.error; 5469e6268dbSMiklos Szeredi fuse_put_request(fc, req); 5472d51013eSMiklos Szeredi if (err) 5482d51013eSMiklos Szeredi goto out_put_forget_req; 5492d51013eSMiklos Szeredi 55039ee059aSMiklos Szeredi err = -EIO; 55139ee059aSMiklos Szeredi if (invalid_nodeid(outarg.nodeid)) 5522d51013eSMiklos Szeredi goto out_put_forget_req; 55339ee059aSMiklos Szeredi 55439ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 5552d51013eSMiklos Szeredi goto out_put_forget_req; 55639ee059aSMiklos Szeredi 5579e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 5581fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 5599e6268dbSMiklos Szeredi if (!inode) { 56007e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 5619e6268dbSMiklos Szeredi return -ENOMEM; 5629e6268dbSMiklos Szeredi } 56307e77dcaSMiklos Szeredi kfree(forget); 5649e6268dbSMiklos Szeredi 565d2a85164SMiklos Szeredi if (S_ISDIR(inode->i_mode)) { 566d2a85164SMiklos Szeredi struct dentry *alias; 567d2a85164SMiklos Szeredi mutex_lock(&fc->inst_mutex); 568d2a85164SMiklos Szeredi alias = d_find_alias(inode); 569d2a85164SMiklos Szeredi if (alias) { 570d2a85164SMiklos Szeredi /* New directory must have moved since mkdir */ 571d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 572d2a85164SMiklos Szeredi dput(alias); 5739e6268dbSMiklos Szeredi iput(inode); 574d2a85164SMiklos Szeredi return -EBUSY; 5759e6268dbSMiklos Szeredi } 5769e6268dbSMiklos Szeredi d_instantiate(entry, inode); 577d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 578d2a85164SMiklos Szeredi } else 579d2a85164SMiklos Szeredi d_instantiate(entry, inode); 580d2a85164SMiklos Szeredi 5811fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 5829e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 5839e6268dbSMiklos Szeredi return 0; 58439ee059aSMiklos Szeredi 5852d51013eSMiklos Szeredi out_put_forget_req: 58607e77dcaSMiklos Szeredi kfree(forget); 58739ee059aSMiklos Szeredi return err; 5889e6268dbSMiklos Szeredi } 5899e6268dbSMiklos Szeredi 5901a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, 5919e6268dbSMiklos Szeredi dev_t rdev) 5929e6268dbSMiklos Szeredi { 5939e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 5949e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 595ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 596ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 597ce1d5a49SMiklos Szeredi return PTR_ERR(req); 5989e6268dbSMiklos Szeredi 599e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 600e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 601e0a43ddcSMiklos Szeredi 6029e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6039e6268dbSMiklos Szeredi inarg.mode = mode; 6049e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 605e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6069e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKNOD; 6079e6268dbSMiklos Szeredi req->in.numargs = 2; 608e0a43ddcSMiklos Szeredi req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE : 609e0a43ddcSMiklos Szeredi sizeof(inarg); 6109e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 6119e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 6129e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 6139e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, mode); 6149e6268dbSMiklos Szeredi } 6159e6268dbSMiklos Szeredi 6164acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, 617ebfc3b49SAl Viro bool excl) 6189e6268dbSMiklos Szeredi { 6199e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 6209e6268dbSMiklos Szeredi } 6219e6268dbSMiklos Szeredi 62218bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) 6239e6268dbSMiklos Szeredi { 6249e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 6259e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 626ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 627ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 628ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6299e6268dbSMiklos Szeredi 630e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 631e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 632e0a43ddcSMiklos Szeredi 6339e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6349e6268dbSMiklos Szeredi inarg.mode = mode; 635e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6369e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKDIR; 6379e6268dbSMiklos Szeredi req->in.numargs = 2; 6389e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 6399e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 6409e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 6419e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 6429e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFDIR); 6439e6268dbSMiklos Szeredi } 6449e6268dbSMiklos Szeredi 6459e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 6469e6268dbSMiklos Szeredi const char *link) 6479e6268dbSMiklos Szeredi { 6489e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6499e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 650ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 651ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 652ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6539e6268dbSMiklos Szeredi 6549e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SYMLINK; 6559e6268dbSMiklos Szeredi req->in.numargs = 2; 6569e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 6579e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 6589e6268dbSMiklos Szeredi req->in.args[1].size = len; 6599e6268dbSMiklos Szeredi req->in.args[1].value = link; 6609e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFLNK); 6619e6268dbSMiklos Szeredi } 6629e6268dbSMiklos Szeredi 6639e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 6649e6268dbSMiklos Szeredi { 6659e6268dbSMiklos Szeredi int err; 6669e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 667ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 668ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 669ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6709e6268dbSMiklos Szeredi 6719e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_UNLINK; 6729e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 6739e6268dbSMiklos Szeredi req->in.numargs = 1; 6749e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 6759e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 676b93f858aSTejun Heo fuse_request_send(fc, req); 6779e6268dbSMiklos Szeredi err = req->out.h.error; 6789e6268dbSMiklos Szeredi fuse_put_request(fc, req); 6799e6268dbSMiklos Szeredi if (!err) { 6809e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 681ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 6829e6268dbSMiklos Szeredi 683ac45d613SMiklos Szeredi spin_lock(&fc->lock); 684ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 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); 6909e6268dbSMiklos Szeredi } else if (err == -EINTR) 6919e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 6929e6268dbSMiklos Szeredi return err; 6939e6268dbSMiklos Szeredi } 6949e6268dbSMiklos Szeredi 6959e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 6969e6268dbSMiklos Szeredi { 6979e6268dbSMiklos Szeredi int err; 6989e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 699ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 700ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 701ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7029e6268dbSMiklos Szeredi 7039e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RMDIR; 7049e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 7059e6268dbSMiklos Szeredi req->in.numargs = 1; 7069e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 7079e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 708b93f858aSTejun Heo fuse_request_send(fc, req); 7099e6268dbSMiklos Szeredi err = req->out.h.error; 7109e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7119e6268dbSMiklos Szeredi if (!err) { 712ce71ec36SDave Hansen clear_nlink(entry->d_inode); 7139e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 7148cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 7159e6268dbSMiklos Szeredi } else if (err == -EINTR) 7169e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7179e6268dbSMiklos Szeredi return err; 7189e6268dbSMiklos Szeredi } 7199e6268dbSMiklos Szeredi 7209e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent, 7219e6268dbSMiklos Szeredi struct inode *newdir, struct dentry *newent) 7229e6268dbSMiklos Szeredi { 7239e6268dbSMiklos Szeredi int err; 7249e6268dbSMiklos Szeredi struct fuse_rename_in inarg; 7259e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 726ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 727e4eaac06SSage Weil 728ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 729ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7309e6268dbSMiklos Szeredi 7319e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7329e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 7339e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RENAME; 7349e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(olddir); 7359e6268dbSMiklos Szeredi req->in.numargs = 3; 7369e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 7379e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 7389e6268dbSMiklos Szeredi req->in.args[1].size = oldent->d_name.len + 1; 7399e6268dbSMiklos Szeredi req->in.args[1].value = oldent->d_name.name; 7409e6268dbSMiklos Szeredi req->in.args[2].size = newent->d_name.len + 1; 7419e6268dbSMiklos Szeredi req->in.args[2].value = newent->d_name.name; 742b93f858aSTejun Heo fuse_request_send(fc, req); 7439e6268dbSMiklos Szeredi err = req->out.h.error; 7449e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7459e6268dbSMiklos Szeredi if (!err) { 74608b63307SMiklos Szeredi /* ctime changes */ 74708b63307SMiklos Szeredi fuse_invalidate_attr(oldent->d_inode); 74808b63307SMiklos 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 */ 7545219f346SMiklos Szeredi if (newent->d_inode) { 7555219f346SMiklos Szeredi fuse_invalidate_attr(newent->d_inode); 7568cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 7575219f346SMiklos Szeredi } 7589e6268dbSMiklos Szeredi } else if (err == -EINTR) { 7599e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 7609e6268dbSMiklos Szeredi rename actually took place. If the invalidation 7619e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 7629e6268dbSMiklos Szeredi directory), then there can be inconsistency between 7639e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 7649e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 7659e6268dbSMiklos Szeredi if (newent->d_inode) 7669e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 7679e6268dbSMiklos Szeredi } 7689e6268dbSMiklos Szeredi 7699e6268dbSMiklos Szeredi return err; 7709e6268dbSMiklos Szeredi } 7719e6268dbSMiklos Szeredi 7729e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 7739e6268dbSMiklos Szeredi struct dentry *newent) 7749e6268dbSMiklos Szeredi { 7759e6268dbSMiklos Szeredi int err; 7769e6268dbSMiklos Szeredi struct fuse_link_in inarg; 7779e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 7789e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 779ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 780ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 781ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7829e6268dbSMiklos Szeredi 7839e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7849e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 7859e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_LINK; 7869e6268dbSMiklos Szeredi req->in.numargs = 2; 7879e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 7889e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 7899e6268dbSMiklos Szeredi req->in.args[1].size = newent->d_name.len + 1; 7909e6268dbSMiklos Szeredi req->in.args[1].value = newent->d_name.name; 7919e6268dbSMiklos Szeredi err = create_new_entry(fc, req, newdir, newent, inode->i_mode); 7929e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 7939e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 7949e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 7959e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 7969e6268dbSMiklos Szeredi etc.) 7979e6268dbSMiklos Szeredi */ 798ac45d613SMiklos Szeredi if (!err) { 799ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 800ac45d613SMiklos Szeredi 801ac45d613SMiklos Szeredi spin_lock(&fc->lock); 802ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 803ac45d613SMiklos Szeredi inc_nlink(inode); 804ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 8059e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 806ac45d613SMiklos Szeredi } else if (err == -EINTR) { 807ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 808ac45d613SMiklos Szeredi } 8099e6268dbSMiklos Szeredi return err; 8109e6268dbSMiklos Szeredi } 8119e6268dbSMiklos Szeredi 8121fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 8131fb69e78SMiklos Szeredi struct kstat *stat) 8141fb69e78SMiklos Szeredi { 815203627bbSMiklos Szeredi unsigned int blkbits; 816203627bbSMiklos Szeredi 8171fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 8181fb69e78SMiklos Szeredi stat->ino = attr->ino; 8191fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 8201fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 8211fb69e78SMiklos Szeredi stat->uid = attr->uid; 8221fb69e78SMiklos Szeredi stat->gid = attr->gid; 8231fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 8241fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 8251fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 8261fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 8271fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 8281fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 8291fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 8301fb69e78SMiklos Szeredi stat->size = attr->size; 8311fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 832203627bbSMiklos Szeredi 833203627bbSMiklos Szeredi if (attr->blksize != 0) 834203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 835203627bbSMiklos Szeredi else 836203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 837203627bbSMiklos Szeredi 838203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 8391fb69e78SMiklos Szeredi } 8401fb69e78SMiklos Szeredi 841c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 842c79e322fSMiklos Szeredi struct file *file) 843e5e5558eSMiklos Szeredi { 844e5e5558eSMiklos Szeredi int err; 845c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 846c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 847e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 8481fb69e78SMiklos Szeredi struct fuse_req *req; 8491fb69e78SMiklos Szeredi u64 attr_version; 8501fb69e78SMiklos Szeredi 8511fb69e78SMiklos Szeredi req = fuse_get_req(fc); 852ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 853ce1d5a49SMiklos Szeredi return PTR_ERR(req); 854e5e5558eSMiklos Szeredi 8557dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 8561fb69e78SMiklos Szeredi 857c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8580e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 859c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 860c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 861c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 862c79e322fSMiklos Szeredi 863c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 864c79e322fSMiklos Szeredi inarg.fh = ff->fh; 865c79e322fSMiklos Szeredi } 866e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_GETATTR; 867e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 868c79e322fSMiklos Szeredi req->in.numargs = 1; 869c79e322fSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 870c79e322fSMiklos Szeredi req->in.args[0].value = &inarg; 871e5e5558eSMiklos Szeredi req->out.numargs = 1; 8720e9663eeSMiklos Szeredi if (fc->minor < 9) 8730e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 8740e9663eeSMiklos Szeredi else 875c79e322fSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 876c79e322fSMiklos Szeredi req->out.args[0].value = &outarg; 877b93f858aSTejun Heo fuse_request_send(fc, req); 878e5e5558eSMiklos Szeredi err = req->out.h.error; 879e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 880e5e5558eSMiklos Szeredi if (!err) { 881c79e322fSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 882e5e5558eSMiklos Szeredi make_bad_inode(inode); 883e5e5558eSMiklos Szeredi err = -EIO; 884e5e5558eSMiklos Szeredi } else { 885c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 886c79e322fSMiklos Szeredi attr_timeout(&outarg), 8871fb69e78SMiklos Szeredi attr_version); 8881fb69e78SMiklos Szeredi if (stat) 889c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 890e5e5558eSMiklos Szeredi } 891e5e5558eSMiklos Szeredi } 892e5e5558eSMiklos Szeredi return err; 893e5e5558eSMiklos Szeredi } 894e5e5558eSMiklos Szeredi 895bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat, 896bcb4be80SMiklos Szeredi struct file *file, bool *refreshed) 897bcb4be80SMiklos Szeredi { 898bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 899bcb4be80SMiklos Szeredi int err; 900bcb4be80SMiklos Szeredi bool r; 901bcb4be80SMiklos Szeredi 902bcb4be80SMiklos Szeredi if (fi->i_time < get_jiffies_64()) { 903bcb4be80SMiklos Szeredi r = true; 904bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 905bcb4be80SMiklos Szeredi } else { 906bcb4be80SMiklos Szeredi r = false; 907bcb4be80SMiklos Szeredi err = 0; 908bcb4be80SMiklos Szeredi if (stat) { 909bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 910bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 91145c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 912bcb4be80SMiklos Szeredi } 913bcb4be80SMiklos Szeredi } 914bcb4be80SMiklos Szeredi 915bcb4be80SMiklos Szeredi if (refreshed != NULL) 916bcb4be80SMiklos Szeredi *refreshed = r; 917bcb4be80SMiklos Szeredi 918bcb4be80SMiklos Szeredi return err; 919bcb4be80SMiklos Szeredi } 920bcb4be80SMiklos Szeredi 9213b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 922451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 9233b463ae0SJohn Muir { 9243b463ae0SJohn Muir int err = -ENOTDIR; 9253b463ae0SJohn Muir struct inode *parent; 9263b463ae0SJohn Muir struct dentry *dir; 9273b463ae0SJohn Muir struct dentry *entry; 9283b463ae0SJohn Muir 9293b463ae0SJohn Muir parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); 9303b463ae0SJohn Muir if (!parent) 9313b463ae0SJohn Muir return -ENOENT; 9323b463ae0SJohn Muir 9333b463ae0SJohn Muir mutex_lock(&parent->i_mutex); 9343b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 9353b463ae0SJohn Muir goto unlock; 9363b463ae0SJohn Muir 9373b463ae0SJohn Muir err = -ENOENT; 9383b463ae0SJohn Muir dir = d_find_alias(parent); 9393b463ae0SJohn Muir if (!dir) 9403b463ae0SJohn Muir goto unlock; 9413b463ae0SJohn Muir 9423b463ae0SJohn Muir entry = d_lookup(dir, name); 9433b463ae0SJohn Muir dput(dir); 9443b463ae0SJohn Muir if (!entry) 9453b463ae0SJohn Muir goto unlock; 9463b463ae0SJohn Muir 9473b463ae0SJohn Muir fuse_invalidate_attr(parent); 9483b463ae0SJohn Muir fuse_invalidate_entry(entry); 949451d0f59SJohn Muir 950451d0f59SJohn Muir if (child_nodeid != 0 && entry->d_inode) { 951451d0f59SJohn Muir mutex_lock(&entry->d_inode->i_mutex); 952451d0f59SJohn Muir if (get_node_id(entry->d_inode) != child_nodeid) { 953451d0f59SJohn Muir err = -ENOENT; 954451d0f59SJohn Muir goto badentry; 955451d0f59SJohn Muir } 956451d0f59SJohn Muir if (d_mountpoint(entry)) { 957451d0f59SJohn Muir err = -EBUSY; 958451d0f59SJohn Muir goto badentry; 959451d0f59SJohn Muir } 960451d0f59SJohn Muir if (S_ISDIR(entry->d_inode->i_mode)) { 961451d0f59SJohn Muir shrink_dcache_parent(entry); 962451d0f59SJohn Muir if (!simple_empty(entry)) { 963451d0f59SJohn Muir err = -ENOTEMPTY; 964451d0f59SJohn Muir goto badentry; 965451d0f59SJohn Muir } 966451d0f59SJohn Muir entry->d_inode->i_flags |= S_DEAD; 967451d0f59SJohn Muir } 968451d0f59SJohn Muir dont_mount(entry); 969451d0f59SJohn Muir clear_nlink(entry->d_inode); 9703b463ae0SJohn Muir err = 0; 971451d0f59SJohn Muir badentry: 972451d0f59SJohn Muir mutex_unlock(&entry->d_inode->i_mutex); 973451d0f59SJohn Muir if (!err) 974451d0f59SJohn Muir d_delete(entry); 975451d0f59SJohn Muir } else { 976451d0f59SJohn Muir err = 0; 977451d0f59SJohn Muir } 978451d0f59SJohn Muir dput(entry); 9793b463ae0SJohn Muir 9803b463ae0SJohn Muir unlock: 9813b463ae0SJohn Muir mutex_unlock(&parent->i_mutex); 9823b463ae0SJohn Muir iput(parent); 9833b463ae0SJohn Muir return err; 9843b463ae0SJohn Muir } 9853b463ae0SJohn Muir 98687729a55SMiklos Szeredi /* 98787729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 98887729a55SMiklos Szeredi * daemon ptrace-like capabilities over the requester process. This 98987729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 99087729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 99187729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 99287729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 99387729a55SMiklos Szeredi * DoS against the requester. 99487729a55SMiklos Szeredi * 99587729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 99687729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 99787729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 99887729a55SMiklos Szeredi */ 999e57ac683SMiklos Szeredi int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) 100087729a55SMiklos Szeredi { 1001c69e8d9cSDavid Howells const struct cred *cred; 1002c69e8d9cSDavid Howells int ret; 1003c69e8d9cSDavid Howells 100487729a55SMiklos Szeredi if (fc->flags & FUSE_ALLOW_OTHER) 100587729a55SMiklos Szeredi return 1; 100687729a55SMiklos Szeredi 1007c69e8d9cSDavid Howells rcu_read_lock(); 1008c69e8d9cSDavid Howells ret = 0; 1009c69e8d9cSDavid Howells cred = __task_cred(task); 1010c69e8d9cSDavid Howells if (cred->euid == fc->user_id && 1011c69e8d9cSDavid Howells cred->suid == fc->user_id && 1012c69e8d9cSDavid Howells cred->uid == fc->user_id && 1013c69e8d9cSDavid Howells cred->egid == fc->group_id && 1014c69e8d9cSDavid Howells cred->sgid == fc->group_id && 1015c69e8d9cSDavid Howells cred->gid == fc->group_id) 1016c69e8d9cSDavid Howells ret = 1; 1017c69e8d9cSDavid Howells rcu_read_unlock(); 101887729a55SMiklos Szeredi 1019c69e8d9cSDavid Howells return ret; 102087729a55SMiklos Szeredi } 102187729a55SMiklos Szeredi 102231d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 102331d40d74SMiklos Szeredi { 102431d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 102531d40d74SMiklos Szeredi struct fuse_req *req; 102631d40d74SMiklos Szeredi struct fuse_access_in inarg; 102731d40d74SMiklos Szeredi int err; 102831d40d74SMiklos Szeredi 102931d40d74SMiklos Szeredi if (fc->no_access) 103031d40d74SMiklos Szeredi return 0; 103131d40d74SMiklos Szeredi 1032ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1033ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1034ce1d5a49SMiklos Szeredi return PTR_ERR(req); 103531d40d74SMiklos Szeredi 103631d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1037e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 103831d40d74SMiklos Szeredi req->in.h.opcode = FUSE_ACCESS; 103931d40d74SMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 104031d40d74SMiklos Szeredi req->in.numargs = 1; 104131d40d74SMiklos Szeredi req->in.args[0].size = sizeof(inarg); 104231d40d74SMiklos Szeredi req->in.args[0].value = &inarg; 1043b93f858aSTejun Heo fuse_request_send(fc, req); 104431d40d74SMiklos Szeredi err = req->out.h.error; 104531d40d74SMiklos Szeredi fuse_put_request(fc, req); 104631d40d74SMiklos Szeredi if (err == -ENOSYS) { 104731d40d74SMiklos Szeredi fc->no_access = 1; 104831d40d74SMiklos Szeredi err = 0; 104931d40d74SMiklos Szeredi } 105031d40d74SMiklos Szeredi return err; 105131d40d74SMiklos Szeredi } 105231d40d74SMiklos Szeredi 105310556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 105419690ddbSMiklos Szeredi { 105510556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 105619690ddbSMiklos Szeredi return -ECHILD; 105719690ddbSMiklos Szeredi 105819690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 105919690ddbSMiklos Szeredi } 106019690ddbSMiklos Szeredi 10616f9f1180SMiklos Szeredi /* 10626f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 10636f9f1180SMiklos Szeredi * 10646f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 10656f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 10666f9f1180SMiklos Szeredi * modell. 10676f9f1180SMiklos Szeredi * 10686f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 10696f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 10706f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 10716f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 10726f9f1180SMiklos Szeredi * locally based on file mode. 10736f9f1180SMiklos Szeredi */ 107410556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask) 1075e5e5558eSMiklos Szeredi { 1076e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1077244f6385SMiklos Szeredi bool refreshed = false; 1078244f6385SMiklos Szeredi int err = 0; 1079e5e5558eSMiklos Szeredi 108087729a55SMiklos Szeredi if (!fuse_allow_task(fc, current)) 1081e5e5558eSMiklos Szeredi return -EACCES; 1082244f6385SMiklos Szeredi 1083244f6385SMiklos Szeredi /* 1084e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1085244f6385SMiklos Szeredi */ 1086e8e96157SMiklos Szeredi if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || 1087e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 108819690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 108919690ddbSMiklos Szeredi 109019690ddbSMiklos Szeredi if (fi->i_time < get_jiffies_64()) { 109119690ddbSMiklos Szeredi refreshed = true; 109219690ddbSMiklos Szeredi 109310556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1094244f6385SMiklos Szeredi if (err) 1095244f6385SMiklos Szeredi return err; 10961fb69e78SMiklos Szeredi } 109719690ddbSMiklos Szeredi } 1098244f6385SMiklos Szeredi 1099244f6385SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 11002830ba7fSAl Viro err = generic_permission(inode, mask); 11011e9a4ed9SMiklos Szeredi 11021e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 11031e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 11041e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1105244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 110610556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 11071e9a4ed9SMiklos Szeredi if (!err) 11082830ba7fSAl Viro err = generic_permission(inode, mask); 11091e9a4ed9SMiklos Szeredi } 11101e9a4ed9SMiklos Szeredi 11116f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 11126f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 11136f9f1180SMiklos Szeredi noticed immediately, only after the attribute 11146f9f1180SMiklos Szeredi timeout has expired */ 11159cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 111610556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 111719690ddbSMiklos Szeredi return -ECHILD; 111819690ddbSMiklos Szeredi 1119e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1120e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1121e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1122e8e96157SMiklos Szeredi if (refreshed) 1123e5e5558eSMiklos Szeredi return -EACCES; 112431d40d74SMiklos Szeredi 112510556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1126e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1127e8e96157SMiklos Szeredi return -EACCES; 1128e8e96157SMiklos Szeredi } 1129e5e5558eSMiklos Szeredi } 1130244f6385SMiklos Szeredi return err; 1131e5e5558eSMiklos Szeredi } 1132e5e5558eSMiklos Szeredi 1133e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file, 1134e5e5558eSMiklos Szeredi void *dstbuf, filldir_t filldir) 1135e5e5558eSMiklos Szeredi { 1136e5e5558eSMiklos Szeredi while (nbytes >= FUSE_NAME_OFFSET) { 1137e5e5558eSMiklos Szeredi struct fuse_dirent *dirent = (struct fuse_dirent *) buf; 1138e5e5558eSMiklos Szeredi size_t reclen = FUSE_DIRENT_SIZE(dirent); 1139e5e5558eSMiklos Szeredi int over; 1140e5e5558eSMiklos Szeredi if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 1141e5e5558eSMiklos Szeredi return -EIO; 1142e5e5558eSMiklos Szeredi if (reclen > nbytes) 1143e5e5558eSMiklos Szeredi break; 1144e5e5558eSMiklos Szeredi 1145e5e5558eSMiklos Szeredi over = filldir(dstbuf, dirent->name, dirent->namelen, 1146e5e5558eSMiklos Szeredi file->f_pos, dirent->ino, dirent->type); 1147e5e5558eSMiklos Szeredi if (over) 1148e5e5558eSMiklos Szeredi break; 1149e5e5558eSMiklos Szeredi 1150e5e5558eSMiklos Szeredi buf += reclen; 1151e5e5558eSMiklos Szeredi nbytes -= reclen; 1152e5e5558eSMiklos Szeredi file->f_pos = dirent->off; 1153e5e5558eSMiklos Szeredi } 1154e5e5558eSMiklos Szeredi 1155e5e5558eSMiklos Szeredi return 0; 1156e5e5558eSMiklos Szeredi } 1157e5e5558eSMiklos Szeredi 1158e5e5558eSMiklos Szeredi static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) 1159e5e5558eSMiklos Szeredi { 116004730fefSMiklos Szeredi int err; 116104730fefSMiklos Szeredi size_t nbytes; 116204730fefSMiklos Szeredi struct page *page; 11637706a9d6SJosef Sipek struct inode *inode = file->f_path.dentry->d_inode; 116404730fefSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1165248d86e8SMiklos Szeredi struct fuse_req *req; 1166248d86e8SMiklos Szeredi 1167248d86e8SMiklos Szeredi if (is_bad_inode(inode)) 1168248d86e8SMiklos Szeredi return -EIO; 1169248d86e8SMiklos Szeredi 1170ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1171ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1172ce1d5a49SMiklos Szeredi return PTR_ERR(req); 1173e5e5558eSMiklos Szeredi 117404730fefSMiklos Szeredi page = alloc_page(GFP_KERNEL); 117504730fefSMiklos Szeredi if (!page) { 117604730fefSMiklos Szeredi fuse_put_request(fc, req); 1177e5e5558eSMiklos Szeredi return -ENOMEM; 117804730fefSMiklos Szeredi } 1179f4975c67SMiklos Szeredi req->out.argpages = 1; 118004730fefSMiklos Szeredi req->num_pages = 1; 118104730fefSMiklos Szeredi req->pages[0] = page; 11822106cb18SMiklos Szeredi fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR); 1183b93f858aSTejun Heo fuse_request_send(fc, req); 1184361b1eb5SMiklos Szeredi nbytes = req->out.args[0].size; 118504730fefSMiklos Szeredi err = req->out.h.error; 118604730fefSMiklos Szeredi fuse_put_request(fc, req); 118704730fefSMiklos Szeredi if (!err) 118804730fefSMiklos Szeredi err = parse_dirfile(page_address(page), nbytes, file, dstbuf, 118904730fefSMiklos Szeredi filldir); 1190e5e5558eSMiklos Szeredi 119104730fefSMiklos Szeredi __free_page(page); 1192b36c31baSMiklos Szeredi fuse_invalidate_attr(inode); /* atime changed */ 119304730fefSMiklos Szeredi return err; 1194e5e5558eSMiklos Szeredi } 1195e5e5558eSMiklos Szeredi 1196e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry) 1197e5e5558eSMiklos Szeredi { 1198e5e5558eSMiklos Szeredi struct inode *inode = dentry->d_inode; 1199e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1200ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 1201e5e5558eSMiklos Szeredi char *link; 1202e5e5558eSMiklos Szeredi 1203ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1204e231c2eeSDavid Howells return ERR_CAST(req); 1205e5e5558eSMiklos Szeredi 1206e5e5558eSMiklos Szeredi link = (char *) __get_free_page(GFP_KERNEL); 1207e5e5558eSMiklos Szeredi if (!link) { 1208e5e5558eSMiklos Szeredi link = ERR_PTR(-ENOMEM); 1209e5e5558eSMiklos Szeredi goto out; 1210e5e5558eSMiklos Szeredi } 1211e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_READLINK; 1212e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 1213e5e5558eSMiklos Szeredi req->out.argvar = 1; 1214e5e5558eSMiklos Szeredi req->out.numargs = 1; 1215e5e5558eSMiklos Szeredi req->out.args[0].size = PAGE_SIZE - 1; 1216e5e5558eSMiklos Szeredi req->out.args[0].value = link; 1217b93f858aSTejun Heo fuse_request_send(fc, req); 1218e5e5558eSMiklos Szeredi if (req->out.h.error) { 1219e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1220e5e5558eSMiklos Szeredi link = ERR_PTR(req->out.h.error); 1221e5e5558eSMiklos Szeredi } else 1222e5e5558eSMiklos Szeredi link[req->out.args[0].size] = '\0'; 1223e5e5558eSMiklos Szeredi out: 1224e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 1225b36c31baSMiklos Szeredi fuse_invalidate_attr(inode); /* atime changed */ 1226e5e5558eSMiklos Szeredi return link; 1227e5e5558eSMiklos Szeredi } 1228e5e5558eSMiklos Szeredi 1229e5e5558eSMiklos Szeredi static void free_link(char *link) 1230e5e5558eSMiklos Szeredi { 1231e5e5558eSMiklos Szeredi if (!IS_ERR(link)) 1232e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1233e5e5558eSMiklos Szeredi } 1234e5e5558eSMiklos Szeredi 1235e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd) 1236e5e5558eSMiklos Szeredi { 1237e5e5558eSMiklos Szeredi nd_set_link(nd, read_link(dentry)); 1238e5e5558eSMiklos Szeredi return NULL; 1239e5e5558eSMiklos Szeredi } 1240e5e5558eSMiklos Szeredi 1241e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c) 1242e5e5558eSMiklos Szeredi { 1243e5e5558eSMiklos Szeredi free_link(nd_get_link(nd)); 1244e5e5558eSMiklos Szeredi } 1245e5e5558eSMiklos Szeredi 1246e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1247e5e5558eSMiklos Szeredi { 124891fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1249e5e5558eSMiklos Szeredi } 1250e5e5558eSMiklos Szeredi 1251e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1252e5e5558eSMiklos Szeredi { 12538b0797a4SMiklos Szeredi fuse_release_common(file, FUSE_RELEASEDIR); 12548b0797a4SMiklos Szeredi 12558b0797a4SMiklos Szeredi return 0; 1256e5e5558eSMiklos Szeredi } 1257e5e5558eSMiklos Szeredi 125802c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 125902c24a82SJosef Bacik int datasync) 126082547981SMiklos Szeredi { 126102c24a82SJosef Bacik return fuse_fsync_common(file, start, end, datasync, 1); 126282547981SMiklos Szeredi } 126382547981SMiklos Szeredi 1264b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1265b18da0c5SMiklos Szeredi unsigned long arg) 1266b18da0c5SMiklos Szeredi { 1267b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1268b18da0c5SMiklos Szeredi 1269b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1270b18da0c5SMiklos Szeredi if (fc->minor < 18) 1271b18da0c5SMiklos Szeredi return -ENOTTY; 1272b18da0c5SMiklos Szeredi 1273b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1274b18da0c5SMiklos Szeredi } 1275b18da0c5SMiklos Szeredi 1276b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1277b18da0c5SMiklos Szeredi unsigned long arg) 1278b18da0c5SMiklos Szeredi { 1279b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1280b18da0c5SMiklos Szeredi 1281b18da0c5SMiklos Szeredi if (fc->minor < 18) 1282b18da0c5SMiklos Szeredi return -ENOTTY; 1283b18da0c5SMiklos Szeredi 1284b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1285b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1286b18da0c5SMiklos Szeredi } 1287b18da0c5SMiklos Szeredi 128817637cbaSMiklos Szeredi static bool update_mtime(unsigned ivalid) 128917637cbaSMiklos Szeredi { 129017637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 129117637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 129217637cbaSMiklos Szeredi return true; 129317637cbaSMiklos Szeredi 129417637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 129517637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 129617637cbaSMiklos Szeredi return false; 129717637cbaSMiklos Szeredi 129817637cbaSMiklos Szeredi /* In all other cases update */ 129917637cbaSMiklos Szeredi return true; 130017637cbaSMiklos Szeredi } 130117637cbaSMiklos Szeredi 1302befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) 13039e6268dbSMiklos Szeredi { 13049e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 13059e6268dbSMiklos Szeredi 13069e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1307befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 13089e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 1309befc649cSMiklos Szeredi arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid; 13109e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 1311befc649cSMiklos Szeredi arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid; 13129e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1313befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 131417637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 131517637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1316befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 131717637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 131817637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 131917637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 132017637cbaSMiklos Szeredi } 132117637cbaSMiklos Szeredi if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) { 132217637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1323befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 132417637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 132517637cbaSMiklos Szeredi if (!(ivalid & ATTR_MTIME_SET)) 132617637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 13279e6268dbSMiklos Szeredi } 13289e6268dbSMiklos Szeredi } 13299e6268dbSMiklos Szeredi 13306f9f1180SMiklos Szeredi /* 13313be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 13323be5a52bSMiklos Szeredi * 13333be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 13343be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 13353be5a52bSMiklos Szeredi */ 13363be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 13373be5a52bSMiklos Szeredi { 13383be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 13393be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 13403be5a52bSMiklos Szeredi 13413be5a52bSMiklos Szeredi BUG_ON(!mutex_is_locked(&inode->i_mutex)); 13423be5a52bSMiklos Szeredi 13433be5a52bSMiklos Szeredi spin_lock(&fc->lock); 13443be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 13453be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 13463be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 13473be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 13483be5a52bSMiklos Szeredi } 13493be5a52bSMiklos Szeredi 13503be5a52bSMiklos Szeredi /* 13513be5a52bSMiklos Szeredi * Allow writepages on inode 13523be5a52bSMiklos Szeredi * 13533be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 13543be5a52bSMiklos Szeredi * writepages. 13553be5a52bSMiklos Szeredi */ 13563be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 13573be5a52bSMiklos Szeredi { 13583be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 13593be5a52bSMiklos Szeredi 13603be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 13613be5a52bSMiklos Szeredi fi->writectr = 0; 13623be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 13633be5a52bSMiklos Szeredi } 13643be5a52bSMiklos Szeredi 13653be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 13663be5a52bSMiklos Szeredi { 13673be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 13683be5a52bSMiklos Szeredi 13693be5a52bSMiklos Szeredi spin_lock(&fc->lock); 13703be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 13713be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 13723be5a52bSMiklos Szeredi } 13733be5a52bSMiklos Szeredi 13743be5a52bSMiklos Szeredi /* 13756f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 13766f9f1180SMiklos Szeredi * 13776f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 13786f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 13799ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 13809ffbb916SMiklos Szeredi * and the actual truncation by hand. 13816f9f1180SMiklos Szeredi */ 138249d4914fSMiklos Szeredi static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, 138349d4914fSMiklos Szeredi struct file *file) 13849e6268dbSMiklos Szeredi { 13859e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 13869e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 13879e6268dbSMiklos Szeredi struct fuse_req *req; 13889e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 13899e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 13903be5a52bSMiklos Szeredi bool is_truncate = false; 13913be5a52bSMiklos Szeredi loff_t oldsize; 13929e6268dbSMiklos Szeredi int err; 13939e6268dbSMiklos Szeredi 1394e57ac683SMiklos Szeredi if (!fuse_allow_task(fc, current)) 1395e57ac683SMiklos Szeredi return -EACCES; 1396e57ac683SMiklos Szeredi 1397db78b877SChristoph Hellwig if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 1398db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1399db78b877SChristoph Hellwig 14001e9a4ed9SMiklos Szeredi err = inode_change_ok(inode, attr); 14011e9a4ed9SMiklos Szeredi if (err) 14021e9a4ed9SMiklos Szeredi return err; 14031e9a4ed9SMiklos Szeredi 14048d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 14058d56adddSMiklos Szeredi if (fc->atomic_o_trunc) 14066ff958edSMiklos Szeredi return 0; 14078d56adddSMiklos Szeredi file = NULL; 14088d56adddSMiklos Szeredi } 14096ff958edSMiklos Szeredi 14102c27c65eSChristoph Hellwig if (attr->ia_valid & ATTR_SIZE) 14113be5a52bSMiklos Szeredi is_truncate = true; 14129e6268dbSMiklos Szeredi 1413ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1414ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1415ce1d5a49SMiklos Szeredi return PTR_ERR(req); 14169e6268dbSMiklos Szeredi 14173be5a52bSMiklos Szeredi if (is_truncate) 14183be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 14193be5a52bSMiklos Szeredi 14209e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 14210e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 1422befc649cSMiklos Szeredi iattr_to_fattr(attr, &inarg); 142349d4914fSMiklos Szeredi if (file) { 142449d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 142549d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 142649d4914fSMiklos Szeredi inarg.fh = ff->fh; 142749d4914fSMiklos Szeredi } 1428f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1429f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1430f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1431f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 1432f3332114SMiklos Szeredi } 14339e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SETATTR; 14349e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 14359e6268dbSMiklos Szeredi req->in.numargs = 1; 14369e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 14379e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 14389e6268dbSMiklos Szeredi req->out.numargs = 1; 14390e9663eeSMiklos Szeredi if (fc->minor < 9) 14400e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 14410e9663eeSMiklos Szeredi else 14429e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 14439e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 1444b93f858aSTejun Heo fuse_request_send(fc, req); 14459e6268dbSMiklos Szeredi err = req->out.h.error; 14469e6268dbSMiklos Szeredi fuse_put_request(fc, req); 1447e00d2c2dSMiklos Szeredi if (err) { 1448e00d2c2dSMiklos Szeredi if (err == -EINTR) 1449e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 14503be5a52bSMiklos Szeredi goto error; 1451e00d2c2dSMiklos Szeredi } 1452e00d2c2dSMiklos Szeredi 14539e6268dbSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 14549e6268dbSMiklos Szeredi make_bad_inode(inode); 14553be5a52bSMiklos Szeredi err = -EIO; 14563be5a52bSMiklos Szeredi goto error; 14579e6268dbSMiklos Szeredi } 14589e6268dbSMiklos Szeredi 14593be5a52bSMiklos Szeredi spin_lock(&fc->lock); 14603be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 14613be5a52bSMiklos Szeredi attr_timeout(&outarg)); 14623be5a52bSMiklos Szeredi oldsize = inode->i_size; 14633be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 14643be5a52bSMiklos Szeredi 14653be5a52bSMiklos Szeredi if (is_truncate) { 14663be5a52bSMiklos Szeredi /* NOTE: this may release/reacquire fc->lock */ 14673be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 14683be5a52bSMiklos Szeredi } 14693be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 14703be5a52bSMiklos Szeredi 14713be5a52bSMiklos Szeredi /* 14723be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 14733be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 14743be5a52bSMiklos Szeredi */ 14753be5a52bSMiklos Szeredi if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 1476c08d3b0eSnpiggin@suse.de truncate_pagecache(inode, oldsize, outarg.attr.size); 14773be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 14783be5a52bSMiklos Szeredi } 14793be5a52bSMiklos Szeredi 1480e00d2c2dSMiklos Szeredi return 0; 14813be5a52bSMiklos Szeredi 14823be5a52bSMiklos Szeredi error: 14833be5a52bSMiklos Szeredi if (is_truncate) 14843be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 14853be5a52bSMiklos Szeredi 14863be5a52bSMiklos Szeredi return err; 14879e6268dbSMiklos Szeredi } 14889e6268dbSMiklos Szeredi 148949d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 149049d4914fSMiklos Szeredi { 149149d4914fSMiklos Szeredi if (attr->ia_valid & ATTR_FILE) 149249d4914fSMiklos Szeredi return fuse_do_setattr(entry, attr, attr->ia_file); 149349d4914fSMiklos Szeredi else 149449d4914fSMiklos Szeredi return fuse_do_setattr(entry, attr, NULL); 149549d4914fSMiklos Szeredi } 149649d4914fSMiklos Szeredi 1497e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, 1498e5e5558eSMiklos Szeredi struct kstat *stat) 1499e5e5558eSMiklos Szeredi { 1500e5e5558eSMiklos Szeredi struct inode *inode = entry->d_inode; 1501244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1502244f6385SMiklos Szeredi 1503244f6385SMiklos Szeredi if (!fuse_allow_task(fc, current)) 1504244f6385SMiklos Szeredi return -EACCES; 1505244f6385SMiklos Szeredi 1506bcb4be80SMiklos Szeredi return fuse_update_attributes(inode, stat, NULL, NULL); 1507e5e5558eSMiklos Szeredi } 1508e5e5558eSMiklos Szeredi 150992a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name, 151092a8780eSMiklos Szeredi const void *value, size_t size, int flags) 151192a8780eSMiklos Szeredi { 151292a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 151392a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 151492a8780eSMiklos Szeredi struct fuse_req *req; 151592a8780eSMiklos Szeredi struct fuse_setxattr_in inarg; 151692a8780eSMiklos Szeredi int err; 151792a8780eSMiklos Szeredi 151892a8780eSMiklos Szeredi if (fc->no_setxattr) 151992a8780eSMiklos Szeredi return -EOPNOTSUPP; 152092a8780eSMiklos Szeredi 1521ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1522ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1523ce1d5a49SMiklos Szeredi return PTR_ERR(req); 152492a8780eSMiklos Szeredi 152592a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 152692a8780eSMiklos Szeredi inarg.size = size; 152792a8780eSMiklos Szeredi inarg.flags = flags; 152892a8780eSMiklos Szeredi req->in.h.opcode = FUSE_SETXATTR; 152992a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 153092a8780eSMiklos Szeredi req->in.numargs = 3; 153192a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 153292a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 153392a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 153492a8780eSMiklos Szeredi req->in.args[1].value = name; 153592a8780eSMiklos Szeredi req->in.args[2].size = size; 153692a8780eSMiklos Szeredi req->in.args[2].value = value; 1537b93f858aSTejun Heo fuse_request_send(fc, req); 153892a8780eSMiklos Szeredi err = req->out.h.error; 153992a8780eSMiklos Szeredi fuse_put_request(fc, req); 154092a8780eSMiklos Szeredi if (err == -ENOSYS) { 154192a8780eSMiklos Szeredi fc->no_setxattr = 1; 154292a8780eSMiklos Szeredi err = -EOPNOTSUPP; 154392a8780eSMiklos Szeredi } 154492a8780eSMiklos Szeredi return err; 154592a8780eSMiklos Szeredi } 154692a8780eSMiklos Szeredi 154792a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name, 154892a8780eSMiklos Szeredi void *value, size_t size) 154992a8780eSMiklos Szeredi { 155092a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 155192a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 155292a8780eSMiklos Szeredi struct fuse_req *req; 155392a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 155492a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 155592a8780eSMiklos Szeredi ssize_t ret; 155692a8780eSMiklos Szeredi 155792a8780eSMiklos Szeredi if (fc->no_getxattr) 155892a8780eSMiklos Szeredi return -EOPNOTSUPP; 155992a8780eSMiklos Szeredi 1560ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1561ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1562ce1d5a49SMiklos Szeredi return PTR_ERR(req); 156392a8780eSMiklos Szeredi 156492a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 156592a8780eSMiklos Szeredi inarg.size = size; 156692a8780eSMiklos Szeredi req->in.h.opcode = FUSE_GETXATTR; 156792a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 156892a8780eSMiklos Szeredi req->in.numargs = 2; 156992a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 157092a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 157192a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 157292a8780eSMiklos Szeredi req->in.args[1].value = name; 157392a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 157492a8780eSMiklos Szeredi req->out.numargs = 1; 157592a8780eSMiklos Szeredi if (size) { 157692a8780eSMiklos Szeredi req->out.argvar = 1; 157792a8780eSMiklos Szeredi req->out.args[0].size = size; 157892a8780eSMiklos Szeredi req->out.args[0].value = value; 157992a8780eSMiklos Szeredi } else { 158092a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 158192a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 158292a8780eSMiklos Szeredi } 1583b93f858aSTejun Heo fuse_request_send(fc, req); 158492a8780eSMiklos Szeredi ret = req->out.h.error; 158592a8780eSMiklos Szeredi if (!ret) 158692a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 158792a8780eSMiklos Szeredi else { 158892a8780eSMiklos Szeredi if (ret == -ENOSYS) { 158992a8780eSMiklos Szeredi fc->no_getxattr = 1; 159092a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 159192a8780eSMiklos Szeredi } 159292a8780eSMiklos Szeredi } 159392a8780eSMiklos Szeredi fuse_put_request(fc, req); 159492a8780eSMiklos Szeredi return ret; 159592a8780eSMiklos Szeredi } 159692a8780eSMiklos Szeredi 159792a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) 159892a8780eSMiklos Szeredi { 159992a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 160092a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 160192a8780eSMiklos Szeredi struct fuse_req *req; 160292a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 160392a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 160492a8780eSMiklos Szeredi ssize_t ret; 160592a8780eSMiklos Szeredi 1606e57ac683SMiklos Szeredi if (!fuse_allow_task(fc, current)) 1607e57ac683SMiklos Szeredi return -EACCES; 1608e57ac683SMiklos Szeredi 160992a8780eSMiklos Szeredi if (fc->no_listxattr) 161092a8780eSMiklos Szeredi return -EOPNOTSUPP; 161192a8780eSMiklos Szeredi 1612ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1613ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1614ce1d5a49SMiklos Szeredi return PTR_ERR(req); 161592a8780eSMiklos Szeredi 161692a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 161792a8780eSMiklos Szeredi inarg.size = size; 161892a8780eSMiklos Szeredi req->in.h.opcode = FUSE_LISTXATTR; 161992a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 162092a8780eSMiklos Szeredi req->in.numargs = 1; 162192a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 162292a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 162392a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 162492a8780eSMiklos Szeredi req->out.numargs = 1; 162592a8780eSMiklos Szeredi if (size) { 162692a8780eSMiklos Szeredi req->out.argvar = 1; 162792a8780eSMiklos Szeredi req->out.args[0].size = size; 162892a8780eSMiklos Szeredi req->out.args[0].value = list; 162992a8780eSMiklos Szeredi } else { 163092a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 163192a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 163292a8780eSMiklos Szeredi } 1633b93f858aSTejun Heo fuse_request_send(fc, req); 163492a8780eSMiklos Szeredi ret = req->out.h.error; 163592a8780eSMiklos Szeredi if (!ret) 163692a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 163792a8780eSMiklos Szeredi else { 163892a8780eSMiklos Szeredi if (ret == -ENOSYS) { 163992a8780eSMiklos Szeredi fc->no_listxattr = 1; 164092a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 164192a8780eSMiklos Szeredi } 164292a8780eSMiklos Szeredi } 164392a8780eSMiklos Szeredi fuse_put_request(fc, req); 164492a8780eSMiklos Szeredi return ret; 164592a8780eSMiklos Szeredi } 164692a8780eSMiklos Szeredi 164792a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name) 164892a8780eSMiklos Szeredi { 164992a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 165092a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 165192a8780eSMiklos Szeredi struct fuse_req *req; 165292a8780eSMiklos Szeredi int err; 165392a8780eSMiklos Szeredi 165492a8780eSMiklos Szeredi if (fc->no_removexattr) 165592a8780eSMiklos Szeredi return -EOPNOTSUPP; 165692a8780eSMiklos Szeredi 1657ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1658ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1659ce1d5a49SMiklos Szeredi return PTR_ERR(req); 166092a8780eSMiklos Szeredi 166192a8780eSMiklos Szeredi req->in.h.opcode = FUSE_REMOVEXATTR; 166292a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 166392a8780eSMiklos Szeredi req->in.numargs = 1; 166492a8780eSMiklos Szeredi req->in.args[0].size = strlen(name) + 1; 166592a8780eSMiklos Szeredi req->in.args[0].value = name; 1666b93f858aSTejun Heo fuse_request_send(fc, req); 166792a8780eSMiklos Szeredi err = req->out.h.error; 166892a8780eSMiklos Szeredi fuse_put_request(fc, req); 166992a8780eSMiklos Szeredi if (err == -ENOSYS) { 167092a8780eSMiklos Szeredi fc->no_removexattr = 1; 167192a8780eSMiklos Szeredi err = -EOPNOTSUPP; 167292a8780eSMiklos Szeredi } 167392a8780eSMiklos Szeredi return err; 167492a8780eSMiklos Szeredi } 167592a8780eSMiklos Szeredi 1676754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1677e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 16789e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 16799e6268dbSMiklos Szeredi .symlink = fuse_symlink, 16809e6268dbSMiklos Szeredi .unlink = fuse_unlink, 16819e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 16829e6268dbSMiklos Szeredi .rename = fuse_rename, 16839e6268dbSMiklos Szeredi .link = fuse_link, 16849e6268dbSMiklos Szeredi .setattr = fuse_setattr, 16859e6268dbSMiklos Szeredi .create = fuse_create, 1686c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 16879e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1688e5e5558eSMiklos Szeredi .permission = fuse_permission, 1689e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 169092a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 169192a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 169292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 169392a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1694e5e5558eSMiklos Szeredi }; 1695e5e5558eSMiklos Szeredi 16964b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1697b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1698e5e5558eSMiklos Szeredi .read = generic_read_dir, 1699e5e5558eSMiklos Szeredi .readdir = fuse_readdir, 1700e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1701e5e5558eSMiklos Szeredi .release = fuse_dir_release, 170282547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1703b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 1704b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 1705e5e5558eSMiklos Szeredi }; 1706e5e5558eSMiklos Szeredi 1707754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 17089e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1709e5e5558eSMiklos Szeredi .permission = fuse_permission, 1710e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 171192a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 171292a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 171392a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 171492a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1715e5e5558eSMiklos Szeredi }; 1716e5e5558eSMiklos Szeredi 1717754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 17189e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1719e5e5558eSMiklos Szeredi .follow_link = fuse_follow_link, 1720e5e5558eSMiklos Szeredi .put_link = fuse_put_link, 1721e5e5558eSMiklos Szeredi .readlink = generic_readlink, 1722e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 172392a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 172492a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 172592a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 172692a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1727e5e5558eSMiklos Szeredi }; 1728e5e5558eSMiklos Szeredi 1729e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1730e5e5558eSMiklos Szeredi { 1731e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1732e5e5558eSMiklos Szeredi } 1733e5e5558eSMiklos Szeredi 1734e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1735e5e5558eSMiklos Szeredi { 1736e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1737e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1738e5e5558eSMiklos Szeredi } 1739e5e5558eSMiklos Szeredi 1740e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1741e5e5558eSMiklos Szeredi { 1742e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 1743e5e5558eSMiklos Szeredi } 1744