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 1156f9f1180SMiklos Szeredi /* 1166f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 1176f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 1186f9f1180SMiklos Szeredi * 1196f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 1206f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 1216f9f1180SMiklos Szeredi * lookup) 1226f9f1180SMiklos Szeredi */ 123dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry) 1248cbdf1e6SMiklos Szeredi { 1250a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 1268cbdf1e6SMiklos Szeredi } 1278cbdf1e6SMiklos Szeredi 1286f9f1180SMiklos Szeredi /* 1296f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 1306f9f1180SMiklos Szeredi * dentry from the hash 1316f9f1180SMiklos Szeredi */ 1328cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1338cbdf1e6SMiklos Szeredi { 1348cbdf1e6SMiklos Szeredi d_invalidate(entry); 1358cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1360aa7c699SMiklos Szeredi } 1370aa7c699SMiklos Szeredi 138c180eebeSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req, 139c180eebeSMiklos Szeredi u64 nodeid, struct qstr *name, 140e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 141e5e5558eSMiklos Szeredi { 1420e9663eeSMiklos Szeredi memset(outarg, 0, sizeof(struct fuse_entry_out)); 143e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_LOOKUP; 144c180eebeSMiklos Szeredi req->in.h.nodeid = nodeid; 145e5e5558eSMiklos Szeredi req->in.numargs = 1; 146c180eebeSMiklos Szeredi req->in.args[0].size = name->len + 1; 147c180eebeSMiklos Szeredi req->in.args[0].value = name->name; 148e5e5558eSMiklos Szeredi req->out.numargs = 1; 1490e9663eeSMiklos Szeredi if (fc->minor < 9) 1500e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 1510e9663eeSMiklos Szeredi else 152e5e5558eSMiklos Szeredi req->out.args[0].size = sizeof(struct fuse_entry_out); 153e5e5558eSMiklos Szeredi req->out.args[0].value = outarg; 154e5e5558eSMiklos Szeredi } 155e5e5558eSMiklos Szeredi 1565c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc) 1577dca9fd3SMiklos Szeredi { 1587dca9fd3SMiklos Szeredi u64 curr_version; 1597dca9fd3SMiklos Szeredi 1607dca9fd3SMiklos Szeredi /* 1617dca9fd3SMiklos Szeredi * The spin lock isn't actually needed on 64bit archs, but we 1627dca9fd3SMiklos Szeredi * don't yet care too much about such optimizations. 1637dca9fd3SMiklos Szeredi */ 1647dca9fd3SMiklos Szeredi spin_lock(&fc->lock); 1657dca9fd3SMiklos Szeredi curr_version = fc->attr_version; 1667dca9fd3SMiklos Szeredi spin_unlock(&fc->lock); 1677dca9fd3SMiklos Szeredi 1687dca9fd3SMiklos Szeredi return curr_version; 1697dca9fd3SMiklos Szeredi } 1707dca9fd3SMiklos Szeredi 1716f9f1180SMiklos Szeredi /* 1726f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1736f9f1180SMiklos Szeredi * 1746f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 1756f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 1766f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 1776f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 1786f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 1796f9f1180SMiklos Szeredi */ 1800b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) 181e5e5558eSMiklos Szeredi { 18234286d66SNick Piggin struct inode *inode; 18328420dadSMiklos Szeredi struct dentry *parent; 18428420dadSMiklos Szeredi struct fuse_conn *fc; 185e2a6b952SMiklos Szeredi int ret; 1868cbdf1e6SMiklos Szeredi 187e7c0a167SMiklos Szeredi inode = ACCESS_ONCE(entry->d_inode); 1888cbdf1e6SMiklos Szeredi if (inode && is_bad_inode(inode)) 189e2a6b952SMiklos Szeredi goto invalid; 1900a0898cfSMiklos Szeredi else if (fuse_dentry_time(entry) < get_jiffies_64()) { 191e5e5558eSMiklos Szeredi int err; 192e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 1938cbdf1e6SMiklos Szeredi struct fuse_req *req; 19407e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 1951fb69e78SMiklos Szeredi u64 attr_version; 1968cbdf1e6SMiklos Szeredi 19750322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 1988cbdf1e6SMiklos Szeredi if (!inode) 199e2a6b952SMiklos Szeredi goto invalid; 2008cbdf1e6SMiklos Szeredi 201e2a6b952SMiklos Szeredi ret = -ECHILD; 2020b728e19SAl Viro if (flags & LOOKUP_RCU) 203e2a6b952SMiklos Szeredi goto out; 204e7c0a167SMiklos Szeredi 2058cbdf1e6SMiklos Szeredi fc = get_fuse_conn(inode); 206b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 207e2a6b952SMiklos Szeredi ret = PTR_ERR(req); 208ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 209e2a6b952SMiklos Szeredi goto out; 210e5e5558eSMiklos Szeredi 21107e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 21207e77dcaSMiklos Szeredi if (!forget) { 2132d51013eSMiklos Szeredi fuse_put_request(fc, req); 214e2a6b952SMiklos Szeredi ret = -ENOMEM; 215e2a6b952SMiklos Szeredi goto out; 2162d51013eSMiklos Szeredi } 2172d51013eSMiklos Szeredi 2187dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 2191fb69e78SMiklos Szeredi 220e956edd0SMiklos Szeredi parent = dget_parent(entry); 221c180eebeSMiklos Szeredi fuse_lookup_init(fc, req, get_node_id(parent->d_inode), 222c180eebeSMiklos Szeredi &entry->d_name, &outarg); 223b93f858aSTejun Heo fuse_request_send(fc, req); 224e956edd0SMiklos Szeredi dput(parent); 225e5e5558eSMiklos Szeredi err = req->out.h.error; 2262d51013eSMiklos Szeredi fuse_put_request(fc, req); 22750322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 22850322fe7SMiklos Szeredi if (!err && !outarg.nodeid) 22950322fe7SMiklos Szeredi err = -ENOENT; 2309e6268dbSMiklos Szeredi if (!err) { 2318cbdf1e6SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 2329e6268dbSMiklos Szeredi if (outarg.nodeid != get_node_id(inode)) { 23307e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 234e2a6b952SMiklos Szeredi goto invalid; 2359e6268dbSMiklos Szeredi } 2368da5ff23SMiklos Szeredi spin_lock(&fc->lock); 2379e6268dbSMiklos Szeredi fi->nlookup++; 2388da5ff23SMiklos Szeredi spin_unlock(&fc->lock); 2399e6268dbSMiklos Szeredi } 24007e77dcaSMiklos Szeredi kfree(forget); 2419e6268dbSMiklos Szeredi if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 242e2a6b952SMiklos Szeredi goto invalid; 243e5e5558eSMiklos Szeredi 2441fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2451fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2461fb69e78SMiklos Szeredi attr_version); 2471fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 24828420dadSMiklos Szeredi } else if (inode) { 24928420dadSMiklos Szeredi fc = get_fuse_conn(inode); 25028420dadSMiklos Szeredi if (fc->readdirplus_auto) { 25128420dadSMiklos Szeredi parent = dget_parent(entry); 25228420dadSMiklos Szeredi fuse_advise_use_readdirplus(parent->d_inode); 25328420dadSMiklos Szeredi dput(parent); 254e5e5558eSMiklos Szeredi } 25528420dadSMiklos Szeredi } 256e2a6b952SMiklos Szeredi ret = 1; 257e2a6b952SMiklos Szeredi out: 258e2a6b952SMiklos Szeredi return ret; 259e2a6b952SMiklos Szeredi 260e2a6b952SMiklos Szeredi invalid: 261e2a6b952SMiklos Szeredi ret = 0; 262*3c70b8eeSMiklos Szeredi 263*3c70b8eeSMiklos Szeredi if (!(flags & LOOKUP_RCU) && check_submounts_and_drop(entry) != 0) 26446ea1562SAnand Avati ret = 1; 265e2a6b952SMiklos Szeredi goto out; 266e5e5558eSMiklos Szeredi } 267e5e5558eSMiklos Szeredi 2688bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid) 2692827d0b2SMiklos Szeredi { 2702827d0b2SMiklos Szeredi return !nodeid || nodeid == FUSE_ROOT_ID; 2712827d0b2SMiklos Szeredi } 2722827d0b2SMiklos Szeredi 2734269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 274e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 275e5e5558eSMiklos Szeredi }; 276e5e5558eSMiklos Szeredi 277a5bfffacSTimo Savola int fuse_valid_type(int m) 27839ee059aSMiklos Szeredi { 27939ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 28039ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 28139ee059aSMiklos Szeredi } 28239ee059aSMiklos Szeredi 283c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, 284c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 285c180eebeSMiklos Szeredi { 286c180eebeSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 287c180eebeSMiklos Szeredi struct fuse_req *req; 28807e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 289c180eebeSMiklos Szeredi u64 attr_version; 290c180eebeSMiklos Szeredi int err; 291c180eebeSMiklos Szeredi 292c180eebeSMiklos Szeredi *inode = NULL; 293c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 294c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 295c180eebeSMiklos Szeredi goto out; 296c180eebeSMiklos Szeredi 297b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 298c180eebeSMiklos Szeredi err = PTR_ERR(req); 299c180eebeSMiklos Szeredi if (IS_ERR(req)) 300c180eebeSMiklos Szeredi goto out; 301c180eebeSMiklos Szeredi 30207e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 30307e77dcaSMiklos Szeredi err = -ENOMEM; 30407e77dcaSMiklos Szeredi if (!forget) { 305c180eebeSMiklos Szeredi fuse_put_request(fc, req); 306c180eebeSMiklos Szeredi goto out; 307c180eebeSMiklos Szeredi } 308c180eebeSMiklos Szeredi 309c180eebeSMiklos Szeredi attr_version = fuse_get_attr_version(fc); 310c180eebeSMiklos Szeredi 311c180eebeSMiklos Szeredi fuse_lookup_init(fc, req, nodeid, name, outarg); 312b93f858aSTejun Heo fuse_request_send(fc, req); 313c180eebeSMiklos Szeredi err = req->out.h.error; 314c180eebeSMiklos Szeredi fuse_put_request(fc, req); 315c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 316c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 317c180eebeSMiklos Szeredi goto out_put_forget; 318c180eebeSMiklos Szeredi 319c180eebeSMiklos Szeredi err = -EIO; 320c180eebeSMiklos Szeredi if (!outarg->nodeid) 321c180eebeSMiklos Szeredi goto out_put_forget; 322c180eebeSMiklos Szeredi if (!fuse_valid_type(outarg->attr.mode)) 323c180eebeSMiklos Szeredi goto out_put_forget; 324c180eebeSMiklos Szeredi 325c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 326c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 327c180eebeSMiklos Szeredi attr_version); 328c180eebeSMiklos Szeredi err = -ENOMEM; 329c180eebeSMiklos Szeredi if (!*inode) { 33007e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg->nodeid, 1); 331c180eebeSMiklos Szeredi goto out; 332c180eebeSMiklos Szeredi } 333c180eebeSMiklos Szeredi err = 0; 334c180eebeSMiklos Szeredi 335c180eebeSMiklos Szeredi out_put_forget: 33607e77dcaSMiklos Szeredi kfree(forget); 337c180eebeSMiklos Szeredi out: 338c180eebeSMiklos Szeredi return err; 339c180eebeSMiklos Szeredi } 340c180eebeSMiklos Szeredi 3415835f339SMiklos Szeredi static struct dentry *fuse_materialise_dentry(struct dentry *dentry, 3425835f339SMiklos Szeredi struct inode *inode) 3435835f339SMiklos Szeredi { 3445835f339SMiklos Szeredi struct dentry *newent; 3455835f339SMiklos Szeredi 3465835f339SMiklos Szeredi if (inode && S_ISDIR(inode->i_mode)) { 3475835f339SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 3485835f339SMiklos Szeredi 3495835f339SMiklos Szeredi mutex_lock(&fc->inst_mutex); 3505835f339SMiklos Szeredi newent = d_materialise_unique(dentry, inode); 3515835f339SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 3525835f339SMiklos Szeredi } else { 3535835f339SMiklos Szeredi newent = d_materialise_unique(dentry, inode); 3545835f339SMiklos Szeredi } 3555835f339SMiklos Szeredi 3565835f339SMiklos Szeredi return newent; 3575835f339SMiklos Szeredi } 3585835f339SMiklos Szeredi 3590aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 36000cd8dd3SAl Viro unsigned int flags) 361e5e5558eSMiklos Szeredi { 362e5e5558eSMiklos Szeredi int err; 363e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 364c180eebeSMiklos Szeredi struct inode *inode; 3650de6256dSMiklos Szeredi struct dentry *newent; 366c180eebeSMiklos Szeredi bool outarg_valid = true; 367e5e5558eSMiklos Szeredi 368c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 369c180eebeSMiklos Szeredi &outarg, &inode); 370c180eebeSMiklos Szeredi if (err == -ENOENT) { 371c180eebeSMiklos Szeredi outarg_valid = false; 372c180eebeSMiklos Szeredi err = 0; 3732d51013eSMiklos Szeredi } 374c180eebeSMiklos Szeredi if (err) 375c180eebeSMiklos Szeredi goto out_err; 3762d51013eSMiklos Szeredi 377ee4e5271SMiklos Szeredi err = -EIO; 378c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 379c180eebeSMiklos Szeredi goto out_iput; 380e5e5558eSMiklos Szeredi 3815835f339SMiklos Szeredi newent = fuse_materialise_dentry(entry, inode); 382c180eebeSMiklos Szeredi err = PTR_ERR(newent); 383c180eebeSMiklos Szeredi if (IS_ERR(newent)) 3845835f339SMiklos Szeredi goto out_err; 385d2a85164SMiklos Szeredi 3860de6256dSMiklos Szeredi entry = newent ? newent : entry; 387c180eebeSMiklos Szeredi if (outarg_valid) 3881fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 3898cbdf1e6SMiklos Szeredi else 3908cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 391c180eebeSMiklos Szeredi 3924582a4abSFeng Shuo fuse_advise_use_readdirplus(dir); 3930de6256dSMiklos Szeredi return newent; 394c180eebeSMiklos Szeredi 395c180eebeSMiklos Szeredi out_iput: 396c180eebeSMiklos Szeredi iput(inode); 397c180eebeSMiklos Szeredi out_err: 398c180eebeSMiklos Szeredi return ERR_PTR(err); 399e5e5558eSMiklos Szeredi } 400e5e5558eSMiklos Szeredi 4016f9f1180SMiklos Szeredi /* 4026f9f1180SMiklos Szeredi * Atomic create+open operation 4036f9f1180SMiklos Szeredi * 4046f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 4056f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 4066f9f1180SMiklos Szeredi */ 407d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 40830d90494SAl Viro struct file *file, unsigned flags, 40947237687SAl Viro umode_t mode, int *opened) 410fd72faacSMiklos Szeredi { 411fd72faacSMiklos Szeredi int err; 412fd72faacSMiklos Szeredi struct inode *inode; 413fd72faacSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 414fd72faacSMiklos Szeredi struct fuse_req *req; 41507e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 416e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 417fd72faacSMiklos Szeredi struct fuse_open_out outopen; 418fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 419fd72faacSMiklos Szeredi struct fuse_file *ff; 420fd72faacSMiklos Szeredi 421af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 422af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 423af109bcaSMiklos Szeredi 42407e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 425c8ccbe03SMiklos Szeredi err = -ENOMEM; 42607e77dcaSMiklos Szeredi if (!forget) 427c8ccbe03SMiklos Szeredi goto out_err; 42851eb01e7SMiklos Szeredi 429b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 43051eb01e7SMiklos Szeredi err = PTR_ERR(req); 431ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 43251eb01e7SMiklos Szeredi goto out_put_forget_req; 433fd72faacSMiklos Szeredi 434ce1d5a49SMiklos Szeredi err = -ENOMEM; 435acf99433STejun Heo ff = fuse_file_alloc(fc); 436fd72faacSMiklos Szeredi if (!ff) 437fd72faacSMiklos Szeredi goto out_put_request; 438fd72faacSMiklos Szeredi 439e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 440e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 441e0a43ddcSMiklos Szeredi 442fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 443fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4440e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 445fd72faacSMiklos Szeredi inarg.flags = flags; 446fd72faacSMiklos Szeredi inarg.mode = mode; 447e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 448fd72faacSMiklos Szeredi req->in.h.opcode = FUSE_CREATE; 449fd72faacSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 450fd72faacSMiklos Szeredi req->in.numargs = 2; 451e0a43ddcSMiklos Szeredi req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) : 452e0a43ddcSMiklos Szeredi sizeof(inarg); 453fd72faacSMiklos Szeredi req->in.args[0].value = &inarg; 454fd72faacSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 455fd72faacSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 456fd72faacSMiklos Szeredi req->out.numargs = 2; 4570e9663eeSMiklos Szeredi if (fc->minor < 9) 4580e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 4590e9663eeSMiklos Szeredi else 460fd72faacSMiklos Szeredi req->out.args[0].size = sizeof(outentry); 461fd72faacSMiklos Szeredi req->out.args[0].value = &outentry; 462fd72faacSMiklos Szeredi req->out.args[1].size = sizeof(outopen); 463fd72faacSMiklos Szeredi req->out.args[1].value = &outopen; 464b93f858aSTejun Heo fuse_request_send(fc, req); 465fd72faacSMiklos Szeredi err = req->out.h.error; 466c8ccbe03SMiklos Szeredi if (err) 467fd72faacSMiklos Szeredi goto out_free_ff; 468fd72faacSMiklos Szeredi 469fd72faacSMiklos Szeredi err = -EIO; 4702827d0b2SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 471fd72faacSMiklos Szeredi goto out_free_ff; 472fd72faacSMiklos Szeredi 47351eb01e7SMiklos Szeredi fuse_put_request(fc, req); 474c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 475c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 476c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 477fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 4781fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 479fd72faacSMiklos Szeredi if (!inode) { 480fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 4818b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 48207e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outentry.nodeid, 1); 483c8ccbe03SMiklos Szeredi err = -ENOMEM; 484c8ccbe03SMiklos Szeredi goto out_err; 485fd72faacSMiklos Szeredi } 48607e77dcaSMiklos Szeredi kfree(forget); 487fd72faacSMiklos Szeredi d_instantiate(entry, inode); 4881fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 4890952b2a4SMiklos Szeredi fuse_invalidate_attr(dir); 49030d90494SAl Viro err = finish_open(file, entry, generic_file_open, opened); 49130d90494SAl Viro if (err) { 4928b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 493c8ccbe03SMiklos Szeredi } else { 494c7b7143cSMiklos Szeredi file->private_data = fuse_file_get(ff); 495c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 496c8ccbe03SMiklos Szeredi } 497d9585277SAl Viro return err; 498fd72faacSMiklos Szeredi 499fd72faacSMiklos Szeredi out_free_ff: 500fd72faacSMiklos Szeredi fuse_file_free(ff); 501fd72faacSMiklos Szeredi out_put_request: 502fd72faacSMiklos Szeredi fuse_put_request(fc, req); 50351eb01e7SMiklos Szeredi out_put_forget_req: 50407e77dcaSMiklos Szeredi kfree(forget); 505c8ccbe03SMiklos Szeredi out_err: 506d9585277SAl Viro return err; 507c8ccbe03SMiklos Szeredi } 508c8ccbe03SMiklos Szeredi 509c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); 510d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 51130d90494SAl Viro struct file *file, unsigned flags, 51247237687SAl Viro umode_t mode, int *opened) 513c8ccbe03SMiklos Szeredi { 514c8ccbe03SMiklos Szeredi int err; 515c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 516c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 517c8ccbe03SMiklos Szeredi 518c8ccbe03SMiklos Szeredi if (d_unhashed(entry)) { 51900cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 520c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 521d9585277SAl Viro return PTR_ERR(res); 522c8ccbe03SMiklos Szeredi 523c8ccbe03SMiklos Szeredi if (res) 524c8ccbe03SMiklos Szeredi entry = res; 525c8ccbe03SMiklos Szeredi } 526c8ccbe03SMiklos Szeredi 527c8ccbe03SMiklos Szeredi if (!(flags & O_CREAT) || entry->d_inode) 528c8ccbe03SMiklos Szeredi goto no_open; 529c8ccbe03SMiklos Szeredi 530c8ccbe03SMiklos Szeredi /* Only creates */ 53147237687SAl Viro *opened |= FILE_CREATED; 532c8ccbe03SMiklos Szeredi 533c8ccbe03SMiklos Szeredi if (fc->no_create) 534c8ccbe03SMiklos Szeredi goto mknod; 535c8ccbe03SMiklos Szeredi 53630d90494SAl Viro err = fuse_create_open(dir, entry, file, flags, mode, opened); 537d9585277SAl Viro if (err == -ENOSYS) { 538c8ccbe03SMiklos Szeredi fc->no_create = 1; 539c8ccbe03SMiklos Szeredi goto mknod; 540c8ccbe03SMiklos Szeredi } 541c8ccbe03SMiklos Szeredi out_dput: 542c8ccbe03SMiklos Szeredi dput(res); 543d9585277SAl Viro return err; 544c8ccbe03SMiklos Szeredi 545c8ccbe03SMiklos Szeredi mknod: 546c8ccbe03SMiklos Szeredi err = fuse_mknod(dir, entry, mode, 0); 547d9585277SAl Viro if (err) 548c8ccbe03SMiklos Szeredi goto out_dput; 549c8ccbe03SMiklos Szeredi no_open: 550e45198a6SAl Viro return finish_no_open(file, res); 551fd72faacSMiklos Szeredi } 552fd72faacSMiklos Szeredi 5536f9f1180SMiklos Szeredi /* 5546f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 5556f9f1180SMiklos Szeredi */ 5569e6268dbSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, 5579e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 558541af6a0SAl Viro umode_t mode) 5599e6268dbSMiklos Szeredi { 5609e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 5619e6268dbSMiklos Szeredi struct inode *inode; 5629e6268dbSMiklos Szeredi int err; 56307e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 5642d51013eSMiklos Szeredi 56507e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 56607e77dcaSMiklos Szeredi if (!forget) { 5672d51013eSMiklos Szeredi fuse_put_request(fc, req); 56807e77dcaSMiklos Szeredi return -ENOMEM; 5692d51013eSMiklos Szeredi } 5709e6268dbSMiklos Szeredi 5710e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 5729e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 5739e6268dbSMiklos Szeredi req->out.numargs = 1; 5740e9663eeSMiklos Szeredi if (fc->minor < 9) 5750e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 5760e9663eeSMiklos Szeredi else 5779e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 5789e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 579b93f858aSTejun Heo fuse_request_send(fc, req); 5809e6268dbSMiklos Szeredi err = req->out.h.error; 5819e6268dbSMiklos Szeredi fuse_put_request(fc, req); 5822d51013eSMiklos Szeredi if (err) 5832d51013eSMiklos Szeredi goto out_put_forget_req; 5842d51013eSMiklos Szeredi 58539ee059aSMiklos Szeredi err = -EIO; 58639ee059aSMiklos Szeredi if (invalid_nodeid(outarg.nodeid)) 5872d51013eSMiklos Szeredi goto out_put_forget_req; 58839ee059aSMiklos Szeredi 58939ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 5902d51013eSMiklos Szeredi goto out_put_forget_req; 59139ee059aSMiklos Szeredi 5929e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 5931fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 5949e6268dbSMiklos Szeredi if (!inode) { 59507e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 5969e6268dbSMiklos Szeredi return -ENOMEM; 5979e6268dbSMiklos Szeredi } 59807e77dcaSMiklos Szeredi kfree(forget); 5999e6268dbSMiklos Szeredi 600d2a85164SMiklos Szeredi if (S_ISDIR(inode->i_mode)) { 601d2a85164SMiklos Szeredi struct dentry *alias; 602d2a85164SMiklos Szeredi mutex_lock(&fc->inst_mutex); 603d2a85164SMiklos Szeredi alias = d_find_alias(inode); 604d2a85164SMiklos Szeredi if (alias) { 605d2a85164SMiklos Szeredi /* New directory must have moved since mkdir */ 606d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 607d2a85164SMiklos Szeredi dput(alias); 6089e6268dbSMiklos Szeredi iput(inode); 609d2a85164SMiklos Szeredi return -EBUSY; 6109e6268dbSMiklos Szeredi } 6119e6268dbSMiklos Szeredi d_instantiate(entry, inode); 612d2a85164SMiklos Szeredi mutex_unlock(&fc->inst_mutex); 613d2a85164SMiklos Szeredi } else 614d2a85164SMiklos Szeredi d_instantiate(entry, inode); 615d2a85164SMiklos Szeredi 6161fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 6179e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 6189e6268dbSMiklos Szeredi return 0; 61939ee059aSMiklos Szeredi 6202d51013eSMiklos Szeredi out_put_forget_req: 62107e77dcaSMiklos Szeredi kfree(forget); 62239ee059aSMiklos Szeredi return err; 6239e6268dbSMiklos Szeredi } 6249e6268dbSMiklos Szeredi 6251a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, 6269e6268dbSMiklos Szeredi dev_t rdev) 6279e6268dbSMiklos Szeredi { 6289e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 6299e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 630b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 631ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 632ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6339e6268dbSMiklos Szeredi 634e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 635e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 636e0a43ddcSMiklos Szeredi 6379e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6389e6268dbSMiklos Szeredi inarg.mode = mode; 6399e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 640e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6419e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKNOD; 6429e6268dbSMiklos Szeredi req->in.numargs = 2; 643e0a43ddcSMiklos Szeredi req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE : 644e0a43ddcSMiklos Szeredi sizeof(inarg); 6459e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 6469e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 6479e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 6489e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, mode); 6499e6268dbSMiklos Szeredi } 6509e6268dbSMiklos Szeredi 6514acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, 652ebfc3b49SAl Viro bool excl) 6539e6268dbSMiklos Szeredi { 6549e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 6559e6268dbSMiklos Szeredi } 6569e6268dbSMiklos Szeredi 65718bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) 6589e6268dbSMiklos Szeredi { 6599e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 6609e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 661b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 662ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 663ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6649e6268dbSMiklos Szeredi 665e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 666e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 667e0a43ddcSMiklos Szeredi 6689e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6699e6268dbSMiklos Szeredi inarg.mode = mode; 670e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6719e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_MKDIR; 6729e6268dbSMiklos Szeredi req->in.numargs = 2; 6739e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 6749e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 6759e6268dbSMiklos Szeredi req->in.args[1].size = entry->d_name.len + 1; 6769e6268dbSMiklos Szeredi req->in.args[1].value = entry->d_name.name; 6779e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFDIR); 6789e6268dbSMiklos Szeredi } 6799e6268dbSMiklos Szeredi 6809e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 6819e6268dbSMiklos Szeredi const char *link) 6829e6268dbSMiklos Szeredi { 6839e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6849e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 685b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 686ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 687ce1d5a49SMiklos Szeredi return PTR_ERR(req); 6889e6268dbSMiklos Szeredi 6899e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SYMLINK; 6909e6268dbSMiklos Szeredi req->in.numargs = 2; 6919e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 6929e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 6939e6268dbSMiklos Szeredi req->in.args[1].size = len; 6949e6268dbSMiklos Szeredi req->in.args[1].value = link; 6959e6268dbSMiklos Szeredi return create_new_entry(fc, req, dir, entry, S_IFLNK); 6969e6268dbSMiklos Szeredi } 6979e6268dbSMiklos Szeredi 6989e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 6999e6268dbSMiklos Szeredi { 7009e6268dbSMiklos Szeredi int err; 7019e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 702b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 703ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 704ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7059e6268dbSMiklos Szeredi 7069e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_UNLINK; 7079e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 7089e6268dbSMiklos Szeredi req->in.numargs = 1; 7099e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 7109e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 711b93f858aSTejun Heo fuse_request_send(fc, req); 7129e6268dbSMiklos Szeredi err = req->out.h.error; 7139e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7149e6268dbSMiklos Szeredi if (!err) { 7159e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 716ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 7179e6268dbSMiklos Szeredi 718ac45d613SMiklos Szeredi spin_lock(&fc->lock); 719ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 720dfca7cebSMiklos Szeredi /* 721dfca7cebSMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 722dfca7cebSMiklos Szeredi * happen if userspace filesystem is careless. It would be 723dfca7cebSMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 724dfca7cebSMiklos Szeredi * condition here 725dfca7cebSMiklos Szeredi */ 726dfca7cebSMiklos Szeredi if (inode->i_nlink > 0) 727ac45d613SMiklos Szeredi drop_nlink(inode); 728ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 7299e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 7309e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 7318cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 7329e6268dbSMiklos Szeredi } else if (err == -EINTR) 7339e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7349e6268dbSMiklos Szeredi return err; 7359e6268dbSMiklos Szeredi } 7369e6268dbSMiklos Szeredi 7379e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 7389e6268dbSMiklos Szeredi { 7399e6268dbSMiklos Szeredi int err; 7409e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 741b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 742ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 743ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7449e6268dbSMiklos Szeredi 7459e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RMDIR; 7469e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(dir); 7479e6268dbSMiklos Szeredi req->in.numargs = 1; 7489e6268dbSMiklos Szeredi req->in.args[0].size = entry->d_name.len + 1; 7499e6268dbSMiklos Szeredi req->in.args[0].value = entry->d_name.name; 750b93f858aSTejun Heo fuse_request_send(fc, req); 7519e6268dbSMiklos Szeredi err = req->out.h.error; 7529e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7539e6268dbSMiklos Szeredi if (!err) { 754ce71ec36SDave Hansen clear_nlink(entry->d_inode); 7559e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 7568cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 7579e6268dbSMiklos Szeredi } else if (err == -EINTR) 7589e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 7599e6268dbSMiklos Szeredi return err; 7609e6268dbSMiklos Szeredi } 7619e6268dbSMiklos Szeredi 7629e6268dbSMiklos Szeredi static int fuse_rename(struct inode *olddir, struct dentry *oldent, 7639e6268dbSMiklos Szeredi struct inode *newdir, struct dentry *newent) 7649e6268dbSMiklos Szeredi { 7659e6268dbSMiklos Szeredi int err; 7669e6268dbSMiklos Szeredi struct fuse_rename_in inarg; 7679e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 768b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 769e4eaac06SSage Weil 770ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 771ce1d5a49SMiklos Szeredi return PTR_ERR(req); 7729e6268dbSMiklos Szeredi 7739e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7749e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 7759e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_RENAME; 7769e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(olddir); 7779e6268dbSMiklos Szeredi req->in.numargs = 3; 7789e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 7799e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 7809e6268dbSMiklos Szeredi req->in.args[1].size = oldent->d_name.len + 1; 7819e6268dbSMiklos Szeredi req->in.args[1].value = oldent->d_name.name; 7829e6268dbSMiklos Szeredi req->in.args[2].size = newent->d_name.len + 1; 7839e6268dbSMiklos Szeredi req->in.args[2].value = newent->d_name.name; 784b93f858aSTejun Heo fuse_request_send(fc, req); 7859e6268dbSMiklos Szeredi err = req->out.h.error; 7869e6268dbSMiklos Szeredi fuse_put_request(fc, req); 7879e6268dbSMiklos Szeredi if (!err) { 78808b63307SMiklos Szeredi /* ctime changes */ 78908b63307SMiklos Szeredi fuse_invalidate_attr(oldent->d_inode); 79008b63307SMiklos Szeredi 7919e6268dbSMiklos Szeredi fuse_invalidate_attr(olddir); 7929e6268dbSMiklos Szeredi if (olddir != newdir) 7939e6268dbSMiklos Szeredi fuse_invalidate_attr(newdir); 7948cbdf1e6SMiklos Szeredi 7958cbdf1e6SMiklos Szeredi /* newent will end up negative */ 7965219f346SMiklos Szeredi if (newent->d_inode) { 7975219f346SMiklos Szeredi fuse_invalidate_attr(newent->d_inode); 7988cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 7995219f346SMiklos Szeredi } 8009e6268dbSMiklos Szeredi } else if (err == -EINTR) { 8019e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 8029e6268dbSMiklos Szeredi rename actually took place. If the invalidation 8039e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 8049e6268dbSMiklos Szeredi directory), then there can be inconsistency between 8059e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 8069e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 8079e6268dbSMiklos Szeredi if (newent->d_inode) 8089e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 8099e6268dbSMiklos Szeredi } 8109e6268dbSMiklos Szeredi 8119e6268dbSMiklos Szeredi return err; 8129e6268dbSMiklos Szeredi } 8139e6268dbSMiklos Szeredi 8149e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 8159e6268dbSMiklos Szeredi struct dentry *newent) 8169e6268dbSMiklos Szeredi { 8179e6268dbSMiklos Szeredi int err; 8189e6268dbSMiklos Szeredi struct fuse_link_in inarg; 8199e6268dbSMiklos Szeredi struct inode *inode = entry->d_inode; 8209e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 821b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 822ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 823ce1d5a49SMiklos Szeredi return PTR_ERR(req); 8249e6268dbSMiklos Szeredi 8259e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8269e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 8279e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_LINK; 8289e6268dbSMiklos Szeredi req->in.numargs = 2; 8299e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 8309e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 8319e6268dbSMiklos Szeredi req->in.args[1].size = newent->d_name.len + 1; 8329e6268dbSMiklos Szeredi req->in.args[1].value = newent->d_name.name; 8339e6268dbSMiklos Szeredi err = create_new_entry(fc, req, newdir, newent, inode->i_mode); 8349e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 8359e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 8369e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 8379e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 8389e6268dbSMiklos Szeredi etc.) 8399e6268dbSMiklos Szeredi */ 840ac45d613SMiklos Szeredi if (!err) { 841ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 842ac45d613SMiklos Szeredi 843ac45d613SMiklos Szeredi spin_lock(&fc->lock); 844ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 845ac45d613SMiklos Szeredi inc_nlink(inode); 846ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 8479e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 848ac45d613SMiklos Szeredi } else if (err == -EINTR) { 849ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 850ac45d613SMiklos Szeredi } 8519e6268dbSMiklos Szeredi return err; 8529e6268dbSMiklos Szeredi } 8539e6268dbSMiklos Szeredi 8541fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 8551fb69e78SMiklos Szeredi struct kstat *stat) 8561fb69e78SMiklos Szeredi { 857203627bbSMiklos Szeredi unsigned int blkbits; 858203627bbSMiklos Szeredi 8591fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 8601fb69e78SMiklos Szeredi stat->ino = attr->ino; 8611fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 8621fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 863499dcf20SEric W. Biederman stat->uid = make_kuid(&init_user_ns, attr->uid); 864499dcf20SEric W. Biederman stat->gid = make_kgid(&init_user_ns, attr->gid); 8651fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 8661fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 8671fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 8681fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 8691fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 8701fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 8711fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 8721fb69e78SMiklos Szeredi stat->size = attr->size; 8731fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 874203627bbSMiklos Szeredi 875203627bbSMiklos Szeredi if (attr->blksize != 0) 876203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 877203627bbSMiklos Szeredi else 878203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 879203627bbSMiklos Szeredi 880203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 8811fb69e78SMiklos Szeredi } 8821fb69e78SMiklos Szeredi 883c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 884c79e322fSMiklos Szeredi struct file *file) 885e5e5558eSMiklos Szeredi { 886e5e5558eSMiklos Szeredi int err; 887c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 888c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 889e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 8901fb69e78SMiklos Szeredi struct fuse_req *req; 8911fb69e78SMiklos Szeredi u64 attr_version; 8921fb69e78SMiklos Szeredi 893b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 894ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 895ce1d5a49SMiklos Szeredi return PTR_ERR(req); 896e5e5558eSMiklos Szeredi 8977dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 8981fb69e78SMiklos Szeredi 899c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 9000e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 901c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 902c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 903c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 904c79e322fSMiklos Szeredi 905c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 906c79e322fSMiklos Szeredi inarg.fh = ff->fh; 907c79e322fSMiklos Szeredi } 908e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_GETATTR; 909e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 910c79e322fSMiklos Szeredi req->in.numargs = 1; 911c79e322fSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 912c79e322fSMiklos Szeredi req->in.args[0].value = &inarg; 913e5e5558eSMiklos Szeredi req->out.numargs = 1; 9140e9663eeSMiklos Szeredi if (fc->minor < 9) 9150e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 9160e9663eeSMiklos Szeredi else 917c79e322fSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 918c79e322fSMiklos Szeredi req->out.args[0].value = &outarg; 919b93f858aSTejun Heo fuse_request_send(fc, req); 920e5e5558eSMiklos Szeredi err = req->out.h.error; 921e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 922e5e5558eSMiklos Szeredi if (!err) { 923c79e322fSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 924e5e5558eSMiklos Szeredi make_bad_inode(inode); 925e5e5558eSMiklos Szeredi err = -EIO; 926e5e5558eSMiklos Szeredi } else { 927c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 928c79e322fSMiklos Szeredi attr_timeout(&outarg), 9291fb69e78SMiklos Szeredi attr_version); 9301fb69e78SMiklos Szeredi if (stat) 931c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 932e5e5558eSMiklos Szeredi } 933e5e5558eSMiklos Szeredi } 934e5e5558eSMiklos Szeredi return err; 935e5e5558eSMiklos Szeredi } 936e5e5558eSMiklos Szeredi 937bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat, 938bcb4be80SMiklos Szeredi struct file *file, bool *refreshed) 939bcb4be80SMiklos Szeredi { 940bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 941bcb4be80SMiklos Szeredi int err; 942bcb4be80SMiklos Szeredi bool r; 943bcb4be80SMiklos Szeredi 944bcb4be80SMiklos Szeredi if (fi->i_time < get_jiffies_64()) { 945bcb4be80SMiklos Szeredi r = true; 946bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 947bcb4be80SMiklos Szeredi } else { 948bcb4be80SMiklos Szeredi r = false; 949bcb4be80SMiklos Szeredi err = 0; 950bcb4be80SMiklos Szeredi if (stat) { 951bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 952bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 95345c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 954bcb4be80SMiklos Szeredi } 955bcb4be80SMiklos Szeredi } 956bcb4be80SMiklos Szeredi 957bcb4be80SMiklos Szeredi if (refreshed != NULL) 958bcb4be80SMiklos Szeredi *refreshed = r; 959bcb4be80SMiklos Szeredi 960bcb4be80SMiklos Szeredi return err; 961bcb4be80SMiklos Szeredi } 962bcb4be80SMiklos Szeredi 9633b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 964451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 9653b463ae0SJohn Muir { 9663b463ae0SJohn Muir int err = -ENOTDIR; 9673b463ae0SJohn Muir struct inode *parent; 9683b463ae0SJohn Muir struct dentry *dir; 9693b463ae0SJohn Muir struct dentry *entry; 9703b463ae0SJohn Muir 9713b463ae0SJohn Muir parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); 9723b463ae0SJohn Muir if (!parent) 9733b463ae0SJohn Muir return -ENOENT; 9743b463ae0SJohn Muir 9753b463ae0SJohn Muir mutex_lock(&parent->i_mutex); 9763b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 9773b463ae0SJohn Muir goto unlock; 9783b463ae0SJohn Muir 9793b463ae0SJohn Muir err = -ENOENT; 9803b463ae0SJohn Muir dir = d_find_alias(parent); 9813b463ae0SJohn Muir if (!dir) 9823b463ae0SJohn Muir goto unlock; 9833b463ae0SJohn Muir 9843b463ae0SJohn Muir entry = d_lookup(dir, name); 9853b463ae0SJohn Muir dput(dir); 9863b463ae0SJohn Muir if (!entry) 9873b463ae0SJohn Muir goto unlock; 9883b463ae0SJohn Muir 9893b463ae0SJohn Muir fuse_invalidate_attr(parent); 9903b463ae0SJohn Muir fuse_invalidate_entry(entry); 991451d0f59SJohn Muir 992451d0f59SJohn Muir if (child_nodeid != 0 && entry->d_inode) { 993451d0f59SJohn Muir mutex_lock(&entry->d_inode->i_mutex); 994451d0f59SJohn Muir if (get_node_id(entry->d_inode) != child_nodeid) { 995451d0f59SJohn Muir err = -ENOENT; 996451d0f59SJohn Muir goto badentry; 997451d0f59SJohn Muir } 998451d0f59SJohn Muir if (d_mountpoint(entry)) { 999451d0f59SJohn Muir err = -EBUSY; 1000451d0f59SJohn Muir goto badentry; 1001451d0f59SJohn Muir } 1002451d0f59SJohn Muir if (S_ISDIR(entry->d_inode->i_mode)) { 1003451d0f59SJohn Muir shrink_dcache_parent(entry); 1004451d0f59SJohn Muir if (!simple_empty(entry)) { 1005451d0f59SJohn Muir err = -ENOTEMPTY; 1006451d0f59SJohn Muir goto badentry; 1007451d0f59SJohn Muir } 1008451d0f59SJohn Muir entry->d_inode->i_flags |= S_DEAD; 1009451d0f59SJohn Muir } 1010451d0f59SJohn Muir dont_mount(entry); 1011451d0f59SJohn Muir clear_nlink(entry->d_inode); 10123b463ae0SJohn Muir err = 0; 1013451d0f59SJohn Muir badentry: 1014451d0f59SJohn Muir mutex_unlock(&entry->d_inode->i_mutex); 1015451d0f59SJohn Muir if (!err) 1016451d0f59SJohn Muir d_delete(entry); 1017451d0f59SJohn Muir } else { 1018451d0f59SJohn Muir err = 0; 1019451d0f59SJohn Muir } 1020451d0f59SJohn Muir dput(entry); 10213b463ae0SJohn Muir 10223b463ae0SJohn Muir unlock: 10233b463ae0SJohn Muir mutex_unlock(&parent->i_mutex); 10243b463ae0SJohn Muir iput(parent); 10253b463ae0SJohn Muir return err; 10263b463ae0SJohn Muir } 10273b463ae0SJohn Muir 102887729a55SMiklos Szeredi /* 102987729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1030c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 103187729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 103287729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 103387729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 103487729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 103587729a55SMiklos Szeredi * DoS against the requester. 103687729a55SMiklos Szeredi * 103787729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 103887729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 103987729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 104087729a55SMiklos Szeredi */ 1041c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc) 104287729a55SMiklos Szeredi { 1043c69e8d9cSDavid Howells const struct cred *cred; 1044c69e8d9cSDavid Howells 104587729a55SMiklos Szeredi if (fc->flags & FUSE_ALLOW_OTHER) 104687729a55SMiklos Szeredi return 1; 104787729a55SMiklos Szeredi 1048c2132c1bSAnatol Pomozov cred = current_cred(); 1049499dcf20SEric W. Biederman if (uid_eq(cred->euid, fc->user_id) && 1050499dcf20SEric W. Biederman uid_eq(cred->suid, fc->user_id) && 1051499dcf20SEric W. Biederman uid_eq(cred->uid, fc->user_id) && 1052499dcf20SEric W. Biederman gid_eq(cred->egid, fc->group_id) && 1053499dcf20SEric W. Biederman gid_eq(cred->sgid, fc->group_id) && 1054499dcf20SEric W. Biederman gid_eq(cred->gid, fc->group_id)) 1055c2132c1bSAnatol Pomozov return 1; 105687729a55SMiklos Szeredi 1057c2132c1bSAnatol Pomozov return 0; 105887729a55SMiklos Szeredi } 105987729a55SMiklos Szeredi 106031d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 106131d40d74SMiklos Szeredi { 106231d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 106331d40d74SMiklos Szeredi struct fuse_req *req; 106431d40d74SMiklos Szeredi struct fuse_access_in inarg; 106531d40d74SMiklos Szeredi int err; 106631d40d74SMiklos Szeredi 106731d40d74SMiklos Szeredi if (fc->no_access) 106831d40d74SMiklos Szeredi return 0; 106931d40d74SMiklos Szeredi 1070b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1071ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1072ce1d5a49SMiklos Szeredi return PTR_ERR(req); 107331d40d74SMiklos Szeredi 107431d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1075e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 107631d40d74SMiklos Szeredi req->in.h.opcode = FUSE_ACCESS; 107731d40d74SMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 107831d40d74SMiklos Szeredi req->in.numargs = 1; 107931d40d74SMiklos Szeredi req->in.args[0].size = sizeof(inarg); 108031d40d74SMiklos Szeredi req->in.args[0].value = &inarg; 1081b93f858aSTejun Heo fuse_request_send(fc, req); 108231d40d74SMiklos Szeredi err = req->out.h.error; 108331d40d74SMiklos Szeredi fuse_put_request(fc, req); 108431d40d74SMiklos Szeredi if (err == -ENOSYS) { 108531d40d74SMiklos Szeredi fc->no_access = 1; 108631d40d74SMiklos Szeredi err = 0; 108731d40d74SMiklos Szeredi } 108831d40d74SMiklos Szeredi return err; 108931d40d74SMiklos Szeredi } 109031d40d74SMiklos Szeredi 109110556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 109219690ddbSMiklos Szeredi { 109310556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 109419690ddbSMiklos Szeredi return -ECHILD; 109519690ddbSMiklos Szeredi 109619690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 109719690ddbSMiklos Szeredi } 109819690ddbSMiklos Szeredi 10996f9f1180SMiklos Szeredi /* 11006f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 11016f9f1180SMiklos Szeredi * 11026f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 11036f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 11046f9f1180SMiklos Szeredi * modell. 11056f9f1180SMiklos Szeredi * 11066f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 11076f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 11086f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 11096f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 11106f9f1180SMiklos Szeredi * locally based on file mode. 11116f9f1180SMiklos Szeredi */ 111210556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask) 1113e5e5558eSMiklos Szeredi { 1114e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1115244f6385SMiklos Szeredi bool refreshed = false; 1116244f6385SMiklos Szeredi int err = 0; 1117e5e5558eSMiklos Szeredi 1118c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1119e5e5558eSMiklos Szeredi return -EACCES; 1120244f6385SMiklos Szeredi 1121244f6385SMiklos Szeredi /* 1122e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1123244f6385SMiklos Szeredi */ 1124e8e96157SMiklos Szeredi if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || 1125e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 112619690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 112719690ddbSMiklos Szeredi 112819690ddbSMiklos Szeredi if (fi->i_time < get_jiffies_64()) { 112919690ddbSMiklos Szeredi refreshed = true; 113019690ddbSMiklos Szeredi 113110556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1132244f6385SMiklos Szeredi if (err) 1133244f6385SMiklos Szeredi return err; 11341fb69e78SMiklos Szeredi } 113519690ddbSMiklos Szeredi } 1136244f6385SMiklos Szeredi 1137244f6385SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 11382830ba7fSAl Viro err = generic_permission(inode, mask); 11391e9a4ed9SMiklos Szeredi 11401e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 11411e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 11421e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1143244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 114410556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 11451e9a4ed9SMiklos Szeredi if (!err) 11462830ba7fSAl Viro err = generic_permission(inode, mask); 11471e9a4ed9SMiklos Szeredi } 11481e9a4ed9SMiklos Szeredi 11496f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 11506f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 11516f9f1180SMiklos Szeredi noticed immediately, only after the attribute 11526f9f1180SMiklos Szeredi timeout has expired */ 11539cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 115410556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 115519690ddbSMiklos Szeredi return -ECHILD; 115619690ddbSMiklos Szeredi 1157e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1158e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1159e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1160e8e96157SMiklos Szeredi if (refreshed) 1161e5e5558eSMiklos Szeredi return -EACCES; 116231d40d74SMiklos Szeredi 116310556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1164e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1165e8e96157SMiklos Szeredi return -EACCES; 1166e8e96157SMiklos Szeredi } 1167e5e5558eSMiklos Szeredi } 1168244f6385SMiklos Szeredi return err; 1169e5e5558eSMiklos Szeredi } 1170e5e5558eSMiklos Szeredi 1171e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file, 11728d3af7f3SAl Viro struct dir_context *ctx) 1173e5e5558eSMiklos Szeredi { 1174e5e5558eSMiklos Szeredi while (nbytes >= FUSE_NAME_OFFSET) { 1175e5e5558eSMiklos Szeredi struct fuse_dirent *dirent = (struct fuse_dirent *) buf; 1176e5e5558eSMiklos Szeredi size_t reclen = FUSE_DIRENT_SIZE(dirent); 1177e5e5558eSMiklos Szeredi if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 1178e5e5558eSMiklos Szeredi return -EIO; 1179e5e5558eSMiklos Szeredi if (reclen > nbytes) 1180e5e5558eSMiklos Szeredi break; 1181efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1182efeb9e60SMiklos Szeredi return -EIO; 1183e5e5558eSMiklos Szeredi 11848d3af7f3SAl Viro if (!dir_emit(ctx, dirent->name, dirent->namelen, 11858d3af7f3SAl Viro dirent->ino, dirent->type)) 1186e5e5558eSMiklos Szeredi break; 1187e5e5558eSMiklos Szeredi 1188e5e5558eSMiklos Szeredi buf += reclen; 1189e5e5558eSMiklos Szeredi nbytes -= reclen; 11908d3af7f3SAl Viro ctx->pos = dirent->off; 1191e5e5558eSMiklos Szeredi } 1192e5e5558eSMiklos Szeredi 1193e5e5558eSMiklos Szeredi return 0; 1194e5e5558eSMiklos Szeredi } 1195e5e5558eSMiklos Szeredi 11960b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file, 11970b05b183SAnand V. Avati struct fuse_direntplus *direntplus, 11980b05b183SAnand V. Avati u64 attr_version) 11990b05b183SAnand V. Avati { 12000b05b183SAnand V. Avati int err; 12010b05b183SAnand V. Avati struct fuse_entry_out *o = &direntplus->entry_out; 12020b05b183SAnand V. Avati struct fuse_dirent *dirent = &direntplus->dirent; 12030b05b183SAnand V. Avati struct dentry *parent = file->f_path.dentry; 12040b05b183SAnand V. Avati struct qstr name = QSTR_INIT(dirent->name, dirent->namelen); 12050b05b183SAnand V. Avati struct dentry *dentry; 12060b05b183SAnand V. Avati struct dentry *alias; 12070b05b183SAnand V. Avati struct inode *dir = parent->d_inode; 12080b05b183SAnand V. Avati struct fuse_conn *fc; 12090b05b183SAnand V. Avati struct inode *inode; 12100b05b183SAnand V. Avati 12110b05b183SAnand V. Avati if (!o->nodeid) { 12120b05b183SAnand V. Avati /* 12130b05b183SAnand V. Avati * Unlike in the case of fuse_lookup, zero nodeid does not mean 12140b05b183SAnand V. Avati * ENOENT. Instead, it only means the userspace filesystem did 12150b05b183SAnand V. Avati * not want to return attributes/handle for this entry. 12160b05b183SAnand V. Avati * 12170b05b183SAnand V. Avati * So do nothing. 12180b05b183SAnand V. Avati */ 12190b05b183SAnand V. Avati return 0; 12200b05b183SAnand V. Avati } 12210b05b183SAnand V. Avati 12220b05b183SAnand V. Avati if (name.name[0] == '.') { 12230b05b183SAnand V. Avati /* 12240b05b183SAnand V. Avati * We could potentially refresh the attributes of the directory 12250b05b183SAnand V. Avati * and its parent? 12260b05b183SAnand V. Avati */ 12270b05b183SAnand V. Avati if (name.len == 1) 12280b05b183SAnand V. Avati return 0; 12290b05b183SAnand V. Avati if (name.name[1] == '.' && name.len == 2) 12300b05b183SAnand V. Avati return 0; 12310b05b183SAnand V. Avati } 1232a28ef45cSMiklos Szeredi 1233a28ef45cSMiklos Szeredi if (invalid_nodeid(o->nodeid)) 1234a28ef45cSMiklos Szeredi return -EIO; 1235a28ef45cSMiklos Szeredi if (!fuse_valid_type(o->attr.mode)) 1236a28ef45cSMiklos Szeredi return -EIO; 1237a28ef45cSMiklos Szeredi 12380b05b183SAnand V. Avati fc = get_fuse_conn(dir); 12390b05b183SAnand V. Avati 12400b05b183SAnand V. Avati name.hash = full_name_hash(name.name, name.len); 12410b05b183SAnand V. Avati dentry = d_lookup(parent, &name); 124253ce9a33SNiels de Vos if (dentry) { 12430b05b183SAnand V. Avati inode = dentry->d_inode; 124453ce9a33SNiels de Vos if (!inode) { 124553ce9a33SNiels de Vos d_drop(dentry); 1246a28ef45cSMiklos Szeredi } else if (get_node_id(inode) != o->nodeid || 1247a28ef45cSMiklos Szeredi ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { 124853ce9a33SNiels de Vos err = d_invalidate(dentry); 124953ce9a33SNiels de Vos if (err) 125053ce9a33SNiels de Vos goto out; 1251a28ef45cSMiklos Szeredi } else if (is_bad_inode(inode)) { 1252a28ef45cSMiklos Szeredi err = -EIO; 1253a28ef45cSMiklos Szeredi goto out; 125453ce9a33SNiels de Vos } else { 12550b05b183SAnand V. Avati struct fuse_inode *fi; 12560b05b183SAnand V. Avati fi = get_fuse_inode(inode); 12570b05b183SAnand V. Avati spin_lock(&fc->lock); 12580b05b183SAnand V. Avati fi->nlookup++; 12590b05b183SAnand V. Avati spin_unlock(&fc->lock); 12600b05b183SAnand V. Avati 1261fa2b7213SMiklos Szeredi fuse_change_attributes(inode, &o->attr, 1262fa2b7213SMiklos Szeredi entry_attr_timeout(o), 1263fa2b7213SMiklos Szeredi attr_version); 1264fa2b7213SMiklos Szeredi 12650b05b183SAnand V. Avati /* 12660b05b183SAnand V. Avati * The other branch to 'found' comes via fuse_iget() 12670b05b183SAnand V. Avati * which bumps nlookup inside 12680b05b183SAnand V. Avati */ 12690b05b183SAnand V. Avati goto found; 12700b05b183SAnand V. Avati } 12710b05b183SAnand V. Avati dput(dentry); 12720b05b183SAnand V. Avati } 12730b05b183SAnand V. Avati 12740b05b183SAnand V. Avati dentry = d_alloc(parent, &name); 12750b05b183SAnand V. Avati err = -ENOMEM; 12760b05b183SAnand V. Avati if (!dentry) 12770b05b183SAnand V. Avati goto out; 12780b05b183SAnand V. Avati 12790b05b183SAnand V. Avati inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, 12800b05b183SAnand V. Avati &o->attr, entry_attr_timeout(o), attr_version); 12810b05b183SAnand V. Avati if (!inode) 12820b05b183SAnand V. Avati goto out; 12830b05b183SAnand V. Avati 12845835f339SMiklos Szeredi alias = fuse_materialise_dentry(dentry, inode); 12850b05b183SAnand V. Avati err = PTR_ERR(alias); 12865835f339SMiklos Szeredi if (IS_ERR(alias)) 12870b05b183SAnand V. Avati goto out; 12882914941eSMiklos Szeredi 12890b05b183SAnand V. Avati if (alias) { 12900b05b183SAnand V. Avati dput(dentry); 12910b05b183SAnand V. Avati dentry = alias; 12920b05b183SAnand V. Avati } 12930b05b183SAnand V. Avati 12940b05b183SAnand V. Avati found: 12950b05b183SAnand V. Avati fuse_change_entry_timeout(dentry, o); 12960b05b183SAnand V. Avati 12970b05b183SAnand V. Avati err = 0; 12980b05b183SAnand V. Avati out: 12990b05b183SAnand V. Avati dput(dentry); 13000b05b183SAnand V. Avati return err; 13010b05b183SAnand V. Avati } 13020b05b183SAnand V. Avati 13030b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, 13048d3af7f3SAl Viro struct dir_context *ctx, u64 attr_version) 13050b05b183SAnand V. Avati { 13060b05b183SAnand V. Avati struct fuse_direntplus *direntplus; 13070b05b183SAnand V. Avati struct fuse_dirent *dirent; 13080b05b183SAnand V. Avati size_t reclen; 13090b05b183SAnand V. Avati int over = 0; 13100b05b183SAnand V. Avati int ret; 13110b05b183SAnand V. Avati 13120b05b183SAnand V. Avati while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) { 13130b05b183SAnand V. Avati direntplus = (struct fuse_direntplus *) buf; 13140b05b183SAnand V. Avati dirent = &direntplus->dirent; 13150b05b183SAnand V. Avati reclen = FUSE_DIRENTPLUS_SIZE(direntplus); 13160b05b183SAnand V. Avati 13170b05b183SAnand V. Avati if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 13180b05b183SAnand V. Avati return -EIO; 13190b05b183SAnand V. Avati if (reclen > nbytes) 13200b05b183SAnand V. Avati break; 1321efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1322efeb9e60SMiklos Szeredi return -EIO; 13230b05b183SAnand V. Avati 13240b05b183SAnand V. Avati if (!over) { 13250b05b183SAnand V. Avati /* We fill entries into dstbuf only as much as 13260b05b183SAnand V. Avati it can hold. But we still continue iterating 13270b05b183SAnand V. Avati over remaining entries to link them. If not, 13280b05b183SAnand V. Avati we need to send a FORGET for each of those 13290b05b183SAnand V. Avati which we did not link. 13300b05b183SAnand V. Avati */ 13318d3af7f3SAl Viro over = !dir_emit(ctx, dirent->name, dirent->namelen, 13328d3af7f3SAl Viro dirent->ino, dirent->type); 13338d3af7f3SAl Viro ctx->pos = dirent->off; 13340b05b183SAnand V. Avati } 13350b05b183SAnand V. Avati 13360b05b183SAnand V. Avati buf += reclen; 13370b05b183SAnand V. Avati nbytes -= reclen; 13380b05b183SAnand V. Avati 13390b05b183SAnand V. Avati ret = fuse_direntplus_link(file, direntplus, attr_version); 13400b05b183SAnand V. Avati if (ret) 13410b05b183SAnand V. Avati fuse_force_forget(file, direntplus->entry_out.nodeid); 13420b05b183SAnand V. Avati } 13430b05b183SAnand V. Avati 13440b05b183SAnand V. Avati return 0; 13450b05b183SAnand V. Avati } 13460b05b183SAnand V. Avati 13478d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx) 1348e5e5558eSMiklos Szeredi { 13494582a4abSFeng Shuo int plus, err; 135004730fefSMiklos Szeredi size_t nbytes; 135104730fefSMiklos Szeredi struct page *page; 1352496ad9aaSAl Viro struct inode *inode = file_inode(file); 135304730fefSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1354248d86e8SMiklos Szeredi struct fuse_req *req; 13550b05b183SAnand V. Avati u64 attr_version = 0; 1356248d86e8SMiklos Szeredi 1357248d86e8SMiklos Szeredi if (is_bad_inode(inode)) 1358248d86e8SMiklos Szeredi return -EIO; 1359248d86e8SMiklos Szeredi 1360b111c8c0SMaxim Patlasov req = fuse_get_req(fc, 1); 1361ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1362ce1d5a49SMiklos Szeredi return PTR_ERR(req); 1363e5e5558eSMiklos Szeredi 136404730fefSMiklos Szeredi page = alloc_page(GFP_KERNEL); 136504730fefSMiklos Szeredi if (!page) { 136604730fefSMiklos Szeredi fuse_put_request(fc, req); 1367e5e5558eSMiklos Szeredi return -ENOMEM; 136804730fefSMiklos Szeredi } 13694582a4abSFeng Shuo 13708d3af7f3SAl Viro plus = fuse_use_readdirplus(inode, ctx); 1371f4975c67SMiklos Szeredi req->out.argpages = 1; 137204730fefSMiklos Szeredi req->num_pages = 1; 137304730fefSMiklos Szeredi req->pages[0] = page; 137485f40aecSMaxim Patlasov req->page_descs[0].length = PAGE_SIZE; 13754582a4abSFeng Shuo if (plus) { 13760b05b183SAnand V. Avati attr_version = fuse_get_attr_version(fc); 13778d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 13780b05b183SAnand V. Avati FUSE_READDIRPLUS); 13790b05b183SAnand V. Avati } else { 13808d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 13810b05b183SAnand V. Avati FUSE_READDIR); 13820b05b183SAnand V. Avati } 1383b93f858aSTejun Heo fuse_request_send(fc, req); 1384361b1eb5SMiklos Szeredi nbytes = req->out.args[0].size; 138504730fefSMiklos Szeredi err = req->out.h.error; 138604730fefSMiklos Szeredi fuse_put_request(fc, req); 13870b05b183SAnand V. Avati if (!err) { 13884582a4abSFeng Shuo if (plus) { 13890b05b183SAnand V. Avati err = parse_dirplusfile(page_address(page), nbytes, 13908d3af7f3SAl Viro file, ctx, 13910b05b183SAnand V. Avati attr_version); 13920b05b183SAnand V. Avati } else { 13930b05b183SAnand V. Avati err = parse_dirfile(page_address(page), nbytes, file, 13948d3af7f3SAl Viro ctx); 13950b05b183SAnand V. Avati } 13960b05b183SAnand V. Avati } 1397e5e5558eSMiklos Szeredi 139804730fefSMiklos Szeredi __free_page(page); 1399b36c31baSMiklos Szeredi fuse_invalidate_attr(inode); /* atime changed */ 140004730fefSMiklos Szeredi return err; 1401e5e5558eSMiklos Szeredi } 1402e5e5558eSMiklos Szeredi 1403e5e5558eSMiklos Szeredi static char *read_link(struct dentry *dentry) 1404e5e5558eSMiklos Szeredi { 1405e5e5558eSMiklos Szeredi struct inode *inode = dentry->d_inode; 1406e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1407b111c8c0SMaxim Patlasov struct fuse_req *req = fuse_get_req_nopages(fc); 1408e5e5558eSMiklos Szeredi char *link; 1409e5e5558eSMiklos Szeredi 1410ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1411e231c2eeSDavid Howells return ERR_CAST(req); 1412e5e5558eSMiklos Szeredi 1413e5e5558eSMiklos Szeredi link = (char *) __get_free_page(GFP_KERNEL); 1414e5e5558eSMiklos Szeredi if (!link) { 1415e5e5558eSMiklos Szeredi link = ERR_PTR(-ENOMEM); 1416e5e5558eSMiklos Szeredi goto out; 1417e5e5558eSMiklos Szeredi } 1418e5e5558eSMiklos Szeredi req->in.h.opcode = FUSE_READLINK; 1419e5e5558eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 1420e5e5558eSMiklos Szeredi req->out.argvar = 1; 1421e5e5558eSMiklos Szeredi req->out.numargs = 1; 1422e5e5558eSMiklos Szeredi req->out.args[0].size = PAGE_SIZE - 1; 1423e5e5558eSMiklos Szeredi req->out.args[0].value = link; 1424b93f858aSTejun Heo fuse_request_send(fc, req); 1425e5e5558eSMiklos Szeredi if (req->out.h.error) { 1426e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1427e5e5558eSMiklos Szeredi link = ERR_PTR(req->out.h.error); 1428e5e5558eSMiklos Szeredi } else 1429e5e5558eSMiklos Szeredi link[req->out.args[0].size] = '\0'; 1430e5e5558eSMiklos Szeredi out: 1431e5e5558eSMiklos Szeredi fuse_put_request(fc, req); 1432b36c31baSMiklos Szeredi fuse_invalidate_attr(inode); /* atime changed */ 1433e5e5558eSMiklos Szeredi return link; 1434e5e5558eSMiklos Szeredi } 1435e5e5558eSMiklos Szeredi 1436e5e5558eSMiklos Szeredi static void free_link(char *link) 1437e5e5558eSMiklos Szeredi { 1438e5e5558eSMiklos Szeredi if (!IS_ERR(link)) 1439e5e5558eSMiklos Szeredi free_page((unsigned long) link); 1440e5e5558eSMiklos Szeredi } 1441e5e5558eSMiklos Szeredi 1442e5e5558eSMiklos Szeredi static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd) 1443e5e5558eSMiklos Szeredi { 1444e5e5558eSMiklos Szeredi nd_set_link(nd, read_link(dentry)); 1445e5e5558eSMiklos Szeredi return NULL; 1446e5e5558eSMiklos Szeredi } 1447e5e5558eSMiklos Szeredi 1448e5e5558eSMiklos Szeredi static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c) 1449e5e5558eSMiklos Szeredi { 1450e5e5558eSMiklos Szeredi free_link(nd_get_link(nd)); 1451e5e5558eSMiklos Szeredi } 1452e5e5558eSMiklos Szeredi 1453e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1454e5e5558eSMiklos Szeredi { 145591fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1456e5e5558eSMiklos Szeredi } 1457e5e5558eSMiklos Szeredi 1458e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1459e5e5558eSMiklos Szeredi { 14608b0797a4SMiklos Szeredi fuse_release_common(file, FUSE_RELEASEDIR); 14618b0797a4SMiklos Szeredi 14628b0797a4SMiklos Szeredi return 0; 1463e5e5558eSMiklos Szeredi } 1464e5e5558eSMiklos Szeredi 146502c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 146602c24a82SJosef Bacik int datasync) 146782547981SMiklos Szeredi { 146802c24a82SJosef Bacik return fuse_fsync_common(file, start, end, datasync, 1); 146982547981SMiklos Szeredi } 147082547981SMiklos Szeredi 1471b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1472b18da0c5SMiklos Szeredi unsigned long arg) 1473b18da0c5SMiklos Szeredi { 1474b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1475b18da0c5SMiklos Szeredi 1476b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1477b18da0c5SMiklos Szeredi if (fc->minor < 18) 1478b18da0c5SMiklos Szeredi return -ENOTTY; 1479b18da0c5SMiklos Szeredi 1480b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1481b18da0c5SMiklos Szeredi } 1482b18da0c5SMiklos Szeredi 1483b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1484b18da0c5SMiklos Szeredi unsigned long arg) 1485b18da0c5SMiklos Szeredi { 1486b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1487b18da0c5SMiklos Szeredi 1488b18da0c5SMiklos Szeredi if (fc->minor < 18) 1489b18da0c5SMiklos Szeredi return -ENOTTY; 1490b18da0c5SMiklos Szeredi 1491b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1492b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1493b18da0c5SMiklos Szeredi } 1494b18da0c5SMiklos Szeredi 149517637cbaSMiklos Szeredi static bool update_mtime(unsigned ivalid) 149617637cbaSMiklos Szeredi { 149717637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 149817637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 149917637cbaSMiklos Szeredi return true; 150017637cbaSMiklos Szeredi 150117637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 150217637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 150317637cbaSMiklos Szeredi return false; 150417637cbaSMiklos Szeredi 150517637cbaSMiklos Szeredi /* In all other cases update */ 150617637cbaSMiklos Szeredi return true; 150717637cbaSMiklos Szeredi } 150817637cbaSMiklos Szeredi 1509befc649cSMiklos Szeredi static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) 15109e6268dbSMiklos Szeredi { 15119e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 15129e6268dbSMiklos Szeredi 15139e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1514befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 15159e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 1516499dcf20SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid); 15179e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 1518499dcf20SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid); 15199e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1520befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 152117637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 152217637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1523befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 152417637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 152517637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 152617637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 152717637cbaSMiklos Szeredi } 152817637cbaSMiklos Szeredi if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) { 152917637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1530befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 153117637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 153217637cbaSMiklos Szeredi if (!(ivalid & ATTR_MTIME_SET)) 153317637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 15349e6268dbSMiklos Szeredi } 15359e6268dbSMiklos Szeredi } 15369e6268dbSMiklos Szeredi 15376f9f1180SMiklos Szeredi /* 15383be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 15393be5a52bSMiklos Szeredi * 15403be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 15413be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 15423be5a52bSMiklos Szeredi */ 15433be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 15443be5a52bSMiklos Szeredi { 15453be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 15463be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15473be5a52bSMiklos Szeredi 15483be5a52bSMiklos Szeredi BUG_ON(!mutex_is_locked(&inode->i_mutex)); 15493be5a52bSMiklos Szeredi 15503be5a52bSMiklos Szeredi spin_lock(&fc->lock); 15513be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 15523be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 15533be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 15543be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 15553be5a52bSMiklos Szeredi } 15563be5a52bSMiklos Szeredi 15573be5a52bSMiklos Szeredi /* 15583be5a52bSMiklos Szeredi * Allow writepages on inode 15593be5a52bSMiklos Szeredi * 15603be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 15613be5a52bSMiklos Szeredi * writepages. 15623be5a52bSMiklos Szeredi */ 15633be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 15643be5a52bSMiklos Szeredi { 15653be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15663be5a52bSMiklos Szeredi 15673be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 15683be5a52bSMiklos Szeredi fi->writectr = 0; 15693be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 15703be5a52bSMiklos Szeredi } 15713be5a52bSMiklos Szeredi 15723be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 15733be5a52bSMiklos Szeredi { 15743be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 15753be5a52bSMiklos Szeredi 15763be5a52bSMiklos Szeredi spin_lock(&fc->lock); 15773be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 15783be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 15793be5a52bSMiklos Szeredi } 15803be5a52bSMiklos Szeredi 15813be5a52bSMiklos Szeredi /* 15826f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 15836f9f1180SMiklos Szeredi * 15846f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 15856f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 15869ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 15879ffbb916SMiklos Szeredi * and the actual truncation by hand. 15886f9f1180SMiklos Szeredi */ 1589efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr, 159049d4914fSMiklos Szeredi struct file *file) 15919e6268dbSMiklos Szeredi { 15929e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 159306a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 15949e6268dbSMiklos Szeredi struct fuse_req *req; 15959e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 15969e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 15973be5a52bSMiklos Szeredi bool is_truncate = false; 15983be5a52bSMiklos Szeredi loff_t oldsize; 15999e6268dbSMiklos Szeredi int err; 16009e6268dbSMiklos Szeredi 1601db78b877SChristoph Hellwig if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 1602db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1603db78b877SChristoph Hellwig 16041e9a4ed9SMiklos Szeredi err = inode_change_ok(inode, attr); 16051e9a4ed9SMiklos Szeredi if (err) 16061e9a4ed9SMiklos Szeredi return err; 16071e9a4ed9SMiklos Szeredi 16088d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 16098d56adddSMiklos Szeredi if (fc->atomic_o_trunc) 16106ff958edSMiklos Szeredi return 0; 16118d56adddSMiklos Szeredi file = NULL; 16128d56adddSMiklos Szeredi } 16136ff958edSMiklos Szeredi 16142c27c65eSChristoph Hellwig if (attr->ia_valid & ATTR_SIZE) 16153be5a52bSMiklos Szeredi is_truncate = true; 16169e6268dbSMiklos Szeredi 1617b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1618ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1619ce1d5a49SMiklos Szeredi return PTR_ERR(req); 16209e6268dbSMiklos Szeredi 162106a7c3c2SMaxim Patlasov if (is_truncate) { 16223be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 162306a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 162406a7c3c2SMaxim Patlasov } 16253be5a52bSMiklos Szeredi 16269e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 16270e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 1628befc649cSMiklos Szeredi iattr_to_fattr(attr, &inarg); 162949d4914fSMiklos Szeredi if (file) { 163049d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 163149d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 163249d4914fSMiklos Szeredi inarg.fh = ff->fh; 163349d4914fSMiklos Szeredi } 1634f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1635f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1636f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1637f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 1638f3332114SMiklos Szeredi } 16399e6268dbSMiklos Szeredi req->in.h.opcode = FUSE_SETATTR; 16409e6268dbSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 16419e6268dbSMiklos Szeredi req->in.numargs = 1; 16429e6268dbSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 16439e6268dbSMiklos Szeredi req->in.args[0].value = &inarg; 16449e6268dbSMiklos Szeredi req->out.numargs = 1; 16450e9663eeSMiklos Szeredi if (fc->minor < 9) 16460e9663eeSMiklos Szeredi req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 16470e9663eeSMiklos Szeredi else 16489e6268dbSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 16499e6268dbSMiklos Szeredi req->out.args[0].value = &outarg; 1650b93f858aSTejun Heo fuse_request_send(fc, req); 16519e6268dbSMiklos Szeredi err = req->out.h.error; 16529e6268dbSMiklos Szeredi fuse_put_request(fc, req); 1653e00d2c2dSMiklos Szeredi if (err) { 1654e00d2c2dSMiklos Szeredi if (err == -EINTR) 1655e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 16563be5a52bSMiklos Szeredi goto error; 1657e00d2c2dSMiklos Szeredi } 1658e00d2c2dSMiklos Szeredi 16599e6268dbSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 16609e6268dbSMiklos Szeredi make_bad_inode(inode); 16613be5a52bSMiklos Szeredi err = -EIO; 16623be5a52bSMiklos Szeredi goto error; 16639e6268dbSMiklos Szeredi } 16649e6268dbSMiklos Szeredi 16653be5a52bSMiklos Szeredi spin_lock(&fc->lock); 16663be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 16673be5a52bSMiklos Szeredi attr_timeout(&outarg)); 16683be5a52bSMiklos Szeredi oldsize = inode->i_size; 16693be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 16703be5a52bSMiklos Szeredi 16713be5a52bSMiklos Szeredi if (is_truncate) { 16723be5a52bSMiklos Szeredi /* NOTE: this may release/reacquire fc->lock */ 16733be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 16743be5a52bSMiklos Szeredi } 16753be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 16763be5a52bSMiklos Szeredi 16773be5a52bSMiklos Szeredi /* 16783be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 16793be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 16803be5a52bSMiklos Szeredi */ 16813be5a52bSMiklos Szeredi if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 16827caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 16833be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 16843be5a52bSMiklos Szeredi } 16853be5a52bSMiklos Szeredi 168606a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 1687e00d2c2dSMiklos Szeredi return 0; 16883be5a52bSMiklos Szeredi 16893be5a52bSMiklos Szeredi error: 16903be5a52bSMiklos Szeredi if (is_truncate) 16913be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 16923be5a52bSMiklos Szeredi 169306a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 16943be5a52bSMiklos Szeredi return err; 16959e6268dbSMiklos Szeredi } 16969e6268dbSMiklos Szeredi 169749d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 169849d4914fSMiklos Szeredi { 1699efb9fa9eSMaxim Patlasov struct inode *inode = entry->d_inode; 1700efb9fa9eSMaxim Patlasov 1701efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1702efb9fa9eSMaxim Patlasov return -EACCES; 1703efb9fa9eSMaxim Patlasov 170449d4914fSMiklos Szeredi if (attr->ia_valid & ATTR_FILE) 1705efb9fa9eSMaxim Patlasov return fuse_do_setattr(inode, attr, attr->ia_file); 170649d4914fSMiklos Szeredi else 1707efb9fa9eSMaxim Patlasov return fuse_do_setattr(inode, attr, NULL); 170849d4914fSMiklos Szeredi } 170949d4914fSMiklos Szeredi 1710e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, 1711e5e5558eSMiklos Szeredi struct kstat *stat) 1712e5e5558eSMiklos Szeredi { 1713e5e5558eSMiklos Szeredi struct inode *inode = entry->d_inode; 1714244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1715244f6385SMiklos Szeredi 1716c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1717244f6385SMiklos Szeredi return -EACCES; 1718244f6385SMiklos Szeredi 1719bcb4be80SMiklos Szeredi return fuse_update_attributes(inode, stat, NULL, NULL); 1720e5e5558eSMiklos Szeredi } 1721e5e5558eSMiklos Szeredi 172292a8780eSMiklos Szeredi static int fuse_setxattr(struct dentry *entry, const char *name, 172392a8780eSMiklos Szeredi const void *value, size_t size, int flags) 172492a8780eSMiklos Szeredi { 172592a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 172692a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 172792a8780eSMiklos Szeredi struct fuse_req *req; 172892a8780eSMiklos Szeredi struct fuse_setxattr_in inarg; 172992a8780eSMiklos Szeredi int err; 173092a8780eSMiklos Szeredi 173192a8780eSMiklos Szeredi if (fc->no_setxattr) 173292a8780eSMiklos Szeredi return -EOPNOTSUPP; 173392a8780eSMiklos Szeredi 1734b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1735ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1736ce1d5a49SMiklos Szeredi return PTR_ERR(req); 173792a8780eSMiklos Szeredi 173892a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 173992a8780eSMiklos Szeredi inarg.size = size; 174092a8780eSMiklos Szeredi inarg.flags = flags; 174192a8780eSMiklos Szeredi req->in.h.opcode = FUSE_SETXATTR; 174292a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 174392a8780eSMiklos Szeredi req->in.numargs = 3; 174492a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 174592a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 174692a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 174792a8780eSMiklos Szeredi req->in.args[1].value = name; 174892a8780eSMiklos Szeredi req->in.args[2].size = size; 174992a8780eSMiklos Szeredi req->in.args[2].value = value; 1750b93f858aSTejun Heo fuse_request_send(fc, req); 175192a8780eSMiklos Szeredi err = req->out.h.error; 175292a8780eSMiklos Szeredi fuse_put_request(fc, req); 175392a8780eSMiklos Szeredi if (err == -ENOSYS) { 175492a8780eSMiklos Szeredi fc->no_setxattr = 1; 175592a8780eSMiklos Szeredi err = -EOPNOTSUPP; 175692a8780eSMiklos Szeredi } 1757d331a415SAnand Avati if (!err) 1758d331a415SAnand Avati fuse_invalidate_attr(inode); 175992a8780eSMiklos Szeredi return err; 176092a8780eSMiklos Szeredi } 176192a8780eSMiklos Szeredi 176292a8780eSMiklos Szeredi static ssize_t fuse_getxattr(struct dentry *entry, const char *name, 176392a8780eSMiklos Szeredi void *value, size_t size) 176492a8780eSMiklos Szeredi { 176592a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 176692a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 176792a8780eSMiklos Szeredi struct fuse_req *req; 176892a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 176992a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 177092a8780eSMiklos Szeredi ssize_t ret; 177192a8780eSMiklos Szeredi 177292a8780eSMiklos Szeredi if (fc->no_getxattr) 177392a8780eSMiklos Szeredi return -EOPNOTSUPP; 177492a8780eSMiklos Szeredi 1775b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1776ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1777ce1d5a49SMiklos Szeredi return PTR_ERR(req); 177892a8780eSMiklos Szeredi 177992a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 178092a8780eSMiklos Szeredi inarg.size = size; 178192a8780eSMiklos Szeredi req->in.h.opcode = FUSE_GETXATTR; 178292a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 178392a8780eSMiklos Szeredi req->in.numargs = 2; 178492a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 178592a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 178692a8780eSMiklos Szeredi req->in.args[1].size = strlen(name) + 1; 178792a8780eSMiklos Szeredi req->in.args[1].value = name; 178892a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 178992a8780eSMiklos Szeredi req->out.numargs = 1; 179092a8780eSMiklos Szeredi if (size) { 179192a8780eSMiklos Szeredi req->out.argvar = 1; 179292a8780eSMiklos Szeredi req->out.args[0].size = size; 179392a8780eSMiklos Szeredi req->out.args[0].value = value; 179492a8780eSMiklos Szeredi } else { 179592a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 179692a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 179792a8780eSMiklos Szeredi } 1798b93f858aSTejun Heo fuse_request_send(fc, req); 179992a8780eSMiklos Szeredi ret = req->out.h.error; 180092a8780eSMiklos Szeredi if (!ret) 180192a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 180292a8780eSMiklos Szeredi else { 180392a8780eSMiklos Szeredi if (ret == -ENOSYS) { 180492a8780eSMiklos Szeredi fc->no_getxattr = 1; 180592a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 180692a8780eSMiklos Szeredi } 180792a8780eSMiklos Szeredi } 180892a8780eSMiklos Szeredi fuse_put_request(fc, req); 180992a8780eSMiklos Szeredi return ret; 181092a8780eSMiklos Szeredi } 181192a8780eSMiklos Szeredi 181292a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) 181392a8780eSMiklos Szeredi { 181492a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 181592a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 181692a8780eSMiklos Szeredi struct fuse_req *req; 181792a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 181892a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 181992a8780eSMiklos Szeredi ssize_t ret; 182092a8780eSMiklos Szeredi 1821c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1822e57ac683SMiklos Szeredi return -EACCES; 1823e57ac683SMiklos Szeredi 182492a8780eSMiklos Szeredi if (fc->no_listxattr) 182592a8780eSMiklos Szeredi return -EOPNOTSUPP; 182692a8780eSMiklos Szeredi 1827b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1828ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1829ce1d5a49SMiklos Szeredi return PTR_ERR(req); 183092a8780eSMiklos Szeredi 183192a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 183292a8780eSMiklos Szeredi inarg.size = size; 183392a8780eSMiklos Szeredi req->in.h.opcode = FUSE_LISTXATTR; 183492a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 183592a8780eSMiklos Szeredi req->in.numargs = 1; 183692a8780eSMiklos Szeredi req->in.args[0].size = sizeof(inarg); 183792a8780eSMiklos Szeredi req->in.args[0].value = &inarg; 183892a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 183992a8780eSMiklos Szeredi req->out.numargs = 1; 184092a8780eSMiklos Szeredi if (size) { 184192a8780eSMiklos Szeredi req->out.argvar = 1; 184292a8780eSMiklos Szeredi req->out.args[0].size = size; 184392a8780eSMiklos Szeredi req->out.args[0].value = list; 184492a8780eSMiklos Szeredi } else { 184592a8780eSMiklos Szeredi req->out.args[0].size = sizeof(outarg); 184692a8780eSMiklos Szeredi req->out.args[0].value = &outarg; 184792a8780eSMiklos Szeredi } 1848b93f858aSTejun Heo fuse_request_send(fc, req); 184992a8780eSMiklos Szeredi ret = req->out.h.error; 185092a8780eSMiklos Szeredi if (!ret) 185192a8780eSMiklos Szeredi ret = size ? req->out.args[0].size : outarg.size; 185292a8780eSMiklos Szeredi else { 185392a8780eSMiklos Szeredi if (ret == -ENOSYS) { 185492a8780eSMiklos Szeredi fc->no_listxattr = 1; 185592a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 185692a8780eSMiklos Szeredi } 185792a8780eSMiklos Szeredi } 185892a8780eSMiklos Szeredi fuse_put_request(fc, req); 185992a8780eSMiklos Szeredi return ret; 186092a8780eSMiklos Szeredi } 186192a8780eSMiklos Szeredi 186292a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name) 186392a8780eSMiklos Szeredi { 186492a8780eSMiklos Szeredi struct inode *inode = entry->d_inode; 186592a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 186692a8780eSMiklos Szeredi struct fuse_req *req; 186792a8780eSMiklos Szeredi int err; 186892a8780eSMiklos Szeredi 186992a8780eSMiklos Szeredi if (fc->no_removexattr) 187092a8780eSMiklos Szeredi return -EOPNOTSUPP; 187192a8780eSMiklos Szeredi 1872b111c8c0SMaxim Patlasov req = fuse_get_req_nopages(fc); 1873ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1874ce1d5a49SMiklos Szeredi return PTR_ERR(req); 187592a8780eSMiklos Szeredi 187692a8780eSMiklos Szeredi req->in.h.opcode = FUSE_REMOVEXATTR; 187792a8780eSMiklos Szeredi req->in.h.nodeid = get_node_id(inode); 187892a8780eSMiklos Szeredi req->in.numargs = 1; 187992a8780eSMiklos Szeredi req->in.args[0].size = strlen(name) + 1; 188092a8780eSMiklos Szeredi req->in.args[0].value = name; 1881b93f858aSTejun Heo fuse_request_send(fc, req); 188292a8780eSMiklos Szeredi err = req->out.h.error; 188392a8780eSMiklos Szeredi fuse_put_request(fc, req); 188492a8780eSMiklos Szeredi if (err == -ENOSYS) { 188592a8780eSMiklos Szeredi fc->no_removexattr = 1; 188692a8780eSMiklos Szeredi err = -EOPNOTSUPP; 188792a8780eSMiklos Szeredi } 1888d331a415SAnand Avati if (!err) 1889d331a415SAnand Avati fuse_invalidate_attr(inode); 189092a8780eSMiklos Szeredi return err; 189192a8780eSMiklos Szeredi } 189292a8780eSMiklos Szeredi 1893754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1894e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 18959e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 18969e6268dbSMiklos Szeredi .symlink = fuse_symlink, 18979e6268dbSMiklos Szeredi .unlink = fuse_unlink, 18989e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 18999e6268dbSMiklos Szeredi .rename = fuse_rename, 19009e6268dbSMiklos Szeredi .link = fuse_link, 19019e6268dbSMiklos Szeredi .setattr = fuse_setattr, 19029e6268dbSMiklos Szeredi .create = fuse_create, 1903c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 19049e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1905e5e5558eSMiklos Szeredi .permission = fuse_permission, 1906e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 190792a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 190892a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 190992a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 191092a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1911e5e5558eSMiklos Szeredi }; 1912e5e5558eSMiklos Szeredi 19134b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1914b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1915e5e5558eSMiklos Szeredi .read = generic_read_dir, 19168d3af7f3SAl Viro .iterate = fuse_readdir, 1917e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1918e5e5558eSMiklos Szeredi .release = fuse_dir_release, 191982547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1920b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 1921b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 1922e5e5558eSMiklos Szeredi }; 1923e5e5558eSMiklos Szeredi 1924754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 19259e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1926e5e5558eSMiklos Szeredi .permission = fuse_permission, 1927e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 192892a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 192992a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 193092a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 193192a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1932e5e5558eSMiklos Szeredi }; 1933e5e5558eSMiklos Szeredi 1934754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 19359e6268dbSMiklos Szeredi .setattr = fuse_setattr, 1936e5e5558eSMiklos Szeredi .follow_link = fuse_follow_link, 1937e5e5558eSMiklos Szeredi .put_link = fuse_put_link, 1938e5e5558eSMiklos Szeredi .readlink = generic_readlink, 1939e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 194092a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 194192a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 194292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 194392a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1944e5e5558eSMiklos Szeredi }; 1945e5e5558eSMiklos Szeredi 1946e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1947e5e5558eSMiklos Szeredi { 1948e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1949e5e5558eSMiklos Szeredi } 1950e5e5558eSMiklos Szeredi 1951e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1952e5e5558eSMiklos Szeredi { 1953e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1954e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1955e5e5558eSMiklos Szeredi } 1956e5e5558eSMiklos Szeredi 1957e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1958e5e5558eSMiklos Szeredi { 1959e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 1960e5e5558eSMiklos Szeredi } 1961