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 178d3af7f3SAl Viro static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx) 184582a4abSFeng Shuo { 194582a4abSFeng Shuo struct fuse_conn *fc = get_fuse_conn(dir); 204582a4abSFeng Shuo struct fuse_inode *fi = get_fuse_inode(dir); 214582a4abSFeng Shuo 224582a4abSFeng Shuo if (!fc->do_readdirplus) 234582a4abSFeng Shuo return false; 24634734b6SEric Wong if (!fc->readdirplus_auto) 25634734b6SEric Wong return true; 264582a4abSFeng Shuo if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state)) 274582a4abSFeng Shuo return true; 288d3af7f3SAl Viro if (ctx->pos == 0) 294582a4abSFeng Shuo return true; 304582a4abSFeng Shuo return false; 314582a4abSFeng Shuo } 324582a4abSFeng Shuo 334582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir) 344582a4abSFeng Shuo { 354582a4abSFeng Shuo struct fuse_inode *fi = get_fuse_inode(dir); 364582a4abSFeng Shuo 374582a4abSFeng Shuo set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state); 384582a4abSFeng Shuo } 394582a4abSFeng Shuo 400a0898cfSMiklos Szeredi #if BITS_PER_LONG >= 64 410a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time) 420a0898cfSMiklos Szeredi { 430a0898cfSMiklos Szeredi entry->d_time = time; 440a0898cfSMiklos Szeredi } 450a0898cfSMiklos Szeredi 460a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry) 470a0898cfSMiklos Szeredi { 480a0898cfSMiklos Szeredi return entry->d_time; 490a0898cfSMiklos Szeredi } 500a0898cfSMiklos Szeredi #else 510a0898cfSMiklos Szeredi /* 520a0898cfSMiklos Szeredi * On 32 bit archs store the high 32 bits of time in d_fsdata 530a0898cfSMiklos Szeredi */ 540a0898cfSMiklos Szeredi static void fuse_dentry_settime(struct dentry *entry, u64 time) 550a0898cfSMiklos Szeredi { 560a0898cfSMiklos Szeredi entry->d_time = time; 570a0898cfSMiklos Szeredi entry->d_fsdata = (void *) (unsigned long) (time >> 32); 580a0898cfSMiklos Szeredi } 590a0898cfSMiklos Szeredi 600a0898cfSMiklos Szeredi static u64 fuse_dentry_time(struct dentry *entry) 610a0898cfSMiklos Szeredi { 620a0898cfSMiklos Szeredi return (u64) entry->d_time + 630a0898cfSMiklos Szeredi ((u64) (unsigned long) entry->d_fsdata << 32); 640a0898cfSMiklos Szeredi } 650a0898cfSMiklos Szeredi #endif 660a0898cfSMiklos Szeredi 676f9f1180SMiklos Szeredi /* 686f9f1180SMiklos Szeredi * FUSE caches dentries and attributes with separate timeout. The 696f9f1180SMiklos Szeredi * time in jiffies until the dentry/attributes are valid is stored in 706f9f1180SMiklos Szeredi * dentry->d_time and fuse_inode->i_time respectively. 716f9f1180SMiklos Szeredi */ 726f9f1180SMiklos Szeredi 736f9f1180SMiklos Szeredi /* 746f9f1180SMiklos Szeredi * Calculate the time in jiffies until a dentry/attributes are valid 756f9f1180SMiklos Szeredi */ 760a0898cfSMiklos Szeredi static u64 time_to_jiffies(unsigned long sec, unsigned long nsec) 77e5e5558eSMiklos Szeredi { 78685d16ddSMiklos Szeredi if (sec || nsec) { 79e5e5558eSMiklos Szeredi struct timespec ts = {sec, nsec}; 800a0898cfSMiklos Szeredi return get_jiffies_64() + timespec_to_jiffies(&ts); 81685d16ddSMiklos Szeredi } else 820a0898cfSMiklos Szeredi return 0; 83e5e5558eSMiklos Szeredi } 84e5e5558eSMiklos Szeredi 856f9f1180SMiklos Szeredi /* 866f9f1180SMiklos Szeredi * Set dentry and possibly attribute timeouts from the lookup/mk* 876f9f1180SMiklos Szeredi * replies 886f9f1180SMiklos Szeredi */ 891fb69e78SMiklos Szeredi static void fuse_change_entry_timeout(struct dentry *entry, 901fb69e78SMiklos Szeredi struct fuse_entry_out *o) 910aa7c699SMiklos Szeredi { 920a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 930a0898cfSMiklos Szeredi time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 941fb69e78SMiklos Szeredi } 951fb69e78SMiklos Szeredi 961fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o) 971fb69e78SMiklos Szeredi { 981fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 991fb69e78SMiklos Szeredi } 1001fb69e78SMiklos Szeredi 1011fb69e78SMiklos Szeredi static u64 entry_attr_timeout(struct fuse_entry_out *o) 1021fb69e78SMiklos Szeredi { 1031fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 1048cbdf1e6SMiklos Szeredi } 1058cbdf1e6SMiklos Szeredi 1066f9f1180SMiklos Szeredi /* 1076f9f1180SMiklos Szeredi * Mark the attributes as stale, so that at the next call to 1086f9f1180SMiklos Szeredi * ->getattr() they will be fetched from userspace 1096f9f1180SMiklos Szeredi */ 1108cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode) 1118cbdf1e6SMiklos Szeredi { 1120a0898cfSMiklos Szeredi get_fuse_inode(inode)->i_time = 0; 1138cbdf1e6SMiklos Szeredi } 1148cbdf1e6SMiklos Szeredi 115*451418fcSAndrew Gallagher /** 116*451418fcSAndrew Gallagher * Mark the attributes as stale due to an atime change. Avoid the invalidate if 117*451418fcSAndrew Gallagher * atime is not used. 118*451418fcSAndrew Gallagher */ 119*451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode) 120*451418fcSAndrew Gallagher { 121*451418fcSAndrew Gallagher if (!IS_RDONLY(inode)) 122*451418fcSAndrew Gallagher fuse_invalidate_attr(inode); 123*451418fcSAndrew Gallagher } 124*451418fcSAndrew Gallagher 1256f9f1180SMiklos Szeredi /* 1266f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 1276f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 1286f9f1180SMiklos Szeredi * 1296f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 1306f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 1316f9f1180SMiklos Szeredi * lookup) 1326f9f1180SMiklos Szeredi */ 133dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry) 1348cbdf1e6SMiklos Szeredi { 1350a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 1368cbdf1e6SMiklos Szeredi } 1378cbdf1e6SMiklos Szeredi 1386f9f1180SMiklos Szeredi /* 1396f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 1406f9f1180SMiklos Szeredi * dentry from the hash 1416f9f1180SMiklos Szeredi */ 1428cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1438cbdf1e6SMiklos Szeredi { 1448cbdf1e6SMiklos Szeredi d_invalidate(entry); 1458cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1460aa7c699SMiklos Szeredi } 1470aa7c699SMiklos Szeredi 148c180eebeSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req, 149c180eebeSMiklos Szeredi u64 nodeid, struct qstr *name, 150e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 151e5e5558eSMiklos Szeredi { 1520e9663eeSMiklos Szeredi memset(outarg, 0, sizeof(struct fuse_entry_out)); 153e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_LOOKUP; 154c180eebeSMiklos Szeredi req->in.h.nodeid = nodeid; 155e5e5558eSMiklos Szeredi req->in.numargs = 1; 156c180eebeSMiklos Szeredi req->in.args[0].size = name->len + 1; 157c180eebeSMiklos Szeredi req->in.args[0].value = name->name; 158e5e5558eSMiklos Szeredi req->out.numargs = 1; 1590e9663eeSMiklos Szeredi if (fc->minor < 9) 1600e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 1610e9663eeSMiklos Szeredi else 162e5e5558eSMiklos Szeredi req->out.args[0].size = sizeof(struct fuse_entry_out); 163e5e5558eSMiklos Szeredi req->out.args[0].value = outarg; 164e5e5558eSMiklos Szeredi } 165e5e5558eSMiklos Szeredi 1665c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc) 1677dca9fd3SMiklos Szeredi { 1687dca9fd3SMiklos Szeredi u64 curr_version; 1697dca9fd3SMiklos Szeredi 1707dca9fd3SMiklos Szeredi /* 1717dca9fd3SMiklos Szeredi * The spin lock isn't actually needed on 64bit archs, but we 1727dca9fd3SMiklos Szeredi * don't yet care too much about such optimizations. 1737dca9fd3SMiklos Szeredi */ 1747dca9fd3SMiklos Szeredi spin_lock(&fc->lock); 1757dca9fd3SMiklos Szeredi curr_version = fc->attr_version; 1767dca9fd3SMiklos Szeredi spin_unlock(&fc->lock); 1777dca9fd3SMiklos Szeredi 1787dca9fd3SMiklos Szeredi return curr_version; 1797dca9fd3SMiklos Szeredi } 1807dca9fd3SMiklos Szeredi 1816f9f1180SMiklos Szeredi /* 1826f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1836f9f1180SMiklos Szeredi * 1846f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 1856f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 1866f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 1876f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 1886f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 1896f9f1180SMiklos Szeredi */ 1900b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) 191e5e5558eSMiklos Szeredi { 19234286d66SNick Piggin struct inode *inode; 19328420dadSMiklos Szeredi struct dentry *parent; 19428420dadSMiklos Szeredi struct fuse_conn *fc; 1956314efeeSMiklos Szeredi struct fuse_inode *fi; 196e2a6b952SMiklos Szeredi int ret; 1978cbdf1e6SMiklos Szeredi 198e7c0a167SMiklos Szeredi inode = ACCESS_ONCE(entry->d_inode); 1998cbdf1e6SMiklos Szeredi if (inode && is_bad_inode(inode)) 200e2a6b952SMiklos Szeredi goto invalid; 2010a0898cfSMiklos Szeredi else if (fuse_dentry_time(entry) < get_jiffies_64()) { 202e5e5558eSMiklos Szeredi int err; 203e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 2048cbdf1e6SMiklos Szeredi struct fuse_req *req; 20507e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 2061fb69e78SMiklos Szeredi u64 attr_version; 2078cbdf1e6SMiklos Szeredi 20850322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 2098cbdf1e6SMiklos Szeredi if (!inode) 210e2a6b952SMiklos Szeredi goto invalid; 2118cbdf1e6SMiklos Szeredi 212e2a6b952SMiklos Szeredi ret = -ECHILD; 2130b728e19SAl Viro if (flags & LOOKUP_RCU) 214e2a6b952SMiklos Szeredi goto out; 215e7c0a167SMiklos Szeredi 2168cbdf1e6SMiklos Szeredi fc = get_fuse_conn(inode); 217b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 218e2a6b952SMiklos Szeredi ret = PTR_ERR(req); 219ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 220e2a6b952SMiklos Szeredi goto out; 221e5e5558eSMiklos Szeredi 22207e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 22307e77dcaSMiklos Szeredi if (!forget) { 2242d51013eSMiklos Szeredi fuse_put_request(fc, req); 225e2a6b952SMiklos Szeredi ret = -ENOMEM; 226e2a6b952SMiklos Szeredi goto out; 2272d51013eSMiklos Szeredi } 2282d51013eSMiklos Szeredi 2297dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 2301fb69e78SMiklos Szeredi 231e956edd0SMiklos Szeredi parent = dget_parent(entry); 232c180eebeSMiklos Szeredi fuse_lookup_init(fc, req, get_node_id(parent->d_inode), 233c180eebeSMiklos Szeredi &entry->d_name, &outarg); 234b93f858aSTejun Heo fuse_request_send(fc, req); 235e956edd0SMiklos Szeredi dput(parent); 236e5e5558eSMiklos Szeredi err = req->out.h.error; 2372d51013eSMiklos Szeredi fuse_put_request(fc, req); 23850322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 23950322fe7SMiklos Szeredi if (!err && !outarg.nodeid) 24050322fe7SMiklos Szeredi err = -ENOENT; 2419e6268dbSMiklos Szeredi if (!err) { 2426314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2439e6268dbSMiklos Szeredi if (outarg.nodeid != get_node_id(inode)) { 24407e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 245e2a6b952SMiklos Szeredi goto invalid; 2469e6268dbSMiklos Szeredi } 2478da5ff23SMiklos Szeredi spin_lock(&fc->lock); 2489e6268dbSMiklos Szeredi fi->nlookup++; 2498da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 2509e6268dbSMiklos Szeredi } 25107e77dcaSMiklos Szeredi kfree(forget); 2529e6268dbSMiklos Szeredi if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 253e2a6b952SMiklos Szeredi goto invalid; 254e5e5558eSMiklos Szeredi 2551fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2561fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2571fb69e78SMiklos Szeredi attr_version); 2581fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 25928420dadSMiklos Szeredi } else if (inode) { 2606314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2616314efeeSMiklos Szeredi if (flags & LOOKUP_RCU) { 2626314efeeSMiklos Szeredi if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) 2636314efeeSMiklos Szeredi return -ECHILD; 2646314efeeSMiklos Szeredi } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { 26528420dadSMiklos Szeredi parent = dget_parent(entry); 26628420dadSMiklos Szeredi fuse_advise_use_readdirplus(parent->d_inode); 26728420dadSMiklos Szeredi dput(parent); 268e5e5558eSMiklos Szeredi } 26928420dadSMiklos Szeredi } 270e2a6b952SMiklos Szeredi ret = 1; 271e2a6b952SMiklos Szeredi out: 272e2a6b952SMiklos Szeredi return ret; 273e2a6b952SMiklos Szeredi 274e2a6b952SMiklos Szeredi invalid: 275e2a6b952SMiklos Szeredi ret = 0; 2763c70b8eeSMiklos Szeredi 2773c70b8eeSMiklos Szeredi if (!(flags & LOOKUP_RCU) && check_submounts_and_drop(entry) != 0) 27846ea1562SAnand Avati ret = 1; 279e2a6b952SMiklos Szeredi goto out; 280e5e5558eSMiklos Szeredi } 281e5e5558eSMiklos Szeredi 2828bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid) 2832827d0b2SMiklos Szeredi { 2842827d0b2SMiklos Szeredi return !nodeid || nodeid == FUSE_ROOT_ID; 2852827d0b2SMiklos Szeredi } 2862827d0b2SMiklos Szeredi 2874269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 288e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 289e5e5558eSMiklos Szeredi }; 290e5e5558eSMiklos Szeredi 291a5bfffacSTimo Savola int fuse_valid_type(int m) 29239ee059aSMiklos Szeredi { 29339ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 29439ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 29539ee059aSMiklos Szeredi } 29639ee059aSMiklos Szeredi 297c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, 298c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 299c180eebeSMiklos Szeredi { 300c180eebeSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 301c180eebeSMiklos Szeredi struct fuse_req *req; 30207e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 303c180eebeSMiklos Szeredi u64 attr_version; 304c180eebeSMiklos Szeredi int err; 305c180eebeSMiklos Szeredi 306c180eebeSMiklos Szeredi *inode = NULL; 307c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 308c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 309c180eebeSMiklos Szeredi goto out; 310c180eebeSMiklos Szeredi 311b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 312c180eebeSMiklos Szeredi err = PTR_ERR(req); 313c180eebeSMiklos Szeredi if (IS_ERR(req)) 314c180eebeSMiklos Szeredi goto out; 315c180eebeSMiklos Szeredi 31607e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 31707e77dcaSMiklos Szeredi err = -ENOMEM; 31807e77dcaSMiklos Szeredi if (!forget) { 319c180eebeSMiklos Szeredi fuse_put_request(fc, req); 320c180eebeSMiklos Szeredi goto out; 321c180eebeSMiklos Szeredi } 322c180eebeSMiklos Szeredi 323c180eebeSMiklos Szeredi attr_version = fuse_get_attr_version(fc); 324c180eebeSMiklos Szeredi 325c180eebeSMiklos Szeredi fuse_lookup_init(fc, req, nodeid, name, outarg); 326b93f858aSTejun Heo fuse_request_send(fc, req); 327c180eebeSMiklos Szeredi err = req->out.h.error; 328c180eebeSMiklos Szeredi fuse_put_request(fc, req); 329c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 330c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 331c180eebeSMiklos Szeredi goto out_put_forget; 332c180eebeSMiklos Szeredi 333c180eebeSMiklos Szeredi err = -EIO; 334c180eebeSMiklos Szeredi if (!outarg->nodeid) 335c180eebeSMiklos Szeredi goto out_put_forget; 336c180eebeSMiklos Szeredi if (!fuse_valid_type(outarg->attr.mode)) 337c180eebeSMiklos Szeredi goto out_put_forget; 338c180eebeSMiklos Szeredi 339c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 340c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 341c180eebeSMiklos Szeredi attr_version); 342c180eebeSMiklos Szeredi err = -ENOMEM; 343c180eebeSMiklos Szeredi if (!*inode) { 34407e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg->nodeid, 1); 345c180eebeSMiklos Szeredi goto out; 346c180eebeSMiklos Szeredi } 347c180eebeSMiklos Szeredi err = 0; 348c180eebeSMiklos Szeredi 349c180eebeSMiklos Szeredi out_put_forget: 35007e77dcaSMiklos Szeredi kfree(forget); 351c180eebeSMiklos Szeredi out: 352c180eebeSMiklos Szeredi return err; 353c180eebeSMiklos Szeredi } 354c180eebeSMiklos Szeredi 3550aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 35600cd8dd3SAl Viro unsigned int flags) 357e5e5558eSMiklos Szeredi { 358e5e5558eSMiklos Szeredi int err; 359e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 360c180eebeSMiklos Szeredi struct inode *inode; 3610de6256dSMiklos Szeredi struct dentry *newent; 362c180eebeSMiklos Szeredi bool outarg_valid = true; 363e5e5558eSMiklos Szeredi 364c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 365c180eebeSMiklos Szeredi &outarg, &inode); 366c180eebeSMiklos Szeredi if (err == -ENOENT) { 367c180eebeSMiklos Szeredi outarg_valid = false; 368c180eebeSMiklos Szeredi err = 0; 3692d51013eSMiklos Szeredi } 370c180eebeSMiklos Szeredi if (err) 371c180eebeSMiklos Szeredi goto out_err; 3722d51013eSMiklos Szeredi 373ee4e5271SMiklos Szeredi err = -EIO; 374c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 375c180eebeSMiklos Szeredi goto out_iput; 376e5e5558eSMiklos Szeredi 377b70a80e7SMiklos Szeredi newent = d_materialise_unique(entry, inode); 378c180eebeSMiklos Szeredi err = PTR_ERR(newent); 379c180eebeSMiklos Szeredi if (IS_ERR(newent)) 3805835f339SMiklos Szeredi goto out_err; 381d2a85164SMiklos Szeredi 3820de6256dSMiklos Szeredi entry = newent ? newent : entry; 383c180eebeSMiklos Szeredi if (outarg_valid) 3841fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 3858cbdf1e6SMiklos Szeredi else 3868cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 387c180eebeSMiklos Szeredi 3884582a4abSFeng Shuo fuse_advise_use_readdirplus(dir); 3890de6256dSMiklos Szeredi return newent; 390c180eebeSMiklos Szeredi 391c180eebeSMiklos Szeredi out_iput: 392c180eebeSMiklos Szeredi iput(inode); 393c180eebeSMiklos Szeredi out_err: 394c180eebeSMiklos Szeredi return ERR_PTR(err); 395e5e5558eSMiklos Szeredi } 396e5e5558eSMiklos Szeredi 3976f9f1180SMiklos Szeredi /* 3986f9f1180SMiklos Szeredi * Atomic create+open operation 3996f9f1180SMiklos Szeredi * 4006f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 4016f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 4026f9f1180SMiklos Szeredi */ 403d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 40430d90494SAl Viro struct file *file, unsigned flags, 40547237687SAl Viro umode_t mode, int *opened) 406fd72faacSMiklos Szeredi { 407fd72faacSMiklos Szeredi int err; 408fd72faacSMiklos Szeredi struct inode *inode; 409fd72faacSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 410fd72faacSMiklos Szeredi struct fuse_req *req; 41107e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 412e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 413fd72faacSMiklos Szeredi struct fuse_open_out outopen; 414fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 415fd72faacSMiklos Szeredi struct fuse_file *ff; 416fd72faacSMiklos Szeredi 417af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 418af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 419af109bcaSMiklos Szeredi 42007e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 421c8ccbe03SMiklos Szeredi err = -ENOMEM; 42207e77dcaSMiklos Szeredi if (!forget) 423c8ccbe03SMiklos Szeredi goto out_err; 42451eb01e7SMiklos Szeredi 425b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 42651eb01e7SMiklos Szeredi err = PTR_ERR(req); 427ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 42851eb01e7SMiklos Szeredi goto out_put_forget_req; 429fd72faacSMiklos Szeredi 430ce1d5a49SMiklos Szeredi err = -ENOMEM; 431acf99433STejun Heo ff = fuse_file_alloc(fc); 432fd72faacSMiklos Szeredi if (!ff) 433fd72faacSMiklos Szeredi goto out_put_request; 434fd72faacSMiklos Szeredi 435e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 436e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 437e0a43ddcSMiklos Szeredi 438fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 439fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4400e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 441fd72faacSMiklos Szeredi inarg.flags = flags; 442fd72faacSMiklos Szeredi inarg.mode = mode; 443e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 444fd72faacSMiklos Szeredi req->in.h.opcode = FUSE_CREATE; 445fd72faacSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 446fd72faacSMiklos Szeredi req->in.numargs = 2; 447e0a43ddcSMiklos Szeredi req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) : 448e0a43ddcSMiklos Szeredi sizeof(inarg); 449fd72faacSMiklos Szeredi req->in.args[0].value = &inarg; 450fd72faacSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 451fd72faacSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 452fd72faacSMiklos Szeredi req->out.numargs = 2; 4530e9663eeSMiklos Szeredi if (fc->minor < 9) 4540e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 4550e9663eeSMiklos Szeredi else 456fd72faacSMiklos Szeredi req->out.args[0].size = sizeof(outentry); 457fd72faacSMiklos Szeredi req->out.args[0].value = &outentry; 458fd72faacSMiklos Szeredi req->out.args[1].size = sizeof(outopen); 459fd72faacSMiklos Szeredi req->out.args[1].value = &outopen; 460b93f858aSTejun Heo fuse_request_send(fc, req); 461fd72faacSMiklos Szeredi err = req->out.h.error; 462c8ccbe03SMiklos Szeredi if (err) 463fd72faacSMiklos Szeredi goto out_free_ff; 464fd72faacSMiklos Szeredi 465fd72faacSMiklos Szeredi err = -EIO; 4662827d0b2SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 467fd72faacSMiklos Szeredi goto out_free_ff; 468fd72faacSMiklos Szeredi 46951eb01e7SMiklos Szeredi fuse_put_request(fc, req); 470c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 471c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 472c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 473fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 4741fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 475fd72faacSMiklos Szeredi if (!inode) { 476fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 4778b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 47807e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outentry.nodeid, 1); 479c8ccbe03SMiklos Szeredi err = -ENOMEM; 480c8ccbe03SMiklos Szeredi goto out_err; 481fd72faacSMiklos Szeredi } 48207e77dcaSMiklos Szeredi kfree(forget); 483fd72faacSMiklos Szeredi d_instantiate(entry, inode); 4841fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 4850952b2a4SMiklos Szeredi fuse_invalidate_attr(dir); 48630d90494SAl Viro err = finish_open(file, entry, generic_file_open, opened); 48730d90494SAl Viro if (err) { 4888b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 489c8ccbe03SMiklos Szeredi } else { 490c7b7143cSMiklos Szeredi file->private_data = fuse_file_get(ff); 491c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 492c8ccbe03SMiklos Szeredi } 493d9585277SAl Viro return err; 494fd72faacSMiklos Szeredi 495fd72faacSMiklos Szeredi out_free_ff: 496fd72faacSMiklos Szeredi fuse_file_free(ff); 497fd72faacSMiklos Szeredi out_put_request: 498fd72faacSMiklos Szeredi fuse_put_request(fc, req); 49951eb01e7SMiklos Szeredi out_put_forget_req: 50007e77dcaSMiklos Szeredi kfree(forget); 501c8ccbe03SMiklos Szeredi out_err: 502d9585277SAl Viro return err; 503c8ccbe03SMiklos Szeredi } 504c8ccbe03SMiklos Szeredi 505c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); 506d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 50730d90494SAl Viro struct file *file, unsigned flags, 50847237687SAl Viro umode_t mode, int *opened) 509c8ccbe03SMiklos Szeredi { 510c8ccbe03SMiklos Szeredi int err; 511c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 512c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 513c8ccbe03SMiklos Szeredi 514c8ccbe03SMiklos Szeredi if (d_unhashed(entry)) { 51500cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 516c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 517d9585277SAl Viro return PTR_ERR(res); 518c8ccbe03SMiklos Szeredi 519c8ccbe03SMiklos Szeredi if (res) 520c8ccbe03SMiklos Szeredi entry = res; 521c8ccbe03SMiklos Szeredi } 522c8ccbe03SMiklos Szeredi 523c8ccbe03SMiklos Szeredi if (!(flags & O_CREAT) || entry->d_inode) 524c8ccbe03SMiklos Szeredi goto no_open; 525c8ccbe03SMiklos Szeredi 526c8ccbe03SMiklos Szeredi /* Only creates */ 52747237687SAl Viro *opened |= FILE_CREATED; 528c8ccbe03SMiklos Szeredi 529c8ccbe03SMiklos Szeredi if (fc->no_create) 530c8ccbe03SMiklos Szeredi goto mknod; 531c8ccbe03SMiklos Szeredi 53230d90494SAl Viro err = fuse_create_open(dir, entry, file, flags, mode, opened); 533d9585277SAl Viro if (err == -ENOSYS) { 534c8ccbe03SMiklos Szeredi fc->no_create = 1; 535c8ccbe03SMiklos Szeredi goto mknod; 536c8ccbe03SMiklos Szeredi } 537c8ccbe03SMiklos Szeredi out_dput: 538c8ccbe03SMiklos Szeredi dput(res); 539d9585277SAl Viro return err; 540c8ccbe03SMiklos Szeredi 541c8ccbe03SMiklos Szeredi mknod: 542c8ccbe03SMiklos Szeredi err = fuse_mknod(dir, entry, mode, 0); 543d9585277SAl Viro if (err) 544c8ccbe03SMiklos Szeredi goto out_dput; 545c8ccbe03SMiklos Szeredi no_open: 546e45198a6SAl Viro return finish_no_open(file, res); 547fd72faacSMiklos Szeredi } 548fd72faacSMiklos Szeredi 5496f9f1180SMiklos Szeredi /* 5506f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 5516f9f1180SMiklos Szeredi */ 5529e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, 5539e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 554541af6a0SAl Viro umode_t mode) 5559e6268dbSMiklos Szeredi { 5569e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 5579e6268dbSMiklos Szeredi struct inode *inode; 5589e6268dbSMiklos Szeredi int err; 55907e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 5602d51013eSMiklos Szeredi 56107e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 56207e77dcaSMiklos Szeredi if (!forget) { 5632d51013eSMiklos Szeredi fuse_put_request(fc, req); 56407e77dcaSMiklos Szeredi return -ENOMEM; 5652d51013eSMiklos Szeredi } 5669e6268dbSMiklos Szeredi 5670e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 5689e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 5699e6268dbSMiklos Szeredi req->out.numargs = 1; 5700e9663eeSMiklos Szeredi if (fc->minor < 9) 5710e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 5720e9663eeSMiklos Szeredi else 5739e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 5749e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 575b93f858aSTejun Heo fuse_request_send(fc, req); 5769e6268dbSMiklos Szeredi err = req->out.h.error; 5779e6268dbSMiklos Szeredi fuse_put_request(fc, req); 5782d51013eSMiklos Szeredi if (err) 5792d51013eSMiklos Szeredi goto out_put_forget_req; 5802d51013eSMiklos Szeredi 58139ee059aSMiklos Szeredi err = -EIO; 58239ee059aSMiklos Szeredi if (invalid_nodeid(outarg.nodeid)) 5832d51013eSMiklos Szeredi goto out_put_forget_req; 58439ee059aSMiklos Szeredi 58539ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 5862d51013eSMiklos Szeredi goto out_put_forget_req; 58739ee059aSMiklos Szeredi 5889e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 5891fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 5909e6268dbSMiklos Szeredi if (!inode) { 59107e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 5929e6268dbSMiklos Szeredi return -ENOMEM; 5939e6268dbSMiklos Szeredi } 59407e77dcaSMiklos Szeredi kfree(forget); 5959e6268dbSMiklos Szeredi 596b70a80e7SMiklos Szeredi err = d_instantiate_no_diralias(entry, inode); 597b70a80e7SMiklos Szeredi if (err) 598b70a80e7SMiklos Szeredi return err; 599d2a85164SMiklos Szeredi 6001fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 6019e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 6029e6268dbSMiklos Szeredi return 0; 60339ee059aSMiklos Szeredi 6042d51013eSMiklos Szeredi out_put_forget_req: 60507e77dcaSMiklos Szeredi kfree(forget); 60639ee059aSMiklos Szeredi return err; 6079e6268dbSMiklos Szeredi } 6089e6268dbSMiklos Szeredi 6091a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, 6109e6268dbSMiklos Szeredi dev_t rdev) 6119e6268dbSMiklos Szeredi { 6129e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 6139e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 614b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 615ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 616ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6179e6268dbSMiklos Szeredi 618e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 619e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 620e0a43ddcSMiklos Szeredi 6219e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6229e6268dbSMiklos Szeredi inarg.mode = mode; 6239e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 624e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6259e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKNOD; 6269e6268dbSMiklos Szeredi req->in.numargs = 2; 627e0a43ddcSMiklos Szeredi req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE : 628e0a43ddcSMiklos Szeredi sizeof(inarg); 6299e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 6309e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 6319e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 6329e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, mode); 6339e6268dbSMiklos Szeredi } 6349e6268dbSMiklos Szeredi 6354acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, 636ebfc3b49SAl Viro bool excl) 6379e6268dbSMiklos Szeredi { 6389e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 6399e6268dbSMiklos Szeredi } 6409e6268dbSMiklos Szeredi 64118bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) 6429e6268dbSMiklos Szeredi { 6439e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 6449e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 645b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 646ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 647ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6489e6268dbSMiklos Szeredi 649e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 650e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 651e0a43ddcSMiklos Szeredi 6529e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6539e6268dbSMiklos Szeredi inarg.mode = mode; 654e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6559e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKDIR; 6569e6268dbSMiklos Szeredi req->in.numargs = 2; 6579e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 6589e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 6599e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 6609e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 6619e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFDIR); 6629e6268dbSMiklos Szeredi } 6639e6268dbSMiklos Szeredi 6649e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 6659e6268dbSMiklos Szeredi const char *link) 6669e6268dbSMiklos Szeredi { 6679e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6689e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 669b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 670ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 671ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6729e6268dbSMiklos Szeredi 6739e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SYMLINK; 6749e6268dbSMiklos Szeredi req->in.numargs = 2; 6759e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 6769e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 6779e6268dbSMiklos Szeredi req->in.args[1].size = len; 6789e6268dbSMiklos Szeredi req->in.args[1].value = link; 6799e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFLNK); 6809e6268dbSMiklos Szeredi } 6819e6268dbSMiklos Szeredi 6829e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 6839e6268dbSMiklos Szeredi { 6849e6268dbSMiklos Szeredi int err; 6859e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 686b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 687ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 688ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6899e6268dbSMiklos Szeredi 6909e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_UNLINK; 6919e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 6929e6268dbSMiklos Szeredi req->in.numargs = 1; 6939e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 6949e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 695b93f858aSTejun Heo fuse_request_send(fc, req); 6969e6268dbSMiklos Szeredi err = req->out.h.error; 6979e6268dbSMiklos Szeredi fuse_put_request(fc, req); 6989e6268dbSMiklos Szeredi if (!err) { 6999e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 700ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 7019e6268dbSMiklos Szeredi 702ac45d613SMiklos Szeredi spin_lock(&fc->lock); 703ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 704dfca7cebSMiklos Szeredi /* 705dfca7cebSMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 706dfca7cebSMiklos Szeredi * happen if userspace filesystem is careless. It would be 707dfca7cebSMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 708dfca7cebSMiklos Szeredi * condition here 709dfca7cebSMiklos Szeredi */ 710dfca7cebSMiklos Szeredi if (inode->i_nlink > 0) 711ac45d613SMiklos Szeredi drop_nlink(inode); 712ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 7139e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 7149e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 7158cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 7169e6268dbSMiklos Szeredi } else if (err == -EINTR) 7179e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7189e6268dbSMiklos Szeredi return err; 7199e6268dbSMiklos Szeredi } 7209e6268dbSMiklos Szeredi 7219e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 7229e6268dbSMiklos Szeredi { 7239e6268dbSMiklos Szeredi int err; 7249e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 725b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 726ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 727ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7289e6268dbSMiklos Szeredi 7299e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RMDIR; 7309e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 7319e6268dbSMiklos Szeredi req->in.numargs = 1; 7329e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 7339e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 734b93f858aSTejun Heo fuse_request_send(fc, req); 7359e6268dbSMiklos Szeredi err = req->out.h.error; 7369e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7379e6268dbSMiklos Szeredi if (!err) { 738ce71ec36SDave Hansen clear_nlink(entry->d_inode); 7399e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 7408cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 7419e6268dbSMiklos Szeredi } else if (err == -EINTR) 7429e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7439e6268dbSMiklos Szeredi return err; 7449e6268dbSMiklos Szeredi } 7459e6268dbSMiklos Szeredi 7469e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent, 7479e6268dbSMiklos Szeredi struct inode *newdir, struct dentry *newent) 7489e6268dbSMiklos Szeredi { 7499e6268dbSMiklos Szeredi int err; 7509e6268dbSMiklos Szeredi struct fuse_rename_in inarg; 7519e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 752b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 753e4eaac06SSage Weil 754ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 755ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7569e6268dbSMiklos Szeredi 7579e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7589e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 7599e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RENAME; 7609e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(olddir); 7619e6268dbSMiklos Szeredi req->in.numargs = 3; 7629e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 7639e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 7649e6268dbSMiklos Szeredi req->in.args[1].size = oldent->d_name.len + 1; 7659e6268dbSMiklos Szeredi req->in.args[1].value = oldent->d_name.name; 7669e6268dbSMiklos Szeredi req->in.args[2].size = newent->d_name.len + 1; 7679e6268dbSMiklos Szeredi req->in.args[2].value = newent->d_name.name; 768b93f858aSTejun Heo fuse_request_send(fc, req); 7699e6268dbSMiklos Szeredi err = req->out.h.error; 7709e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7719e6268dbSMiklos Szeredi if (!err) { 77208b63307SMiklos Szeredi /* ctime changes */ 77308b63307SMiklos Szeredi fuse_invalidate_attr(oldent->d_inode); 77408b63307SMiklos Szeredi 7759e6268dbSMiklos Szeredi fuse_invalidate_attr(olddir); 7769e6268dbSMiklos Szeredi if (olddir != newdir) 7779e6268dbSMiklos Szeredi fuse_invalidate_attr(newdir); 7788cbdf1e6SMiklos Szeredi 7798cbdf1e6SMiklos Szeredi /* newent will end up negative */ 7805219f346SMiklos Szeredi if (newent->d_inode) { 7815219f346SMiklos Szeredi fuse_invalidate_attr(newent->d_inode); 7828cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 7835219f346SMiklos Szeredi } 7849e6268dbSMiklos Szeredi } else if (err == -EINTR) { 7859e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 7869e6268dbSMiklos Szeredi rename actually took place. If the invalidation 7879e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 7889e6268dbSMiklos Szeredi directory), then there can be inconsistency between 7899e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 7909e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 7919e6268dbSMiklos Szeredi if (newent->d_inode) 7929e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 7939e6268dbSMiklos Szeredi } 7949e6268dbSMiklos Szeredi 7959e6268dbSMiklos Szeredi return err; 7969e6268dbSMiklos Szeredi } 7979e6268dbSMiklos Szeredi 7989e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 7999e6268dbSMiklos Szeredi struct dentry *newent) 8009e6268dbSMiklos Szeredi { 8019e6268dbSMiklos Szeredi int err; 8029e6268dbSMiklos Szeredi struct fuse_link_in inarg; 8039e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 8049e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 805b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 806ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 807ce1d5a49SMiklos Szeredi return PTR_ERR(req); 8089e6268dbSMiklos Szeredi 8099e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8109e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 8119e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_LINK; 8129e6268dbSMiklos Szeredi req->in.numargs = 2; 8139e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 8149e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 8159e6268dbSMiklos Szeredi req->in.args[1].size = newent->d_name.len + 1; 8169e6268dbSMiklos Szeredi req->in.args[1].value = newent->d_name.name; 8179e6268dbSMiklos Szeredi err = create_new_entry(fc, req, newdir, newent, inode->i_mode); 8189e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 8199e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 8209e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 8219e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 8229e6268dbSMiklos Szeredi etc.) 8239e6268dbSMiklos Szeredi */ 824ac45d613SMiklos Szeredi if (!err) { 825ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 826ac45d613SMiklos Szeredi 827ac45d613SMiklos Szeredi spin_lock(&fc->lock); 828ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 829ac45d613SMiklos Szeredi inc_nlink(inode); 830ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 8319e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 832ac45d613SMiklos Szeredi } else if (err == -EINTR) { 833ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 834ac45d613SMiklos Szeredi } 8359e6268dbSMiklos Szeredi return err; 8369e6268dbSMiklos Szeredi } 8379e6268dbSMiklos Szeredi 8381fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 8391fb69e78SMiklos Szeredi struct kstat *stat) 8401fb69e78SMiklos Szeredi { 841203627bbSMiklos Szeredi unsigned int blkbits; 842203627bbSMiklos Szeredi 8431fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 8441fb69e78SMiklos Szeredi stat->ino = attr->ino; 8451fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 8461fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 847499dcf20SEric W. Biederman stat->uid = make_kuid(&init_user_ns, attr->uid); 848499dcf20SEric W. Biederman stat->gid = make_kgid(&init_user_ns, attr->gid); 8491fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 8501fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 8511fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 8521fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 8531fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 8541fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 8551fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 8561fb69e78SMiklos Szeredi stat->size = attr->size; 8571fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 858203627bbSMiklos Szeredi 859203627bbSMiklos Szeredi if (attr->blksize != 0) 860203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 861203627bbSMiklos Szeredi else 862203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 863203627bbSMiklos Szeredi 864203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 8651fb69e78SMiklos Szeredi } 8661fb69e78SMiklos Szeredi 867c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 868c79e322fSMiklos Szeredi struct file *file) 869e5e5558eSMiklos Szeredi { 870e5e5558eSMiklos Szeredi int err; 871c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 872c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 873e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 8741fb69e78SMiklos Szeredi struct fuse_req *req; 8751fb69e78SMiklos Szeredi u64 attr_version; 8761fb69e78SMiklos Szeredi 877b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 878ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 879ce1d5a49SMiklos Szeredi return PTR_ERR(req); 880e5e5558eSMiklos Szeredi 8817dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 8821fb69e78SMiklos Szeredi 883c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8840e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 885c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 886c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 887c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 888c79e322fSMiklos Szeredi 889c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 890c79e322fSMiklos Szeredi inarg.fh = ff->fh; 891c79e322fSMiklos Szeredi } 892e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_GETATTR; 893e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 894c79e322fSMiklos Szeredi req->in.numargs = 1; 895c79e322fSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 896c79e322fSMiklos Szeredi req->in.args[0].value = &inarg; 897e5e5558eSMiklos Szeredi req->out.numargs = 1; 8980e9663eeSMiklos Szeredi if (fc->minor < 9) 8990e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 9000e9663eeSMiklos Szeredi else 901c79e322fSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 902c79e322fSMiklos Szeredi req->out.args[0].value = &outarg; 903b93f858aSTejun Heo fuse_request_send(fc, req); 904e5e5558eSMiklos Szeredi err = req->out.h.error; 905e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 906e5e5558eSMiklos Szeredi if (!err) { 907c79e322fSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 908e5e5558eSMiklos Szeredi make_bad_inode(inode); 909e5e5558eSMiklos Szeredi err = -EIO; 910e5e5558eSMiklos Szeredi } else { 911c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 912c79e322fSMiklos Szeredi attr_timeout(&outarg), 9131fb69e78SMiklos Szeredi attr_version); 9141fb69e78SMiklos Szeredi if (stat) 915c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 916e5e5558eSMiklos Szeredi } 917e5e5558eSMiklos Szeredi } 918e5e5558eSMiklos Szeredi return err; 919e5e5558eSMiklos Szeredi } 920e5e5558eSMiklos Szeredi 921bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat, 922bcb4be80SMiklos Szeredi struct file *file, bool *refreshed) 923bcb4be80SMiklos Szeredi { 924bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 925bcb4be80SMiklos Szeredi int err; 926bcb4be80SMiklos Szeredi bool r; 927bcb4be80SMiklos Szeredi 928bcb4be80SMiklos Szeredi if (fi->i_time < get_jiffies_64()) { 929bcb4be80SMiklos Szeredi r = true; 930bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 931bcb4be80SMiklos Szeredi } else { 932bcb4be80SMiklos Szeredi r = false; 933bcb4be80SMiklos Szeredi err = 0; 934bcb4be80SMiklos Szeredi if (stat) { 935bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 936bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 93745c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 938bcb4be80SMiklos Szeredi } 939bcb4be80SMiklos Szeredi } 940bcb4be80SMiklos Szeredi 941bcb4be80SMiklos Szeredi if (refreshed != NULL) 942bcb4be80SMiklos Szeredi *refreshed = r; 943bcb4be80SMiklos Szeredi 944bcb4be80SMiklos Szeredi return err; 945bcb4be80SMiklos Szeredi } 946bcb4be80SMiklos Szeredi 9473b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 948451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 9493b463ae0SJohn Muir { 9503b463ae0SJohn Muir int err = -ENOTDIR; 9513b463ae0SJohn Muir struct inode *parent; 9523b463ae0SJohn Muir struct dentry *dir; 9533b463ae0SJohn Muir struct dentry *entry; 9543b463ae0SJohn Muir 9553b463ae0SJohn Muir parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); 9563b463ae0SJohn Muir if (!parent) 9573b463ae0SJohn Muir return -ENOENT; 9583b463ae0SJohn Muir 9593b463ae0SJohn Muir mutex_lock(&parent->i_mutex); 9603b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 9613b463ae0SJohn Muir goto unlock; 9623b463ae0SJohn Muir 9633b463ae0SJohn Muir err = -ENOENT; 9643b463ae0SJohn Muir dir = d_find_alias(parent); 9653b463ae0SJohn Muir if (!dir) 9663b463ae0SJohn Muir goto unlock; 9673b463ae0SJohn Muir 9683b463ae0SJohn Muir entry = d_lookup(dir, name); 9693b463ae0SJohn Muir dput(dir); 9703b463ae0SJohn Muir if (!entry) 9713b463ae0SJohn Muir goto unlock; 9723b463ae0SJohn Muir 9733b463ae0SJohn Muir fuse_invalidate_attr(parent); 9743b463ae0SJohn Muir fuse_invalidate_entry(entry); 975451d0f59SJohn Muir 976451d0f59SJohn Muir if (child_nodeid != 0 && entry->d_inode) { 977451d0f59SJohn Muir mutex_lock(&entry->d_inode->i_mutex); 978451d0f59SJohn Muir if (get_node_id(entry->d_inode) != child_nodeid) { 979451d0f59SJohn Muir err = -ENOENT; 980451d0f59SJohn Muir goto badentry; 981451d0f59SJohn Muir } 982451d0f59SJohn Muir if (d_mountpoint(entry)) { 983451d0f59SJohn Muir err = -EBUSY; 984451d0f59SJohn Muir goto badentry; 985451d0f59SJohn Muir } 986451d0f59SJohn Muir if (S_ISDIR(entry->d_inode->i_mode)) { 987451d0f59SJohn Muir shrink_dcache_parent(entry); 988451d0f59SJohn Muir if (!simple_empty(entry)) { 989451d0f59SJohn Muir err = -ENOTEMPTY; 990451d0f59SJohn Muir goto badentry; 991451d0f59SJohn Muir } 992451d0f59SJohn Muir entry->d_inode->i_flags |= S_DEAD; 993451d0f59SJohn Muir } 994451d0f59SJohn Muir dont_mount(entry); 995451d0f59SJohn Muir clear_nlink(entry->d_inode); 9963b463ae0SJohn Muir err = 0; 997451d0f59SJohn Muir badentry: 998451d0f59SJohn Muir mutex_unlock(&entry->d_inode->i_mutex); 999451d0f59SJohn Muir if (!err) 1000451d0f59SJohn Muir d_delete(entry); 1001451d0f59SJohn Muir } else { 1002451d0f59SJohn Muir err = 0; 1003451d0f59SJohn Muir } 1004451d0f59SJohn Muir dput(entry); 10053b463ae0SJohn Muir 10063b463ae0SJohn Muir unlock: 10073b463ae0SJohn Muir mutex_unlock(&parent->i_mutex); 10083b463ae0SJohn Muir iput(parent); 10093b463ae0SJohn Muir return err; 10103b463ae0SJohn Muir } 10113b463ae0SJohn Muir 101287729a55SMiklos Szeredi /* 101387729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1014c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 101587729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 101687729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 101787729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 101887729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 101987729a55SMiklos Szeredi * DoS against the requester. 102087729a55SMiklos Szeredi * 102187729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 102287729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 102387729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 102487729a55SMiklos Szeredi */ 1025c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc) 102687729a55SMiklos Szeredi { 1027c69e8d9cSDavid Howells const struct cred *cred; 1028c69e8d9cSDavid Howells 102987729a55SMiklos Szeredi if (fc->flags & FUSE_ALLOW_OTHER) 103087729a55SMiklos Szeredi return 1; 103187729a55SMiklos Szeredi 1032c2132c1bSAnatol Pomozov cred = current_cred(); 1033499dcf20SEric W. Biederman if (uid_eq(cred->euid, fc->user_id) && 1034499dcf20SEric W. Biederman uid_eq(cred->suid, fc->user_id) && 1035499dcf20SEric W. Biederman uid_eq(cred->uid, fc->user_id) && 1036499dcf20SEric W. Biederman gid_eq(cred->egid, fc->group_id) && 1037499dcf20SEric W. Biederman gid_eq(cred->sgid, fc->group_id) && 1038499dcf20SEric W. Biederman gid_eq(cred->gid, fc->group_id)) 1039c2132c1bSAnatol Pomozov return 1; 104087729a55SMiklos Szeredi 1041c2132c1bSAnatol Pomozov return 0; 104287729a55SMiklos Szeredi } 104387729a55SMiklos Szeredi 104431d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 104531d40d74SMiklos Szeredi { 104631d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 104731d40d74SMiklos Szeredi struct fuse_req *req; 104831d40d74SMiklos Szeredi struct fuse_access_in inarg; 104931d40d74SMiklos Szeredi int err; 105031d40d74SMiklos Szeredi 1051698fa1d1SMiklos Szeredi BUG_ON(mask & MAY_NOT_BLOCK); 1052698fa1d1SMiklos Szeredi 105331d40d74SMiklos Szeredi if (fc->no_access) 105431d40d74SMiklos Szeredi return 0; 105531d40d74SMiklos Szeredi 1056b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1057ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1058ce1d5a49SMiklos Szeredi return PTR_ERR(req); 105931d40d74SMiklos Szeredi 106031d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1061e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 106231d40d74SMiklos Szeredi req->in.h.opcode = FUSE_ACCESS; 106331d40d74SMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 106431d40d74SMiklos Szeredi req->in.numargs = 1; 106531d40d74SMiklos Szeredi req->in.args[0].size = sizeof(inarg); 106631d40d74SMiklos Szeredi req->in.args[0].value = &inarg; 1067b93f858aSTejun Heo fuse_request_send(fc, req); 106831d40d74SMiklos Szeredi err = req->out.h.error; 106931d40d74SMiklos Szeredi fuse_put_request(fc, req); 107031d40d74SMiklos Szeredi if (err == -ENOSYS) { 107131d40d74SMiklos Szeredi fc->no_access = 1; 107231d40d74SMiklos Szeredi err = 0; 107331d40d74SMiklos Szeredi } 107431d40d74SMiklos Szeredi return err; 107531d40d74SMiklos Szeredi } 107631d40d74SMiklos Szeredi 107710556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 107819690ddbSMiklos Szeredi { 107910556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 108019690ddbSMiklos Szeredi return -ECHILD; 108119690ddbSMiklos Szeredi 108219690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 108319690ddbSMiklos Szeredi } 108419690ddbSMiklos Szeredi 10856f9f1180SMiklos Szeredi /* 10866f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 10876f9f1180SMiklos Szeredi * 10886f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 10896f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 10906f9f1180SMiklos Szeredi * modell. 10916f9f1180SMiklos Szeredi * 10926f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 10936f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 10946f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 10956f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 10966f9f1180SMiklos Szeredi * locally based on file mode. 10976f9f1180SMiklos Szeredi */ 109810556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask) 1099e5e5558eSMiklos Szeredi { 1100e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1101244f6385SMiklos Szeredi bool refreshed = false; 1102244f6385SMiklos Szeredi int err = 0; 1103e5e5558eSMiklos Szeredi 1104c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1105e5e5558eSMiklos Szeredi return -EACCES; 1106244f6385SMiklos Szeredi 1107244f6385SMiklos Szeredi /* 1108e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1109244f6385SMiklos Szeredi */ 1110e8e96157SMiklos Szeredi if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || 1111e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 111219690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 111319690ddbSMiklos Szeredi 111419690ddbSMiklos Szeredi if (fi->i_time < get_jiffies_64()) { 111519690ddbSMiklos Szeredi refreshed = true; 111619690ddbSMiklos Szeredi 111710556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1118244f6385SMiklos Szeredi if (err) 1119244f6385SMiklos Szeredi return err; 11201fb69e78SMiklos Szeredi } 112119690ddbSMiklos Szeredi } 1122244f6385SMiklos Szeredi 1123244f6385SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 11242830ba7fSAl Viro err = generic_permission(inode, mask); 11251e9a4ed9SMiklos Szeredi 11261e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 11271e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 11281e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1129244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 113010556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 11311e9a4ed9SMiklos Szeredi if (!err) 11322830ba7fSAl Viro err = generic_permission(inode, mask); 11331e9a4ed9SMiklos Szeredi } 11341e9a4ed9SMiklos Szeredi 11356f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 11366f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 11376f9f1180SMiklos Szeredi noticed immediately, only after the attribute 11386f9f1180SMiklos Szeredi timeout has expired */ 11399cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1140e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1141e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1142e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1143e8e96157SMiklos Szeredi if (refreshed) 1144e5e5558eSMiklos Szeredi return -EACCES; 114531d40d74SMiklos Szeredi 114610556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1147e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1148e8e96157SMiklos Szeredi return -EACCES; 1149e8e96157SMiklos Szeredi } 1150e5e5558eSMiklos Szeredi } 1151244f6385SMiklos Szeredi return err; 1152e5e5558eSMiklos Szeredi } 1153e5e5558eSMiklos Szeredi 1154e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file, 11558d3af7f3SAl Viro struct dir_context *ctx) 1156e5e5558eSMiklos Szeredi { 1157e5e5558eSMiklos Szeredi while (nbytes >= FUSE_NAME_OFFSET) { 1158e5e5558eSMiklos Szeredi struct fuse_dirent *dirent = (struct fuse_dirent *) buf; 1159e5e5558eSMiklos Szeredi size_t reclen = FUSE_DIRENT_SIZE(dirent); 1160e5e5558eSMiklos Szeredi if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 1161e5e5558eSMiklos Szeredi return -EIO; 1162e5e5558eSMiklos Szeredi if (reclen > nbytes) 1163e5e5558eSMiklos Szeredi break; 1164efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1165efeb9e60SMiklos Szeredi return -EIO; 1166e5e5558eSMiklos Szeredi 11678d3af7f3SAl Viro if (!dir_emit(ctx, dirent->name, dirent->namelen, 11688d3af7f3SAl Viro dirent->ino, dirent->type)) 1169e5e5558eSMiklos Szeredi break; 1170e5e5558eSMiklos Szeredi 1171e5e5558eSMiklos Szeredi buf += reclen; 1172e5e5558eSMiklos Szeredi nbytes -= reclen; 11738d3af7f3SAl Viro ctx->pos = dirent->off; 1174e5e5558eSMiklos Szeredi } 1175e5e5558eSMiklos Szeredi 1176e5e5558eSMiklos Szeredi return 0; 1177e5e5558eSMiklos Szeredi } 1178e5e5558eSMiklos Szeredi 11790b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file, 11800b05b183SAnand V. Avati struct fuse_direntplus *direntplus, 11810b05b183SAnand V. Avati u64 attr_version) 11820b05b183SAnand V. Avati { 11830b05b183SAnand V. Avati int err; 11840b05b183SAnand V. Avati struct fuse_entry_out *o = &direntplus->entry_out; 11850b05b183SAnand V. Avati struct fuse_dirent *dirent = &direntplus->dirent; 11860b05b183SAnand V. Avati struct dentry *parent = file->f_path.dentry; 11870b05b183SAnand V. Avati struct qstr name = QSTR_INIT(dirent->name, dirent->namelen); 11880b05b183SAnand V. Avati struct dentry *dentry; 11890b05b183SAnand V. Avati struct dentry *alias; 11900b05b183SAnand V. Avati struct inode *dir = parent->d_inode; 11910b05b183SAnand V. Avati struct fuse_conn *fc; 11920b05b183SAnand V. Avati struct inode *inode; 11930b05b183SAnand V. Avati 11940b05b183SAnand V. Avati if (!o->nodeid) { 11950b05b183SAnand V. Avati /* 11960b05b183SAnand V. Avati * Unlike in the case of fuse_lookup, zero nodeid does not mean 11970b05b183SAnand V. Avati * ENOENT. Instead, it only means the userspace filesystem did 11980b05b183SAnand V. Avati * not want to return attributes/handle for this entry. 11990b05b183SAnand V. Avati * 12000b05b183SAnand V. Avati * So do nothing. 12010b05b183SAnand V. Avati */ 12020b05b183SAnand V. Avati return 0; 12030b05b183SAnand V. Avati } 12040b05b183SAnand V. Avati 12050b05b183SAnand V. Avati if (name.name[0] == '.') { 12060b05b183SAnand V. Avati /* 12070b05b183SAnand V. Avati * We could potentially refresh the attributes of the directory 12080b05b183SAnand V. Avati * and its parent? 12090b05b183SAnand V. Avati */ 12100b05b183SAnand V. Avati if (name.len == 1) 12110b05b183SAnand V. Avati return 0; 12120b05b183SAnand V. Avati if (name.name[1] == '.' && name.len == 2) 12130b05b183SAnand V. Avati return 0; 12140b05b183SAnand V. Avati } 1215a28ef45cSMiklos Szeredi 1216a28ef45cSMiklos Szeredi if (invalid_nodeid(o->nodeid)) 1217a28ef45cSMiklos Szeredi return -EIO; 1218a28ef45cSMiklos Szeredi if (!fuse_valid_type(o->attr.mode)) 1219a28ef45cSMiklos Szeredi return -EIO; 1220a28ef45cSMiklos Szeredi 12210b05b183SAnand V. Avati fc = get_fuse_conn(dir); 12220b05b183SAnand V. Avati 12230b05b183SAnand V. Avati name.hash = full_name_hash(name.name, name.len); 12240b05b183SAnand V. Avati dentry = d_lookup(parent, &name); 122553ce9a33SNiels de Vos if (dentry) { 12260b05b183SAnand V. Avati inode = dentry->d_inode; 122753ce9a33SNiels de Vos if (!inode) { 122853ce9a33SNiels de Vos d_drop(dentry); 1229a28ef45cSMiklos Szeredi } else if (get_node_id(inode) != o->nodeid || 1230a28ef45cSMiklos Szeredi ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { 123153ce9a33SNiels de Vos err = d_invalidate(dentry); 123253ce9a33SNiels de Vos if (err) 123353ce9a33SNiels de Vos goto out; 1234a28ef45cSMiklos Szeredi } else if (is_bad_inode(inode)) { 1235a28ef45cSMiklos Szeredi err = -EIO; 1236a28ef45cSMiklos Szeredi goto out; 123753ce9a33SNiels de Vos } else { 12380b05b183SAnand V. Avati struct fuse_inode *fi; 12390b05b183SAnand V. Avati fi = get_fuse_inode(inode); 12400b05b183SAnand V. Avati spin_lock(&fc->lock); 12410b05b183SAnand V. Avati fi->nlookup++; 12420b05b183SAnand V. Avati spin_unlock(&fc->lock); 12430b05b183SAnand V. Avati 1244fa2b7213SMiklos Szeredi fuse_change_attributes(inode, &o->attr, 1245fa2b7213SMiklos Szeredi entry_attr_timeout(o), 1246fa2b7213SMiklos Szeredi attr_version); 1247fa2b7213SMiklos Szeredi 12480b05b183SAnand V. Avati /* 12490b05b183SAnand V. Avati * The other branch to 'found' comes via fuse_iget() 12500b05b183SAnand V. Avati * which bumps nlookup inside 12510b05b183SAnand V. Avati */ 12520b05b183SAnand V. Avati goto found; 12530b05b183SAnand V. Avati } 12540b05b183SAnand V. Avati dput(dentry); 12550b05b183SAnand V. Avati } 12560b05b183SAnand V. Avati 12570b05b183SAnand V. Avati dentry = d_alloc(parent, &name); 12580b05b183SAnand V. Avati err = -ENOMEM; 12590b05b183SAnand V. Avati if (!dentry) 12600b05b183SAnand V. Avati goto out; 12610b05b183SAnand V. Avati 12620b05b183SAnand V. Avati inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, 12630b05b183SAnand V. Avati &o->attr, entry_attr_timeout(o), attr_version); 12640b05b183SAnand V. Avati if (!inode) 12650b05b183SAnand V. Avati goto out; 12660b05b183SAnand V. Avati 1267b70a80e7SMiklos Szeredi alias = d_materialise_unique(dentry, inode); 12680b05b183SAnand V. Avati err = PTR_ERR(alias); 12695835f339SMiklos Szeredi if (IS_ERR(alias)) 12700b05b183SAnand V. Avati goto out; 12712914941eSMiklos Szeredi 12720b05b183SAnand V. Avati if (alias) { 12730b05b183SAnand V. Avati dput(dentry); 12740b05b183SAnand V. Avati dentry = alias; 12750b05b183SAnand V. Avati } 12760b05b183SAnand V. Avati 12770b05b183SAnand V. Avati found: 12786314efeeSMiklos Szeredi if (fc->readdirplus_auto) 12796314efeeSMiklos Szeredi set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); 12800b05b183SAnand V. Avati fuse_change_entry_timeout(dentry, o); 12810b05b183SAnand V. Avati 12820b05b183SAnand V. Avati err = 0; 12830b05b183SAnand V. Avati out: 12840b05b183SAnand V. Avati dput(dentry); 12850b05b183SAnand V. Avati return err; 12860b05b183SAnand V. Avati } 12870b05b183SAnand V. Avati 12880b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, 12898d3af7f3SAl Viro struct dir_context *ctx, u64 attr_version) 12900b05b183SAnand V. Avati { 12910b05b183SAnand V. Avati struct fuse_direntplus *direntplus; 12920b05b183SAnand V. Avati struct fuse_dirent *dirent; 12930b05b183SAnand V. Avati size_t reclen; 12940b05b183SAnand V. Avati int over = 0; 12950b05b183SAnand V. Avati int ret; 12960b05b183SAnand V. Avati 12970b05b183SAnand V. Avati while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) { 12980b05b183SAnand V. Avati direntplus = (struct fuse_direntplus *) buf; 12990b05b183SAnand V. Avati dirent = &direntplus->dirent; 13000b05b183SAnand V. Avati reclen = FUSE_DIRENTPLUS_SIZE(direntplus); 13010b05b183SAnand V. Avati 13020b05b183SAnand V. Avati if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 13030b05b183SAnand V. Avati return -EIO; 13040b05b183SAnand V. Avati if (reclen > nbytes) 13050b05b183SAnand V. Avati break; 1306efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1307efeb9e60SMiklos Szeredi return -EIO; 13080b05b183SAnand V. Avati 13090b05b183SAnand V. Avati if (!over) { 13100b05b183SAnand V. Avati /* We fill entries into dstbuf only as much as 13110b05b183SAnand V. Avati it can hold. But we still continue iterating 13120b05b183SAnand V. Avati over remaining entries to link them. If not, 13130b05b183SAnand V. Avati we need to send a FORGET for each of those 13140b05b183SAnand V. Avati which we did not link. 13150b05b183SAnand V. Avati */ 13168d3af7f3SAl Viro over = !dir_emit(ctx, dirent->name, dirent->namelen, 13178d3af7f3SAl Viro dirent->ino, dirent->type); 13188d3af7f3SAl Viro ctx->pos = dirent->off; 13190b05b183SAnand V. Avati } 13200b05b183SAnand V. Avati 13210b05b183SAnand V. Avati buf += reclen; 13220b05b183SAnand V. Avati nbytes -= reclen; 13230b05b183SAnand V. Avati 13240b05b183SAnand V. Avati ret = fuse_direntplus_link(file, direntplus, attr_version); 13250b05b183SAnand V. Avati if (ret) 13260b05b183SAnand V. Avati fuse_force_forget(file, direntplus->entry_out.nodeid); 13270b05b183SAnand V. Avati } 13280b05b183SAnand V. Avati 13290b05b183SAnand V. Avati return 0; 13300b05b183SAnand V. Avati } 13310b05b183SAnand V. Avati 13328d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx) 1333e5e5558eSMiklos Szeredi { 13344582a4abSFeng Shuo int plus, err; 133504730fefSMiklos Szeredi size_t nbytes; 133604730fefSMiklos Szeredi struct page *page; 1337496ad9aaSAl Viro struct inode *inode = file_inode(file); 133804730fefSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1339248d86e8SMiklos Szeredi struct fuse_req *req; 13400b05b183SAnand V. Avati u64 attr_version = 0; 1341248d86e8SMiklos Szeredi 1342248d86e8SMiklos Szeredi if (is_bad_inode(inode)) 1343248d86e8SMiklos Szeredi return -EIO; 1344248d86e8SMiklos Szeredi 1345b111c8c0SMaxim Patlasov req = fuse_get_req(fc, 1); 1346ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1347ce1d5a49SMiklos Szeredi return PTR_ERR(req); 1348e5e5558eSMiklos Szeredi 134904730fefSMiklos Szeredi page = alloc_page(GFP_KERNEL); 135004730fefSMiklos Szeredi if (!page) { 135104730fefSMiklos Szeredi fuse_put_request(fc, req); 1352e5e5558eSMiklos Szeredi return -ENOMEM; 135304730fefSMiklos Szeredi } 13544582a4abSFeng Shuo 13558d3af7f3SAl Viro plus = fuse_use_readdirplus(inode, ctx); 1356f4975c67SMiklos Szeredi req->out.argpages = 1; 135704730fefSMiklos Szeredi req->num_pages = 1; 135804730fefSMiklos Szeredi req->pages[0] = page; 135985f40aecSMaxim Patlasov req->page_descs[0].length = PAGE_SIZE; 13604582a4abSFeng Shuo if (plus) { 13610b05b183SAnand V. Avati attr_version = fuse_get_attr_version(fc); 13628d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 13630b05b183SAnand V. Avati FUSE_READDIRPLUS); 13640b05b183SAnand V. Avati } else { 13658d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 13660b05b183SAnand V. Avati FUSE_READDIR); 13670b05b183SAnand V. Avati } 1368b93f858aSTejun Heo fuse_request_send(fc, req); 1369361b1eb5SMiklos Szeredi nbytes = req->out.args[0].size; 137004730fefSMiklos Szeredi err = req->out.h.error; 137104730fefSMiklos Szeredi fuse_put_request(fc, req); 13720b05b183SAnand V. Avati if (!err) { 13734582a4abSFeng Shuo if (plus) { 13740b05b183SAnand V. Avati err = parse_dirplusfile(page_address(page), nbytes, 13758d3af7f3SAl Viro file, ctx, 13760b05b183SAnand V. Avati attr_version); 13770b05b183SAnand V. Avati } else { 13780b05b183SAnand V. Avati err = parse_dirfile(page_address(page), nbytes, file, 13798d3af7f3SAl Viro ctx); 13800b05b183SAnand V. Avati } 13810b05b183SAnand V. Avati } 1382e5e5558eSMiklos Szeredi 138304730fefSMiklos Szeredi __free_page(page); 1384*451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 138504730fefSMiklos Szeredi return err; 1386e5e5558eSMiklos Szeredi } 1387e5e5558eSMiklos Szeredi 1388e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry) 1389e5e5558eSMiklos Szeredi { 1390e5e5558eSMiklos Szeredi struct inode *inode = dentry->d_inode; 1391e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1392b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 1393e5e5558eSMiklos Szeredi char *link; 1394e5e5558eSMiklos Szeredi 1395ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1396e231c2eeSDavid Howells return ERR_CAST(req); 1397e5e5558eSMiklos Szeredi 1398e5e5558eSMiklos Szeredi link = (char *) __get_free_page(GFP_KERNEL); 1399e5e5558eSMiklos Szeredi if (!link) { 1400e5e5558eSMiklos Szeredi link = ERR_PTR(-ENOMEM); 1401e5e5558eSMiklos Szeredi goto out; 1402e5e5558eSMiklos Szeredi } 1403e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_READLINK; 1404e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 1405e5e5558eSMiklos Szeredi req->out.argvar = 1; 1406e5e5558eSMiklos Szeredi req->out.numargs = 1; 1407e5e5558eSMiklos Szeredi req->out.args[0].size = PAGE_SIZE - 1; 1408e5e5558eSMiklos Szeredi req->out.args[0].value = link; 1409b93f858aSTejun Heo fuse_request_send(fc, req); 1410e5e5558eSMiklos Szeredi if (req->out.h.error) { 1411e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1412e5e5558eSMiklos Szeredi link = ERR_PTR(req->out.h.error); 1413e5e5558eSMiklos Szeredi } else 1414e5e5558eSMiklos Szeredi link[req->out.args[0].size] = '\0'; 1415e5e5558eSMiklos Szeredi out: 1416e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 1417*451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 1418e5e5558eSMiklos Szeredi return link; 1419e5e5558eSMiklos Szeredi } 1420e5e5558eSMiklos Szeredi 1421e5e5558eSMiklos Szeredi static void free_link(char *link) 1422e5e5558eSMiklos Szeredi { 1423e5e5558eSMiklos Szeredi if (!IS_ERR(link)) 1424e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1425e5e5558eSMiklos Szeredi } 1426e5e5558eSMiklos Szeredi 1427e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd) 1428e5e5558eSMiklos Szeredi { 1429e5e5558eSMiklos Szeredi nd_set_link(nd, read_link(dentry)); 1430e5e5558eSMiklos Szeredi return NULL; 1431e5e5558eSMiklos Szeredi } 1432e5e5558eSMiklos Szeredi 1433e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c) 1434e5e5558eSMiklos Szeredi { 1435e5e5558eSMiklos Szeredi free_link(nd_get_link(nd)); 1436e5e5558eSMiklos Szeredi } 1437e5e5558eSMiklos Szeredi 1438e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1439e5e5558eSMiklos Szeredi { 144091fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1441e5e5558eSMiklos Szeredi } 1442e5e5558eSMiklos Szeredi 1443e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1444e5e5558eSMiklos Szeredi { 14458b0797a4SMiklos Szeredi fuse_release_common(file, FUSE_RELEASEDIR); 14468b0797a4SMiklos Szeredi 14478b0797a4SMiklos Szeredi return 0; 1448e5e5558eSMiklos Szeredi } 1449e5e5558eSMiklos Szeredi 145002c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 145102c24a82SJosef Bacik int datasync) 145282547981SMiklos Szeredi { 145302c24a82SJosef Bacik return fuse_fsync_common(file, start, end, datasync, 1); 145482547981SMiklos Szeredi } 145582547981SMiklos Szeredi 1456b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1457b18da0c5SMiklos Szeredi unsigned long arg) 1458b18da0c5SMiklos Szeredi { 1459b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1460b18da0c5SMiklos Szeredi 1461b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1462b18da0c5SMiklos Szeredi if (fc->minor < 18) 1463b18da0c5SMiklos Szeredi return -ENOTTY; 1464b18da0c5SMiklos Szeredi 1465b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1466b18da0c5SMiklos Szeredi } 1467b18da0c5SMiklos Szeredi 1468b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1469b18da0c5SMiklos Szeredi unsigned long arg) 1470b18da0c5SMiklos Szeredi { 1471b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1472b18da0c5SMiklos Szeredi 1473b18da0c5SMiklos Szeredi if (fc->minor < 18) 1474b18da0c5SMiklos Szeredi return -ENOTTY; 1475b18da0c5SMiklos Szeredi 1476b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1477b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1478b18da0c5SMiklos Szeredi } 1479b18da0c5SMiklos Szeredi 148017637cbaSMiklos Szeredi static bool update_mtime(unsigned ivalid) 148117637cbaSMiklos Szeredi { 148217637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 148317637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 148417637cbaSMiklos Szeredi return true; 148517637cbaSMiklos Szeredi 148617637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 148717637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 148817637cbaSMiklos Szeredi return false; 148917637cbaSMiklos Szeredi 149017637cbaSMiklos Szeredi /* In all other cases update */ 149117637cbaSMiklos Szeredi return true; 149217637cbaSMiklos Szeredi } 149317637cbaSMiklos Szeredi 1494befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) 14959e6268dbSMiklos Szeredi { 14969e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 14979e6268dbSMiklos Szeredi 14989e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1499befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 15009e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 1501499dcf20SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid); 15029e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 1503499dcf20SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid); 15049e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1505befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 150617637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 150717637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1508befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 150917637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 151017637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 151117637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 151217637cbaSMiklos Szeredi } 151317637cbaSMiklos Szeredi if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) { 151417637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1515befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 151617637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 151717637cbaSMiklos Szeredi if (!(ivalid & ATTR_MTIME_SET)) 151817637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 15199e6268dbSMiklos Szeredi } 15209e6268dbSMiklos Szeredi } 15219e6268dbSMiklos Szeredi 15226f9f1180SMiklos Szeredi /* 15233be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 15243be5a52bSMiklos Szeredi * 15253be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 15263be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 15273be5a52bSMiklos Szeredi */ 15283be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 15293be5a52bSMiklos Szeredi { 15303be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 15313be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15323be5a52bSMiklos Szeredi 15333be5a52bSMiklos Szeredi BUG_ON(!mutex_is_locked(&inode->i_mutex)); 15343be5a52bSMiklos Szeredi 15353be5a52bSMiklos Szeredi spin_lock(&fc->lock); 15363be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 15373be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 15383be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 15393be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 15403be5a52bSMiklos Szeredi } 15413be5a52bSMiklos Szeredi 15423be5a52bSMiklos Szeredi /* 15433be5a52bSMiklos Szeredi * Allow writepages on inode 15443be5a52bSMiklos Szeredi * 15453be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 15463be5a52bSMiklos Szeredi * writepages. 15473be5a52bSMiklos Szeredi */ 15483be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 15493be5a52bSMiklos Szeredi { 15503be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15513be5a52bSMiklos Szeredi 15523be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 15533be5a52bSMiklos Szeredi fi->writectr = 0; 15543be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 15553be5a52bSMiklos Szeredi } 15563be5a52bSMiklos Szeredi 15573be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 15583be5a52bSMiklos Szeredi { 15593be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 15603be5a52bSMiklos Szeredi 15613be5a52bSMiklos Szeredi spin_lock(&fc->lock); 15623be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 15633be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 15643be5a52bSMiklos Szeredi } 15653be5a52bSMiklos Szeredi 15663be5a52bSMiklos Szeredi /* 15676f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 15686f9f1180SMiklos Szeredi * 15696f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 15706f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 15719ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 15729ffbb916SMiklos Szeredi * and the actual truncation by hand. 15736f9f1180SMiklos Szeredi */ 1574efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr, 157549d4914fSMiklos Szeredi struct file *file) 15769e6268dbSMiklos Szeredi { 15779e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 157806a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 15799e6268dbSMiklos Szeredi struct fuse_req *req; 15809e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 15819e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 15823be5a52bSMiklos Szeredi bool is_truncate = false; 15833be5a52bSMiklos Szeredi loff_t oldsize; 15849e6268dbSMiklos Szeredi int err; 15859e6268dbSMiklos Szeredi 1586db78b877SChristoph Hellwig if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 1587db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1588db78b877SChristoph Hellwig 15891e9a4ed9SMiklos Szeredi err = inode_change_ok(inode, attr); 15901e9a4ed9SMiklos Szeredi if (err) 15911e9a4ed9SMiklos Szeredi return err; 15921e9a4ed9SMiklos Szeredi 15938d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 15948d56adddSMiklos Szeredi if (fc->atomic_o_trunc) 15956ff958edSMiklos Szeredi return 0; 15968d56adddSMiklos Szeredi file = NULL; 15978d56adddSMiklos Szeredi } 15986ff958edSMiklos Szeredi 15992c27c65eSChristoph Hellwig if (attr->ia_valid & ATTR_SIZE) 16003be5a52bSMiklos Szeredi is_truncate = true; 16019e6268dbSMiklos Szeredi 1602b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1603ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1604ce1d5a49SMiklos Szeredi return PTR_ERR(req); 16059e6268dbSMiklos Szeredi 160606a7c3c2SMaxim Patlasov if (is_truncate) { 16073be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 160806a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 160906a7c3c2SMaxim Patlasov } 16103be5a52bSMiklos Szeredi 16119e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 16120e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 1613befc649cSMiklos Szeredi iattr_to_fattr(attr, &inarg); 161449d4914fSMiklos Szeredi if (file) { 161549d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 161649d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 161749d4914fSMiklos Szeredi inarg.fh = ff->fh; 161849d4914fSMiklos Szeredi } 1619f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1620f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1621f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1622f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 1623f3332114SMiklos Szeredi } 16249e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SETATTR; 16259e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 16269e6268dbSMiklos Szeredi req->in.numargs = 1; 16279e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 16289e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 16299e6268dbSMiklos Szeredi req->out.numargs = 1; 16300e9663eeSMiklos Szeredi if (fc->minor < 9) 16310e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 16320e9663eeSMiklos Szeredi else 16339e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 16349e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 1635b93f858aSTejun Heo fuse_request_send(fc, req); 16369e6268dbSMiklos Szeredi err = req->out.h.error; 16379e6268dbSMiklos Szeredi fuse_put_request(fc, req); 1638e00d2c2dSMiklos Szeredi if (err) { 1639e00d2c2dSMiklos Szeredi if (err == -EINTR) 1640e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 16413be5a52bSMiklos Szeredi goto error; 1642e00d2c2dSMiklos Szeredi } 1643e00d2c2dSMiklos Szeredi 16449e6268dbSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 16459e6268dbSMiklos Szeredi make_bad_inode(inode); 16463be5a52bSMiklos Szeredi err = -EIO; 16473be5a52bSMiklos Szeredi goto error; 16489e6268dbSMiklos Szeredi } 16499e6268dbSMiklos Szeredi 16503be5a52bSMiklos Szeredi spin_lock(&fc->lock); 16513be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 16523be5a52bSMiklos Szeredi attr_timeout(&outarg)); 16533be5a52bSMiklos Szeredi oldsize = inode->i_size; 16543be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 16553be5a52bSMiklos Szeredi 16563be5a52bSMiklos Szeredi if (is_truncate) { 16573be5a52bSMiklos Szeredi /* NOTE: this may release/reacquire fc->lock */ 16583be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 16593be5a52bSMiklos Szeredi } 16603be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 16613be5a52bSMiklos Szeredi 16623be5a52bSMiklos Szeredi /* 16633be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 16643be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 16653be5a52bSMiklos Szeredi */ 16663be5a52bSMiklos Szeredi if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 16677caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 16683be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 16693be5a52bSMiklos Szeredi } 16703be5a52bSMiklos Szeredi 167106a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 1672e00d2c2dSMiklos Szeredi return 0; 16733be5a52bSMiklos Szeredi 16743be5a52bSMiklos Szeredi error: 16753be5a52bSMiklos Szeredi if (is_truncate) 16763be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 16773be5a52bSMiklos Szeredi 167806a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 16793be5a52bSMiklos Szeredi return err; 16809e6268dbSMiklos Szeredi } 16819e6268dbSMiklos Szeredi 168249d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 168349d4914fSMiklos Szeredi { 1684efb9fa9eSMaxim Patlasov struct inode *inode = entry->d_inode; 1685efb9fa9eSMaxim Patlasov 1686efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1687efb9fa9eSMaxim Patlasov return -EACCES; 1688efb9fa9eSMaxim Patlasov 168949d4914fSMiklos Szeredi if (attr->ia_valid & ATTR_FILE) 1690efb9fa9eSMaxim Patlasov return fuse_do_setattr(inode, attr, attr->ia_file); 169149d4914fSMiklos Szeredi else 1692efb9fa9eSMaxim Patlasov return fuse_do_setattr(inode, attr, NULL); 169349d4914fSMiklos Szeredi } 169449d4914fSMiklos Szeredi 1695e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, 1696e5e5558eSMiklos Szeredi struct kstat *stat) 1697e5e5558eSMiklos Szeredi { 1698e5e5558eSMiklos Szeredi struct inode *inode = entry->d_inode; 1699244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1700244f6385SMiklos Szeredi 1701c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1702244f6385SMiklos Szeredi return -EACCES; 1703244f6385SMiklos Szeredi 1704bcb4be80SMiklos Szeredi return fuse_update_attributes(inode, stat, NULL, NULL); 1705e5e5558eSMiklos Szeredi } 1706e5e5558eSMiklos Szeredi 170792a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name, 170892a8780eSMiklos Szeredi const void *value, size_t size, int flags) 170992a8780eSMiklos Szeredi { 171092a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 171192a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 171292a8780eSMiklos Szeredi struct fuse_req *req; 171392a8780eSMiklos Szeredi struct fuse_setxattr_in inarg; 171492a8780eSMiklos Szeredi int err; 171592a8780eSMiklos Szeredi 171692a8780eSMiklos Szeredi if (fc->no_setxattr) 171792a8780eSMiklos Szeredi return -EOPNOTSUPP; 171892a8780eSMiklos Szeredi 1719b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1720ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1721ce1d5a49SMiklos Szeredi return PTR_ERR(req); 172292a8780eSMiklos Szeredi 172392a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 172492a8780eSMiklos Szeredi inarg.size = size; 172592a8780eSMiklos Szeredi inarg.flags = flags; 172692a8780eSMiklos Szeredi req->in.h.opcode = FUSE_SETXATTR; 172792a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 172892a8780eSMiklos Szeredi req->in.numargs = 3; 172992a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 173092a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 173192a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 173292a8780eSMiklos Szeredi req->in.args[1].value = name; 173392a8780eSMiklos Szeredi req->in.args[2].size = size; 173492a8780eSMiklos Szeredi req->in.args[2].value = value; 1735b93f858aSTejun Heo fuse_request_send(fc, req); 173692a8780eSMiklos Szeredi err = req->out.h.error; 173792a8780eSMiklos Szeredi fuse_put_request(fc, req); 173892a8780eSMiklos Szeredi if (err == -ENOSYS) { 173992a8780eSMiklos Szeredi fc->no_setxattr = 1; 174092a8780eSMiklos Szeredi err = -EOPNOTSUPP; 174192a8780eSMiklos Szeredi } 1742d331a415SAnand Avati if (!err) 1743d331a415SAnand Avati fuse_invalidate_attr(inode); 174492a8780eSMiklos Szeredi return err; 174592a8780eSMiklos Szeredi } 174692a8780eSMiklos Szeredi 174792a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name, 174892a8780eSMiklos Szeredi void *value, size_t size) 174992a8780eSMiklos Szeredi { 175092a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 175192a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 175292a8780eSMiklos Szeredi struct fuse_req *req; 175392a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 175492a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 175592a8780eSMiklos Szeredi ssize_t ret; 175692a8780eSMiklos Szeredi 175792a8780eSMiklos Szeredi if (fc->no_getxattr) 175892a8780eSMiklos Szeredi return -EOPNOTSUPP; 175992a8780eSMiklos Szeredi 1760b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1761ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1762ce1d5a49SMiklos Szeredi return PTR_ERR(req); 176392a8780eSMiklos Szeredi 176492a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 176592a8780eSMiklos Szeredi inarg.size = size; 176692a8780eSMiklos Szeredi req->in.h.opcode = FUSE_GETXATTR; 176792a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 176892a8780eSMiklos Szeredi req->in.numargs = 2; 176992a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 177092a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 177192a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 177292a8780eSMiklos Szeredi req->in.args[1].value = name; 177392a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 177492a8780eSMiklos Szeredi req->out.numargs = 1; 177592a8780eSMiklos Szeredi if (size) { 177692a8780eSMiklos Szeredi req->out.argvar = 1; 177792a8780eSMiklos Szeredi req->out.args[0].size = size; 177892a8780eSMiklos Szeredi req->out.args[0].value = value; 177992a8780eSMiklos Szeredi } else { 178092a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 178192a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 178292a8780eSMiklos Szeredi } 1783b93f858aSTejun Heo fuse_request_send(fc, req); 178492a8780eSMiklos Szeredi ret = req->out.h.error; 178592a8780eSMiklos Szeredi if (!ret) 178692a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 178792a8780eSMiklos Szeredi else { 178892a8780eSMiklos Szeredi if (ret == -ENOSYS) { 178992a8780eSMiklos Szeredi fc->no_getxattr = 1; 179092a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 179192a8780eSMiklos Szeredi } 179292a8780eSMiklos Szeredi } 179392a8780eSMiklos Szeredi fuse_put_request(fc, req); 179492a8780eSMiklos Szeredi return ret; 179592a8780eSMiklos Szeredi } 179692a8780eSMiklos Szeredi 179792a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) 179892a8780eSMiklos Szeredi { 179992a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 180092a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 180192a8780eSMiklos Szeredi struct fuse_req *req; 180292a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 180392a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 180492a8780eSMiklos Szeredi ssize_t ret; 180592a8780eSMiklos Szeredi 1806c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1807e57ac683SMiklos Szeredi return -EACCES; 1808e57ac683SMiklos Szeredi 180992a8780eSMiklos Szeredi if (fc->no_listxattr) 181092a8780eSMiklos Szeredi return -EOPNOTSUPP; 181192a8780eSMiklos Szeredi 1812b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1813ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1814ce1d5a49SMiklos Szeredi return PTR_ERR(req); 181592a8780eSMiklos Szeredi 181692a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 181792a8780eSMiklos Szeredi inarg.size = size; 181892a8780eSMiklos Szeredi req->in.h.opcode = FUSE_LISTXATTR; 181992a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 182092a8780eSMiklos Szeredi req->in.numargs = 1; 182192a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 182292a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 182392a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 182492a8780eSMiklos Szeredi req->out.numargs = 1; 182592a8780eSMiklos Szeredi if (size) { 182692a8780eSMiklos Szeredi req->out.argvar = 1; 182792a8780eSMiklos Szeredi req->out.args[0].size = size; 182892a8780eSMiklos Szeredi req->out.args[0].value = list; 182992a8780eSMiklos Szeredi } else { 183092a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 183192a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 183292a8780eSMiklos Szeredi } 1833b93f858aSTejun Heo fuse_request_send(fc, req); 183492a8780eSMiklos Szeredi ret = req->out.h.error; 183592a8780eSMiklos Szeredi if (!ret) 183692a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 183792a8780eSMiklos Szeredi else { 183892a8780eSMiklos Szeredi if (ret == -ENOSYS) { 183992a8780eSMiklos Szeredi fc->no_listxattr = 1; 184092a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 184192a8780eSMiklos Szeredi } 184292a8780eSMiklos Szeredi } 184392a8780eSMiklos Szeredi fuse_put_request(fc, req); 184492a8780eSMiklos Szeredi return ret; 184592a8780eSMiklos Szeredi } 184692a8780eSMiklos Szeredi 184792a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name) 184892a8780eSMiklos Szeredi { 184992a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 185092a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 185192a8780eSMiklos Szeredi struct fuse_req *req; 185292a8780eSMiklos Szeredi int err; 185392a8780eSMiklos Szeredi 185492a8780eSMiklos Szeredi if (fc->no_removexattr) 185592a8780eSMiklos Szeredi return -EOPNOTSUPP; 185692a8780eSMiklos Szeredi 1857b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1858ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1859ce1d5a49SMiklos Szeredi return PTR_ERR(req); 186092a8780eSMiklos Szeredi 186192a8780eSMiklos Szeredi req->in.h.opcode = FUSE_REMOVEXATTR; 186292a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 186392a8780eSMiklos Szeredi req->in.numargs = 1; 186492a8780eSMiklos Szeredi req->in.args[0].size = strlen(name) + 1; 186592a8780eSMiklos Szeredi req->in.args[0].value = name; 1866b93f858aSTejun Heo fuse_request_send(fc, req); 186792a8780eSMiklos Szeredi err = req->out.h.error; 186892a8780eSMiklos Szeredi fuse_put_request(fc, req); 186992a8780eSMiklos Szeredi if (err == -ENOSYS) { 187092a8780eSMiklos Szeredi fc->no_removexattr = 1; 187192a8780eSMiklos Szeredi err = -EOPNOTSUPP; 187292a8780eSMiklos Szeredi } 1873d331a415SAnand Avati if (!err) 1874d331a415SAnand Avati fuse_invalidate_attr(inode); 187592a8780eSMiklos Szeredi return err; 187692a8780eSMiklos Szeredi } 187792a8780eSMiklos Szeredi 1878754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1879e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 18809e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 18819e6268dbSMiklos Szeredi .symlink = fuse_symlink, 18829e6268dbSMiklos Szeredi .unlink = fuse_unlink, 18839e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 18849e6268dbSMiklos Szeredi .rename = fuse_rename, 18859e6268dbSMiklos Szeredi .link = fuse_link, 18869e6268dbSMiklos Szeredi .setattr = fuse_setattr, 18879e6268dbSMiklos Szeredi .create = fuse_create, 1888c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 18899e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1890e5e5558eSMiklos Szeredi .permission = fuse_permission, 1891e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 189292a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 189392a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 189492a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 189592a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1896e5e5558eSMiklos Szeredi }; 1897e5e5558eSMiklos Szeredi 18984b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1899b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1900e5e5558eSMiklos Szeredi .read = generic_read_dir, 19018d3af7f3SAl Viro .iterate = fuse_readdir, 1902e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1903e5e5558eSMiklos Szeredi .release = fuse_dir_release, 190482547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1905b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 1906b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 1907e5e5558eSMiklos Szeredi }; 1908e5e5558eSMiklos Szeredi 1909754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 19109e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1911e5e5558eSMiklos Szeredi .permission = fuse_permission, 1912e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 191392a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 191492a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 191592a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 191692a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1917e5e5558eSMiklos Szeredi }; 1918e5e5558eSMiklos Szeredi 1919754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 19209e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1921e5e5558eSMiklos Szeredi .follow_link = fuse_follow_link, 1922e5e5558eSMiklos Szeredi .put_link = fuse_put_link, 1923e5e5558eSMiklos Szeredi .readlink = generic_readlink, 1924e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 192592a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 192692a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 192792a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 192892a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1929e5e5558eSMiklos Szeredi }; 1930e5e5558eSMiklos Szeredi 1931e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1932e5e5558eSMiklos Szeredi { 1933e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1934e5e5558eSMiklos Szeredi } 1935e5e5558eSMiklos Szeredi 1936e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1937e5e5558eSMiklos Szeredi { 1938e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1939e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1940e5e5558eSMiklos Szeredi } 1941e5e5558eSMiklos Szeredi 1942e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1943e5e5558eSMiklos Szeredi { 1944e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 1945e5e5558eSMiklos Szeredi } 1946