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 115451418fcSAndrew Gallagher /** 116451418fcSAndrew Gallagher * Mark the attributes as stale due to an atime change. Avoid the invalidate if 117451418fcSAndrew Gallagher * atime is not used. 118451418fcSAndrew Gallagher */ 119451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode) 120451418fcSAndrew Gallagher { 121451418fcSAndrew Gallagher if (!IS_RDONLY(inode)) 122451418fcSAndrew Gallagher fuse_invalidate_attr(inode); 123451418fcSAndrew Gallagher } 124451418fcSAndrew 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 68231f3267bSMaxim Patlasov static inline void fuse_update_ctime(struct inode *inode) 68331f3267bSMaxim Patlasov { 68431f3267bSMaxim Patlasov if (!IS_NOCMTIME(inode)) { 68531f3267bSMaxim Patlasov inode->i_ctime = current_fs_time(inode->i_sb); 68631f3267bSMaxim Patlasov mark_inode_dirty_sync(inode); 68731f3267bSMaxim Patlasov } 68831f3267bSMaxim Patlasov } 68931f3267bSMaxim Patlasov 6909e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 6919e6268dbSMiklos Szeredi { 6929e6268dbSMiklos Szeredi int err; 6939e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 694b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 695ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 696ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6979e6268dbSMiklos Szeredi 6989e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_UNLINK; 6999e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 7009e6268dbSMiklos Szeredi req->in.numargs = 1; 7019e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 7029e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 703b93f858aSTejun Heo fuse_request_send(fc, req); 7049e6268dbSMiklos Szeredi err = req->out.h.error; 7059e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7069e6268dbSMiklos Szeredi if (!err) { 7079e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 708ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 7099e6268dbSMiklos Szeredi 710ac45d613SMiklos Szeredi spin_lock(&fc->lock); 711ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 712dfca7cebSMiklos Szeredi /* 713dfca7cebSMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 714dfca7cebSMiklos Szeredi * happen if userspace filesystem is careless. It would be 715dfca7cebSMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 716dfca7cebSMiklos Szeredi * condition here 717dfca7cebSMiklos Szeredi */ 718dfca7cebSMiklos Szeredi if (inode->i_nlink > 0) 719ac45d613SMiklos Szeredi drop_nlink(inode); 720ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 7219e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 7229e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 7238cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 72431f3267bSMaxim Patlasov fuse_update_ctime(inode); 7259e6268dbSMiklos Szeredi } else if (err == -EINTR) 7269e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7279e6268dbSMiklos Szeredi return err; 7289e6268dbSMiklos Szeredi } 7299e6268dbSMiklos Szeredi 7309e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 7319e6268dbSMiklos Szeredi { 7329e6268dbSMiklos Szeredi int err; 7339e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 734b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 735ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 736ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7379e6268dbSMiklos Szeredi 7389e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RMDIR; 7399e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 7409e6268dbSMiklos Szeredi req->in.numargs = 1; 7419e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 7429e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 743b93f858aSTejun Heo fuse_request_send(fc, req); 7449e6268dbSMiklos Szeredi err = req->out.h.error; 7459e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7469e6268dbSMiklos Szeredi if (!err) { 747ce71ec36SDave Hansen clear_nlink(entry->d_inode); 7489e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 7498cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 7509e6268dbSMiklos Szeredi } else if (err == -EINTR) 7519e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7529e6268dbSMiklos Szeredi return err; 7539e6268dbSMiklos Szeredi } 7549e6268dbSMiklos Szeredi 755*1560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, 756*1560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 757*1560c974SMiklos Szeredi unsigned int flags, int opcode, size_t argsize) 7589e6268dbSMiklos Szeredi { 7599e6268dbSMiklos Szeredi int err; 760*1560c974SMiklos Szeredi struct fuse_rename2_in inarg; 7619e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 762*1560c974SMiklos Szeredi struct fuse_req *req; 763e4eaac06SSage Weil 764*1560c974SMiklos Szeredi req = fuse_get_req_nopages(fc); 765ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 766ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7679e6268dbSMiklos Szeredi 768*1560c974SMiklos Szeredi memset(&inarg, 0, argsize); 7699e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 770*1560c974SMiklos Szeredi inarg.flags = flags; 771*1560c974SMiklos Szeredi req->in.h.opcode = opcode; 7729e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(olddir); 7739e6268dbSMiklos Szeredi req->in.numargs = 3; 774*1560c974SMiklos Szeredi req->in.args[0].size = argsize; 7759e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 7769e6268dbSMiklos Szeredi req->in.args[1].size = oldent->d_name.len + 1; 7779e6268dbSMiklos Szeredi req->in.args[1].value = oldent->d_name.name; 7789e6268dbSMiklos Szeredi req->in.args[2].size = newent->d_name.len + 1; 7799e6268dbSMiklos Szeredi req->in.args[2].value = newent->d_name.name; 780b93f858aSTejun Heo fuse_request_send(fc, req); 7819e6268dbSMiklos Szeredi err = req->out.h.error; 7829e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7839e6268dbSMiklos Szeredi if (!err) { 78408b63307SMiklos Szeredi /* ctime changes */ 78508b63307SMiklos Szeredi fuse_invalidate_attr(oldent->d_inode); 78631f3267bSMaxim Patlasov fuse_update_ctime(oldent->d_inode); 78708b63307SMiklos Szeredi 788*1560c974SMiklos Szeredi if (flags & RENAME_EXCHANGE) { 789*1560c974SMiklos Szeredi fuse_invalidate_attr(newent->d_inode); 790*1560c974SMiklos Szeredi fuse_update_ctime(newent->d_inode); 791*1560c974SMiklos Szeredi } 792*1560c974SMiklos Szeredi 7939e6268dbSMiklos Szeredi fuse_invalidate_attr(olddir); 7949e6268dbSMiklos Szeredi if (olddir != newdir) 7959e6268dbSMiklos Szeredi fuse_invalidate_attr(newdir); 7968cbdf1e6SMiklos Szeredi 7978cbdf1e6SMiklos Szeredi /* newent will end up negative */ 798*1560c974SMiklos Szeredi if (!(flags & RENAME_EXCHANGE) && newent->d_inode) { 7995219f346SMiklos Szeredi fuse_invalidate_attr(newent->d_inode); 8008cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 80131f3267bSMaxim Patlasov fuse_update_ctime(newent->d_inode); 8025219f346SMiklos Szeredi } 8039e6268dbSMiklos Szeredi } else if (err == -EINTR) { 8049e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 8059e6268dbSMiklos Szeredi rename actually took place. If the invalidation 8069e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 8079e6268dbSMiklos Szeredi directory), then there can be inconsistency between 8089e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 8099e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 8109e6268dbSMiklos Szeredi if (newent->d_inode) 8119e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 8129e6268dbSMiklos Szeredi } 8139e6268dbSMiklos Szeredi 8149e6268dbSMiklos Szeredi return err; 8159e6268dbSMiklos Szeredi } 8169e6268dbSMiklos Szeredi 817*1560c974SMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent, 818*1560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent) 819*1560c974SMiklos Szeredi { 820*1560c974SMiklos Szeredi return fuse_rename_common(olddir, oldent, newdir, newent, 0, 821*1560c974SMiklos Szeredi FUSE_RENAME, sizeof(struct fuse_rename_in)); 822*1560c974SMiklos Szeredi } 823*1560c974SMiklos Szeredi 824*1560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent, 825*1560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 826*1560c974SMiklos Szeredi unsigned int flags) 827*1560c974SMiklos Szeredi { 828*1560c974SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 829*1560c974SMiklos Szeredi int err; 830*1560c974SMiklos Szeredi 831*1560c974SMiklos Szeredi if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) 832*1560c974SMiklos Szeredi return -EINVAL; 833*1560c974SMiklos Szeredi 834*1560c974SMiklos Szeredi if (fc->no_rename2 || fc->minor < 23) 835*1560c974SMiklos Szeredi return -EINVAL; 836*1560c974SMiklos Szeredi 837*1560c974SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, flags, 838*1560c974SMiklos Szeredi FUSE_RENAME2, sizeof(struct fuse_rename2_in)); 839*1560c974SMiklos Szeredi if (err == -ENOSYS) { 840*1560c974SMiklos Szeredi fc->no_rename2 = 1; 841*1560c974SMiklos Szeredi err = -EINVAL; 842*1560c974SMiklos Szeredi } 843*1560c974SMiklos Szeredi return err; 844*1560c974SMiklos Szeredi 845*1560c974SMiklos Szeredi } 846*1560c974SMiklos Szeredi 8479e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 8489e6268dbSMiklos Szeredi struct dentry *newent) 8499e6268dbSMiklos Szeredi { 8509e6268dbSMiklos Szeredi int err; 8519e6268dbSMiklos Szeredi struct fuse_link_in inarg; 8529e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 8539e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 854b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 855ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 856ce1d5a49SMiklos Szeredi return PTR_ERR(req); 8579e6268dbSMiklos Szeredi 8589e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8599e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 8609e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_LINK; 8619e6268dbSMiklos Szeredi req->in.numargs = 2; 8629e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 8639e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 8649e6268dbSMiklos Szeredi req->in.args[1].size = newent->d_name.len + 1; 8659e6268dbSMiklos Szeredi req->in.args[1].value = newent->d_name.name; 8669e6268dbSMiklos Szeredi err = create_new_entry(fc, req, newdir, newent, inode->i_mode); 8679e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 8689e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 8699e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 8709e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 8719e6268dbSMiklos Szeredi etc.) 8729e6268dbSMiklos Szeredi */ 873ac45d613SMiklos Szeredi if (!err) { 874ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 875ac45d613SMiklos Szeredi 876ac45d613SMiklos Szeredi spin_lock(&fc->lock); 877ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 878ac45d613SMiklos Szeredi inc_nlink(inode); 879ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 8809e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 88131f3267bSMaxim Patlasov fuse_update_ctime(inode); 882ac45d613SMiklos Szeredi } else if (err == -EINTR) { 883ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 884ac45d613SMiklos Szeredi } 8859e6268dbSMiklos Szeredi return err; 8869e6268dbSMiklos Szeredi } 8879e6268dbSMiklos Szeredi 8881fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 8891fb69e78SMiklos Szeredi struct kstat *stat) 8901fb69e78SMiklos Szeredi { 891203627bbSMiklos Szeredi unsigned int blkbits; 8928373200bSPavel Emelyanov struct fuse_conn *fc = get_fuse_conn(inode); 8938373200bSPavel Emelyanov 8948373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 895b0aa7606SMaxim Patlasov if (fc->writeback_cache && S_ISREG(inode->i_mode)) { 8968373200bSPavel Emelyanov attr->size = i_size_read(inode); 897b0aa7606SMaxim Patlasov attr->mtime = inode->i_mtime.tv_sec; 898b0aa7606SMaxim Patlasov attr->mtimensec = inode->i_mtime.tv_nsec; 89931f3267bSMaxim Patlasov attr->ctime = inode->i_ctime.tv_sec; 90031f3267bSMaxim Patlasov attr->ctimensec = inode->i_ctime.tv_nsec; 901b0aa7606SMaxim Patlasov } 902203627bbSMiklos Szeredi 9031fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 9041fb69e78SMiklos Szeredi stat->ino = attr->ino; 9051fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 9061fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 907499dcf20SEric W. Biederman stat->uid = make_kuid(&init_user_ns, attr->uid); 908499dcf20SEric W. Biederman stat->gid = make_kgid(&init_user_ns, attr->gid); 9091fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 9101fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 9111fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 9121fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 9131fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 9141fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 9151fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 9161fb69e78SMiklos Szeredi stat->size = attr->size; 9171fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 918203627bbSMiklos Szeredi 919203627bbSMiklos Szeredi if (attr->blksize != 0) 920203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 921203627bbSMiklos Szeredi else 922203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 923203627bbSMiklos Szeredi 924203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 9251fb69e78SMiklos Szeredi } 9261fb69e78SMiklos Szeredi 927c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 928c79e322fSMiklos Szeredi struct file *file) 929e5e5558eSMiklos Szeredi { 930e5e5558eSMiklos Szeredi int err; 931c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 932c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 933e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 9341fb69e78SMiklos Szeredi struct fuse_req *req; 9351fb69e78SMiklos Szeredi u64 attr_version; 9361fb69e78SMiklos Szeredi 937b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 938ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 939ce1d5a49SMiklos Szeredi return PTR_ERR(req); 940e5e5558eSMiklos Szeredi 9417dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 9421fb69e78SMiklos Szeredi 943c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 9440e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 945c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 946c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 947c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 948c79e322fSMiklos Szeredi 949c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 950c79e322fSMiklos Szeredi inarg.fh = ff->fh; 951c79e322fSMiklos Szeredi } 952e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_GETATTR; 953e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 954c79e322fSMiklos Szeredi req->in.numargs = 1; 955c79e322fSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 956c79e322fSMiklos Szeredi req->in.args[0].value = &inarg; 957e5e5558eSMiklos Szeredi req->out.numargs = 1; 9580e9663eeSMiklos Szeredi if (fc->minor < 9) 9590e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 9600e9663eeSMiklos Szeredi else 961c79e322fSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 962c79e322fSMiklos Szeredi req->out.args[0].value = &outarg; 963b93f858aSTejun Heo fuse_request_send(fc, req); 964e5e5558eSMiklos Szeredi err = req->out.h.error; 965e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 966e5e5558eSMiklos Szeredi if (!err) { 967c79e322fSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 968e5e5558eSMiklos Szeredi make_bad_inode(inode); 969e5e5558eSMiklos Szeredi err = -EIO; 970e5e5558eSMiklos Szeredi } else { 971c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 972c79e322fSMiklos Szeredi attr_timeout(&outarg), 9731fb69e78SMiklos Szeredi attr_version); 9741fb69e78SMiklos Szeredi if (stat) 975c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 976e5e5558eSMiklos Szeredi } 977e5e5558eSMiklos Szeredi } 978e5e5558eSMiklos Szeredi return err; 979e5e5558eSMiklos Szeredi } 980e5e5558eSMiklos Szeredi 981bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat, 982bcb4be80SMiklos Szeredi struct file *file, bool *refreshed) 983bcb4be80SMiklos Szeredi { 984bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 985bcb4be80SMiklos Szeredi int err; 986bcb4be80SMiklos Szeredi bool r; 987bcb4be80SMiklos Szeredi 988bcb4be80SMiklos Szeredi if (fi->i_time < get_jiffies_64()) { 989bcb4be80SMiklos Szeredi r = true; 990bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 991bcb4be80SMiklos Szeredi } else { 992bcb4be80SMiklos Szeredi r = false; 993bcb4be80SMiklos Szeredi err = 0; 994bcb4be80SMiklos Szeredi if (stat) { 995bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 996bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 99745c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 998bcb4be80SMiklos Szeredi } 999bcb4be80SMiklos Szeredi } 1000bcb4be80SMiklos Szeredi 1001bcb4be80SMiklos Szeredi if (refreshed != NULL) 1002bcb4be80SMiklos Szeredi *refreshed = r; 1003bcb4be80SMiklos Szeredi 1004bcb4be80SMiklos Szeredi return err; 1005bcb4be80SMiklos Szeredi } 1006bcb4be80SMiklos Szeredi 10073b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 1008451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 10093b463ae0SJohn Muir { 10103b463ae0SJohn Muir int err = -ENOTDIR; 10113b463ae0SJohn Muir struct inode *parent; 10123b463ae0SJohn Muir struct dentry *dir; 10133b463ae0SJohn Muir struct dentry *entry; 10143b463ae0SJohn Muir 10153b463ae0SJohn Muir parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); 10163b463ae0SJohn Muir if (!parent) 10173b463ae0SJohn Muir return -ENOENT; 10183b463ae0SJohn Muir 10193b463ae0SJohn Muir mutex_lock(&parent->i_mutex); 10203b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 10213b463ae0SJohn Muir goto unlock; 10223b463ae0SJohn Muir 10233b463ae0SJohn Muir err = -ENOENT; 10243b463ae0SJohn Muir dir = d_find_alias(parent); 10253b463ae0SJohn Muir if (!dir) 10263b463ae0SJohn Muir goto unlock; 10273b463ae0SJohn Muir 10283b463ae0SJohn Muir entry = d_lookup(dir, name); 10293b463ae0SJohn Muir dput(dir); 10303b463ae0SJohn Muir if (!entry) 10313b463ae0SJohn Muir goto unlock; 10323b463ae0SJohn Muir 10333b463ae0SJohn Muir fuse_invalidate_attr(parent); 10343b463ae0SJohn Muir fuse_invalidate_entry(entry); 1035451d0f59SJohn Muir 1036451d0f59SJohn Muir if (child_nodeid != 0 && entry->d_inode) { 1037451d0f59SJohn Muir mutex_lock(&entry->d_inode->i_mutex); 1038451d0f59SJohn Muir if (get_node_id(entry->d_inode) != child_nodeid) { 1039451d0f59SJohn Muir err = -ENOENT; 1040451d0f59SJohn Muir goto badentry; 1041451d0f59SJohn Muir } 1042451d0f59SJohn Muir if (d_mountpoint(entry)) { 1043451d0f59SJohn Muir err = -EBUSY; 1044451d0f59SJohn Muir goto badentry; 1045451d0f59SJohn Muir } 1046451d0f59SJohn Muir if (S_ISDIR(entry->d_inode->i_mode)) { 1047451d0f59SJohn Muir shrink_dcache_parent(entry); 1048451d0f59SJohn Muir if (!simple_empty(entry)) { 1049451d0f59SJohn Muir err = -ENOTEMPTY; 1050451d0f59SJohn Muir goto badentry; 1051451d0f59SJohn Muir } 1052451d0f59SJohn Muir entry->d_inode->i_flags |= S_DEAD; 1053451d0f59SJohn Muir } 1054451d0f59SJohn Muir dont_mount(entry); 1055451d0f59SJohn Muir clear_nlink(entry->d_inode); 10563b463ae0SJohn Muir err = 0; 1057451d0f59SJohn Muir badentry: 1058451d0f59SJohn Muir mutex_unlock(&entry->d_inode->i_mutex); 1059451d0f59SJohn Muir if (!err) 1060451d0f59SJohn Muir d_delete(entry); 1061451d0f59SJohn Muir } else { 1062451d0f59SJohn Muir err = 0; 1063451d0f59SJohn Muir } 1064451d0f59SJohn Muir dput(entry); 10653b463ae0SJohn Muir 10663b463ae0SJohn Muir unlock: 10673b463ae0SJohn Muir mutex_unlock(&parent->i_mutex); 10683b463ae0SJohn Muir iput(parent); 10693b463ae0SJohn Muir return err; 10703b463ae0SJohn Muir } 10713b463ae0SJohn Muir 107287729a55SMiklos Szeredi /* 107387729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1074c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 107587729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 107687729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 107787729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 107887729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 107987729a55SMiklos Szeredi * DoS against the requester. 108087729a55SMiklos Szeredi * 108187729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 108287729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 108387729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 108487729a55SMiklos Szeredi */ 1085c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc) 108687729a55SMiklos Szeredi { 1087c69e8d9cSDavid Howells const struct cred *cred; 1088c69e8d9cSDavid Howells 108987729a55SMiklos Szeredi if (fc->flags & FUSE_ALLOW_OTHER) 109087729a55SMiklos Szeredi return 1; 109187729a55SMiklos Szeredi 1092c2132c1bSAnatol Pomozov cred = current_cred(); 1093499dcf20SEric W. Biederman if (uid_eq(cred->euid, fc->user_id) && 1094499dcf20SEric W. Biederman uid_eq(cred->suid, fc->user_id) && 1095499dcf20SEric W. Biederman uid_eq(cred->uid, fc->user_id) && 1096499dcf20SEric W. Biederman gid_eq(cred->egid, fc->group_id) && 1097499dcf20SEric W. Biederman gid_eq(cred->sgid, fc->group_id) && 1098499dcf20SEric W. Biederman gid_eq(cred->gid, fc->group_id)) 1099c2132c1bSAnatol Pomozov return 1; 110087729a55SMiklos Szeredi 1101c2132c1bSAnatol Pomozov return 0; 110287729a55SMiklos Szeredi } 110387729a55SMiklos Szeredi 110431d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 110531d40d74SMiklos Szeredi { 110631d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 110731d40d74SMiklos Szeredi struct fuse_req *req; 110831d40d74SMiklos Szeredi struct fuse_access_in inarg; 110931d40d74SMiklos Szeredi int err; 111031d40d74SMiklos Szeredi 1111698fa1d1SMiklos Szeredi BUG_ON(mask & MAY_NOT_BLOCK); 1112698fa1d1SMiklos Szeredi 111331d40d74SMiklos Szeredi if (fc->no_access) 111431d40d74SMiklos Szeredi return 0; 111531d40d74SMiklos Szeredi 1116b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1117ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1118ce1d5a49SMiklos Szeredi return PTR_ERR(req); 111931d40d74SMiklos Szeredi 112031d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1121e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 112231d40d74SMiklos Szeredi req->in.h.opcode = FUSE_ACCESS; 112331d40d74SMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 112431d40d74SMiklos Szeredi req->in.numargs = 1; 112531d40d74SMiklos Szeredi req->in.args[0].size = sizeof(inarg); 112631d40d74SMiklos Szeredi req->in.args[0].value = &inarg; 1127b93f858aSTejun Heo fuse_request_send(fc, req); 112831d40d74SMiklos Szeredi err = req->out.h.error; 112931d40d74SMiklos Szeredi fuse_put_request(fc, req); 113031d40d74SMiklos Szeredi if (err == -ENOSYS) { 113131d40d74SMiklos Szeredi fc->no_access = 1; 113231d40d74SMiklos Szeredi err = 0; 113331d40d74SMiklos Szeredi } 113431d40d74SMiklos Szeredi return err; 113531d40d74SMiklos Szeredi } 113631d40d74SMiklos Szeredi 113710556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 113819690ddbSMiklos Szeredi { 113910556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 114019690ddbSMiklos Szeredi return -ECHILD; 114119690ddbSMiklos Szeredi 114219690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 114319690ddbSMiklos Szeredi } 114419690ddbSMiklos Szeredi 11456f9f1180SMiklos Szeredi /* 11466f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 11476f9f1180SMiklos Szeredi * 11486f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 11496f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 11506f9f1180SMiklos Szeredi * modell. 11516f9f1180SMiklos Szeredi * 11526f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 11536f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 11546f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 11556f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 11566f9f1180SMiklos Szeredi * locally based on file mode. 11576f9f1180SMiklos Szeredi */ 115810556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask) 1159e5e5558eSMiklos Szeredi { 1160e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1161244f6385SMiklos Szeredi bool refreshed = false; 1162244f6385SMiklos Szeredi int err = 0; 1163e5e5558eSMiklos Szeredi 1164c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1165e5e5558eSMiklos Szeredi return -EACCES; 1166244f6385SMiklos Szeredi 1167244f6385SMiklos Szeredi /* 1168e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1169244f6385SMiklos Szeredi */ 1170e8e96157SMiklos Szeredi if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || 1171e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 117219690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 117319690ddbSMiklos Szeredi 117419690ddbSMiklos Szeredi if (fi->i_time < get_jiffies_64()) { 117519690ddbSMiklos Szeredi refreshed = true; 117619690ddbSMiklos Szeredi 117710556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1178244f6385SMiklos Szeredi if (err) 1179244f6385SMiklos Szeredi return err; 11801fb69e78SMiklos Szeredi } 118119690ddbSMiklos Szeredi } 1182244f6385SMiklos Szeredi 1183244f6385SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 11842830ba7fSAl Viro err = generic_permission(inode, mask); 11851e9a4ed9SMiklos Szeredi 11861e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 11871e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 11881e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1189244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 119010556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 11911e9a4ed9SMiklos Szeredi if (!err) 11922830ba7fSAl Viro err = generic_permission(inode, mask); 11931e9a4ed9SMiklos Szeredi } 11941e9a4ed9SMiklos Szeredi 11956f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 11966f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 11976f9f1180SMiklos Szeredi noticed immediately, only after the attribute 11986f9f1180SMiklos Szeredi timeout has expired */ 11999cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1200e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1201e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1202e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1203e8e96157SMiklos Szeredi if (refreshed) 1204e5e5558eSMiklos Szeredi return -EACCES; 120531d40d74SMiklos Szeredi 120610556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1207e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1208e8e96157SMiklos Szeredi return -EACCES; 1209e8e96157SMiklos Szeredi } 1210e5e5558eSMiklos Szeredi } 1211244f6385SMiklos Szeredi return err; 1212e5e5558eSMiklos Szeredi } 1213e5e5558eSMiklos Szeredi 1214e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file, 12158d3af7f3SAl Viro struct dir_context *ctx) 1216e5e5558eSMiklos Szeredi { 1217e5e5558eSMiklos Szeredi while (nbytes >= FUSE_NAME_OFFSET) { 1218e5e5558eSMiklos Szeredi struct fuse_dirent *dirent = (struct fuse_dirent *) buf; 1219e5e5558eSMiklos Szeredi size_t reclen = FUSE_DIRENT_SIZE(dirent); 1220e5e5558eSMiklos Szeredi if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 1221e5e5558eSMiklos Szeredi return -EIO; 1222e5e5558eSMiklos Szeredi if (reclen > nbytes) 1223e5e5558eSMiklos Szeredi break; 1224efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1225efeb9e60SMiklos Szeredi return -EIO; 1226e5e5558eSMiklos Szeredi 12278d3af7f3SAl Viro if (!dir_emit(ctx, dirent->name, dirent->namelen, 12288d3af7f3SAl Viro dirent->ino, dirent->type)) 1229e5e5558eSMiklos Szeredi break; 1230e5e5558eSMiklos Szeredi 1231e5e5558eSMiklos Szeredi buf += reclen; 1232e5e5558eSMiklos Szeredi nbytes -= reclen; 12338d3af7f3SAl Viro ctx->pos = dirent->off; 1234e5e5558eSMiklos Szeredi } 1235e5e5558eSMiklos Szeredi 1236e5e5558eSMiklos Szeredi return 0; 1237e5e5558eSMiklos Szeredi } 1238e5e5558eSMiklos Szeredi 12390b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file, 12400b05b183SAnand V. Avati struct fuse_direntplus *direntplus, 12410b05b183SAnand V. Avati u64 attr_version) 12420b05b183SAnand V. Avati { 12430b05b183SAnand V. Avati int err; 12440b05b183SAnand V. Avati struct fuse_entry_out *o = &direntplus->entry_out; 12450b05b183SAnand V. Avati struct fuse_dirent *dirent = &direntplus->dirent; 12460b05b183SAnand V. Avati struct dentry *parent = file->f_path.dentry; 12470b05b183SAnand V. Avati struct qstr name = QSTR_INIT(dirent->name, dirent->namelen); 12480b05b183SAnand V. Avati struct dentry *dentry; 12490b05b183SAnand V. Avati struct dentry *alias; 12500b05b183SAnand V. Avati struct inode *dir = parent->d_inode; 12510b05b183SAnand V. Avati struct fuse_conn *fc; 12520b05b183SAnand V. Avati struct inode *inode; 12530b05b183SAnand V. Avati 12540b05b183SAnand V. Avati if (!o->nodeid) { 12550b05b183SAnand V. Avati /* 12560b05b183SAnand V. Avati * Unlike in the case of fuse_lookup, zero nodeid does not mean 12570b05b183SAnand V. Avati * ENOENT. Instead, it only means the userspace filesystem did 12580b05b183SAnand V. Avati * not want to return attributes/handle for this entry. 12590b05b183SAnand V. Avati * 12600b05b183SAnand V. Avati * So do nothing. 12610b05b183SAnand V. Avati */ 12620b05b183SAnand V. Avati return 0; 12630b05b183SAnand V. Avati } 12640b05b183SAnand V. Avati 12650b05b183SAnand V. Avati if (name.name[0] == '.') { 12660b05b183SAnand V. Avati /* 12670b05b183SAnand V. Avati * We could potentially refresh the attributes of the directory 12680b05b183SAnand V. Avati * and its parent? 12690b05b183SAnand V. Avati */ 12700b05b183SAnand V. Avati if (name.len == 1) 12710b05b183SAnand V. Avati return 0; 12720b05b183SAnand V. Avati if (name.name[1] == '.' && name.len == 2) 12730b05b183SAnand V. Avati return 0; 12740b05b183SAnand V. Avati } 1275a28ef45cSMiklos Szeredi 1276a28ef45cSMiklos Szeredi if (invalid_nodeid(o->nodeid)) 1277a28ef45cSMiklos Szeredi return -EIO; 1278a28ef45cSMiklos Szeredi if (!fuse_valid_type(o->attr.mode)) 1279a28ef45cSMiklos Szeredi return -EIO; 1280a28ef45cSMiklos Szeredi 12810b05b183SAnand V. Avati fc = get_fuse_conn(dir); 12820b05b183SAnand V. Avati 12830b05b183SAnand V. Avati name.hash = full_name_hash(name.name, name.len); 12840b05b183SAnand V. Avati dentry = d_lookup(parent, &name); 128553ce9a33SNiels de Vos if (dentry) { 12860b05b183SAnand V. Avati inode = dentry->d_inode; 128753ce9a33SNiels de Vos if (!inode) { 128853ce9a33SNiels de Vos d_drop(dentry); 1289a28ef45cSMiklos Szeredi } else if (get_node_id(inode) != o->nodeid || 1290a28ef45cSMiklos Szeredi ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { 129153ce9a33SNiels de Vos err = d_invalidate(dentry); 129253ce9a33SNiels de Vos if (err) 129353ce9a33SNiels de Vos goto out; 1294a28ef45cSMiklos Szeredi } else if (is_bad_inode(inode)) { 1295a28ef45cSMiklos Szeredi err = -EIO; 1296a28ef45cSMiklos Szeredi goto out; 129753ce9a33SNiels de Vos } else { 12980b05b183SAnand V. Avati struct fuse_inode *fi; 12990b05b183SAnand V. Avati fi = get_fuse_inode(inode); 13000b05b183SAnand V. Avati spin_lock(&fc->lock); 13010b05b183SAnand V. Avati fi->nlookup++; 13020b05b183SAnand V. Avati spin_unlock(&fc->lock); 13030b05b183SAnand V. Avati 1304fa2b7213SMiklos Szeredi fuse_change_attributes(inode, &o->attr, 1305fa2b7213SMiklos Szeredi entry_attr_timeout(o), 1306fa2b7213SMiklos Szeredi attr_version); 1307fa2b7213SMiklos Szeredi 13080b05b183SAnand V. Avati /* 13090b05b183SAnand V. Avati * The other branch to 'found' comes via fuse_iget() 13100b05b183SAnand V. Avati * which bumps nlookup inside 13110b05b183SAnand V. Avati */ 13120b05b183SAnand V. Avati goto found; 13130b05b183SAnand V. Avati } 13140b05b183SAnand V. Avati dput(dentry); 13150b05b183SAnand V. Avati } 13160b05b183SAnand V. Avati 13170b05b183SAnand V. Avati dentry = d_alloc(parent, &name); 13180b05b183SAnand V. Avati err = -ENOMEM; 13190b05b183SAnand V. Avati if (!dentry) 13200b05b183SAnand V. Avati goto out; 13210b05b183SAnand V. Avati 13220b05b183SAnand V. Avati inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, 13230b05b183SAnand V. Avati &o->attr, entry_attr_timeout(o), attr_version); 13240b05b183SAnand V. Avati if (!inode) 13250b05b183SAnand V. Avati goto out; 13260b05b183SAnand V. Avati 1327b70a80e7SMiklos Szeredi alias = d_materialise_unique(dentry, inode); 13280b05b183SAnand V. Avati err = PTR_ERR(alias); 13295835f339SMiklos Szeredi if (IS_ERR(alias)) 13300b05b183SAnand V. Avati goto out; 13312914941eSMiklos Szeredi 13320b05b183SAnand V. Avati if (alias) { 13330b05b183SAnand V. Avati dput(dentry); 13340b05b183SAnand V. Avati dentry = alias; 13350b05b183SAnand V. Avati } 13360b05b183SAnand V. Avati 13370b05b183SAnand V. Avati found: 13386314efeeSMiklos Szeredi if (fc->readdirplus_auto) 13396314efeeSMiklos Szeredi set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); 13400b05b183SAnand V. Avati fuse_change_entry_timeout(dentry, o); 13410b05b183SAnand V. Avati 13420b05b183SAnand V. Avati err = 0; 13430b05b183SAnand V. Avati out: 13440b05b183SAnand V. Avati dput(dentry); 13450b05b183SAnand V. Avati return err; 13460b05b183SAnand V. Avati } 13470b05b183SAnand V. Avati 13480b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, 13498d3af7f3SAl Viro struct dir_context *ctx, u64 attr_version) 13500b05b183SAnand V. Avati { 13510b05b183SAnand V. Avati struct fuse_direntplus *direntplus; 13520b05b183SAnand V. Avati struct fuse_dirent *dirent; 13530b05b183SAnand V. Avati size_t reclen; 13540b05b183SAnand V. Avati int over = 0; 13550b05b183SAnand V. Avati int ret; 13560b05b183SAnand V. Avati 13570b05b183SAnand V. Avati while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) { 13580b05b183SAnand V. Avati direntplus = (struct fuse_direntplus *) buf; 13590b05b183SAnand V. Avati dirent = &direntplus->dirent; 13600b05b183SAnand V. Avati reclen = FUSE_DIRENTPLUS_SIZE(direntplus); 13610b05b183SAnand V. Avati 13620b05b183SAnand V. Avati if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 13630b05b183SAnand V. Avati return -EIO; 13640b05b183SAnand V. Avati if (reclen > nbytes) 13650b05b183SAnand V. Avati break; 1366efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1367efeb9e60SMiklos Szeredi return -EIO; 13680b05b183SAnand V. Avati 13690b05b183SAnand V. Avati if (!over) { 13700b05b183SAnand V. Avati /* We fill entries into dstbuf only as much as 13710b05b183SAnand V. Avati it can hold. But we still continue iterating 13720b05b183SAnand V. Avati over remaining entries to link them. If not, 13730b05b183SAnand V. Avati we need to send a FORGET for each of those 13740b05b183SAnand V. Avati which we did not link. 13750b05b183SAnand V. Avati */ 13768d3af7f3SAl Viro over = !dir_emit(ctx, dirent->name, dirent->namelen, 13778d3af7f3SAl Viro dirent->ino, dirent->type); 13788d3af7f3SAl Viro ctx->pos = dirent->off; 13790b05b183SAnand V. Avati } 13800b05b183SAnand V. Avati 13810b05b183SAnand V. Avati buf += reclen; 13820b05b183SAnand V. Avati nbytes -= reclen; 13830b05b183SAnand V. Avati 13840b05b183SAnand V. Avati ret = fuse_direntplus_link(file, direntplus, attr_version); 13850b05b183SAnand V. Avati if (ret) 13860b05b183SAnand V. Avati fuse_force_forget(file, direntplus->entry_out.nodeid); 13870b05b183SAnand V. Avati } 13880b05b183SAnand V. Avati 13890b05b183SAnand V. Avati return 0; 13900b05b183SAnand V. Avati } 13910b05b183SAnand V. Avati 13928d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx) 1393e5e5558eSMiklos Szeredi { 13944582a4abSFeng Shuo int plus, err; 139504730fefSMiklos Szeredi size_t nbytes; 139604730fefSMiklos Szeredi struct page *page; 1397496ad9aaSAl Viro struct inode *inode = file_inode(file); 139804730fefSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1399248d86e8SMiklos Szeredi struct fuse_req *req; 14000b05b183SAnand V. Avati u64 attr_version = 0; 1401248d86e8SMiklos Szeredi 1402248d86e8SMiklos Szeredi if (is_bad_inode(inode)) 1403248d86e8SMiklos Szeredi return -EIO; 1404248d86e8SMiklos Szeredi 1405b111c8c0SMaxim Patlasov req = fuse_get_req(fc, 1); 1406ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1407ce1d5a49SMiklos Szeredi return PTR_ERR(req); 1408e5e5558eSMiklos Szeredi 140904730fefSMiklos Szeredi page = alloc_page(GFP_KERNEL); 141004730fefSMiklos Szeredi if (!page) { 141104730fefSMiklos Szeredi fuse_put_request(fc, req); 1412e5e5558eSMiklos Szeredi return -ENOMEM; 141304730fefSMiklos Szeredi } 14144582a4abSFeng Shuo 14158d3af7f3SAl Viro plus = fuse_use_readdirplus(inode, ctx); 1416f4975c67SMiklos Szeredi req->out.argpages = 1; 141704730fefSMiklos Szeredi req->num_pages = 1; 141804730fefSMiklos Szeredi req->pages[0] = page; 141985f40aecSMaxim Patlasov req->page_descs[0].length = PAGE_SIZE; 14204582a4abSFeng Shuo if (plus) { 14210b05b183SAnand V. Avati attr_version = fuse_get_attr_version(fc); 14228d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 14230b05b183SAnand V. Avati FUSE_READDIRPLUS); 14240b05b183SAnand V. Avati } else { 14258d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 14260b05b183SAnand V. Avati FUSE_READDIR); 14270b05b183SAnand V. Avati } 1428b93f858aSTejun Heo fuse_request_send(fc, req); 1429361b1eb5SMiklos Szeredi nbytes = req->out.args[0].size; 143004730fefSMiklos Szeredi err = req->out.h.error; 143104730fefSMiklos Szeredi fuse_put_request(fc, req); 14320b05b183SAnand V. Avati if (!err) { 14334582a4abSFeng Shuo if (plus) { 14340b05b183SAnand V. Avati err = parse_dirplusfile(page_address(page), nbytes, 14358d3af7f3SAl Viro file, ctx, 14360b05b183SAnand V. Avati attr_version); 14370b05b183SAnand V. Avati } else { 14380b05b183SAnand V. Avati err = parse_dirfile(page_address(page), nbytes, file, 14398d3af7f3SAl Viro ctx); 14400b05b183SAnand V. Avati } 14410b05b183SAnand V. Avati } 1442e5e5558eSMiklos Szeredi 144304730fefSMiklos Szeredi __free_page(page); 1444451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 144504730fefSMiklos Szeredi return err; 1446e5e5558eSMiklos Szeredi } 1447e5e5558eSMiklos Szeredi 1448e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry) 1449e5e5558eSMiklos Szeredi { 1450e5e5558eSMiklos Szeredi struct inode *inode = dentry->d_inode; 1451e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1452b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 1453e5e5558eSMiklos Szeredi char *link; 1454e5e5558eSMiklos Szeredi 1455ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1456e231c2eeSDavid Howells return ERR_CAST(req); 1457e5e5558eSMiklos Szeredi 1458e5e5558eSMiklos Szeredi link = (char *) __get_free_page(GFP_KERNEL); 1459e5e5558eSMiklos Szeredi if (!link) { 1460e5e5558eSMiklos Szeredi link = ERR_PTR(-ENOMEM); 1461e5e5558eSMiklos Szeredi goto out; 1462e5e5558eSMiklos Szeredi } 1463e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_READLINK; 1464e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 1465e5e5558eSMiklos Szeredi req->out.argvar = 1; 1466e5e5558eSMiklos Szeredi req->out.numargs = 1; 1467e5e5558eSMiklos Szeredi req->out.args[0].size = PAGE_SIZE - 1; 1468e5e5558eSMiklos Szeredi req->out.args[0].value = link; 1469b93f858aSTejun Heo fuse_request_send(fc, req); 1470e5e5558eSMiklos Szeredi if (req->out.h.error) { 1471e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1472e5e5558eSMiklos Szeredi link = ERR_PTR(req->out.h.error); 1473e5e5558eSMiklos Szeredi } else 1474e5e5558eSMiklos Szeredi link[req->out.args[0].size] = '\0'; 1475e5e5558eSMiklos Szeredi out: 1476e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 1477451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 1478e5e5558eSMiklos Szeredi return link; 1479e5e5558eSMiklos Szeredi } 1480e5e5558eSMiklos Szeredi 1481e5e5558eSMiklos Szeredi static void free_link(char *link) 1482e5e5558eSMiklos Szeredi { 1483e5e5558eSMiklos Szeredi if (!IS_ERR(link)) 1484e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1485e5e5558eSMiklos Szeredi } 1486e5e5558eSMiklos Szeredi 1487e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd) 1488e5e5558eSMiklos Szeredi { 1489e5e5558eSMiklos Szeredi nd_set_link(nd, read_link(dentry)); 1490e5e5558eSMiklos Szeredi return NULL; 1491e5e5558eSMiklos Szeredi } 1492e5e5558eSMiklos Szeredi 1493e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c) 1494e5e5558eSMiklos Szeredi { 1495e5e5558eSMiklos Szeredi free_link(nd_get_link(nd)); 1496e5e5558eSMiklos Szeredi } 1497e5e5558eSMiklos Szeredi 1498e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1499e5e5558eSMiklos Szeredi { 150091fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1501e5e5558eSMiklos Szeredi } 1502e5e5558eSMiklos Szeredi 1503e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1504e5e5558eSMiklos Szeredi { 15058b0797a4SMiklos Szeredi fuse_release_common(file, FUSE_RELEASEDIR); 15068b0797a4SMiklos Szeredi 15078b0797a4SMiklos Szeredi return 0; 1508e5e5558eSMiklos Szeredi } 1509e5e5558eSMiklos Szeredi 151002c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 151102c24a82SJosef Bacik int datasync) 151282547981SMiklos Szeredi { 151302c24a82SJosef Bacik return fuse_fsync_common(file, start, end, datasync, 1); 151482547981SMiklos Szeredi } 151582547981SMiklos Szeredi 1516b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1517b18da0c5SMiklos Szeredi unsigned long arg) 1518b18da0c5SMiklos Szeredi { 1519b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1520b18da0c5SMiklos Szeredi 1521b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1522b18da0c5SMiklos Szeredi if (fc->minor < 18) 1523b18da0c5SMiklos Szeredi return -ENOTTY; 1524b18da0c5SMiklos Szeredi 1525b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1526b18da0c5SMiklos Szeredi } 1527b18da0c5SMiklos Szeredi 1528b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1529b18da0c5SMiklos Szeredi unsigned long arg) 1530b18da0c5SMiklos Szeredi { 1531b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1532b18da0c5SMiklos Szeredi 1533b18da0c5SMiklos Szeredi if (fc->minor < 18) 1534b18da0c5SMiklos Szeredi return -ENOTTY; 1535b18da0c5SMiklos Szeredi 1536b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1537b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1538b18da0c5SMiklos Szeredi } 1539b18da0c5SMiklos Szeredi 1540b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime) 154117637cbaSMiklos Szeredi { 154217637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 154317637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 154417637cbaSMiklos Szeredi return true; 154517637cbaSMiklos Szeredi 1546b0aa7606SMaxim Patlasov /* Or if kernel i_mtime is the official one */ 1547b0aa7606SMaxim Patlasov if (trust_local_mtime) 1548b0aa7606SMaxim Patlasov return true; 1549b0aa7606SMaxim Patlasov 155017637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 155117637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 155217637cbaSMiklos Szeredi return false; 155317637cbaSMiklos Szeredi 155417637cbaSMiklos Szeredi /* In all other cases update */ 155517637cbaSMiklos Szeredi return true; 155617637cbaSMiklos Szeredi } 155717637cbaSMiklos Szeredi 1558b0aa7606SMaxim Patlasov static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg, 15593ad22c62SMaxim Patlasov bool trust_local_cmtime) 15609e6268dbSMiklos Szeredi { 15619e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 15629e6268dbSMiklos Szeredi 15639e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1564befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 15659e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 1566499dcf20SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid); 15679e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 1568499dcf20SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid); 15699e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1570befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 157117637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 157217637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1573befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 157417637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 157517637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 157617637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 157717637cbaSMiklos Szeredi } 15783ad22c62SMaxim Patlasov if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) { 157917637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1580befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 158117637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 15823ad22c62SMaxim Patlasov if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime) 158317637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 15849e6268dbSMiklos Szeredi } 15853ad22c62SMaxim Patlasov if ((ivalid & ATTR_CTIME) && trust_local_cmtime) { 15863ad22c62SMaxim Patlasov arg->valid |= FATTR_CTIME; 15873ad22c62SMaxim Patlasov arg->ctime = iattr->ia_ctime.tv_sec; 15883ad22c62SMaxim Patlasov arg->ctimensec = iattr->ia_ctime.tv_nsec; 15893ad22c62SMaxim Patlasov } 15909e6268dbSMiklos Szeredi } 15919e6268dbSMiklos Szeredi 15926f9f1180SMiklos Szeredi /* 15933be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 15943be5a52bSMiklos Szeredi * 15953be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 15963be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 15973be5a52bSMiklos Szeredi */ 15983be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 15993be5a52bSMiklos Szeredi { 16003be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 16013be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 16023be5a52bSMiklos Szeredi 16033be5a52bSMiklos Szeredi BUG_ON(!mutex_is_locked(&inode->i_mutex)); 16043be5a52bSMiklos Szeredi 16053be5a52bSMiklos Szeredi spin_lock(&fc->lock); 16063be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 16073be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 16083be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 16093be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 16103be5a52bSMiklos Szeredi } 16113be5a52bSMiklos Szeredi 16123be5a52bSMiklos Szeredi /* 16133be5a52bSMiklos Szeredi * Allow writepages on inode 16143be5a52bSMiklos Szeredi * 16153be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 16163be5a52bSMiklos Szeredi * writepages. 16173be5a52bSMiklos Szeredi */ 16183be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 16193be5a52bSMiklos Szeredi { 16203be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 16213be5a52bSMiklos Szeredi 16223be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 16233be5a52bSMiklos Szeredi fi->writectr = 0; 16243be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 16253be5a52bSMiklos Szeredi } 16263be5a52bSMiklos Szeredi 16273be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 16283be5a52bSMiklos Szeredi { 16293be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 16303be5a52bSMiklos Szeredi 16313be5a52bSMiklos Szeredi spin_lock(&fc->lock); 16323be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 16333be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 16343be5a52bSMiklos Szeredi } 16353be5a52bSMiklos Szeredi 1636b0aa7606SMaxim Patlasov static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req, 1637b0aa7606SMaxim Patlasov struct inode *inode, 1638b0aa7606SMaxim Patlasov struct fuse_setattr_in *inarg_p, 1639b0aa7606SMaxim Patlasov struct fuse_attr_out *outarg_p) 1640b0aa7606SMaxim Patlasov { 1641b0aa7606SMaxim Patlasov req->in.h.opcode = FUSE_SETATTR; 1642b0aa7606SMaxim Patlasov req->in.h.nodeid = get_node_id(inode); 1643b0aa7606SMaxim Patlasov req->in.numargs = 1; 1644b0aa7606SMaxim Patlasov req->in.args[0].size = sizeof(*inarg_p); 1645b0aa7606SMaxim Patlasov req->in.args[0].value = inarg_p; 1646b0aa7606SMaxim Patlasov req->out.numargs = 1; 1647b0aa7606SMaxim Patlasov if (fc->minor < 9) 1648b0aa7606SMaxim Patlasov req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 1649b0aa7606SMaxim Patlasov else 1650b0aa7606SMaxim Patlasov req->out.args[0].size = sizeof(*outarg_p); 1651b0aa7606SMaxim Patlasov req->out.args[0].value = outarg_p; 1652b0aa7606SMaxim Patlasov } 1653b0aa7606SMaxim Patlasov 1654b0aa7606SMaxim Patlasov /* 1655b0aa7606SMaxim Patlasov * Flush inode->i_mtime to the server 1656b0aa7606SMaxim Patlasov */ 1657ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff) 1658b0aa7606SMaxim Patlasov { 1659b0aa7606SMaxim Patlasov struct fuse_conn *fc = get_fuse_conn(inode); 16601e18bda8SMiklos Szeredi struct fuse_req *req; 1661b0aa7606SMaxim Patlasov struct fuse_setattr_in inarg; 1662b0aa7606SMaxim Patlasov struct fuse_attr_out outarg; 1663b0aa7606SMaxim Patlasov int err; 1664b0aa7606SMaxim Patlasov 1665b0aa7606SMaxim Patlasov req = fuse_get_req_nopages(fc); 1666b0aa7606SMaxim Patlasov if (IS_ERR(req)) 1667b0aa7606SMaxim Patlasov return PTR_ERR(req); 1668b0aa7606SMaxim Patlasov 1669b0aa7606SMaxim Patlasov memset(&inarg, 0, sizeof(inarg)); 1670b0aa7606SMaxim Patlasov memset(&outarg, 0, sizeof(outarg)); 1671b0aa7606SMaxim Patlasov 1672ab9e13f7SMaxim Patlasov inarg.valid = FATTR_MTIME; 1673b0aa7606SMaxim Patlasov inarg.mtime = inode->i_mtime.tv_sec; 1674b0aa7606SMaxim Patlasov inarg.mtimensec = inode->i_mtime.tv_nsec; 1675ab9e13f7SMaxim Patlasov if (fc->minor >= 23) { 1676ab9e13f7SMaxim Patlasov inarg.valid |= FATTR_CTIME; 1677ab9e13f7SMaxim Patlasov inarg.ctime = inode->i_ctime.tv_sec; 1678ab9e13f7SMaxim Patlasov inarg.ctimensec = inode->i_ctime.tv_nsec; 1679ab9e13f7SMaxim Patlasov } 16801e18bda8SMiklos Szeredi if (ff) { 16811e18bda8SMiklos Szeredi inarg.valid |= FATTR_FH; 16821e18bda8SMiklos Szeredi inarg.fh = ff->fh; 16831e18bda8SMiklos Szeredi } 1684b0aa7606SMaxim Patlasov fuse_setattr_fill(fc, req, inode, &inarg, &outarg); 1685b0aa7606SMaxim Patlasov fuse_request_send(fc, req); 1686b0aa7606SMaxim Patlasov err = req->out.h.error; 1687b0aa7606SMaxim Patlasov fuse_put_request(fc, req); 1688b0aa7606SMaxim Patlasov 1689b0aa7606SMaxim Patlasov return err; 1690b0aa7606SMaxim Patlasov } 1691b0aa7606SMaxim Patlasov 16923be5a52bSMiklos Szeredi /* 16936f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 16946f9f1180SMiklos Szeredi * 16956f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 16966f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 16979ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 16989ffbb916SMiklos Szeredi * and the actual truncation by hand. 16996f9f1180SMiklos Szeredi */ 1700efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr, 170149d4914fSMiklos Szeredi struct file *file) 17029e6268dbSMiklos Szeredi { 17039e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 170406a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 17059e6268dbSMiklos Szeredi struct fuse_req *req; 17069e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 17079e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 17083be5a52bSMiklos Szeredi bool is_truncate = false; 17098373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 17103be5a52bSMiklos Szeredi loff_t oldsize; 17119e6268dbSMiklos Szeredi int err; 17123ad22c62SMaxim Patlasov bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode); 17139e6268dbSMiklos Szeredi 1714db78b877SChristoph Hellwig if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 1715db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1716db78b877SChristoph Hellwig 17171e9a4ed9SMiklos Szeredi err = inode_change_ok(inode, attr); 17181e9a4ed9SMiklos Szeredi if (err) 17191e9a4ed9SMiklos Szeredi return err; 17201e9a4ed9SMiklos Szeredi 17218d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 17228d56adddSMiklos Szeredi if (fc->atomic_o_trunc) 17236ff958edSMiklos Szeredi return 0; 17248d56adddSMiklos Szeredi file = NULL; 17258d56adddSMiklos Szeredi } 17266ff958edSMiklos Szeredi 17272c27c65eSChristoph Hellwig if (attr->ia_valid & ATTR_SIZE) 17283be5a52bSMiklos Szeredi is_truncate = true; 17299e6268dbSMiklos Szeredi 1730b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1731ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1732ce1d5a49SMiklos Szeredi return PTR_ERR(req); 17339e6268dbSMiklos Szeredi 173406a7c3c2SMaxim Patlasov if (is_truncate) { 17353be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 173606a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 17373ad22c62SMaxim Patlasov if (trust_local_cmtime && attr->ia_size != inode->i_size) 17383ad22c62SMaxim Patlasov attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; 173906a7c3c2SMaxim Patlasov } 17403be5a52bSMiklos Szeredi 17419e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 17420e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 17433ad22c62SMaxim Patlasov iattr_to_fattr(attr, &inarg, trust_local_cmtime); 174449d4914fSMiklos Szeredi if (file) { 174549d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 174649d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 174749d4914fSMiklos Szeredi inarg.fh = ff->fh; 174849d4914fSMiklos Szeredi } 1749f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1750f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1751f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1752f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 1753f3332114SMiklos Szeredi } 1754b0aa7606SMaxim Patlasov fuse_setattr_fill(fc, req, inode, &inarg, &outarg); 1755b93f858aSTejun Heo fuse_request_send(fc, req); 17569e6268dbSMiklos Szeredi err = req->out.h.error; 17579e6268dbSMiklos Szeredi fuse_put_request(fc, req); 1758e00d2c2dSMiklos Szeredi if (err) { 1759e00d2c2dSMiklos Szeredi if (err == -EINTR) 1760e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 17613be5a52bSMiklos Szeredi goto error; 1762e00d2c2dSMiklos Szeredi } 1763e00d2c2dSMiklos Szeredi 17649e6268dbSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 17659e6268dbSMiklos Szeredi make_bad_inode(inode); 17663be5a52bSMiklos Szeredi err = -EIO; 17673be5a52bSMiklos Szeredi goto error; 17689e6268dbSMiklos Szeredi } 17699e6268dbSMiklos Szeredi 17703be5a52bSMiklos Szeredi spin_lock(&fc->lock); 1771b0aa7606SMaxim Patlasov /* the kernel maintains i_mtime locally */ 17723ad22c62SMaxim Patlasov if (trust_local_cmtime) { 17733ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_MTIME) 1774b0aa7606SMaxim Patlasov inode->i_mtime = attr->ia_mtime; 17753ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_CTIME) 17763ad22c62SMaxim Patlasov inode->i_ctime = attr->ia_ctime; 17771e18bda8SMiklos Szeredi /* FIXME: clear I_DIRTY_SYNC? */ 1778b0aa7606SMaxim Patlasov } 1779b0aa7606SMaxim Patlasov 17803be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 17813be5a52bSMiklos Szeredi attr_timeout(&outarg)); 17823be5a52bSMiklos Szeredi oldsize = inode->i_size; 17838373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 17848373200bSPavel Emelyanov if (!is_wb || is_truncate || !S_ISREG(inode->i_mode)) 17853be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 17863be5a52bSMiklos Szeredi 17873be5a52bSMiklos Szeredi if (is_truncate) { 17883be5a52bSMiklos Szeredi /* NOTE: this may release/reacquire fc->lock */ 17893be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 17903be5a52bSMiklos Szeredi } 17913be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 17923be5a52bSMiklos Szeredi 17933be5a52bSMiklos Szeredi /* 17943be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 17953be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 17963be5a52bSMiklos Szeredi */ 17978373200bSPavel Emelyanov if ((is_truncate || !is_wb) && 17988373200bSPavel Emelyanov S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 17997caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 18003be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 18013be5a52bSMiklos Szeredi } 18023be5a52bSMiklos Szeredi 180306a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 1804e00d2c2dSMiklos Szeredi return 0; 18053be5a52bSMiklos Szeredi 18063be5a52bSMiklos Szeredi error: 18073be5a52bSMiklos Szeredi if (is_truncate) 18083be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 18093be5a52bSMiklos Szeredi 181006a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 18113be5a52bSMiklos Szeredi return err; 18129e6268dbSMiklos Szeredi } 18139e6268dbSMiklos Szeredi 181449d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 181549d4914fSMiklos Szeredi { 1816efb9fa9eSMaxim Patlasov struct inode *inode = entry->d_inode; 1817efb9fa9eSMaxim Patlasov 1818efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1819efb9fa9eSMaxim Patlasov return -EACCES; 1820efb9fa9eSMaxim Patlasov 182149d4914fSMiklos Szeredi if (attr->ia_valid & ATTR_FILE) 1822efb9fa9eSMaxim Patlasov return fuse_do_setattr(inode, attr, attr->ia_file); 182349d4914fSMiklos Szeredi else 1824efb9fa9eSMaxim Patlasov return fuse_do_setattr(inode, attr, NULL); 182549d4914fSMiklos Szeredi } 182649d4914fSMiklos Szeredi 1827e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, 1828e5e5558eSMiklos Szeredi struct kstat *stat) 1829e5e5558eSMiklos Szeredi { 1830e5e5558eSMiklos Szeredi struct inode *inode = entry->d_inode; 1831244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1832244f6385SMiklos Szeredi 1833c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1834244f6385SMiklos Szeredi return -EACCES; 1835244f6385SMiklos Szeredi 1836bcb4be80SMiklos Szeredi return fuse_update_attributes(inode, stat, NULL, NULL); 1837e5e5558eSMiklos Szeredi } 1838e5e5558eSMiklos Szeredi 183992a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name, 184092a8780eSMiklos Szeredi const void *value, size_t size, int flags) 184192a8780eSMiklos Szeredi { 184292a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 184392a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 184492a8780eSMiklos Szeredi struct fuse_req *req; 184592a8780eSMiklos Szeredi struct fuse_setxattr_in inarg; 184692a8780eSMiklos Szeredi int err; 184792a8780eSMiklos Szeredi 184892a8780eSMiklos Szeredi if (fc->no_setxattr) 184992a8780eSMiklos Szeredi return -EOPNOTSUPP; 185092a8780eSMiklos Szeredi 1851b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1852ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1853ce1d5a49SMiklos Szeredi return PTR_ERR(req); 185492a8780eSMiklos Szeredi 185592a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 185692a8780eSMiklos Szeredi inarg.size = size; 185792a8780eSMiklos Szeredi inarg.flags = flags; 185892a8780eSMiklos Szeredi req->in.h.opcode = FUSE_SETXATTR; 185992a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 186092a8780eSMiklos Szeredi req->in.numargs = 3; 186192a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 186292a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 186392a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 186492a8780eSMiklos Szeredi req->in.args[1].value = name; 186592a8780eSMiklos Szeredi req->in.args[2].size = size; 186692a8780eSMiklos Szeredi req->in.args[2].value = value; 1867b93f858aSTejun Heo fuse_request_send(fc, req); 186892a8780eSMiklos Szeredi err = req->out.h.error; 186992a8780eSMiklos Szeredi fuse_put_request(fc, req); 187092a8780eSMiklos Szeredi if (err == -ENOSYS) { 187192a8780eSMiklos Szeredi fc->no_setxattr = 1; 187292a8780eSMiklos Szeredi err = -EOPNOTSUPP; 187392a8780eSMiklos Szeredi } 187431f3267bSMaxim Patlasov if (!err) { 1875d331a415SAnand Avati fuse_invalidate_attr(inode); 187631f3267bSMaxim Patlasov fuse_update_ctime(inode); 187731f3267bSMaxim Patlasov } 187892a8780eSMiklos Szeredi return err; 187992a8780eSMiklos Szeredi } 188092a8780eSMiklos Szeredi 188192a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name, 188292a8780eSMiklos Szeredi void *value, size_t size) 188392a8780eSMiklos Szeredi { 188492a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 188592a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 188692a8780eSMiklos Szeredi struct fuse_req *req; 188792a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 188892a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 188992a8780eSMiklos Szeredi ssize_t ret; 189092a8780eSMiklos Szeredi 189192a8780eSMiklos Szeredi if (fc->no_getxattr) 189292a8780eSMiklos Szeredi return -EOPNOTSUPP; 189392a8780eSMiklos Szeredi 1894b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1895ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1896ce1d5a49SMiklos Szeredi return PTR_ERR(req); 189792a8780eSMiklos Szeredi 189892a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 189992a8780eSMiklos Szeredi inarg.size = size; 190092a8780eSMiklos Szeredi req->in.h.opcode = FUSE_GETXATTR; 190192a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 190292a8780eSMiklos Szeredi req->in.numargs = 2; 190392a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 190492a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 190592a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 190692a8780eSMiklos Szeredi req->in.args[1].value = name; 190792a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 190892a8780eSMiklos Szeredi req->out.numargs = 1; 190992a8780eSMiklos Szeredi if (size) { 191092a8780eSMiklos Szeredi req->out.argvar = 1; 191192a8780eSMiklos Szeredi req->out.args[0].size = size; 191292a8780eSMiklos Szeredi req->out.args[0].value = value; 191392a8780eSMiklos Szeredi } else { 191492a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 191592a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 191692a8780eSMiklos Szeredi } 1917b93f858aSTejun Heo fuse_request_send(fc, req); 191892a8780eSMiklos Szeredi ret = req->out.h.error; 191992a8780eSMiklos Szeredi if (!ret) 192092a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 192192a8780eSMiklos Szeredi else { 192292a8780eSMiklos Szeredi if (ret == -ENOSYS) { 192392a8780eSMiklos Szeredi fc->no_getxattr = 1; 192492a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 192592a8780eSMiklos Szeredi } 192692a8780eSMiklos Szeredi } 192792a8780eSMiklos Szeredi fuse_put_request(fc, req); 192892a8780eSMiklos Szeredi return ret; 192992a8780eSMiklos Szeredi } 193092a8780eSMiklos Szeredi 193192a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) 193292a8780eSMiklos Szeredi { 193392a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 193492a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 193592a8780eSMiklos Szeredi struct fuse_req *req; 193692a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 193792a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 193892a8780eSMiklos Szeredi ssize_t ret; 193992a8780eSMiklos Szeredi 1940c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1941e57ac683SMiklos Szeredi return -EACCES; 1942e57ac683SMiklos Szeredi 194392a8780eSMiklos Szeredi if (fc->no_listxattr) 194492a8780eSMiklos Szeredi return -EOPNOTSUPP; 194592a8780eSMiklos Szeredi 1946b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1947ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1948ce1d5a49SMiklos Szeredi return PTR_ERR(req); 194992a8780eSMiklos Szeredi 195092a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 195192a8780eSMiklos Szeredi inarg.size = size; 195292a8780eSMiklos Szeredi req->in.h.opcode = FUSE_LISTXATTR; 195392a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 195492a8780eSMiklos Szeredi req->in.numargs = 1; 195592a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 195692a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 195792a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 195892a8780eSMiklos Szeredi req->out.numargs = 1; 195992a8780eSMiklos Szeredi if (size) { 196092a8780eSMiklos Szeredi req->out.argvar = 1; 196192a8780eSMiklos Szeredi req->out.args[0].size = size; 196292a8780eSMiklos Szeredi req->out.args[0].value = list; 196392a8780eSMiklos Szeredi } else { 196492a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 196592a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 196692a8780eSMiklos Szeredi } 1967b93f858aSTejun Heo fuse_request_send(fc, req); 196892a8780eSMiklos Szeredi ret = req->out.h.error; 196992a8780eSMiklos Szeredi if (!ret) 197092a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 197192a8780eSMiklos Szeredi else { 197292a8780eSMiklos Szeredi if (ret == -ENOSYS) { 197392a8780eSMiklos Szeredi fc->no_listxattr = 1; 197492a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 197592a8780eSMiklos Szeredi } 197692a8780eSMiklos Szeredi } 197792a8780eSMiklos Szeredi fuse_put_request(fc, req); 197892a8780eSMiklos Szeredi return ret; 197992a8780eSMiklos Szeredi } 198092a8780eSMiklos Szeredi 198192a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name) 198292a8780eSMiklos Szeredi { 198392a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 198492a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 198592a8780eSMiklos Szeredi struct fuse_req *req; 198692a8780eSMiklos Szeredi int err; 198792a8780eSMiklos Szeredi 198892a8780eSMiklos Szeredi if (fc->no_removexattr) 198992a8780eSMiklos Szeredi return -EOPNOTSUPP; 199092a8780eSMiklos Szeredi 1991b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1992ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1993ce1d5a49SMiklos Szeredi return PTR_ERR(req); 199492a8780eSMiklos Szeredi 199592a8780eSMiklos Szeredi req->in.h.opcode = FUSE_REMOVEXATTR; 199692a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 199792a8780eSMiklos Szeredi req->in.numargs = 1; 199892a8780eSMiklos Szeredi req->in.args[0].size = strlen(name) + 1; 199992a8780eSMiklos Szeredi req->in.args[0].value = name; 2000b93f858aSTejun Heo fuse_request_send(fc, req); 200192a8780eSMiklos Szeredi err = req->out.h.error; 200292a8780eSMiklos Szeredi fuse_put_request(fc, req); 200392a8780eSMiklos Szeredi if (err == -ENOSYS) { 200492a8780eSMiklos Szeredi fc->no_removexattr = 1; 200592a8780eSMiklos Szeredi err = -EOPNOTSUPP; 200692a8780eSMiklos Szeredi } 200731f3267bSMaxim Patlasov if (!err) { 2008d331a415SAnand Avati fuse_invalidate_attr(inode); 200931f3267bSMaxim Patlasov fuse_update_ctime(inode); 201031f3267bSMaxim Patlasov } 201192a8780eSMiklos Szeredi return err; 201292a8780eSMiklos Szeredi } 201392a8780eSMiklos Szeredi 2014754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 2015e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 20169e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 20179e6268dbSMiklos Szeredi .symlink = fuse_symlink, 20189e6268dbSMiklos Szeredi .unlink = fuse_unlink, 20199e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 20209e6268dbSMiklos Szeredi .rename = fuse_rename, 2021*1560c974SMiklos Szeredi .rename2 = fuse_rename2, 20229e6268dbSMiklos Szeredi .link = fuse_link, 20239e6268dbSMiklos Szeredi .setattr = fuse_setattr, 20249e6268dbSMiklos Szeredi .create = fuse_create, 2025c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 20269e6268dbSMiklos Szeredi .mknod = fuse_mknod, 2027e5e5558eSMiklos Szeredi .permission = fuse_permission, 2028e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 202992a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 203092a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 203192a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 203292a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 2033e5e5558eSMiklos Szeredi }; 2034e5e5558eSMiklos Szeredi 20354b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 2036b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 2037e5e5558eSMiklos Szeredi .read = generic_read_dir, 20388d3af7f3SAl Viro .iterate = fuse_readdir, 2039e5e5558eSMiklos Szeredi .open = fuse_dir_open, 2040e5e5558eSMiklos Szeredi .release = fuse_dir_release, 204182547981SMiklos Szeredi .fsync = fuse_dir_fsync, 2042b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 2043b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 2044e5e5558eSMiklos Szeredi }; 2045e5e5558eSMiklos Szeredi 2046754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 20479e6268dbSMiklos Szeredi .setattr = fuse_setattr, 2048e5e5558eSMiklos Szeredi .permission = fuse_permission, 2049e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 205092a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 205192a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 205292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 205392a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 2054e5e5558eSMiklos Szeredi }; 2055e5e5558eSMiklos Szeredi 2056754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 20579e6268dbSMiklos Szeredi .setattr = fuse_setattr, 2058e5e5558eSMiklos Szeredi .follow_link = fuse_follow_link, 2059e5e5558eSMiklos Szeredi .put_link = fuse_put_link, 2060e5e5558eSMiklos Szeredi .readlink = generic_readlink, 2061e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 206292a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 206392a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 206492a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 206592a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 2066e5e5558eSMiklos Szeredi }; 2067e5e5558eSMiklos Szeredi 2068e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 2069e5e5558eSMiklos Szeredi { 2070e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 2071e5e5558eSMiklos Szeredi } 2072e5e5558eSMiklos Szeredi 2073e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 2074e5e5558eSMiklos Szeredi { 2075e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 2076e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 2077e5e5558eSMiklos Szeredi } 2078e5e5558eSMiklos Szeredi 2079e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 2080e5e5558eSMiklos Szeredi { 2081e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 2082e5e5558eSMiklos Szeredi } 2083