1e5e5558eSMiklos Szeredi /* 2e5e5558eSMiklos Szeredi FUSE: Filesystem in Userspace 351eb01e7SMiklos Szeredi Copyright (C) 2001-2006 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 */ 660aa7c699SMiklos Szeredi static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) 670aa7c699SMiklos Szeredi { 680a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 690a0898cfSMiklos Szeredi time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 708cbdf1e6SMiklos Szeredi if (entry->d_inode) 718cbdf1e6SMiklos Szeredi get_fuse_inode(entry->d_inode)->i_time = 728cbdf1e6SMiklos Szeredi time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 738cbdf1e6SMiklos Szeredi } 748cbdf1e6SMiklos Szeredi 756f9f1180SMiklos Szeredi /* 766f9f1180SMiklos Szeredi * Mark the attributes as stale, so that at the next call to 776f9f1180SMiklos Szeredi * ->getattr() they will be fetched from userspace 786f9f1180SMiklos Szeredi */ 798cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode) 808cbdf1e6SMiklos Szeredi { 810a0898cfSMiklos Szeredi get_fuse_inode(inode)->i_time = 0; 828cbdf1e6SMiklos Szeredi } 838cbdf1e6SMiklos Szeredi 846f9f1180SMiklos Szeredi /* 856f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 866f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 876f9f1180SMiklos Szeredi * 886f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 896f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 906f9f1180SMiklos Szeredi * lookup) 916f9f1180SMiklos Szeredi */ 928cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry_cache(struct dentry *entry) 938cbdf1e6SMiklos Szeredi { 940a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 958cbdf1e6SMiklos Szeredi } 968cbdf1e6SMiklos Szeredi 976f9f1180SMiklos Szeredi /* 986f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 996f9f1180SMiklos Szeredi * dentry from the hash 1006f9f1180SMiklos Szeredi */ 1018cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1028cbdf1e6SMiklos Szeredi { 1038cbdf1e6SMiklos Szeredi d_invalidate(entry); 1048cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1050aa7c699SMiklos Szeredi } 1060aa7c699SMiklos Szeredi 107e5e5558eSMiklos Szeredi static void fuse_lookup_init(struct fuse_req *req, struct inode *dir, 108e5e5558eSMiklos Szeredi struct dentry *entry, 109e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 110e5e5558eSMiklos Szeredi { 111e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_LOOKUP; 112e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 113e5e5558eSMiklos Szeredi req->in.numargs = 1; 114e5e5558eSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 115e5e5558eSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 116e5e5558eSMiklos Szeredi req->out.numargs = 1; 117e5e5558eSMiklos Szeredi req->out.args[0].size = sizeof(struct fuse_entry_out); 118e5e5558eSMiklos Szeredi req->out.args[0].value = outarg; 119e5e5558eSMiklos Szeredi } 120e5e5558eSMiklos Szeredi 1216f9f1180SMiklos Szeredi /* 1226f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1236f9f1180SMiklos Szeredi * 1246f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 1256f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 1266f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 1276f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 1286f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 1296f9f1180SMiklos Szeredi */ 130e5e5558eSMiklos Szeredi static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) 131e5e5558eSMiklos Szeredi { 1328cbdf1e6SMiklos Szeredi struct inode *inode = entry->d_inode; 1338cbdf1e6SMiklos Szeredi 1348cbdf1e6SMiklos Szeredi if (inode && is_bad_inode(inode)) 135e5e5558eSMiklos Szeredi return 0; 1360a0898cfSMiklos Szeredi else if (fuse_dentry_time(entry) < get_jiffies_64()) { 137e5e5558eSMiklos Szeredi int err; 138e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 1398cbdf1e6SMiklos Szeredi struct fuse_conn *fc; 1408cbdf1e6SMiklos Szeredi struct fuse_req *req; 1412d51013eSMiklos Szeredi struct fuse_req *forget_req; 142e956edd0SMiklos Szeredi struct dentry *parent; 1438cbdf1e6SMiklos Szeredi 14450322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 1458cbdf1e6SMiklos Szeredi if (!inode) 1468cbdf1e6SMiklos Szeredi return 0; 1478cbdf1e6SMiklos Szeredi 1488cbdf1e6SMiklos Szeredi fc = get_fuse_conn(inode); 149ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 150ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 151e5e5558eSMiklos Szeredi return 0; 152e5e5558eSMiklos Szeredi 1532d51013eSMiklos Szeredi forget_req = fuse_get_req(fc); 1542d51013eSMiklos Szeredi if (IS_ERR(forget_req)) { 1552d51013eSMiklos Szeredi fuse_put_request(fc, req); 1562d51013eSMiklos Szeredi return 0; 1572d51013eSMiklos Szeredi } 1582d51013eSMiklos Szeredi 159e956edd0SMiklos Szeredi parent = dget_parent(entry); 160e956edd0SMiklos Szeredi fuse_lookup_init(req, parent->d_inode, entry, &outarg); 1617c352bdfSMiklos Szeredi request_send(fc, req); 162e956edd0SMiklos Szeredi dput(parent); 163e5e5558eSMiklos Szeredi err = req->out.h.error; 1642d51013eSMiklos Szeredi fuse_put_request(fc, req); 16550322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 16650322fe7SMiklos Szeredi if (!err && !outarg.nodeid) 16750322fe7SMiklos Szeredi err = -ENOENT; 1689e6268dbSMiklos Szeredi if (!err) { 1698cbdf1e6SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1709e6268dbSMiklos Szeredi if (outarg.nodeid != get_node_id(inode)) { 1712d51013eSMiklos Szeredi fuse_send_forget(fc, forget_req, 1722d51013eSMiklos Szeredi outarg.nodeid, 1); 1739e6268dbSMiklos Szeredi return 0; 1749e6268dbSMiklos Szeredi } 1758da5ff23SMiklos Szeredi spin_lock(&fc->lock); 1769e6268dbSMiklos Szeredi fi->nlookup ++; 1778da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 1789e6268dbSMiklos Szeredi } 1792d51013eSMiklos Szeredi fuse_put_request(fc, forget_req); 1809e6268dbSMiklos Szeredi if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 181e5e5558eSMiklos Szeredi return 0; 182e5e5558eSMiklos Szeredi 183e5e5558eSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr); 1840aa7c699SMiklos Szeredi fuse_change_timeout(entry, &outarg); 185e5e5558eSMiklos Szeredi } 186e5e5558eSMiklos Szeredi return 1; 187e5e5558eSMiklos Szeredi } 188e5e5558eSMiklos Szeredi 1898bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid) 1902827d0b2SMiklos Szeredi { 1912827d0b2SMiklos Szeredi return !nodeid || nodeid == FUSE_ROOT_ID; 1922827d0b2SMiklos Szeredi } 1932827d0b2SMiklos Szeredi 194e5e5558eSMiklos Szeredi static struct dentry_operations fuse_dentry_operations = { 195e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 196e5e5558eSMiklos Szeredi }; 197e5e5558eSMiklos Szeredi 198a5bfffacSTimo Savola int fuse_valid_type(int m) 19939ee059aSMiklos Szeredi { 20039ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 20139ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 20239ee059aSMiklos Szeredi } 20339ee059aSMiklos Szeredi 204d2a85164SMiklos Szeredi /* 205d2a85164SMiklos Szeredi * Add a directory inode to a dentry, ensuring that no other dentry 206d2a85164SMiklos Szeredi * refers to this inode. Called with fc->inst_mutex. 207d2a85164SMiklos Szeredi */ 208d2a85164SMiklos Szeredi static int fuse_d_add_directory(struct dentry *entry, struct inode *inode) 209d2a85164SMiklos Szeredi { 210d2a85164SMiklos Szeredi struct dentry *alias = d_find_alias(inode); 211d2a85164SMiklos Szeredi if (alias) { 212d2a85164SMiklos Szeredi /* This tries to shrink the subtree below alias */ 213d2a85164SMiklos Szeredi fuse_invalidate_entry(alias); 214d2a85164SMiklos Szeredi dput(alias); 215d2a85164SMiklos Szeredi if (!list_empty(&inode->i_dentry)) 216d2a85164SMiklos Szeredi return -EBUSY; 217d2a85164SMiklos Szeredi } 218d2a85164SMiklos Szeredi d_add(entry, inode); 219d2a85164SMiklos Szeredi return 0; 220d2a85164SMiklos Szeredi } 221d2a85164SMiklos Szeredi 2220aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 2230aa7c699SMiklos Szeredi struct nameidata *nd) 224e5e5558eSMiklos Szeredi { 225e5e5558eSMiklos Szeredi int err; 226e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 227e5e5558eSMiklos Szeredi struct inode *inode = NULL; 228e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 229e5e5558eSMiklos Szeredi struct fuse_req *req; 2302d51013eSMiklos Szeredi struct fuse_req *forget_req; 231e5e5558eSMiklos Szeredi 232e5e5558eSMiklos Szeredi if (entry->d_name.len > FUSE_NAME_MAX) 2330aa7c699SMiklos Szeredi return ERR_PTR(-ENAMETOOLONG); 234e5e5558eSMiklos Szeredi 235ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 236ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 237ce1d5a49SMiklos Szeredi return ERR_PTR(PTR_ERR(req)); 238e5e5558eSMiklos Szeredi 2392d51013eSMiklos Szeredi forget_req = fuse_get_req(fc); 2402d51013eSMiklos Szeredi if (IS_ERR(forget_req)) { 2412d51013eSMiklos Szeredi fuse_put_request(fc, req); 2422d51013eSMiklos Szeredi return ERR_PTR(PTR_ERR(forget_req)); 2432d51013eSMiklos Szeredi } 2442d51013eSMiklos Szeredi 245e5e5558eSMiklos Szeredi fuse_lookup_init(req, dir, entry, &outarg); 246e5e5558eSMiklos Szeredi request_send(fc, req); 247e5e5558eSMiklos Szeredi err = req->out.h.error; 2482d51013eSMiklos Szeredi fuse_put_request(fc, req); 24950322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 25050322fe7SMiklos Szeredi if (!err && outarg.nodeid && 251a5bfffacSTimo Savola (invalid_nodeid(outarg.nodeid) || 252a5bfffacSTimo Savola !fuse_valid_type(outarg.attr.mode))) 253ee4e5271SMiklos Szeredi err = -EIO; 2548cbdf1e6SMiklos Szeredi if (!err && outarg.nodeid) { 255e5e5558eSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 2569e6268dbSMiklos Szeredi &outarg.attr); 257e5e5558eSMiklos Szeredi if (!inode) { 2582d51013eSMiklos Szeredi fuse_send_forget(fc, forget_req, outarg.nodeid, 1); 2590aa7c699SMiklos Szeredi return ERR_PTR(-ENOMEM); 260e5e5558eSMiklos Szeredi } 261e5e5558eSMiklos Szeredi } 2622d51013eSMiklos Szeredi fuse_put_request(fc, forget_req); 263e5e5558eSMiklos Szeredi if (err && err != -ENOENT) 2640aa7c699SMiklos Szeredi return ERR_PTR(err); 265e5e5558eSMiklos Szeredi 266d2a85164SMiklos Szeredi if (inode && S_ISDIR(inode->i_mode)) { 267d2a85164SMiklos Szeredi mutex_lock(&fc->inst_mutex); 268d2a85164SMiklos Szeredi err = fuse_d_add_directory(entry, inode); 269d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 270d2a85164SMiklos Szeredi if (err) { 2710aa7c699SMiklos Szeredi iput(inode); 272d2a85164SMiklos Szeredi return ERR_PTR(err); 273e5e5558eSMiklos Szeredi } 274d2a85164SMiklos Szeredi } else 2750aa7c699SMiklos Szeredi d_add(entry, inode); 276d2a85164SMiklos Szeredi 277e5e5558eSMiklos Szeredi entry->d_op = &fuse_dentry_operations; 2788cbdf1e6SMiklos Szeredi if (!err) 2790aa7c699SMiklos Szeredi fuse_change_timeout(entry, &outarg); 2808cbdf1e6SMiklos Szeredi else 2818cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 2820aa7c699SMiklos Szeredi return NULL; 283e5e5558eSMiklos Szeredi } 284e5e5558eSMiklos Szeredi 2856f9f1180SMiklos Szeredi /* 28651eb01e7SMiklos Szeredi * Synchronous release for the case when something goes wrong in CREATE_OPEN 28751eb01e7SMiklos Szeredi */ 28851eb01e7SMiklos Szeredi static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff, 28951eb01e7SMiklos Szeredi u64 nodeid, int flags) 29051eb01e7SMiklos Szeredi { 29151eb01e7SMiklos Szeredi struct fuse_req *req; 29251eb01e7SMiklos Szeredi 29351eb01e7SMiklos Szeredi req = fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE); 29451eb01e7SMiklos Szeredi req->force = 1; 29551eb01e7SMiklos Szeredi request_send(fc, req); 29651eb01e7SMiklos Szeredi fuse_put_request(fc, req); 29751eb01e7SMiklos Szeredi } 29851eb01e7SMiklos Szeredi 29951eb01e7SMiklos Szeredi /* 3006f9f1180SMiklos Szeredi * Atomic create+open operation 3016f9f1180SMiklos Szeredi * 3026f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 3036f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 3046f9f1180SMiklos Szeredi */ 305fd72faacSMiklos Szeredi static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, 306fd72faacSMiklos Szeredi struct nameidata *nd) 307fd72faacSMiklos Szeredi { 308fd72faacSMiklos Szeredi int err; 309fd72faacSMiklos Szeredi struct inode *inode; 310fd72faacSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 311fd72faacSMiklos Szeredi struct fuse_req *req; 31251eb01e7SMiklos Szeredi struct fuse_req *forget_req; 313fd72faacSMiklos Szeredi struct fuse_open_in inarg; 314fd72faacSMiklos Szeredi struct fuse_open_out outopen; 315fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 316fd72faacSMiklos Szeredi struct fuse_file *ff; 317fd72faacSMiklos Szeredi struct file *file; 318fd72faacSMiklos Szeredi int flags = nd->intent.open.flags - 1; 319fd72faacSMiklos Szeredi 320fd72faacSMiklos Szeredi if (fc->no_create) 321ce1d5a49SMiklos Szeredi return -ENOSYS; 322fd72faacSMiklos Szeredi 32351eb01e7SMiklos Szeredi forget_req = fuse_get_req(fc); 32451eb01e7SMiklos Szeredi if (IS_ERR(forget_req)) 32551eb01e7SMiklos Szeredi return PTR_ERR(forget_req); 32651eb01e7SMiklos Szeredi 327ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 32851eb01e7SMiklos Szeredi err = PTR_ERR(req); 329ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 33051eb01e7SMiklos Szeredi goto out_put_forget_req; 331fd72faacSMiklos Szeredi 332ce1d5a49SMiklos Szeredi err = -ENOMEM; 333fd72faacSMiklos Szeredi ff = fuse_file_alloc(); 334fd72faacSMiklos Szeredi if (!ff) 335fd72faacSMiklos Szeredi goto out_put_request; 336fd72faacSMiklos Szeredi 337fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 338fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 339fd72faacSMiklos Szeredi inarg.flags = flags; 340fd72faacSMiklos Szeredi inarg.mode = mode; 341fd72faacSMiklos Szeredi req->in.h.opcode = FUSE_CREATE; 342fd72faacSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 343fd72faacSMiklos Szeredi req->in.numargs = 2; 344fd72faacSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 345fd72faacSMiklos Szeredi req->in.args[0].value = &inarg; 346fd72faacSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 347fd72faacSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 348fd72faacSMiklos Szeredi req->out.numargs = 2; 349fd72faacSMiklos Szeredi req->out.args[0].size = sizeof(outentry); 350fd72faacSMiklos Szeredi req->out.args[0].value = &outentry; 351fd72faacSMiklos Szeredi req->out.args[1].size = sizeof(outopen); 352fd72faacSMiklos Szeredi req->out.args[1].value = &outopen; 353fd72faacSMiklos Szeredi request_send(fc, req); 354fd72faacSMiklos Szeredi err = req->out.h.error; 355fd72faacSMiklos Szeredi if (err) { 356fd72faacSMiklos Szeredi if (err == -ENOSYS) 357fd72faacSMiklos Szeredi fc->no_create = 1; 358fd72faacSMiklos Szeredi goto out_free_ff; 359fd72faacSMiklos Szeredi } 360fd72faacSMiklos Szeredi 361fd72faacSMiklos Szeredi err = -EIO; 3622827d0b2SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 363fd72faacSMiklos Szeredi goto out_free_ff; 364fd72faacSMiklos Szeredi 36551eb01e7SMiklos Szeredi fuse_put_request(fc, req); 366fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 367fd72faacSMiklos Szeredi &outentry.attr); 368fd72faacSMiklos Szeredi if (!inode) { 369fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 370fd72faacSMiklos Szeredi ff->fh = outopen.fh; 37151eb01e7SMiklos Szeredi fuse_sync_release(fc, ff, outentry.nodeid, flags); 37251eb01e7SMiklos Szeredi fuse_send_forget(fc, forget_req, outentry.nodeid, 1); 37351eb01e7SMiklos Szeredi return -ENOMEM; 374fd72faacSMiklos Szeredi } 37551eb01e7SMiklos Szeredi fuse_put_request(fc, forget_req); 376fd72faacSMiklos Szeredi d_instantiate(entry, inode); 3770aa7c699SMiklos Szeredi fuse_change_timeout(entry, &outentry); 378fd72faacSMiklos Szeredi file = lookup_instantiate_filp(nd, entry, generic_file_open); 379fd72faacSMiklos Szeredi if (IS_ERR(file)) { 380fd72faacSMiklos Szeredi ff->fh = outopen.fh; 38151eb01e7SMiklos Szeredi fuse_sync_release(fc, ff, outentry.nodeid, flags); 382fd72faacSMiklos Szeredi return PTR_ERR(file); 383fd72faacSMiklos Szeredi } 384fd72faacSMiklos Szeredi fuse_finish_open(inode, file, ff, &outopen); 385fd72faacSMiklos Szeredi return 0; 386fd72faacSMiklos Szeredi 387fd72faacSMiklos Szeredi out_free_ff: 388fd72faacSMiklos Szeredi fuse_file_free(ff); 389fd72faacSMiklos Szeredi out_put_request: 390fd72faacSMiklos Szeredi fuse_put_request(fc, req); 39151eb01e7SMiklos Szeredi out_put_forget_req: 39251eb01e7SMiklos Szeredi fuse_put_request(fc, forget_req); 393fd72faacSMiklos Szeredi return err; 394fd72faacSMiklos Szeredi } 395fd72faacSMiklos Szeredi 3966f9f1180SMiklos Szeredi /* 3976f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 3986f9f1180SMiklos Szeredi */ 3999e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, 4009e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 4019e6268dbSMiklos Szeredi int mode) 4029e6268dbSMiklos Szeredi { 4039e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 4049e6268dbSMiklos Szeredi struct inode *inode; 4059e6268dbSMiklos Szeredi int err; 4062d51013eSMiklos Szeredi struct fuse_req *forget_req; 4072d51013eSMiklos Szeredi 4082d51013eSMiklos Szeredi forget_req = fuse_get_req(fc); 4092d51013eSMiklos Szeredi if (IS_ERR(forget_req)) { 4102d51013eSMiklos Szeredi fuse_put_request(fc, req); 4112d51013eSMiklos Szeredi return PTR_ERR(forget_req); 4122d51013eSMiklos Szeredi } 4139e6268dbSMiklos Szeredi 4149e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 4159e6268dbSMiklos Szeredi req->out.numargs = 1; 4169e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 4179e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 4189e6268dbSMiklos Szeredi request_send(fc, req); 4199e6268dbSMiklos Szeredi err = req->out.h.error; 4209e6268dbSMiklos Szeredi fuse_put_request(fc, req); 4212d51013eSMiklos Szeredi if (err) 4222d51013eSMiklos Szeredi goto out_put_forget_req; 4232d51013eSMiklos Szeredi 42439ee059aSMiklos Szeredi err = -EIO; 42539ee059aSMiklos Szeredi if (invalid_nodeid(outarg.nodeid)) 4262d51013eSMiklos Szeredi goto out_put_forget_req; 42739ee059aSMiklos Szeredi 42839ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 4292d51013eSMiklos Szeredi goto out_put_forget_req; 43039ee059aSMiklos Szeredi 4319e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 4329e6268dbSMiklos Szeredi &outarg.attr); 4339e6268dbSMiklos Szeredi if (!inode) { 4342d51013eSMiklos Szeredi fuse_send_forget(fc, forget_req, outarg.nodeid, 1); 4359e6268dbSMiklos Szeredi return -ENOMEM; 4369e6268dbSMiklos Szeredi } 4372d51013eSMiklos Szeredi fuse_put_request(fc, forget_req); 4389e6268dbSMiklos Szeredi 439d2a85164SMiklos Szeredi if (S_ISDIR(inode->i_mode)) { 440d2a85164SMiklos Szeredi struct dentry *alias; 441d2a85164SMiklos Szeredi mutex_lock(&fc->inst_mutex); 442d2a85164SMiklos Szeredi alias = d_find_alias(inode); 443d2a85164SMiklos Szeredi if (alias) { 444d2a85164SMiklos Szeredi /* New directory must have moved since mkdir */ 445d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 446d2a85164SMiklos Szeredi dput(alias); 4479e6268dbSMiklos Szeredi iput(inode); 448d2a85164SMiklos Szeredi return -EBUSY; 4499e6268dbSMiklos Szeredi } 4509e6268dbSMiklos Szeredi d_instantiate(entry, inode); 451d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 452d2a85164SMiklos Szeredi } else 453d2a85164SMiklos Szeredi d_instantiate(entry, inode); 454d2a85164SMiklos Szeredi 4550aa7c699SMiklos Szeredi fuse_change_timeout(entry, &outarg); 4569e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 4579e6268dbSMiklos Szeredi return 0; 45839ee059aSMiklos Szeredi 4592d51013eSMiklos Szeredi out_put_forget_req: 4602d51013eSMiklos Szeredi fuse_put_request(fc, forget_req); 46139ee059aSMiklos Szeredi return err; 4629e6268dbSMiklos Szeredi } 4639e6268dbSMiklos Szeredi 4649e6268dbSMiklos Szeredi static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, 4659e6268dbSMiklos Szeredi dev_t rdev) 4669e6268dbSMiklos Szeredi { 4679e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 4689e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 469ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 470ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 471ce1d5a49SMiklos Szeredi return PTR_ERR(req); 4729e6268dbSMiklos Szeredi 4739e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4749e6268dbSMiklos Szeredi inarg.mode = mode; 4759e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 4769e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKNOD; 4779e6268dbSMiklos Szeredi req->in.numargs = 2; 4789e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 4799e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 4809e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 4819e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 4829e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, mode); 4839e6268dbSMiklos Szeredi } 4849e6268dbSMiklos Szeredi 4859e6268dbSMiklos Szeredi static int fuse_create(struct inode *dir, struct dentry *entry, int mode, 4869e6268dbSMiklos Szeredi struct nameidata *nd) 4879e6268dbSMiklos Szeredi { 488*b9ba347fSMiklos Szeredi if (nd && (nd->flags & LOOKUP_OPEN)) { 489fd72faacSMiklos Szeredi int err = fuse_create_open(dir, entry, mode, nd); 490fd72faacSMiklos Szeredi if (err != -ENOSYS) 491fd72faacSMiklos Szeredi return err; 492fd72faacSMiklos Szeredi /* Fall back on mknod */ 493fd72faacSMiklos Szeredi } 4949e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 4959e6268dbSMiklos Szeredi } 4969e6268dbSMiklos Szeredi 4979e6268dbSMiklos Szeredi static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode) 4989e6268dbSMiklos Szeredi { 4999e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 5009e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 501ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 502ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 503ce1d5a49SMiklos Szeredi return PTR_ERR(req); 5049e6268dbSMiklos Szeredi 5059e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 5069e6268dbSMiklos Szeredi inarg.mode = mode; 5079e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKDIR; 5089e6268dbSMiklos Szeredi req->in.numargs = 2; 5099e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 5109e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 5119e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 5129e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 5139e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFDIR); 5149e6268dbSMiklos Szeredi } 5159e6268dbSMiklos Szeredi 5169e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 5179e6268dbSMiklos Szeredi const char *link) 5189e6268dbSMiklos Szeredi { 5199e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 5209e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 521ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 522ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 523ce1d5a49SMiklos Szeredi return PTR_ERR(req); 5249e6268dbSMiklos Szeredi 5259e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SYMLINK; 5269e6268dbSMiklos Szeredi req->in.numargs = 2; 5279e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 5289e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 5299e6268dbSMiklos Szeredi req->in.args[1].size = len; 5309e6268dbSMiklos Szeredi req->in.args[1].value = link; 5319e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFLNK); 5329e6268dbSMiklos Szeredi } 5339e6268dbSMiklos Szeredi 5349e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 5359e6268dbSMiklos Szeredi { 5369e6268dbSMiklos Szeredi int err; 5379e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 538ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 539ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 540ce1d5a49SMiklos Szeredi return PTR_ERR(req); 5419e6268dbSMiklos Szeredi 5429e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_UNLINK; 5439e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 5449e6268dbSMiklos Szeredi req->in.numargs = 1; 5459e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 5469e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 5479e6268dbSMiklos Szeredi request_send(fc, req); 5489e6268dbSMiklos Szeredi err = req->out.h.error; 5499e6268dbSMiklos Szeredi fuse_put_request(fc, req); 5509e6268dbSMiklos Szeredi if (!err) { 5519e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 5529e6268dbSMiklos Szeredi 5539e6268dbSMiklos Szeredi /* Set nlink to zero so the inode can be cleared, if 5549e6268dbSMiklos Szeredi the inode does have more links this will be 5559e6268dbSMiklos Szeredi discovered at the next lookup/getattr */ 556ce71ec36SDave Hansen clear_nlink(inode); 5579e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 5589e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 5598cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 5609e6268dbSMiklos Szeredi } else if (err == -EINTR) 5619e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 5629e6268dbSMiklos Szeredi return err; 5639e6268dbSMiklos Szeredi } 5649e6268dbSMiklos Szeredi 5659e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 5669e6268dbSMiklos Szeredi { 5679e6268dbSMiklos Szeredi int err; 5689e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 569ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 570ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 571ce1d5a49SMiklos Szeredi return PTR_ERR(req); 5729e6268dbSMiklos Szeredi 5739e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RMDIR; 5749e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 5759e6268dbSMiklos Szeredi req->in.numargs = 1; 5769e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 5779e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 5789e6268dbSMiklos Szeredi request_send(fc, req); 5799e6268dbSMiklos Szeredi err = req->out.h.error; 5809e6268dbSMiklos Szeredi fuse_put_request(fc, req); 5819e6268dbSMiklos Szeredi if (!err) { 582ce71ec36SDave Hansen clear_nlink(entry->d_inode); 5839e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 5848cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 5859e6268dbSMiklos Szeredi } else if (err == -EINTR) 5869e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 5879e6268dbSMiklos Szeredi return err; 5889e6268dbSMiklos Szeredi } 5899e6268dbSMiklos Szeredi 5909e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent, 5919e6268dbSMiklos Szeredi struct inode *newdir, struct dentry *newent) 5929e6268dbSMiklos Szeredi { 5939e6268dbSMiklos Szeredi int err; 5949e6268dbSMiklos Szeredi struct fuse_rename_in inarg; 5959e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 596ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 597ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 598ce1d5a49SMiklos Szeredi return PTR_ERR(req); 5999e6268dbSMiklos Szeredi 6009e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6019e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 6029e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RENAME; 6039e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(olddir); 6049e6268dbSMiklos Szeredi req->in.numargs = 3; 6059e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 6069e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 6079e6268dbSMiklos Szeredi req->in.args[1].size = oldent->d_name.len + 1; 6089e6268dbSMiklos Szeredi req->in.args[1].value = oldent->d_name.name; 6099e6268dbSMiklos Szeredi req->in.args[2].size = newent->d_name.len + 1; 6109e6268dbSMiklos Szeredi req->in.args[2].value = newent->d_name.name; 6119e6268dbSMiklos Szeredi request_send(fc, req); 6129e6268dbSMiklos Szeredi err = req->out.h.error; 6139e6268dbSMiklos Szeredi fuse_put_request(fc, req); 6149e6268dbSMiklos Szeredi if (!err) { 6159e6268dbSMiklos Szeredi fuse_invalidate_attr(olddir); 6169e6268dbSMiklos Szeredi if (olddir != newdir) 6179e6268dbSMiklos Szeredi fuse_invalidate_attr(newdir); 6188cbdf1e6SMiklos Szeredi 6198cbdf1e6SMiklos Szeredi /* newent will end up negative */ 6208cbdf1e6SMiklos Szeredi if (newent->d_inode) 6218cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 6229e6268dbSMiklos Szeredi } else if (err == -EINTR) { 6239e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 6249e6268dbSMiklos Szeredi rename actually took place. If the invalidation 6259e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 6269e6268dbSMiklos Szeredi directory), then there can be inconsistency between 6279e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 6289e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 6299e6268dbSMiklos Szeredi if (newent->d_inode) 6309e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 6319e6268dbSMiklos Szeredi } 6329e6268dbSMiklos Szeredi 6339e6268dbSMiklos Szeredi return err; 6349e6268dbSMiklos Szeredi } 6359e6268dbSMiklos Szeredi 6369e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 6379e6268dbSMiklos Szeredi struct dentry *newent) 6389e6268dbSMiklos Szeredi { 6399e6268dbSMiklos Szeredi int err; 6409e6268dbSMiklos Szeredi struct fuse_link_in inarg; 6419e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 6429e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 643ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 644ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 645ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6469e6268dbSMiklos Szeredi 6479e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6489e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 6499e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_LINK; 6509e6268dbSMiklos Szeredi req->in.numargs = 2; 6519e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 6529e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 6539e6268dbSMiklos Szeredi req->in.args[1].size = newent->d_name.len + 1; 6549e6268dbSMiklos Szeredi req->in.args[1].value = newent->d_name.name; 6559e6268dbSMiklos Szeredi err = create_new_entry(fc, req, newdir, newent, inode->i_mode); 6569e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 6579e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 6589e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 6599e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 6609e6268dbSMiklos Szeredi etc.) 6619e6268dbSMiklos Szeredi */ 6629e6268dbSMiklos Szeredi if (!err || err == -EINTR) 6639e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 6649e6268dbSMiklos Szeredi return err; 6659e6268dbSMiklos Szeredi } 6669e6268dbSMiklos Szeredi 667e5e5558eSMiklos Szeredi int fuse_do_getattr(struct inode *inode) 668e5e5558eSMiklos Szeredi { 669e5e5558eSMiklos Szeredi int err; 670e5e5558eSMiklos Szeredi struct fuse_attr_out arg; 671e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 672ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 673ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 674ce1d5a49SMiklos Szeredi return PTR_ERR(req); 675e5e5558eSMiklos Szeredi 676e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_GETATTR; 677e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 678e5e5558eSMiklos Szeredi req->out.numargs = 1; 679e5e5558eSMiklos Szeredi req->out.args[0].size = sizeof(arg); 680e5e5558eSMiklos Szeredi req->out.args[0].value = &arg; 681e5e5558eSMiklos Szeredi request_send(fc, req); 682e5e5558eSMiklos Szeredi err = req->out.h.error; 683e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 684e5e5558eSMiklos Szeredi if (!err) { 685e5e5558eSMiklos Szeredi if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) { 686e5e5558eSMiklos Szeredi make_bad_inode(inode); 687e5e5558eSMiklos Szeredi err = -EIO; 688e5e5558eSMiklos Szeredi } else { 689e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 690e5e5558eSMiklos Szeredi fuse_change_attributes(inode, &arg.attr); 691e5e5558eSMiklos Szeredi fi->i_time = time_to_jiffies(arg.attr_valid, 692e5e5558eSMiklos Szeredi arg.attr_valid_nsec); 693e5e5558eSMiklos Szeredi } 694e5e5558eSMiklos Szeredi } 695e5e5558eSMiklos Szeredi return err; 696e5e5558eSMiklos Szeredi } 697e5e5558eSMiklos Szeredi 69887729a55SMiklos Szeredi /* 69987729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 70087729a55SMiklos Szeredi * daemon ptrace-like capabilities over the requester process. This 70187729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 70287729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 70387729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 70487729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 70587729a55SMiklos Szeredi * DoS against the requester. 70687729a55SMiklos Szeredi * 70787729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 70887729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 70987729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 71087729a55SMiklos Szeredi */ 71187729a55SMiklos Szeredi static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) 71287729a55SMiklos Szeredi { 71387729a55SMiklos Szeredi if (fc->flags & FUSE_ALLOW_OTHER) 71487729a55SMiklos Szeredi return 1; 71587729a55SMiklos Szeredi 71687729a55SMiklos Szeredi if (task->euid == fc->user_id && 71787729a55SMiklos Szeredi task->suid == fc->user_id && 71887729a55SMiklos Szeredi task->uid == fc->user_id && 71987729a55SMiklos Szeredi task->egid == fc->group_id && 72087729a55SMiklos Szeredi task->sgid == fc->group_id && 72187729a55SMiklos Szeredi task->gid == fc->group_id) 72287729a55SMiklos Szeredi return 1; 72387729a55SMiklos Szeredi 72487729a55SMiklos Szeredi return 0; 72587729a55SMiklos Szeredi } 72687729a55SMiklos Szeredi 7276f9f1180SMiklos Szeredi /* 7286f9f1180SMiklos Szeredi * Check whether the inode attributes are still valid 7296f9f1180SMiklos Szeredi * 7306f9f1180SMiklos Szeredi * If the attribute validity timeout has expired, then fetch the fresh 7316f9f1180SMiklos Szeredi * attributes with a 'getattr' request 7326f9f1180SMiklos Szeredi * 7336f9f1180SMiklos Szeredi * I'm not sure why cached attributes are never returned for the root 7346f9f1180SMiklos Szeredi * inode, this is probably being too cautious. 7356f9f1180SMiklos Szeredi */ 736e5e5558eSMiklos Szeredi static int fuse_revalidate(struct dentry *entry) 737e5e5558eSMiklos Szeredi { 738e5e5558eSMiklos Szeredi struct inode *inode = entry->d_inode; 739e5e5558eSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 740e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 741e5e5558eSMiklos Szeredi 74287729a55SMiklos Szeredi if (!fuse_allow_task(fc, current)) 743e5e5558eSMiklos Szeredi return -EACCES; 74487729a55SMiklos Szeredi if (get_node_id(inode) != FUSE_ROOT_ID && 7450a0898cfSMiklos Szeredi fi->i_time >= get_jiffies_64()) 746e5e5558eSMiklos Szeredi return 0; 747e5e5558eSMiklos Szeredi 748e5e5558eSMiklos Szeredi return fuse_do_getattr(inode); 749e5e5558eSMiklos Szeredi } 750e5e5558eSMiklos Szeredi 75131d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 75231d40d74SMiklos Szeredi { 75331d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 75431d40d74SMiklos Szeredi struct fuse_req *req; 75531d40d74SMiklos Szeredi struct fuse_access_in inarg; 75631d40d74SMiklos Szeredi int err; 75731d40d74SMiklos Szeredi 75831d40d74SMiklos Szeredi if (fc->no_access) 75931d40d74SMiklos Szeredi return 0; 76031d40d74SMiklos Szeredi 761ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 762ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 763ce1d5a49SMiklos Szeredi return PTR_ERR(req); 76431d40d74SMiklos Szeredi 76531d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 76631d40d74SMiklos Szeredi inarg.mask = mask; 76731d40d74SMiklos Szeredi req->in.h.opcode = FUSE_ACCESS; 76831d40d74SMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 76931d40d74SMiklos Szeredi req->in.numargs = 1; 77031d40d74SMiklos Szeredi req->in.args[0].size = sizeof(inarg); 77131d40d74SMiklos Szeredi req->in.args[0].value = &inarg; 77231d40d74SMiklos Szeredi request_send(fc, req); 77331d40d74SMiklos Szeredi err = req->out.h.error; 77431d40d74SMiklos Szeredi fuse_put_request(fc, req); 77531d40d74SMiklos Szeredi if (err == -ENOSYS) { 77631d40d74SMiklos Szeredi fc->no_access = 1; 77731d40d74SMiklos Szeredi err = 0; 77831d40d74SMiklos Szeredi } 77931d40d74SMiklos Szeredi return err; 78031d40d74SMiklos Szeredi } 78131d40d74SMiklos Szeredi 7826f9f1180SMiklos Szeredi /* 7836f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 7846f9f1180SMiklos Szeredi * 7856f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 7866f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 7876f9f1180SMiklos Szeredi * modell. 7886f9f1180SMiklos Szeredi * 7896f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 7906f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 7916f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 7926f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 7936f9f1180SMiklos Szeredi * locally based on file mode. 7946f9f1180SMiklos Szeredi */ 795e5e5558eSMiklos Szeredi static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) 796e5e5558eSMiklos Szeredi { 797e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 798e5e5558eSMiklos Szeredi 79987729a55SMiklos Szeredi if (!fuse_allow_task(fc, current)) 800e5e5558eSMiklos Szeredi return -EACCES; 8011e9a4ed9SMiklos Szeredi else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 8021e9a4ed9SMiklos Szeredi int err = generic_permission(inode, mask, NULL); 8031e9a4ed9SMiklos Szeredi 8041e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 8051e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 8061e9a4ed9SMiklos Szeredi node will at first have no permissions */ 8071e9a4ed9SMiklos Szeredi if (err == -EACCES) { 8081e9a4ed9SMiklos Szeredi err = fuse_do_getattr(inode); 8091e9a4ed9SMiklos Szeredi if (!err) 8101e9a4ed9SMiklos Szeredi err = generic_permission(inode, mask, NULL); 8111e9a4ed9SMiklos Szeredi } 8121e9a4ed9SMiklos Szeredi 8136f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 8146f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 8156f9f1180SMiklos Szeredi noticed immediately, only after the attribute 8166f9f1180SMiklos Szeredi timeout has expired */ 8171e9a4ed9SMiklos Szeredi 8181e9a4ed9SMiklos Szeredi return err; 8191e9a4ed9SMiklos Szeredi } else { 820e5e5558eSMiklos Szeredi int mode = inode->i_mode; 821e5e5558eSMiklos Szeredi if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) 822e5e5558eSMiklos Szeredi return -EACCES; 82331d40d74SMiklos Szeredi 824650a8983SMiklos Szeredi if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) 82531d40d74SMiklos Szeredi return fuse_access(inode, mask); 826e5e5558eSMiklos Szeredi return 0; 827e5e5558eSMiklos Szeredi } 828e5e5558eSMiklos Szeredi } 829e5e5558eSMiklos Szeredi 830e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file, 831e5e5558eSMiklos Szeredi void *dstbuf, filldir_t filldir) 832e5e5558eSMiklos Szeredi { 833e5e5558eSMiklos Szeredi while (nbytes >= FUSE_NAME_OFFSET) { 834e5e5558eSMiklos Szeredi struct fuse_dirent *dirent = (struct fuse_dirent *) buf; 835e5e5558eSMiklos Szeredi size_t reclen = FUSE_DIRENT_SIZE(dirent); 836e5e5558eSMiklos Szeredi int over; 837e5e5558eSMiklos Szeredi if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 838e5e5558eSMiklos Szeredi return -EIO; 839e5e5558eSMiklos Szeredi if (reclen > nbytes) 840e5e5558eSMiklos Szeredi break; 841e5e5558eSMiklos Szeredi 842e5e5558eSMiklos Szeredi over = filldir(dstbuf, dirent->name, dirent->namelen, 843e5e5558eSMiklos Szeredi file->f_pos, dirent->ino, dirent->type); 844e5e5558eSMiklos Szeredi if (over) 845e5e5558eSMiklos Szeredi break; 846e5e5558eSMiklos Szeredi 847e5e5558eSMiklos Szeredi buf += reclen; 848e5e5558eSMiklos Szeredi nbytes -= reclen; 849e5e5558eSMiklos Szeredi file->f_pos = dirent->off; 850e5e5558eSMiklos Szeredi } 851e5e5558eSMiklos Szeredi 852e5e5558eSMiklos Szeredi return 0; 853e5e5558eSMiklos Szeredi } 854e5e5558eSMiklos Szeredi 855e5e5558eSMiklos Szeredi static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) 856e5e5558eSMiklos Szeredi { 85704730fefSMiklos Szeredi int err; 85804730fefSMiklos Szeredi size_t nbytes; 85904730fefSMiklos Szeredi struct page *page; 8607706a9d6SJosef Sipek struct inode *inode = file->f_path.dentry->d_inode; 86104730fefSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 862248d86e8SMiklos Szeredi struct fuse_req *req; 863248d86e8SMiklos Szeredi 864248d86e8SMiklos Szeredi if (is_bad_inode(inode)) 865248d86e8SMiklos Szeredi return -EIO; 866248d86e8SMiklos Szeredi 867ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 868ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 869ce1d5a49SMiklos Szeredi return PTR_ERR(req); 870e5e5558eSMiklos Szeredi 87104730fefSMiklos Szeredi page = alloc_page(GFP_KERNEL); 87204730fefSMiklos Szeredi if (!page) { 87304730fefSMiklos Szeredi fuse_put_request(fc, req); 874e5e5558eSMiklos Szeredi return -ENOMEM; 87504730fefSMiklos Szeredi } 87604730fefSMiklos Szeredi req->num_pages = 1; 87704730fefSMiklos Szeredi req->pages[0] = page; 878361b1eb5SMiklos Szeredi fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); 879361b1eb5SMiklos Szeredi request_send(fc, req); 880361b1eb5SMiklos Szeredi nbytes = req->out.args[0].size; 88104730fefSMiklos Szeredi err = req->out.h.error; 88204730fefSMiklos Szeredi fuse_put_request(fc, req); 88304730fefSMiklos Szeredi if (!err) 88404730fefSMiklos Szeredi err = parse_dirfile(page_address(page), nbytes, file, dstbuf, 88504730fefSMiklos Szeredi filldir); 886e5e5558eSMiklos Szeredi 88704730fefSMiklos Szeredi __free_page(page); 888b36c31baSMiklos Szeredi fuse_invalidate_attr(inode); /* atime changed */ 88904730fefSMiklos Szeredi return err; 890e5e5558eSMiklos Szeredi } 891e5e5558eSMiklos Szeredi 892e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry) 893e5e5558eSMiklos Szeredi { 894e5e5558eSMiklos Szeredi struct inode *inode = dentry->d_inode; 895e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 896ce1d5a49SMiklos Szeredi struct fuse_req *req = fuse_get_req(fc); 897e5e5558eSMiklos Szeredi char *link; 898e5e5558eSMiklos Szeredi 899ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 900ce1d5a49SMiklos Szeredi return ERR_PTR(PTR_ERR(req)); 901e5e5558eSMiklos Szeredi 902e5e5558eSMiklos Szeredi link = (char *) __get_free_page(GFP_KERNEL); 903e5e5558eSMiklos Szeredi if (!link) { 904e5e5558eSMiklos Szeredi link = ERR_PTR(-ENOMEM); 905e5e5558eSMiklos Szeredi goto out; 906e5e5558eSMiklos Szeredi } 907e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_READLINK; 908e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 909e5e5558eSMiklos Szeredi req->out.argvar = 1; 910e5e5558eSMiklos Szeredi req->out.numargs = 1; 911e5e5558eSMiklos Szeredi req->out.args[0].size = PAGE_SIZE - 1; 912e5e5558eSMiklos Szeredi req->out.args[0].value = link; 913e5e5558eSMiklos Szeredi request_send(fc, req); 914e5e5558eSMiklos Szeredi if (req->out.h.error) { 915e5e5558eSMiklos Szeredi free_page((unsigned long) link); 916e5e5558eSMiklos Szeredi link = ERR_PTR(req->out.h.error); 917e5e5558eSMiklos Szeredi } else 918e5e5558eSMiklos Szeredi link[req->out.args[0].size] = '\0'; 919e5e5558eSMiklos Szeredi out: 920e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 921b36c31baSMiklos Szeredi fuse_invalidate_attr(inode); /* atime changed */ 922e5e5558eSMiklos Szeredi return link; 923e5e5558eSMiklos Szeredi } 924e5e5558eSMiklos Szeredi 925e5e5558eSMiklos Szeredi static void free_link(char *link) 926e5e5558eSMiklos Szeredi { 927e5e5558eSMiklos Szeredi if (!IS_ERR(link)) 928e5e5558eSMiklos Szeredi free_page((unsigned long) link); 929e5e5558eSMiklos Szeredi } 930e5e5558eSMiklos Szeredi 931e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd) 932e5e5558eSMiklos Szeredi { 933e5e5558eSMiklos Szeredi nd_set_link(nd, read_link(dentry)); 934e5e5558eSMiklos Szeredi return NULL; 935e5e5558eSMiklos Szeredi } 936e5e5558eSMiklos Szeredi 937e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c) 938e5e5558eSMiklos Szeredi { 939e5e5558eSMiklos Szeredi free_link(nd_get_link(nd)); 940e5e5558eSMiklos Szeredi } 941e5e5558eSMiklos Szeredi 942e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 943e5e5558eSMiklos Szeredi { 94404730fefSMiklos Szeredi return fuse_open_common(inode, file, 1); 945e5e5558eSMiklos Szeredi } 946e5e5558eSMiklos Szeredi 947e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 948e5e5558eSMiklos Szeredi { 94904730fefSMiklos Szeredi return fuse_release_common(inode, file, 1); 950e5e5558eSMiklos Szeredi } 951e5e5558eSMiklos Szeredi 95282547981SMiklos Szeredi static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) 95382547981SMiklos Szeredi { 95482547981SMiklos Szeredi /* nfsd can call this with no file */ 95582547981SMiklos Szeredi return file ? fuse_fsync_common(file, de, datasync, 1) : 0; 95682547981SMiklos Szeredi } 95782547981SMiklos Szeredi 958befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) 9599e6268dbSMiklos Szeredi { 9609e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 9619e6268dbSMiklos Szeredi 9629e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 963befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 9649e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 965befc649cSMiklos Szeredi arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid; 9669e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 967befc649cSMiklos Szeredi arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid; 9689e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 969befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 9709e6268dbSMiklos Szeredi /* You can only _set_ these together (they may change by themselves) */ 9719e6268dbSMiklos Szeredi if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) { 972befc649cSMiklos Szeredi arg->valid |= FATTR_ATIME | FATTR_MTIME; 973befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 974befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 9759e6268dbSMiklos Szeredi } 976befc649cSMiklos Szeredi if (ivalid & ATTR_FILE) { 977befc649cSMiklos Szeredi struct fuse_file *ff = iattr->ia_file->private_data; 978befc649cSMiklos Szeredi arg->valid |= FATTR_FH; 979befc649cSMiklos Szeredi arg->fh = ff->fh; 980befc649cSMiklos Szeredi } 9819e6268dbSMiklos Szeredi } 9829e6268dbSMiklos Szeredi 9839ffbb916SMiklos Szeredi static void fuse_vmtruncate(struct inode *inode, loff_t offset) 9849ffbb916SMiklos Szeredi { 9859ffbb916SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 9869ffbb916SMiklos Szeredi int need_trunc; 9879ffbb916SMiklos Szeredi 9889ffbb916SMiklos Szeredi spin_lock(&fc->lock); 9899ffbb916SMiklos Szeredi need_trunc = inode->i_size > offset; 9909ffbb916SMiklos Szeredi i_size_write(inode, offset); 9919ffbb916SMiklos Szeredi spin_unlock(&fc->lock); 9929ffbb916SMiklos Szeredi 9939ffbb916SMiklos Szeredi if (need_trunc) { 9949ffbb916SMiklos Szeredi struct address_space *mapping = inode->i_mapping; 9959ffbb916SMiklos Szeredi unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); 9969ffbb916SMiklos Szeredi truncate_inode_pages(mapping, offset); 9979ffbb916SMiklos Szeredi } 9989ffbb916SMiklos Szeredi } 9999ffbb916SMiklos Szeredi 10006f9f1180SMiklos Szeredi /* 10016f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 10026f9f1180SMiklos Szeredi * 10036f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 10046f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 10059ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 10069ffbb916SMiklos Szeredi * and the actual truncation by hand. 10076f9f1180SMiklos Szeredi */ 10089e6268dbSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 10099e6268dbSMiklos Szeredi { 10109e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 10119e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 10129e6268dbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 10139e6268dbSMiklos Szeredi struct fuse_req *req; 10149e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 10159e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 10169e6268dbSMiklos Szeredi int err; 10179e6268dbSMiklos Szeredi int is_truncate = 0; 10189e6268dbSMiklos Szeredi 10191e9a4ed9SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 10201e9a4ed9SMiklos Szeredi err = inode_change_ok(inode, attr); 10211e9a4ed9SMiklos Szeredi if (err) 10221e9a4ed9SMiklos Szeredi return err; 10231e9a4ed9SMiklos Szeredi } 10241e9a4ed9SMiklos Szeredi 10259e6268dbSMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 10269e6268dbSMiklos Szeredi unsigned long limit; 10279e6268dbSMiklos Szeredi is_truncate = 1; 1028b2d2272fSMiklos Szeredi if (IS_SWAPFILE(inode)) 1029b2d2272fSMiklos Szeredi return -ETXTBSY; 10309e6268dbSMiklos Szeredi limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; 10319e6268dbSMiklos Szeredi if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) { 10329e6268dbSMiklos Szeredi send_sig(SIGXFSZ, current, 0); 10339e6268dbSMiklos Szeredi return -EFBIG; 10349e6268dbSMiklos Szeredi } 10359e6268dbSMiklos Szeredi } 10369e6268dbSMiklos Szeredi 1037ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1038ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1039ce1d5a49SMiklos Szeredi return PTR_ERR(req); 10409e6268dbSMiklos Szeredi 10419e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1042befc649cSMiklos Szeredi iattr_to_fattr(attr, &inarg); 10439e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SETATTR; 10449e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 10459e6268dbSMiklos Szeredi req->in.numargs = 1; 10469e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 10479e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 10489e6268dbSMiklos Szeredi req->out.numargs = 1; 10499e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 10509e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 10519e6268dbSMiklos Szeredi request_send(fc, req); 10529e6268dbSMiklos Szeredi err = req->out.h.error; 10539e6268dbSMiklos Szeredi fuse_put_request(fc, req); 10549e6268dbSMiklos Szeredi if (!err) { 10559e6268dbSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 10569e6268dbSMiklos Szeredi make_bad_inode(inode); 10579e6268dbSMiklos Szeredi err = -EIO; 10589e6268dbSMiklos Szeredi } else { 10599ffbb916SMiklos Szeredi if (is_truncate) 10609ffbb916SMiklos Szeredi fuse_vmtruncate(inode, outarg.attr.size); 10619e6268dbSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr); 10629e6268dbSMiklos Szeredi fi->i_time = time_to_jiffies(outarg.attr_valid, 10639e6268dbSMiklos Szeredi outarg.attr_valid_nsec); 10649e6268dbSMiklos Szeredi } 10659e6268dbSMiklos Szeredi } else if (err == -EINTR) 10669e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 10679e6268dbSMiklos Szeredi 10689e6268dbSMiklos Szeredi return err; 10699e6268dbSMiklos Szeredi } 10709e6268dbSMiklos Szeredi 1071e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, 1072e5e5558eSMiklos Szeredi struct kstat *stat) 1073e5e5558eSMiklos Szeredi { 1074e5e5558eSMiklos Szeredi struct inode *inode = entry->d_inode; 1075e5e5558eSMiklos Szeredi int err = fuse_revalidate(entry); 1076e5e5558eSMiklos Szeredi if (!err) 1077e5e5558eSMiklos Szeredi generic_fillattr(inode, stat); 1078e5e5558eSMiklos Szeredi 1079e5e5558eSMiklos Szeredi return err; 1080e5e5558eSMiklos Szeredi } 1081e5e5558eSMiklos Szeredi 108292a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name, 108392a8780eSMiklos Szeredi const void *value, size_t size, int flags) 108492a8780eSMiklos Szeredi { 108592a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 108692a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 108792a8780eSMiklos Szeredi struct fuse_req *req; 108892a8780eSMiklos Szeredi struct fuse_setxattr_in inarg; 108992a8780eSMiklos Szeredi int err; 109092a8780eSMiklos Szeredi 109192a8780eSMiklos Szeredi if (fc->no_setxattr) 109292a8780eSMiklos Szeredi return -EOPNOTSUPP; 109392a8780eSMiklos Szeredi 1094ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1095ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1096ce1d5a49SMiklos Szeredi return PTR_ERR(req); 109792a8780eSMiklos Szeredi 109892a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 109992a8780eSMiklos Szeredi inarg.size = size; 110092a8780eSMiklos Szeredi inarg.flags = flags; 110192a8780eSMiklos Szeredi req->in.h.opcode = FUSE_SETXATTR; 110292a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 110392a8780eSMiklos Szeredi req->in.numargs = 3; 110492a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 110592a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 110692a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 110792a8780eSMiklos Szeredi req->in.args[1].value = name; 110892a8780eSMiklos Szeredi req->in.args[2].size = size; 110992a8780eSMiklos Szeredi req->in.args[2].value = value; 111092a8780eSMiklos Szeredi request_send(fc, req); 111192a8780eSMiklos Szeredi err = req->out.h.error; 111292a8780eSMiklos Szeredi fuse_put_request(fc, req); 111392a8780eSMiklos Szeredi if (err == -ENOSYS) { 111492a8780eSMiklos Szeredi fc->no_setxattr = 1; 111592a8780eSMiklos Szeredi err = -EOPNOTSUPP; 111692a8780eSMiklos Szeredi } 111792a8780eSMiklos Szeredi return err; 111892a8780eSMiklos Szeredi } 111992a8780eSMiklos Szeredi 112092a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name, 112192a8780eSMiklos Szeredi void *value, size_t size) 112292a8780eSMiklos Szeredi { 112392a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 112492a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 112592a8780eSMiklos Szeredi struct fuse_req *req; 112692a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 112792a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 112892a8780eSMiklos Szeredi ssize_t ret; 112992a8780eSMiklos Szeredi 113092a8780eSMiklos Szeredi if (fc->no_getxattr) 113192a8780eSMiklos Szeredi return -EOPNOTSUPP; 113292a8780eSMiklos Szeredi 1133ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1134ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1135ce1d5a49SMiklos Szeredi return PTR_ERR(req); 113692a8780eSMiklos Szeredi 113792a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 113892a8780eSMiklos Szeredi inarg.size = size; 113992a8780eSMiklos Szeredi req->in.h.opcode = FUSE_GETXATTR; 114092a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 114192a8780eSMiklos Szeredi req->in.numargs = 2; 114292a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 114392a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 114492a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 114592a8780eSMiklos Szeredi req->in.args[1].value = name; 114692a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 114792a8780eSMiklos Szeredi req->out.numargs = 1; 114892a8780eSMiklos Szeredi if (size) { 114992a8780eSMiklos Szeredi req->out.argvar = 1; 115092a8780eSMiklos Szeredi req->out.args[0].size = size; 115192a8780eSMiklos Szeredi req->out.args[0].value = value; 115292a8780eSMiklos Szeredi } else { 115392a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 115492a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 115592a8780eSMiklos Szeredi } 115692a8780eSMiklos Szeredi request_send(fc, req); 115792a8780eSMiklos Szeredi ret = req->out.h.error; 115892a8780eSMiklos Szeredi if (!ret) 115992a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 116092a8780eSMiklos Szeredi else { 116192a8780eSMiklos Szeredi if (ret == -ENOSYS) { 116292a8780eSMiklos Szeredi fc->no_getxattr = 1; 116392a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 116492a8780eSMiklos Szeredi } 116592a8780eSMiklos Szeredi } 116692a8780eSMiklos Szeredi fuse_put_request(fc, req); 116792a8780eSMiklos Szeredi return ret; 116892a8780eSMiklos Szeredi } 116992a8780eSMiklos Szeredi 117092a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) 117192a8780eSMiklos Szeredi { 117292a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 117392a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 117492a8780eSMiklos Szeredi struct fuse_req *req; 117592a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 117692a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 117792a8780eSMiklos Szeredi ssize_t ret; 117892a8780eSMiklos Szeredi 117992a8780eSMiklos Szeredi if (fc->no_listxattr) 118092a8780eSMiklos Szeredi return -EOPNOTSUPP; 118192a8780eSMiklos Szeredi 1182ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1183ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1184ce1d5a49SMiklos Szeredi return PTR_ERR(req); 118592a8780eSMiklos Szeredi 118692a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 118792a8780eSMiklos Szeredi inarg.size = size; 118892a8780eSMiklos Szeredi req->in.h.opcode = FUSE_LISTXATTR; 118992a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 119092a8780eSMiklos Szeredi req->in.numargs = 1; 119192a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 119292a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 119392a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 119492a8780eSMiklos Szeredi req->out.numargs = 1; 119592a8780eSMiklos Szeredi if (size) { 119692a8780eSMiklos Szeredi req->out.argvar = 1; 119792a8780eSMiklos Szeredi req->out.args[0].size = size; 119892a8780eSMiklos Szeredi req->out.args[0].value = list; 119992a8780eSMiklos Szeredi } else { 120092a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 120192a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 120292a8780eSMiklos Szeredi } 120392a8780eSMiklos Szeredi request_send(fc, req); 120492a8780eSMiklos Szeredi ret = req->out.h.error; 120592a8780eSMiklos Szeredi if (!ret) 120692a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 120792a8780eSMiklos Szeredi else { 120892a8780eSMiklos Szeredi if (ret == -ENOSYS) { 120992a8780eSMiklos Szeredi fc->no_listxattr = 1; 121092a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 121192a8780eSMiklos Szeredi } 121292a8780eSMiklos Szeredi } 121392a8780eSMiklos Szeredi fuse_put_request(fc, req); 121492a8780eSMiklos Szeredi return ret; 121592a8780eSMiklos Szeredi } 121692a8780eSMiklos Szeredi 121792a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name) 121892a8780eSMiklos Szeredi { 121992a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 122092a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 122192a8780eSMiklos Szeredi struct fuse_req *req; 122292a8780eSMiklos Szeredi int err; 122392a8780eSMiklos Szeredi 122492a8780eSMiklos Szeredi if (fc->no_removexattr) 122592a8780eSMiklos Szeredi return -EOPNOTSUPP; 122692a8780eSMiklos Szeredi 1227ce1d5a49SMiklos Szeredi req = fuse_get_req(fc); 1228ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1229ce1d5a49SMiklos Szeredi return PTR_ERR(req); 123092a8780eSMiklos Szeredi 123192a8780eSMiklos Szeredi req->in.h.opcode = FUSE_REMOVEXATTR; 123292a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 123392a8780eSMiklos Szeredi req->in.numargs = 1; 123492a8780eSMiklos Szeredi req->in.args[0].size = strlen(name) + 1; 123592a8780eSMiklos Szeredi req->in.args[0].value = name; 123692a8780eSMiklos Szeredi request_send(fc, req); 123792a8780eSMiklos Szeredi err = req->out.h.error; 123892a8780eSMiklos Szeredi fuse_put_request(fc, req); 123992a8780eSMiklos Szeredi if (err == -ENOSYS) { 124092a8780eSMiklos Szeredi fc->no_removexattr = 1; 124192a8780eSMiklos Szeredi err = -EOPNOTSUPP; 124292a8780eSMiklos Szeredi } 124392a8780eSMiklos Szeredi return err; 124492a8780eSMiklos Szeredi } 124592a8780eSMiklos Szeredi 1246754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1247e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 12489e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 12499e6268dbSMiklos Szeredi .symlink = fuse_symlink, 12509e6268dbSMiklos Szeredi .unlink = fuse_unlink, 12519e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 12529e6268dbSMiklos Szeredi .rename = fuse_rename, 12539e6268dbSMiklos Szeredi .link = fuse_link, 12549e6268dbSMiklos Szeredi .setattr = fuse_setattr, 12559e6268dbSMiklos Szeredi .create = fuse_create, 12569e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1257e5e5558eSMiklos Szeredi .permission = fuse_permission, 1258e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 125992a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 126092a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 126192a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 126292a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1263e5e5558eSMiklos Szeredi }; 1264e5e5558eSMiklos Szeredi 12654b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1266b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1267e5e5558eSMiklos Szeredi .read = generic_read_dir, 1268e5e5558eSMiklos Szeredi .readdir = fuse_readdir, 1269e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1270e5e5558eSMiklos Szeredi .release = fuse_dir_release, 127182547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1272e5e5558eSMiklos Szeredi }; 1273e5e5558eSMiklos Szeredi 1274754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 12759e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1276e5e5558eSMiklos Szeredi .permission = fuse_permission, 1277e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 127892a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 127992a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 128092a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 128192a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1282e5e5558eSMiklos Szeredi }; 1283e5e5558eSMiklos Szeredi 1284754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 12859e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1286e5e5558eSMiklos Szeredi .follow_link = fuse_follow_link, 1287e5e5558eSMiklos Szeredi .put_link = fuse_put_link, 1288e5e5558eSMiklos Szeredi .readlink = generic_readlink, 1289e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 129092a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 129192a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 129292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 129392a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1294e5e5558eSMiklos Szeredi }; 1295e5e5558eSMiklos Szeredi 1296e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1297e5e5558eSMiklos Szeredi { 1298e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1299e5e5558eSMiklos Szeredi } 1300e5e5558eSMiklos Szeredi 1301e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1302e5e5558eSMiklos Szeredi { 1303e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1304e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1305e5e5558eSMiklos Szeredi } 1306e5e5558eSMiklos Szeredi 1307e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1308e5e5558eSMiklos Szeredi { 1309e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 1310e5e5558eSMiklos Szeredi } 1311