1e5e5558eSMiklos Szeredi /* 2e5e5558eSMiklos Szeredi FUSE: Filesystem in Userspace 31729a16cSMiklos Szeredi Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> 4e5e5558eSMiklos Szeredi 5e5e5558eSMiklos Szeredi This program can be distributed under the terms of the GNU GPL. 6e5e5558eSMiklos Szeredi See the file COPYING. 7e5e5558eSMiklos Szeredi */ 8e5e5558eSMiklos Szeredi 9e5e5558eSMiklos Szeredi #include "fuse_i.h" 10e5e5558eSMiklos Szeredi 11e5e5558eSMiklos Szeredi #include <linux/pagemap.h> 12e5e5558eSMiklos Szeredi #include <linux/file.h> 13e5e5558eSMiklos Szeredi #include <linux/sched.h> 14e5e5558eSMiklos Szeredi #include <linux/namei.h> 1507e77dcaSMiklos Szeredi #include <linux/slab.h> 16e5e5558eSMiklos Szeredi 178d3af7f3SAl Viro static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx) 184582a4abSFeng Shuo { 194582a4abSFeng Shuo struct fuse_conn *fc = get_fuse_conn(dir); 204582a4abSFeng Shuo struct fuse_inode *fi = get_fuse_inode(dir); 214582a4abSFeng Shuo 224582a4abSFeng Shuo if (!fc->do_readdirplus) 234582a4abSFeng Shuo return false; 24634734b6SEric Wong if (!fc->readdirplus_auto) 25634734b6SEric Wong return true; 264582a4abSFeng Shuo if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state)) 274582a4abSFeng Shuo return true; 288d3af7f3SAl Viro if (ctx->pos == 0) 294582a4abSFeng Shuo return true; 304582a4abSFeng Shuo return false; 314582a4abSFeng Shuo } 324582a4abSFeng Shuo 334582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir) 344582a4abSFeng Shuo { 354582a4abSFeng Shuo struct fuse_inode *fi = get_fuse_inode(dir); 364582a4abSFeng Shuo 374582a4abSFeng Shuo set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state); 384582a4abSFeng Shuo } 394582a4abSFeng Shuo 400a0898cfSMiklos Szeredi #if BITS_PER_LONG >= 64 410a0898cfSMiklos Szeredi static inline void fuse_dentry_settime(struct dentry *entry, u64 time) 420a0898cfSMiklos Szeredi { 430a0898cfSMiklos Szeredi entry->d_time = time; 440a0898cfSMiklos Szeredi } 450a0898cfSMiklos Szeredi 460a0898cfSMiklos Szeredi static inline u64 fuse_dentry_time(struct dentry *entry) 470a0898cfSMiklos Szeredi { 480a0898cfSMiklos Szeredi return entry->d_time; 490a0898cfSMiklos Szeredi } 500a0898cfSMiklos Szeredi #else 510a0898cfSMiklos Szeredi /* 520a0898cfSMiklos Szeredi * On 32 bit archs store the high 32 bits of time in d_fsdata 530a0898cfSMiklos Szeredi */ 540a0898cfSMiklos Szeredi static void fuse_dentry_settime(struct dentry *entry, u64 time) 550a0898cfSMiklos Szeredi { 560a0898cfSMiklos Szeredi entry->d_time = time; 570a0898cfSMiklos Szeredi entry->d_fsdata = (void *) (unsigned long) (time >> 32); 580a0898cfSMiklos Szeredi } 590a0898cfSMiklos Szeredi 600a0898cfSMiklos Szeredi static u64 fuse_dentry_time(struct dentry *entry) 610a0898cfSMiklos Szeredi { 620a0898cfSMiklos Szeredi return (u64) entry->d_time + 630a0898cfSMiklos Szeredi ((u64) (unsigned long) entry->d_fsdata << 32); 640a0898cfSMiklos Szeredi } 650a0898cfSMiklos Szeredi #endif 660a0898cfSMiklos Szeredi 676f9f1180SMiklos Szeredi /* 686f9f1180SMiklos Szeredi * FUSE caches dentries and attributes with separate timeout. The 696f9f1180SMiklos Szeredi * time in jiffies until the dentry/attributes are valid is stored in 706f9f1180SMiklos Szeredi * dentry->d_time and fuse_inode->i_time respectively. 716f9f1180SMiklos Szeredi */ 726f9f1180SMiklos Szeredi 736f9f1180SMiklos Szeredi /* 746f9f1180SMiklos Szeredi * Calculate the time in jiffies until a dentry/attributes are valid 756f9f1180SMiklos Szeredi */ 760a0898cfSMiklos Szeredi static u64 time_to_jiffies(unsigned long sec, unsigned long nsec) 77e5e5558eSMiklos Szeredi { 78685d16ddSMiklos Szeredi if (sec || nsec) { 79e5e5558eSMiklos Szeredi struct timespec ts = {sec, nsec}; 800a0898cfSMiklos Szeredi return get_jiffies_64() + timespec_to_jiffies(&ts); 81685d16ddSMiklos Szeredi } else 820a0898cfSMiklos Szeredi return 0; 83e5e5558eSMiklos Szeredi } 84e5e5558eSMiklos Szeredi 856f9f1180SMiklos Szeredi /* 866f9f1180SMiklos Szeredi * Set dentry and possibly attribute timeouts from the lookup/mk* 876f9f1180SMiklos Szeredi * replies 886f9f1180SMiklos Szeredi */ 891fb69e78SMiklos Szeredi static void fuse_change_entry_timeout(struct dentry *entry, 901fb69e78SMiklos Szeredi struct fuse_entry_out *o) 910aa7c699SMiklos Szeredi { 920a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 930a0898cfSMiklos Szeredi time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 941fb69e78SMiklos Szeredi } 951fb69e78SMiklos Szeredi 961fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o) 971fb69e78SMiklos Szeredi { 981fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 991fb69e78SMiklos Szeredi } 1001fb69e78SMiklos Szeredi 1011fb69e78SMiklos Szeredi static u64 entry_attr_timeout(struct fuse_entry_out *o) 1021fb69e78SMiklos Szeredi { 1031fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 1048cbdf1e6SMiklos Szeredi } 1058cbdf1e6SMiklos Szeredi 1066f9f1180SMiklos Szeredi /* 1076f9f1180SMiklos Szeredi * Mark the attributes as stale, so that at the next call to 1086f9f1180SMiklos Szeredi * ->getattr() they will be fetched from userspace 1096f9f1180SMiklos Szeredi */ 1108cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode) 1118cbdf1e6SMiklos Szeredi { 1120a0898cfSMiklos Szeredi get_fuse_inode(inode)->i_time = 0; 1138cbdf1e6SMiklos Szeredi } 1148cbdf1e6SMiklos Szeredi 115451418fcSAndrew Gallagher /** 116451418fcSAndrew Gallagher * Mark the attributes as stale due to an atime change. Avoid the invalidate if 117451418fcSAndrew Gallagher * atime is not used. 118451418fcSAndrew Gallagher */ 119451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode) 120451418fcSAndrew Gallagher { 121451418fcSAndrew Gallagher if (!IS_RDONLY(inode)) 122451418fcSAndrew Gallagher fuse_invalidate_attr(inode); 123451418fcSAndrew Gallagher } 124451418fcSAndrew Gallagher 1256f9f1180SMiklos Szeredi /* 1266f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 1276f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 1286f9f1180SMiklos Szeredi * 1296f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 1306f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 1316f9f1180SMiklos Szeredi * lookup) 1326f9f1180SMiklos Szeredi */ 133dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry) 1348cbdf1e6SMiklos Szeredi { 1350a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 1368cbdf1e6SMiklos Szeredi } 1378cbdf1e6SMiklos Szeredi 1386f9f1180SMiklos Szeredi /* 1396f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 1406f9f1180SMiklos Szeredi * dentry from the hash 1416f9f1180SMiklos Szeredi */ 1428cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1438cbdf1e6SMiklos Szeredi { 1448cbdf1e6SMiklos Szeredi d_invalidate(entry); 1458cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1460aa7c699SMiklos Szeredi } 1470aa7c699SMiklos Szeredi 1487078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, 149c180eebeSMiklos Szeredi u64 nodeid, struct qstr *name, 150e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 151e5e5558eSMiklos Szeredi { 1520e9663eeSMiklos Szeredi memset(outarg, 0, sizeof(struct fuse_entry_out)); 1537078187aSMiklos Szeredi args->in.h.opcode = FUSE_LOOKUP; 1547078187aSMiklos Szeredi args->in.h.nodeid = nodeid; 1557078187aSMiklos Szeredi args->in.numargs = 1; 1567078187aSMiklos Szeredi args->in.args[0].size = name->len + 1; 1577078187aSMiklos Szeredi args->in.args[0].value = name->name; 1587078187aSMiklos Szeredi args->out.numargs = 1; 1597078187aSMiklos Szeredi args->out.args[0].size = sizeof(struct fuse_entry_out); 1607078187aSMiklos Szeredi args->out.args[0].value = outarg; 161e5e5558eSMiklos Szeredi } 162e5e5558eSMiklos Szeredi 1635c5c5e51SMiklos Szeredi u64 fuse_get_attr_version(struct fuse_conn *fc) 1647dca9fd3SMiklos Szeredi { 1657dca9fd3SMiklos Szeredi u64 curr_version; 1667dca9fd3SMiklos Szeredi 1677dca9fd3SMiklos Szeredi /* 1687dca9fd3SMiklos Szeredi * The spin lock isn't actually needed on 64bit archs, but we 1697dca9fd3SMiklos Szeredi * don't yet care too much about such optimizations. 1707dca9fd3SMiklos Szeredi */ 1717dca9fd3SMiklos Szeredi spin_lock(&fc->lock); 1727dca9fd3SMiklos Szeredi curr_version = fc->attr_version; 1737dca9fd3SMiklos Szeredi spin_unlock(&fc->lock); 1747dca9fd3SMiklos Szeredi 1757dca9fd3SMiklos Szeredi return curr_version; 1767dca9fd3SMiklos Szeredi } 1777dca9fd3SMiklos Szeredi 1786f9f1180SMiklos Szeredi /* 1796f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1806f9f1180SMiklos Szeredi * 1816f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 1826f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 1836f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 1846f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 1856f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 1866f9f1180SMiklos Szeredi */ 1870b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) 188e5e5558eSMiklos Szeredi { 18934286d66SNick Piggin struct inode *inode; 19028420dadSMiklos Szeredi struct dentry *parent; 19128420dadSMiklos Szeredi struct fuse_conn *fc; 1926314efeeSMiklos Szeredi struct fuse_inode *fi; 193e2a6b952SMiklos Szeredi int ret; 1948cbdf1e6SMiklos Szeredi 1952b0143b5SDavid Howells inode = d_inode_rcu(entry); 1968cbdf1e6SMiklos Szeredi if (inode && is_bad_inode(inode)) 197e2a6b952SMiklos Szeredi goto invalid; 198154210ccSAnand Avati else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || 199154210ccSAnand Avati (flags & LOOKUP_REVAL)) { 200e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 2017078187aSMiklos Szeredi FUSE_ARGS(args); 20207e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 2031fb69e78SMiklos Szeredi u64 attr_version; 2048cbdf1e6SMiklos Szeredi 20550322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 2068cbdf1e6SMiklos Szeredi if (!inode) 207e2a6b952SMiklos Szeredi goto invalid; 2088cbdf1e6SMiklos Szeredi 209e2a6b952SMiklos Szeredi ret = -ECHILD; 2100b728e19SAl Viro if (flags & LOOKUP_RCU) 211e2a6b952SMiklos Szeredi goto out; 212e7c0a167SMiklos Szeredi 2138cbdf1e6SMiklos Szeredi fc = get_fuse_conn(inode); 214e5e5558eSMiklos Szeredi 21507e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 216e2a6b952SMiklos Szeredi ret = -ENOMEM; 2177078187aSMiklos Szeredi if (!forget) 218e2a6b952SMiklos Szeredi goto out; 2192d51013eSMiklos Szeredi 2207dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 2211fb69e78SMiklos Szeredi 222e956edd0SMiklos Szeredi parent = dget_parent(entry); 2232b0143b5SDavid Howells fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)), 224c180eebeSMiklos Szeredi &entry->d_name, &outarg); 2257078187aSMiklos Szeredi ret = fuse_simple_request(fc, &args); 226e956edd0SMiklos Szeredi dput(parent); 22750322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 2287078187aSMiklos Szeredi if (!ret && !outarg.nodeid) 2297078187aSMiklos Szeredi ret = -ENOENT; 2307078187aSMiklos Szeredi if (!ret) { 2316314efeeSMiklos Szeredi 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); 2417078187aSMiklos Szeredi if (ret == -ENOMEM) 2427078187aSMiklos Szeredi goto out; 2437078187aSMiklos Szeredi if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 244e2a6b952SMiklos Szeredi goto invalid; 245e5e5558eSMiklos Szeredi 2461fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2471fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2481fb69e78SMiklos Szeredi attr_version); 2491fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 25028420dadSMiklos Szeredi } else if (inode) { 2516314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2526314efeeSMiklos Szeredi if (flags & LOOKUP_RCU) { 2536314efeeSMiklos Szeredi if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) 2546314efeeSMiklos Szeredi return -ECHILD; 2556314efeeSMiklos Szeredi } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { 25628420dadSMiklos Szeredi parent = dget_parent(entry); 2572b0143b5SDavid Howells fuse_advise_use_readdirplus(d_inode(parent)); 25828420dadSMiklos Szeredi dput(parent); 259e5e5558eSMiklos Szeredi } 26028420dadSMiklos Szeredi } 261e2a6b952SMiklos Szeredi ret = 1; 262e2a6b952SMiklos Szeredi out: 263e2a6b952SMiklos Szeredi return ret; 264e2a6b952SMiklos Szeredi 265e2a6b952SMiklos Szeredi invalid: 266e2a6b952SMiklos Szeredi ret = 0; 267e2a6b952SMiklos Szeredi goto out; 268e5e5558eSMiklos Szeredi } 269e5e5558eSMiklos Szeredi 2708bfc016dSMiklos Szeredi static int invalid_nodeid(u64 nodeid) 2712827d0b2SMiklos Szeredi { 2722827d0b2SMiklos Szeredi return !nodeid || nodeid == FUSE_ROOT_ID; 2732827d0b2SMiklos Szeredi } 2742827d0b2SMiklos Szeredi 2754269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 276e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 277e5e5558eSMiklos Szeredi }; 278e5e5558eSMiklos Szeredi 279a5bfffacSTimo Savola int fuse_valid_type(int m) 28039ee059aSMiklos Szeredi { 28139ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 28239ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 28339ee059aSMiklos Szeredi } 28439ee059aSMiklos Szeredi 285c180eebeSMiklos Szeredi int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, 286c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 287c180eebeSMiklos Szeredi { 288c180eebeSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(sb); 2897078187aSMiklos Szeredi FUSE_ARGS(args); 29007e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 291c180eebeSMiklos Szeredi u64 attr_version; 292c180eebeSMiklos Szeredi int err; 293c180eebeSMiklos Szeredi 294c180eebeSMiklos Szeredi *inode = NULL; 295c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 296c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 297c180eebeSMiklos Szeredi goto out; 298c180eebeSMiklos Szeredi 299c180eebeSMiklos Szeredi 30007e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 30107e77dcaSMiklos Szeredi err = -ENOMEM; 3027078187aSMiklos Szeredi if (!forget) 303c180eebeSMiklos Szeredi goto out; 304c180eebeSMiklos Szeredi 305c180eebeSMiklos Szeredi attr_version = fuse_get_attr_version(fc); 306c180eebeSMiklos Szeredi 3077078187aSMiklos Szeredi fuse_lookup_init(fc, &args, nodeid, name, outarg); 3087078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 309c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 310c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 311c180eebeSMiklos Szeredi goto out_put_forget; 312c180eebeSMiklos Szeredi 313c180eebeSMiklos Szeredi err = -EIO; 314c180eebeSMiklos Szeredi if (!outarg->nodeid) 315c180eebeSMiklos Szeredi goto out_put_forget; 316c180eebeSMiklos Szeredi if (!fuse_valid_type(outarg->attr.mode)) 317c180eebeSMiklos Szeredi goto out_put_forget; 318c180eebeSMiklos Szeredi 319c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 320c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 321c180eebeSMiklos Szeredi attr_version); 322c180eebeSMiklos Szeredi err = -ENOMEM; 323c180eebeSMiklos Szeredi if (!*inode) { 32407e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg->nodeid, 1); 325c180eebeSMiklos Szeredi goto out; 326c180eebeSMiklos Szeredi } 327c180eebeSMiklos Szeredi err = 0; 328c180eebeSMiklos Szeredi 329c180eebeSMiklos Szeredi out_put_forget: 33007e77dcaSMiklos Szeredi kfree(forget); 331c180eebeSMiklos Szeredi out: 332c180eebeSMiklos Szeredi return err; 333c180eebeSMiklos Szeredi } 334c180eebeSMiklos Szeredi 3350aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 33600cd8dd3SAl Viro unsigned int flags) 337e5e5558eSMiklos Szeredi { 338e5e5558eSMiklos Szeredi int err; 339e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 340c180eebeSMiklos Szeredi struct inode *inode; 3410de6256dSMiklos Szeredi struct dentry *newent; 342c180eebeSMiklos Szeredi bool outarg_valid = true; 343e5e5558eSMiklos Szeredi 344*5c672ab3SMiklos Szeredi fuse_lock_inode(dir); 345c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 346c180eebeSMiklos Szeredi &outarg, &inode); 347*5c672ab3SMiklos Szeredi fuse_unlock_inode(dir); 348c180eebeSMiklos Szeredi if (err == -ENOENT) { 349c180eebeSMiklos Szeredi outarg_valid = false; 350c180eebeSMiklos Szeredi err = 0; 3512d51013eSMiklos Szeredi } 352c180eebeSMiklos Szeredi if (err) 353c180eebeSMiklos Szeredi goto out_err; 3542d51013eSMiklos Szeredi 355ee4e5271SMiklos Szeredi err = -EIO; 356c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 357c180eebeSMiklos Szeredi goto out_iput; 358e5e5558eSMiklos Szeredi 35941d28bcaSAl Viro newent = d_splice_alias(inode, entry); 360c180eebeSMiklos Szeredi err = PTR_ERR(newent); 361c180eebeSMiklos Szeredi if (IS_ERR(newent)) 3625835f339SMiklos Szeredi goto out_err; 363d2a85164SMiklos Szeredi 3640de6256dSMiklos Szeredi entry = newent ? newent : entry; 365c180eebeSMiklos Szeredi if (outarg_valid) 3661fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 3678cbdf1e6SMiklos Szeredi else 3688cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 369c180eebeSMiklos Szeredi 3704582a4abSFeng Shuo fuse_advise_use_readdirplus(dir); 3710de6256dSMiklos Szeredi return newent; 372c180eebeSMiklos Szeredi 373c180eebeSMiklos Szeredi out_iput: 374c180eebeSMiklos Szeredi iput(inode); 375c180eebeSMiklos Szeredi out_err: 376c180eebeSMiklos Szeredi return ERR_PTR(err); 377e5e5558eSMiklos Szeredi } 378e5e5558eSMiklos Szeredi 3796f9f1180SMiklos Szeredi /* 3806f9f1180SMiklos Szeredi * Atomic create+open operation 3816f9f1180SMiklos Szeredi * 3826f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 3836f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 3846f9f1180SMiklos Szeredi */ 385d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 38630d90494SAl Viro struct file *file, unsigned flags, 38747237687SAl Viro umode_t mode, int *opened) 388fd72faacSMiklos Szeredi { 389fd72faacSMiklos Szeredi int err; 390fd72faacSMiklos Szeredi struct inode *inode; 391fd72faacSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 3927078187aSMiklos Szeredi FUSE_ARGS(args); 39307e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 394e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 395fd72faacSMiklos Szeredi struct fuse_open_out outopen; 396fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 397fd72faacSMiklos Szeredi struct fuse_file *ff; 398fd72faacSMiklos Szeredi 399af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 400af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 401af109bcaSMiklos Szeredi 40207e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 403c8ccbe03SMiklos Szeredi err = -ENOMEM; 40407e77dcaSMiklos Szeredi if (!forget) 405c8ccbe03SMiklos Szeredi goto out_err; 40651eb01e7SMiklos Szeredi 407ce1d5a49SMiklos Szeredi err = -ENOMEM; 408acf99433STejun Heo ff = fuse_file_alloc(fc); 409fd72faacSMiklos Szeredi if (!ff) 4107078187aSMiklos Szeredi goto out_put_forget_req; 411fd72faacSMiklos Szeredi 412e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 413e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 414e0a43ddcSMiklos Szeredi 415fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 416fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 4170e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 418fd72faacSMiklos Szeredi inarg.flags = flags; 419fd72faacSMiklos Szeredi inarg.mode = mode; 420e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 4217078187aSMiklos Szeredi args.in.h.opcode = FUSE_CREATE; 4227078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(dir); 4237078187aSMiklos Szeredi args.in.numargs = 2; 42421f62174SMiklos Szeredi args.in.args[0].size = sizeof(inarg); 4257078187aSMiklos Szeredi args.in.args[0].value = &inarg; 4267078187aSMiklos Szeredi args.in.args[1].size = entry->d_name.len + 1; 4277078187aSMiklos Szeredi args.in.args[1].value = entry->d_name.name; 4287078187aSMiklos Szeredi args.out.numargs = 2; 4297078187aSMiklos Szeredi args.out.args[0].size = sizeof(outentry); 4307078187aSMiklos Szeredi args.out.args[0].value = &outentry; 4317078187aSMiklos Szeredi args.out.args[1].size = sizeof(outopen); 4327078187aSMiklos Szeredi args.out.args[1].value = &outopen; 4337078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 434c8ccbe03SMiklos Szeredi if (err) 435fd72faacSMiklos Szeredi goto out_free_ff; 436fd72faacSMiklos Szeredi 437fd72faacSMiklos Szeredi err = -EIO; 4382827d0b2SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 439fd72faacSMiklos Szeredi goto out_free_ff; 440fd72faacSMiklos Szeredi 441c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 442c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 443c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 444fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 4451fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 446fd72faacSMiklos Szeredi if (!inode) { 447fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 4488b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 44907e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outentry.nodeid, 1); 450c8ccbe03SMiklos Szeredi err = -ENOMEM; 451c8ccbe03SMiklos Szeredi goto out_err; 452fd72faacSMiklos Szeredi } 45307e77dcaSMiklos Szeredi kfree(forget); 454fd72faacSMiklos Szeredi d_instantiate(entry, inode); 4551fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 4560952b2a4SMiklos Szeredi fuse_invalidate_attr(dir); 45730d90494SAl Viro err = finish_open(file, entry, generic_file_open, opened); 45830d90494SAl Viro if (err) { 4598b0797a4SMiklos Szeredi fuse_sync_release(ff, flags); 460c8ccbe03SMiklos Szeredi } else { 461c7b7143cSMiklos Szeredi file->private_data = fuse_file_get(ff); 462c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 463c8ccbe03SMiklos Szeredi } 464d9585277SAl Viro return err; 465fd72faacSMiklos Szeredi 466fd72faacSMiklos Szeredi out_free_ff: 467fd72faacSMiklos Szeredi fuse_file_free(ff); 46851eb01e7SMiklos Szeredi out_put_forget_req: 46907e77dcaSMiklos Szeredi kfree(forget); 470c8ccbe03SMiklos Szeredi out_err: 471d9585277SAl Viro return err; 472c8ccbe03SMiklos Szeredi } 473c8ccbe03SMiklos Szeredi 474c8ccbe03SMiklos Szeredi static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); 475d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 47630d90494SAl Viro struct file *file, unsigned flags, 47747237687SAl Viro umode_t mode, int *opened) 478c8ccbe03SMiklos Szeredi { 479c8ccbe03SMiklos Szeredi int err; 480c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 481c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 482c8ccbe03SMiklos Szeredi 483c8ccbe03SMiklos Szeredi if (d_unhashed(entry)) { 48400cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 485c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 486d9585277SAl Viro return PTR_ERR(res); 487c8ccbe03SMiklos Szeredi 488c8ccbe03SMiklos Szeredi if (res) 489c8ccbe03SMiklos Szeredi entry = res; 490c8ccbe03SMiklos Szeredi } 491c8ccbe03SMiklos Szeredi 4922b0143b5SDavid Howells if (!(flags & O_CREAT) || d_really_is_positive(entry)) 493c8ccbe03SMiklos Szeredi goto no_open; 494c8ccbe03SMiklos Szeredi 495c8ccbe03SMiklos Szeredi /* Only creates */ 49647237687SAl Viro *opened |= FILE_CREATED; 497c8ccbe03SMiklos Szeredi 498c8ccbe03SMiklos Szeredi if (fc->no_create) 499c8ccbe03SMiklos Szeredi goto mknod; 500c8ccbe03SMiklos Szeredi 50130d90494SAl Viro err = fuse_create_open(dir, entry, file, flags, mode, opened); 502d9585277SAl Viro if (err == -ENOSYS) { 503c8ccbe03SMiklos Szeredi fc->no_create = 1; 504c8ccbe03SMiklos Szeredi goto mknod; 505c8ccbe03SMiklos Szeredi } 506c8ccbe03SMiklos Szeredi out_dput: 507c8ccbe03SMiklos Szeredi dput(res); 508d9585277SAl Viro return err; 509c8ccbe03SMiklos Szeredi 510c8ccbe03SMiklos Szeredi mknod: 511c8ccbe03SMiklos Szeredi err = fuse_mknod(dir, entry, mode, 0); 512d9585277SAl Viro if (err) 513c8ccbe03SMiklos Szeredi goto out_dput; 514c8ccbe03SMiklos Szeredi no_open: 515e45198a6SAl Viro return finish_no_open(file, res); 516fd72faacSMiklos Szeredi } 517fd72faacSMiklos Szeredi 5186f9f1180SMiklos Szeredi /* 5196f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 5206f9f1180SMiklos Szeredi */ 5217078187aSMiklos Szeredi static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, 5229e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 523541af6a0SAl Viro umode_t mode) 5249e6268dbSMiklos Szeredi { 5259e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 5269e6268dbSMiklos Szeredi struct inode *inode; 5279e6268dbSMiklos Szeredi int err; 52807e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 5292d51013eSMiklos Szeredi 53007e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 5317078187aSMiklos Szeredi if (!forget) 53207e77dcaSMiklos Szeredi return -ENOMEM; 5339e6268dbSMiklos Szeredi 5340e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 5357078187aSMiklos Szeredi args->in.h.nodeid = get_node_id(dir); 5367078187aSMiklos Szeredi args->out.numargs = 1; 5377078187aSMiklos Szeredi args->out.args[0].size = sizeof(outarg); 5387078187aSMiklos Szeredi args->out.args[0].value = &outarg; 5397078187aSMiklos Szeredi err = fuse_simple_request(fc, args); 5402d51013eSMiklos Szeredi if (err) 5412d51013eSMiklos Szeredi goto out_put_forget_req; 5422d51013eSMiklos Szeredi 54339ee059aSMiklos Szeredi err = -EIO; 54439ee059aSMiklos Szeredi if (invalid_nodeid(outarg.nodeid)) 5452d51013eSMiklos Szeredi goto out_put_forget_req; 54639ee059aSMiklos Szeredi 54739ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 5482d51013eSMiklos Szeredi goto out_put_forget_req; 54939ee059aSMiklos Szeredi 5509e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 5511fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 5529e6268dbSMiklos Szeredi if (!inode) { 55307e77dcaSMiklos Szeredi fuse_queue_forget(fc, forget, outarg.nodeid, 1); 5549e6268dbSMiklos Szeredi return -ENOMEM; 5559e6268dbSMiklos Szeredi } 55607e77dcaSMiklos Szeredi kfree(forget); 5579e6268dbSMiklos Szeredi 558b70a80e7SMiklos Szeredi err = d_instantiate_no_diralias(entry, inode); 559b70a80e7SMiklos Szeredi if (err) 560b70a80e7SMiklos Szeredi return err; 561d2a85164SMiklos Szeredi 5621fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 5639e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 5649e6268dbSMiklos Szeredi return 0; 56539ee059aSMiklos Szeredi 5662d51013eSMiklos Szeredi out_put_forget_req: 56707e77dcaSMiklos Szeredi kfree(forget); 56839ee059aSMiklos Szeredi return err; 5699e6268dbSMiklos Szeredi } 5709e6268dbSMiklos Szeredi 5711a67aafbSAl Viro static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, 5729e6268dbSMiklos Szeredi dev_t rdev) 5739e6268dbSMiklos Szeredi { 5749e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 5759e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 5767078187aSMiklos Szeredi FUSE_ARGS(args); 5779e6268dbSMiklos Szeredi 578e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 579e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 580e0a43ddcSMiklos Szeredi 5819e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 5829e6268dbSMiklos Szeredi inarg.mode = mode; 5839e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 584e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 5857078187aSMiklos Szeredi args.in.h.opcode = FUSE_MKNOD; 5867078187aSMiklos Szeredi args.in.numargs = 2; 58721f62174SMiklos Szeredi args.in.args[0].size = sizeof(inarg); 5887078187aSMiklos Szeredi args.in.args[0].value = &inarg; 5897078187aSMiklos Szeredi args.in.args[1].size = entry->d_name.len + 1; 5907078187aSMiklos Szeredi args.in.args[1].value = entry->d_name.name; 5917078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, mode); 5929e6268dbSMiklos Szeredi } 5939e6268dbSMiklos Szeredi 5944acdaf27SAl Viro static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, 595ebfc3b49SAl Viro bool excl) 5969e6268dbSMiklos Szeredi { 5979e6268dbSMiklos Szeredi return fuse_mknod(dir, entry, mode, 0); 5989e6268dbSMiklos Szeredi } 5999e6268dbSMiklos Szeredi 60018bb1db3SAl Viro static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode) 6019e6268dbSMiklos Szeredi { 6029e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 6039e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6047078187aSMiklos Szeredi FUSE_ARGS(args); 6059e6268dbSMiklos Szeredi 606e0a43ddcSMiklos Szeredi if (!fc->dont_mask) 607e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 608e0a43ddcSMiklos Szeredi 6099e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6109e6268dbSMiklos Szeredi inarg.mode = mode; 611e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 6127078187aSMiklos Szeredi args.in.h.opcode = FUSE_MKDIR; 6137078187aSMiklos Szeredi args.in.numargs = 2; 6147078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 6157078187aSMiklos Szeredi args.in.args[0].value = &inarg; 6167078187aSMiklos Szeredi args.in.args[1].size = entry->d_name.len + 1; 6177078187aSMiklos Szeredi args.in.args[1].value = entry->d_name.name; 6187078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, S_IFDIR); 6199e6268dbSMiklos Szeredi } 6209e6268dbSMiklos Szeredi 6219e6268dbSMiklos Szeredi static int fuse_symlink(struct inode *dir, struct dentry *entry, 6229e6268dbSMiklos Szeredi const char *link) 6239e6268dbSMiklos Szeredi { 6249e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6259e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 6267078187aSMiklos Szeredi FUSE_ARGS(args); 6279e6268dbSMiklos Szeredi 6287078187aSMiklos Szeredi args.in.h.opcode = FUSE_SYMLINK; 6297078187aSMiklos Szeredi args.in.numargs = 2; 6307078187aSMiklos Szeredi args.in.args[0].size = entry->d_name.len + 1; 6317078187aSMiklos Szeredi args.in.args[0].value = entry->d_name.name; 6327078187aSMiklos Szeredi args.in.args[1].size = len; 6337078187aSMiklos Szeredi args.in.args[1].value = link; 6347078187aSMiklos Szeredi return create_new_entry(fc, &args, dir, entry, S_IFLNK); 6359e6268dbSMiklos Szeredi } 6369e6268dbSMiklos Szeredi 63731f3267bSMaxim Patlasov static inline void fuse_update_ctime(struct inode *inode) 63831f3267bSMaxim Patlasov { 63931f3267bSMaxim Patlasov if (!IS_NOCMTIME(inode)) { 64031f3267bSMaxim Patlasov inode->i_ctime = current_fs_time(inode->i_sb); 64131f3267bSMaxim Patlasov mark_inode_dirty_sync(inode); 64231f3267bSMaxim Patlasov } 64331f3267bSMaxim Patlasov } 64431f3267bSMaxim Patlasov 6459e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 6469e6268dbSMiklos Szeredi { 6479e6268dbSMiklos Szeredi int err; 6489e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6497078187aSMiklos Szeredi FUSE_ARGS(args); 6509e6268dbSMiklos Szeredi 6517078187aSMiklos Szeredi args.in.h.opcode = FUSE_UNLINK; 6527078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(dir); 6537078187aSMiklos Szeredi args.in.numargs = 1; 6547078187aSMiklos Szeredi args.in.args[0].size = entry->d_name.len + 1; 6557078187aSMiklos Szeredi args.in.args[0].value = entry->d_name.name; 6567078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 6579e6268dbSMiklos Szeredi if (!err) { 6582b0143b5SDavid Howells struct inode *inode = d_inode(entry); 659ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 6609e6268dbSMiklos Szeredi 661ac45d613SMiklos Szeredi spin_lock(&fc->lock); 662ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 663dfca7cebSMiklos Szeredi /* 664dfca7cebSMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 665dfca7cebSMiklos Szeredi * happen if userspace filesystem is careless. It would be 666dfca7cebSMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 667dfca7cebSMiklos Szeredi * condition here 668dfca7cebSMiklos Szeredi */ 669dfca7cebSMiklos Szeredi if (inode->i_nlink > 0) 670ac45d613SMiklos Szeredi drop_nlink(inode); 671ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 6729e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 6739e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 6748cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 67531f3267bSMaxim Patlasov fuse_update_ctime(inode); 6769e6268dbSMiklos Szeredi } else if (err == -EINTR) 6779e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 6789e6268dbSMiklos Szeredi return err; 6799e6268dbSMiklos Szeredi } 6809e6268dbSMiklos Szeredi 6819e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 6829e6268dbSMiklos Szeredi { 6839e6268dbSMiklos Szeredi int err; 6849e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 6857078187aSMiklos Szeredi FUSE_ARGS(args); 6869e6268dbSMiklos Szeredi 6877078187aSMiklos Szeredi args.in.h.opcode = FUSE_RMDIR; 6887078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(dir); 6897078187aSMiklos Szeredi args.in.numargs = 1; 6907078187aSMiklos Szeredi args.in.args[0].size = entry->d_name.len + 1; 6917078187aSMiklos Szeredi args.in.args[0].value = entry->d_name.name; 6927078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 6939e6268dbSMiklos Szeredi if (!err) { 6942b0143b5SDavid Howells clear_nlink(d_inode(entry)); 6959e6268dbSMiklos Szeredi fuse_invalidate_attr(dir); 6968cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 6979e6268dbSMiklos Szeredi } else if (err == -EINTR) 6989e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 6999e6268dbSMiklos Szeredi return err; 7009e6268dbSMiklos Szeredi } 7019e6268dbSMiklos Szeredi 7021560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, 7031560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 7041560c974SMiklos Szeredi unsigned int flags, int opcode, size_t argsize) 7059e6268dbSMiklos Szeredi { 7069e6268dbSMiklos Szeredi int err; 7071560c974SMiklos Szeredi struct fuse_rename2_in inarg; 7089e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 7097078187aSMiklos Szeredi FUSE_ARGS(args); 7109e6268dbSMiklos Szeredi 7111560c974SMiklos Szeredi memset(&inarg, 0, argsize); 7129e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 7131560c974SMiklos Szeredi inarg.flags = flags; 7147078187aSMiklos Szeredi args.in.h.opcode = opcode; 7157078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(olddir); 7167078187aSMiklos Szeredi args.in.numargs = 3; 7177078187aSMiklos Szeredi args.in.args[0].size = argsize; 7187078187aSMiklos Szeredi args.in.args[0].value = &inarg; 7197078187aSMiklos Szeredi args.in.args[1].size = oldent->d_name.len + 1; 7207078187aSMiklos Szeredi args.in.args[1].value = oldent->d_name.name; 7217078187aSMiklos Szeredi args.in.args[2].size = newent->d_name.len + 1; 7227078187aSMiklos Szeredi args.in.args[2].value = newent->d_name.name; 7237078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 7249e6268dbSMiklos Szeredi if (!err) { 72508b63307SMiklos Szeredi /* ctime changes */ 7262b0143b5SDavid Howells fuse_invalidate_attr(d_inode(oldent)); 7272b0143b5SDavid Howells fuse_update_ctime(d_inode(oldent)); 72808b63307SMiklos Szeredi 7291560c974SMiklos Szeredi if (flags & RENAME_EXCHANGE) { 7302b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 7312b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 7321560c974SMiklos Szeredi } 7331560c974SMiklos Szeredi 7349e6268dbSMiklos Szeredi fuse_invalidate_attr(olddir); 7359e6268dbSMiklos Szeredi if (olddir != newdir) 7369e6268dbSMiklos Szeredi fuse_invalidate_attr(newdir); 7378cbdf1e6SMiklos Szeredi 7388cbdf1e6SMiklos Szeredi /* newent will end up negative */ 7392b0143b5SDavid Howells if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { 7402b0143b5SDavid Howells fuse_invalidate_attr(d_inode(newent)); 7418cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(newent); 7422b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 7435219f346SMiklos Szeredi } 7449e6268dbSMiklos Szeredi } else if (err == -EINTR) { 7459e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 7469e6268dbSMiklos Szeredi rename actually took place. If the invalidation 7479e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 7489e6268dbSMiklos Szeredi directory), then there can be inconsistency between 7499e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 7509e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 7512b0143b5SDavid Howells if (d_really_is_positive(newent)) 7529e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 7539e6268dbSMiklos Szeredi } 7549e6268dbSMiklos Szeredi 7559e6268dbSMiklos Szeredi return err; 7569e6268dbSMiklos Szeredi } 7579e6268dbSMiklos Szeredi 7581560c974SMiklos Szeredi static int fuse_rename2(struct inode *olddir, struct dentry *oldent, 7591560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 7601560c974SMiklos Szeredi unsigned int flags) 7611560c974SMiklos Szeredi { 7621560c974SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 7631560c974SMiklos Szeredi int err; 7641560c974SMiklos Szeredi 7651560c974SMiklos Szeredi if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) 7661560c974SMiklos Szeredi return -EINVAL; 7671560c974SMiklos Szeredi 7684237ba43SMiklos Szeredi if (flags) { 7691560c974SMiklos Szeredi if (fc->no_rename2 || fc->minor < 23) 7701560c974SMiklos Szeredi return -EINVAL; 7711560c974SMiklos Szeredi 7721560c974SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, flags, 7734237ba43SMiklos Szeredi FUSE_RENAME2, 7744237ba43SMiklos Szeredi sizeof(struct fuse_rename2_in)); 7751560c974SMiklos Szeredi if (err == -ENOSYS) { 7761560c974SMiklos Szeredi fc->no_rename2 = 1; 7771560c974SMiklos Szeredi err = -EINVAL; 7781560c974SMiklos Szeredi } 7794237ba43SMiklos Szeredi } else { 7804237ba43SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, 0, 7814237ba43SMiklos Szeredi FUSE_RENAME, 7824237ba43SMiklos Szeredi sizeof(struct fuse_rename_in)); 7834237ba43SMiklos Szeredi } 7841560c974SMiklos Szeredi 7854237ba43SMiklos Szeredi return err; 7864237ba43SMiklos Szeredi } 7874237ba43SMiklos Szeredi 7889e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 7899e6268dbSMiklos Szeredi struct dentry *newent) 7909e6268dbSMiklos Szeredi { 7919e6268dbSMiklos Szeredi int err; 7929e6268dbSMiklos Szeredi struct fuse_link_in inarg; 7932b0143b5SDavid Howells struct inode *inode = d_inode(entry); 7949e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 7957078187aSMiklos Szeredi FUSE_ARGS(args); 7969e6268dbSMiklos Szeredi 7979e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 7989e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 7997078187aSMiklos Szeredi args.in.h.opcode = FUSE_LINK; 8007078187aSMiklos Szeredi args.in.numargs = 2; 8017078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 8027078187aSMiklos Szeredi args.in.args[0].value = &inarg; 8037078187aSMiklos Szeredi args.in.args[1].size = newent->d_name.len + 1; 8047078187aSMiklos Szeredi args.in.args[1].value = newent->d_name.name; 8057078187aSMiklos Szeredi err = create_new_entry(fc, &args, newdir, newent, inode->i_mode); 8069e6268dbSMiklos Szeredi /* Contrary to "normal" filesystems it can happen that link 8079e6268dbSMiklos Szeredi makes two "logical" inodes point to the same "physical" 8089e6268dbSMiklos Szeredi inode. We invalidate the attributes of the old one, so it 8099e6268dbSMiklos Szeredi will reflect changes in the backing inode (link count, 8109e6268dbSMiklos Szeredi etc.) 8119e6268dbSMiklos Szeredi */ 812ac45d613SMiklos Szeredi if (!err) { 813ac45d613SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 814ac45d613SMiklos Szeredi 815ac45d613SMiklos Szeredi spin_lock(&fc->lock); 816ac45d613SMiklos Szeredi fi->attr_version = ++fc->attr_version; 817ac45d613SMiklos Szeredi inc_nlink(inode); 818ac45d613SMiklos Szeredi spin_unlock(&fc->lock); 8199e6268dbSMiklos Szeredi fuse_invalidate_attr(inode); 82031f3267bSMaxim Patlasov fuse_update_ctime(inode); 821ac45d613SMiklos Szeredi } else if (err == -EINTR) { 822ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 823ac45d613SMiklos Szeredi } 8249e6268dbSMiklos Szeredi return err; 8259e6268dbSMiklos Szeredi } 8269e6268dbSMiklos Szeredi 8271fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 8281fb69e78SMiklos Szeredi struct kstat *stat) 8291fb69e78SMiklos Szeredi { 830203627bbSMiklos Szeredi unsigned int blkbits; 8318373200bSPavel Emelyanov struct fuse_conn *fc = get_fuse_conn(inode); 8328373200bSPavel Emelyanov 8338373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 834b0aa7606SMaxim Patlasov if (fc->writeback_cache && S_ISREG(inode->i_mode)) { 8358373200bSPavel Emelyanov attr->size = i_size_read(inode); 836b0aa7606SMaxim Patlasov attr->mtime = inode->i_mtime.tv_sec; 837b0aa7606SMaxim Patlasov attr->mtimensec = inode->i_mtime.tv_nsec; 83831f3267bSMaxim Patlasov attr->ctime = inode->i_ctime.tv_sec; 83931f3267bSMaxim Patlasov attr->ctimensec = inode->i_ctime.tv_nsec; 840b0aa7606SMaxim Patlasov } 841203627bbSMiklos Szeredi 8421fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 8431fb69e78SMiklos Szeredi stat->ino = attr->ino; 8441fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 8451fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 846499dcf20SEric W. Biederman stat->uid = make_kuid(&init_user_ns, attr->uid); 847499dcf20SEric W. Biederman stat->gid = make_kgid(&init_user_ns, attr->gid); 8481fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 8491fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 8501fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 8511fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 8521fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 8531fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 8541fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 8551fb69e78SMiklos Szeredi stat->size = attr->size; 8561fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 857203627bbSMiklos Szeredi 858203627bbSMiklos Szeredi if (attr->blksize != 0) 859203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 860203627bbSMiklos Szeredi else 861203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 862203627bbSMiklos Szeredi 863203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 8641fb69e78SMiklos Szeredi } 8651fb69e78SMiklos Szeredi 866c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 867c79e322fSMiklos Szeredi struct file *file) 868e5e5558eSMiklos Szeredi { 869e5e5558eSMiklos Szeredi int err; 870c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 871c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 872e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 8737078187aSMiklos Szeredi FUSE_ARGS(args); 8741fb69e78SMiklos Szeredi u64 attr_version; 8751fb69e78SMiklos Szeredi 8767dca9fd3SMiklos Szeredi attr_version = fuse_get_attr_version(fc); 8771fb69e78SMiklos Szeredi 878c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8790e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 880c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 881c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 882c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 883c79e322fSMiklos Szeredi 884c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 885c79e322fSMiklos Szeredi inarg.fh = ff->fh; 886c79e322fSMiklos Szeredi } 8877078187aSMiklos Szeredi args.in.h.opcode = FUSE_GETATTR; 8887078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 8897078187aSMiklos Szeredi args.in.numargs = 1; 8907078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 8917078187aSMiklos Szeredi args.in.args[0].value = &inarg; 8927078187aSMiklos Szeredi args.out.numargs = 1; 8937078187aSMiklos Szeredi args.out.args[0].size = sizeof(outarg); 8947078187aSMiklos Szeredi args.out.args[0].value = &outarg; 8957078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 896e5e5558eSMiklos Szeredi if (!err) { 897c79e322fSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 898e5e5558eSMiklos Szeredi make_bad_inode(inode); 899e5e5558eSMiklos Szeredi err = -EIO; 900e5e5558eSMiklos Szeredi } else { 901c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 902c79e322fSMiklos Szeredi attr_timeout(&outarg), 9031fb69e78SMiklos Szeredi attr_version); 9041fb69e78SMiklos Szeredi if (stat) 905c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 906e5e5558eSMiklos Szeredi } 907e5e5558eSMiklos Szeredi } 908e5e5558eSMiklos Szeredi return err; 909e5e5558eSMiklos Szeredi } 910e5e5558eSMiklos Szeredi 911bcb4be80SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct kstat *stat, 912bcb4be80SMiklos Szeredi struct file *file, bool *refreshed) 913bcb4be80SMiklos Szeredi { 914bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 915bcb4be80SMiklos Szeredi int err; 916bcb4be80SMiklos Szeredi bool r; 917bcb4be80SMiklos Szeredi 918126b9d43SMiklos Szeredi if (time_before64(fi->i_time, get_jiffies_64())) { 919bcb4be80SMiklos Szeredi r = true; 920bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 921bcb4be80SMiklos Szeredi } else { 922bcb4be80SMiklos Szeredi r = false; 923bcb4be80SMiklos Szeredi err = 0; 924bcb4be80SMiklos Szeredi if (stat) { 925bcb4be80SMiklos Szeredi generic_fillattr(inode, stat); 926bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 92745c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 928bcb4be80SMiklos Szeredi } 929bcb4be80SMiklos Szeredi } 930bcb4be80SMiklos Szeredi 931bcb4be80SMiklos Szeredi if (refreshed != NULL) 932bcb4be80SMiklos Szeredi *refreshed = r; 933bcb4be80SMiklos Szeredi 934bcb4be80SMiklos Szeredi return err; 935bcb4be80SMiklos Szeredi } 936bcb4be80SMiklos Szeredi 9373b463ae0SJohn Muir int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, 938451d0f59SJohn Muir u64 child_nodeid, struct qstr *name) 9393b463ae0SJohn Muir { 9403b463ae0SJohn Muir int err = -ENOTDIR; 9413b463ae0SJohn Muir struct inode *parent; 9423b463ae0SJohn Muir struct dentry *dir; 9433b463ae0SJohn Muir struct dentry *entry; 9443b463ae0SJohn Muir 9453b463ae0SJohn Muir parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); 9463b463ae0SJohn Muir if (!parent) 9473b463ae0SJohn Muir return -ENOENT; 9483b463ae0SJohn Muir 9495955102cSAl Viro inode_lock(parent); 9503b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 9513b463ae0SJohn Muir goto unlock; 9523b463ae0SJohn Muir 9533b463ae0SJohn Muir err = -ENOENT; 9543b463ae0SJohn Muir dir = d_find_alias(parent); 9553b463ae0SJohn Muir if (!dir) 9563b463ae0SJohn Muir goto unlock; 9573b463ae0SJohn Muir 9583b463ae0SJohn Muir entry = d_lookup(dir, name); 9593b463ae0SJohn Muir dput(dir); 9603b463ae0SJohn Muir if (!entry) 9613b463ae0SJohn Muir goto unlock; 9623b463ae0SJohn Muir 9633b463ae0SJohn Muir fuse_invalidate_attr(parent); 9643b463ae0SJohn Muir fuse_invalidate_entry(entry); 965451d0f59SJohn Muir 9662b0143b5SDavid Howells if (child_nodeid != 0 && d_really_is_positive(entry)) { 9675955102cSAl Viro inode_lock(d_inode(entry)); 9682b0143b5SDavid Howells if (get_node_id(d_inode(entry)) != child_nodeid) { 969451d0f59SJohn Muir err = -ENOENT; 970451d0f59SJohn Muir goto badentry; 971451d0f59SJohn Muir } 972451d0f59SJohn Muir if (d_mountpoint(entry)) { 973451d0f59SJohn Muir err = -EBUSY; 974451d0f59SJohn Muir goto badentry; 975451d0f59SJohn Muir } 976e36cb0b8SDavid Howells if (d_is_dir(entry)) { 977451d0f59SJohn Muir shrink_dcache_parent(entry); 978451d0f59SJohn Muir if (!simple_empty(entry)) { 979451d0f59SJohn Muir err = -ENOTEMPTY; 980451d0f59SJohn Muir goto badentry; 981451d0f59SJohn Muir } 9822b0143b5SDavid Howells d_inode(entry)->i_flags |= S_DEAD; 983451d0f59SJohn Muir } 984451d0f59SJohn Muir dont_mount(entry); 9852b0143b5SDavid Howells clear_nlink(d_inode(entry)); 9863b463ae0SJohn Muir err = 0; 987451d0f59SJohn Muir badentry: 9885955102cSAl Viro inode_unlock(d_inode(entry)); 989451d0f59SJohn Muir if (!err) 990451d0f59SJohn Muir d_delete(entry); 991451d0f59SJohn Muir } else { 992451d0f59SJohn Muir err = 0; 993451d0f59SJohn Muir } 994451d0f59SJohn Muir dput(entry); 9953b463ae0SJohn Muir 9963b463ae0SJohn Muir unlock: 9975955102cSAl Viro inode_unlock(parent); 9983b463ae0SJohn Muir iput(parent); 9993b463ae0SJohn Muir return err; 10003b463ae0SJohn Muir } 10013b463ae0SJohn Muir 100287729a55SMiklos Szeredi /* 100387729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1004c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 100587729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 100687729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 100787729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 100887729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 100987729a55SMiklos Szeredi * DoS against the requester. 101087729a55SMiklos Szeredi * 101187729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 101287729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 101387729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 101487729a55SMiklos Szeredi */ 1015c2132c1bSAnatol Pomozov int fuse_allow_current_process(struct fuse_conn *fc) 101687729a55SMiklos Szeredi { 1017c69e8d9cSDavid Howells const struct cred *cred; 1018c69e8d9cSDavid Howells 101987729a55SMiklos Szeredi if (fc->flags & FUSE_ALLOW_OTHER) 102087729a55SMiklos Szeredi return 1; 102187729a55SMiklos Szeredi 1022c2132c1bSAnatol Pomozov cred = current_cred(); 1023499dcf20SEric W. Biederman if (uid_eq(cred->euid, fc->user_id) && 1024499dcf20SEric W. Biederman uid_eq(cred->suid, fc->user_id) && 1025499dcf20SEric W. Biederman uid_eq(cred->uid, fc->user_id) && 1026499dcf20SEric W. Biederman gid_eq(cred->egid, fc->group_id) && 1027499dcf20SEric W. Biederman gid_eq(cred->sgid, fc->group_id) && 1028499dcf20SEric W. Biederman gid_eq(cred->gid, fc->group_id)) 1029c2132c1bSAnatol Pomozov return 1; 103087729a55SMiklos Szeredi 1031c2132c1bSAnatol Pomozov return 0; 103287729a55SMiklos Szeredi } 103387729a55SMiklos Szeredi 103431d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 103531d40d74SMiklos Szeredi { 103631d40d74SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 10377078187aSMiklos Szeredi FUSE_ARGS(args); 103831d40d74SMiklos Szeredi struct fuse_access_in inarg; 103931d40d74SMiklos Szeredi int err; 104031d40d74SMiklos Szeredi 1041698fa1d1SMiklos Szeredi BUG_ON(mask & MAY_NOT_BLOCK); 1042698fa1d1SMiklos Szeredi 104331d40d74SMiklos Szeredi if (fc->no_access) 104431d40d74SMiklos Szeredi return 0; 104531d40d74SMiklos Szeredi 104631d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1047e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 10487078187aSMiklos Szeredi args.in.h.opcode = FUSE_ACCESS; 10497078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 10507078187aSMiklos Szeredi args.in.numargs = 1; 10517078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 10527078187aSMiklos Szeredi args.in.args[0].value = &inarg; 10537078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 105431d40d74SMiklos Szeredi if (err == -ENOSYS) { 105531d40d74SMiklos Szeredi fc->no_access = 1; 105631d40d74SMiklos Szeredi err = 0; 105731d40d74SMiklos Szeredi } 105831d40d74SMiklos Szeredi return err; 105931d40d74SMiklos Szeredi } 106031d40d74SMiklos Szeredi 106110556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 106219690ddbSMiklos Szeredi { 106310556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 106419690ddbSMiklos Szeredi return -ECHILD; 106519690ddbSMiklos Szeredi 106619690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 106719690ddbSMiklos Szeredi } 106819690ddbSMiklos Szeredi 10696f9f1180SMiklos Szeredi /* 10706f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 10716f9f1180SMiklos Szeredi * 10726f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 10736f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 10746f9f1180SMiklos Szeredi * modell. 10756f9f1180SMiklos Szeredi * 10766f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 10776f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 10786f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 10796f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 10806f9f1180SMiklos Szeredi * locally based on file mode. 10816f9f1180SMiklos Szeredi */ 108210556cb2SAl Viro static int fuse_permission(struct inode *inode, int mask) 1083e5e5558eSMiklos Szeredi { 1084e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1085244f6385SMiklos Szeredi bool refreshed = false; 1086244f6385SMiklos Szeredi int err = 0; 1087e5e5558eSMiklos Szeredi 1088c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1089e5e5558eSMiklos Szeredi return -EACCES; 1090244f6385SMiklos Szeredi 1091244f6385SMiklos Szeredi /* 1092e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1093244f6385SMiklos Szeredi */ 1094e8e96157SMiklos Szeredi if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || 1095e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 109619690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 109719690ddbSMiklos Szeredi 1098126b9d43SMiklos Szeredi if (time_before64(fi->i_time, get_jiffies_64())) { 109919690ddbSMiklos Szeredi refreshed = true; 110019690ddbSMiklos Szeredi 110110556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1102244f6385SMiklos Szeredi if (err) 1103244f6385SMiklos Szeredi return err; 11041fb69e78SMiklos Szeredi } 110519690ddbSMiklos Szeredi } 1106244f6385SMiklos Szeredi 1107244f6385SMiklos Szeredi if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 11082830ba7fSAl Viro err = generic_permission(inode, mask); 11091e9a4ed9SMiklos Szeredi 11101e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 11111e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 11121e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1113244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 111410556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 11151e9a4ed9SMiklos Szeredi if (!err) 11162830ba7fSAl Viro err = generic_permission(inode, mask); 11171e9a4ed9SMiklos Szeredi } 11181e9a4ed9SMiklos Szeredi 11196f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 11206f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 11216f9f1180SMiklos Szeredi noticed immediately, only after the attribute 11226f9f1180SMiklos Szeredi timeout has expired */ 11239cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1124e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1125e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1126e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1127e8e96157SMiklos Szeredi if (refreshed) 1128e5e5558eSMiklos Szeredi return -EACCES; 112931d40d74SMiklos Szeredi 113010556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1131e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1132e8e96157SMiklos Szeredi return -EACCES; 1133e8e96157SMiklos Szeredi } 1134e5e5558eSMiklos Szeredi } 1135244f6385SMiklos Szeredi return err; 1136e5e5558eSMiklos Szeredi } 1137e5e5558eSMiklos Szeredi 1138e5e5558eSMiklos Szeredi static int parse_dirfile(char *buf, size_t nbytes, struct file *file, 11398d3af7f3SAl Viro struct dir_context *ctx) 1140e5e5558eSMiklos Szeredi { 1141e5e5558eSMiklos Szeredi while (nbytes >= FUSE_NAME_OFFSET) { 1142e5e5558eSMiklos Szeredi struct fuse_dirent *dirent = (struct fuse_dirent *) buf; 1143e5e5558eSMiklos Szeredi size_t reclen = FUSE_DIRENT_SIZE(dirent); 1144e5e5558eSMiklos Szeredi if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 1145e5e5558eSMiklos Szeredi return -EIO; 1146e5e5558eSMiklos Szeredi if (reclen > nbytes) 1147e5e5558eSMiklos Szeredi break; 1148efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1149efeb9e60SMiklos Szeredi return -EIO; 1150e5e5558eSMiklos Szeredi 11518d3af7f3SAl Viro if (!dir_emit(ctx, dirent->name, dirent->namelen, 11528d3af7f3SAl Viro dirent->ino, dirent->type)) 1153e5e5558eSMiklos Szeredi break; 1154e5e5558eSMiklos Szeredi 1155e5e5558eSMiklos Szeredi buf += reclen; 1156e5e5558eSMiklos Szeredi nbytes -= reclen; 11578d3af7f3SAl Viro ctx->pos = dirent->off; 1158e5e5558eSMiklos Szeredi } 1159e5e5558eSMiklos Szeredi 1160e5e5558eSMiklos Szeredi return 0; 1161e5e5558eSMiklos Szeredi } 1162e5e5558eSMiklos Szeredi 11630b05b183SAnand V. Avati static int fuse_direntplus_link(struct file *file, 11640b05b183SAnand V. Avati struct fuse_direntplus *direntplus, 11650b05b183SAnand V. Avati u64 attr_version) 11660b05b183SAnand V. Avati { 11670b05b183SAnand V. Avati struct fuse_entry_out *o = &direntplus->entry_out; 11680b05b183SAnand V. Avati struct fuse_dirent *dirent = &direntplus->dirent; 11690b05b183SAnand V. Avati struct dentry *parent = file->f_path.dentry; 11700b05b183SAnand V. Avati struct qstr name = QSTR_INIT(dirent->name, dirent->namelen); 11710b05b183SAnand V. Avati struct dentry *dentry; 11720b05b183SAnand V. Avati struct dentry *alias; 11732b0143b5SDavid Howells struct inode *dir = d_inode(parent); 11740b05b183SAnand V. Avati struct fuse_conn *fc; 11750b05b183SAnand V. Avati struct inode *inode; 1176d9b3dbdcSAl Viro DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); 11770b05b183SAnand V. Avati 11780b05b183SAnand V. Avati if (!o->nodeid) { 11790b05b183SAnand V. Avati /* 11800b05b183SAnand V. Avati * Unlike in the case of fuse_lookup, zero nodeid does not mean 11810b05b183SAnand V. Avati * ENOENT. Instead, it only means the userspace filesystem did 11820b05b183SAnand V. Avati * not want to return attributes/handle for this entry. 11830b05b183SAnand V. Avati * 11840b05b183SAnand V. Avati * So do nothing. 11850b05b183SAnand V. Avati */ 11860b05b183SAnand V. Avati return 0; 11870b05b183SAnand V. Avati } 11880b05b183SAnand V. Avati 11890b05b183SAnand V. Avati if (name.name[0] == '.') { 11900b05b183SAnand V. Avati /* 11910b05b183SAnand V. Avati * We could potentially refresh the attributes of the directory 11920b05b183SAnand V. Avati * and its parent? 11930b05b183SAnand V. Avati */ 11940b05b183SAnand V. Avati if (name.len == 1) 11950b05b183SAnand V. Avati return 0; 11960b05b183SAnand V. Avati if (name.name[1] == '.' && name.len == 2) 11970b05b183SAnand V. Avati return 0; 11980b05b183SAnand V. Avati } 1199a28ef45cSMiklos Szeredi 1200a28ef45cSMiklos Szeredi if (invalid_nodeid(o->nodeid)) 1201a28ef45cSMiklos Szeredi return -EIO; 1202a28ef45cSMiklos Szeredi if (!fuse_valid_type(o->attr.mode)) 1203a28ef45cSMiklos Szeredi return -EIO; 1204a28ef45cSMiklos Szeredi 12050b05b183SAnand V. Avati fc = get_fuse_conn(dir); 12060b05b183SAnand V. Avati 12070b05b183SAnand V. Avati name.hash = full_name_hash(name.name, name.len); 12080b05b183SAnand V. Avati dentry = d_lookup(parent, &name); 1209d9b3dbdcSAl Viro if (!dentry) { 1210d9b3dbdcSAl Viro retry: 1211d9b3dbdcSAl Viro dentry = d_alloc_parallel(parent, &name, &wq); 1212d9b3dbdcSAl Viro if (IS_ERR(dentry)) 1213d9b3dbdcSAl Viro return PTR_ERR(dentry); 1214d9b3dbdcSAl Viro } 1215d9b3dbdcSAl Viro if (!d_in_lookup(dentry)) { 1216d9b3dbdcSAl Viro struct fuse_inode *fi; 12172b0143b5SDavid Howells inode = d_inode(dentry); 1218d9b3dbdcSAl Viro if (!inode || 1219d9b3dbdcSAl Viro get_node_id(inode) != o->nodeid || 1220a28ef45cSMiklos Szeredi ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { 12215542aa2fSEric W. Biederman d_invalidate(dentry); 1222d9b3dbdcSAl Viro dput(dentry); 1223d9b3dbdcSAl Viro goto retry; 1224d9b3dbdcSAl Viro } 1225d9b3dbdcSAl Viro if (is_bad_inode(inode)) { 1226d9b3dbdcSAl Viro dput(dentry); 1227d9b3dbdcSAl Viro return -EIO; 1228d9b3dbdcSAl Viro } 1229d9b3dbdcSAl Viro 12300b05b183SAnand V. Avati fi = get_fuse_inode(inode); 12310b05b183SAnand V. Avati spin_lock(&fc->lock); 12320b05b183SAnand V. Avati fi->nlookup++; 12330b05b183SAnand V. Avati spin_unlock(&fc->lock); 12340b05b183SAnand V. Avati 1235fa2b7213SMiklos Szeredi fuse_change_attributes(inode, &o->attr, 1236fa2b7213SMiklos Szeredi entry_attr_timeout(o), 1237fa2b7213SMiklos Szeredi attr_version); 12380b05b183SAnand V. Avati /* 1239d9b3dbdcSAl Viro * The other branch comes via fuse_iget() 12400b05b183SAnand V. Avati * which bumps nlookup inside 12410b05b183SAnand V. Avati */ 1242d9b3dbdcSAl Viro } else { 12430b05b183SAnand V. Avati inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, 1244d9b3dbdcSAl Viro &o->attr, entry_attr_timeout(o), 1245d9b3dbdcSAl Viro attr_version); 12460b05b183SAnand V. Avati if (!inode) 1247d9b3dbdcSAl Viro inode = ERR_PTR(-ENOMEM); 12480b05b183SAnand V. Avati 124941d28bcaSAl Viro alias = d_splice_alias(inode, dentry); 1250d9b3dbdcSAl Viro d_lookup_done(dentry); 12510b05b183SAnand V. Avati if (alias) { 12520b05b183SAnand V. Avati dput(dentry); 12530b05b183SAnand V. Avati dentry = alias; 12540b05b183SAnand V. Avati } 1255d9b3dbdcSAl Viro if (IS_ERR(dentry)) 1256d9b3dbdcSAl Viro return PTR_ERR(dentry); 1257d9b3dbdcSAl Viro } 12586314efeeSMiklos Szeredi if (fc->readdirplus_auto) 12596314efeeSMiklos Szeredi set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); 12600b05b183SAnand V. Avati fuse_change_entry_timeout(dentry, o); 12610b05b183SAnand V. Avati 12620b05b183SAnand V. Avati dput(dentry); 1263d9b3dbdcSAl Viro return 0; 12640b05b183SAnand V. Avati } 12650b05b183SAnand V. Avati 12660b05b183SAnand V. Avati static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, 12678d3af7f3SAl Viro struct dir_context *ctx, u64 attr_version) 12680b05b183SAnand V. Avati { 12690b05b183SAnand V. Avati struct fuse_direntplus *direntplus; 12700b05b183SAnand V. Avati struct fuse_dirent *dirent; 12710b05b183SAnand V. Avati size_t reclen; 12720b05b183SAnand V. Avati int over = 0; 12730b05b183SAnand V. Avati int ret; 12740b05b183SAnand V. Avati 12750b05b183SAnand V. Avati while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) { 12760b05b183SAnand V. Avati direntplus = (struct fuse_direntplus *) buf; 12770b05b183SAnand V. Avati dirent = &direntplus->dirent; 12780b05b183SAnand V. Avati reclen = FUSE_DIRENTPLUS_SIZE(direntplus); 12790b05b183SAnand V. Avati 12800b05b183SAnand V. Avati if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) 12810b05b183SAnand V. Avati return -EIO; 12820b05b183SAnand V. Avati if (reclen > nbytes) 12830b05b183SAnand V. Avati break; 1284efeb9e60SMiklos Szeredi if (memchr(dirent->name, '/', dirent->namelen) != NULL) 1285efeb9e60SMiklos Szeredi return -EIO; 12860b05b183SAnand V. Avati 12870b05b183SAnand V. Avati if (!over) { 12880b05b183SAnand V. Avati /* We fill entries into dstbuf only as much as 12890b05b183SAnand V. Avati it can hold. But we still continue iterating 12900b05b183SAnand V. Avati over remaining entries to link them. If not, 12910b05b183SAnand V. Avati we need to send a FORGET for each of those 12920b05b183SAnand V. Avati which we did not link. 12930b05b183SAnand V. Avati */ 12948d3af7f3SAl Viro over = !dir_emit(ctx, dirent->name, dirent->namelen, 12958d3af7f3SAl Viro dirent->ino, dirent->type); 12968d3af7f3SAl Viro ctx->pos = dirent->off; 12970b05b183SAnand V. Avati } 12980b05b183SAnand V. Avati 12990b05b183SAnand V. Avati buf += reclen; 13000b05b183SAnand V. Avati nbytes -= reclen; 13010b05b183SAnand V. Avati 13020b05b183SAnand V. Avati ret = fuse_direntplus_link(file, direntplus, attr_version); 13030b05b183SAnand V. Avati if (ret) 13040b05b183SAnand V. Avati fuse_force_forget(file, direntplus->entry_out.nodeid); 13050b05b183SAnand V. Avati } 13060b05b183SAnand V. Avati 13070b05b183SAnand V. Avati return 0; 13080b05b183SAnand V. Avati } 13090b05b183SAnand V. Avati 13108d3af7f3SAl Viro static int fuse_readdir(struct file *file, struct dir_context *ctx) 1311e5e5558eSMiklos Szeredi { 13124582a4abSFeng Shuo int plus, err; 131304730fefSMiklos Szeredi size_t nbytes; 131404730fefSMiklos Szeredi struct page *page; 1315496ad9aaSAl Viro struct inode *inode = file_inode(file); 131604730fefSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1317248d86e8SMiklos Szeredi struct fuse_req *req; 13180b05b183SAnand V. Avati u64 attr_version = 0; 1319248d86e8SMiklos Szeredi 1320248d86e8SMiklos Szeredi if (is_bad_inode(inode)) 1321248d86e8SMiklos Szeredi return -EIO; 1322248d86e8SMiklos Szeredi 1323b111c8c0SMaxim Patlasov req = fuse_get_req(fc, 1); 1324ce1d5a49SMiklos Szeredi if (IS_ERR(req)) 1325ce1d5a49SMiklos Szeredi return PTR_ERR(req); 1326e5e5558eSMiklos Szeredi 132704730fefSMiklos Szeredi page = alloc_page(GFP_KERNEL); 132804730fefSMiklos Szeredi if (!page) { 132904730fefSMiklos Szeredi fuse_put_request(fc, req); 1330e5e5558eSMiklos Szeredi return -ENOMEM; 133104730fefSMiklos Szeredi } 13324582a4abSFeng Shuo 13338d3af7f3SAl Viro plus = fuse_use_readdirplus(inode, ctx); 1334f4975c67SMiklos Szeredi req->out.argpages = 1; 133504730fefSMiklos Szeredi req->num_pages = 1; 133604730fefSMiklos Szeredi req->pages[0] = page; 133785f40aecSMaxim Patlasov req->page_descs[0].length = PAGE_SIZE; 13384582a4abSFeng Shuo if (plus) { 13390b05b183SAnand V. Avati attr_version = fuse_get_attr_version(fc); 13408d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 13410b05b183SAnand V. Avati FUSE_READDIRPLUS); 13420b05b183SAnand V. Avati } else { 13438d3af7f3SAl Viro fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, 13440b05b183SAnand V. Avati FUSE_READDIR); 13450b05b183SAnand V. Avati } 1346*5c672ab3SMiklos Szeredi fuse_lock_inode(inode); 1347b93f858aSTejun Heo fuse_request_send(fc, req); 1348*5c672ab3SMiklos Szeredi fuse_unlock_inode(inode); 1349361b1eb5SMiklos Szeredi nbytes = req->out.args[0].size; 135004730fefSMiklos Szeredi err = req->out.h.error; 135104730fefSMiklos Szeredi fuse_put_request(fc, req); 13520b05b183SAnand V. Avati if (!err) { 13534582a4abSFeng Shuo if (plus) { 13540b05b183SAnand V. Avati err = parse_dirplusfile(page_address(page), nbytes, 13558d3af7f3SAl Viro file, ctx, 13560b05b183SAnand V. Avati attr_version); 13570b05b183SAnand V. Avati } else { 13580b05b183SAnand V. Avati err = parse_dirfile(page_address(page), nbytes, file, 13598d3af7f3SAl Viro ctx); 13600b05b183SAnand V. Avati } 13610b05b183SAnand V. Avati } 1362e5e5558eSMiklos Szeredi 136304730fefSMiklos Szeredi __free_page(page); 1364451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 136504730fefSMiklos Szeredi return err; 1366e5e5558eSMiklos Szeredi } 1367e5e5558eSMiklos Szeredi 13686b255391SAl Viro static const char *fuse_get_link(struct dentry *dentry, 1369fceef393SAl Viro struct inode *inode, 1370fceef393SAl Viro struct delayed_call *done) 1371e5e5558eSMiklos Szeredi { 1372e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 13737078187aSMiklos Szeredi FUSE_ARGS(args); 1374e5e5558eSMiklos Szeredi char *link; 13757078187aSMiklos Szeredi ssize_t ret; 1376e5e5558eSMiklos Szeredi 13776b255391SAl Viro if (!dentry) 13786b255391SAl Viro return ERR_PTR(-ECHILD); 13796b255391SAl Viro 1380cd3417c8SAl Viro link = kmalloc(PAGE_SIZE, GFP_KERNEL); 13817078187aSMiklos Szeredi if (!link) 13827078187aSMiklos Szeredi return ERR_PTR(-ENOMEM); 13837078187aSMiklos Szeredi 13847078187aSMiklos Szeredi args.in.h.opcode = FUSE_READLINK; 13857078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 13867078187aSMiklos Szeredi args.out.argvar = 1; 13877078187aSMiklos Szeredi args.out.numargs = 1; 13887078187aSMiklos Szeredi args.out.args[0].size = PAGE_SIZE - 1; 13897078187aSMiklos Szeredi args.out.args[0].value = link; 13907078187aSMiklos Szeredi ret = fuse_simple_request(fc, &args); 13917078187aSMiklos Szeredi if (ret < 0) { 1392cd3417c8SAl Viro kfree(link); 13937078187aSMiklos Szeredi link = ERR_PTR(ret); 13947078187aSMiklos Szeredi } else { 13957078187aSMiklos Szeredi link[ret] = '\0'; 1396fceef393SAl Viro set_delayed_call(done, kfree_link, link); 13977078187aSMiklos Szeredi } 1398451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 1399e5e5558eSMiklos Szeredi return link; 1400e5e5558eSMiklos Szeredi } 1401e5e5558eSMiklos Szeredi 1402e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1403e5e5558eSMiklos Szeredi { 140491fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1405e5e5558eSMiklos Szeredi } 1406e5e5558eSMiklos Szeredi 1407e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1408e5e5558eSMiklos Szeredi { 14098b0797a4SMiklos Szeredi fuse_release_common(file, FUSE_RELEASEDIR); 14108b0797a4SMiklos Szeredi 14118b0797a4SMiklos Szeredi return 0; 1412e5e5558eSMiklos Szeredi } 1413e5e5558eSMiklos Szeredi 141402c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 141502c24a82SJosef Bacik int datasync) 141682547981SMiklos Szeredi { 141702c24a82SJosef Bacik return fuse_fsync_common(file, start, end, datasync, 1); 141882547981SMiklos Szeredi } 141982547981SMiklos Szeredi 1420b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1421b18da0c5SMiklos Szeredi unsigned long arg) 1422b18da0c5SMiklos Szeredi { 1423b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1424b18da0c5SMiklos Szeredi 1425b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1426b18da0c5SMiklos Szeredi if (fc->minor < 18) 1427b18da0c5SMiklos Szeredi return -ENOTTY; 1428b18da0c5SMiklos Szeredi 1429b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1430b18da0c5SMiklos Szeredi } 1431b18da0c5SMiklos Szeredi 1432b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1433b18da0c5SMiklos Szeredi unsigned long arg) 1434b18da0c5SMiklos Szeredi { 1435b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1436b18da0c5SMiklos Szeredi 1437b18da0c5SMiklos Szeredi if (fc->minor < 18) 1438b18da0c5SMiklos Szeredi return -ENOTTY; 1439b18da0c5SMiklos Szeredi 1440b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1441b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1442b18da0c5SMiklos Szeredi } 1443b18da0c5SMiklos Szeredi 1444b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime) 144517637cbaSMiklos Szeredi { 144617637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 144717637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 144817637cbaSMiklos Szeredi return true; 144917637cbaSMiklos Szeredi 1450b0aa7606SMaxim Patlasov /* Or if kernel i_mtime is the official one */ 1451b0aa7606SMaxim Patlasov if (trust_local_mtime) 1452b0aa7606SMaxim Patlasov return true; 1453b0aa7606SMaxim Patlasov 145417637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 145517637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 145617637cbaSMiklos Szeredi return false; 145717637cbaSMiklos Szeredi 145817637cbaSMiklos Szeredi /* In all other cases update */ 145917637cbaSMiklos Szeredi return true; 146017637cbaSMiklos Szeredi } 146117637cbaSMiklos Szeredi 1462b0aa7606SMaxim Patlasov static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg, 14633ad22c62SMaxim Patlasov bool trust_local_cmtime) 14649e6268dbSMiklos Szeredi { 14659e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 14669e6268dbSMiklos Szeredi 14679e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1468befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 14699e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 1470499dcf20SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid); 14719e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 1472499dcf20SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid); 14739e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1474befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 147517637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 147617637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1477befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 147817637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 147917637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 148017637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 148117637cbaSMiklos Szeredi } 14823ad22c62SMaxim Patlasov if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) { 148317637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1484befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 148517637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 14863ad22c62SMaxim Patlasov if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime) 148717637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 14889e6268dbSMiklos Szeredi } 14893ad22c62SMaxim Patlasov if ((ivalid & ATTR_CTIME) && trust_local_cmtime) { 14903ad22c62SMaxim Patlasov arg->valid |= FATTR_CTIME; 14913ad22c62SMaxim Patlasov arg->ctime = iattr->ia_ctime.tv_sec; 14923ad22c62SMaxim Patlasov arg->ctimensec = iattr->ia_ctime.tv_nsec; 14933ad22c62SMaxim Patlasov } 14949e6268dbSMiklos Szeredi } 14959e6268dbSMiklos Szeredi 14966f9f1180SMiklos Szeredi /* 14973be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 14983be5a52bSMiklos Szeredi * 14993be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 15003be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 15013be5a52bSMiklos Szeredi */ 15023be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 15033be5a52bSMiklos Szeredi { 15043be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 15053be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15063be5a52bSMiklos Szeredi 15075955102cSAl Viro BUG_ON(!inode_is_locked(inode)); 15083be5a52bSMiklos Szeredi 15093be5a52bSMiklos Szeredi spin_lock(&fc->lock); 15103be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 15113be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 15123be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 15133be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 15143be5a52bSMiklos Szeredi } 15153be5a52bSMiklos Szeredi 15163be5a52bSMiklos Szeredi /* 15173be5a52bSMiklos Szeredi * Allow writepages on inode 15183be5a52bSMiklos Szeredi * 15193be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 15203be5a52bSMiklos Szeredi * writepages. 15213be5a52bSMiklos Szeredi */ 15223be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 15233be5a52bSMiklos Szeredi { 15243be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 15253be5a52bSMiklos Szeredi 15263be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 15273be5a52bSMiklos Szeredi fi->writectr = 0; 15283be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 15293be5a52bSMiklos Szeredi } 15303be5a52bSMiklos Szeredi 15313be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 15323be5a52bSMiklos Szeredi { 15333be5a52bSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 15343be5a52bSMiklos Szeredi 15353be5a52bSMiklos Szeredi spin_lock(&fc->lock); 15363be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 15373be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 15383be5a52bSMiklos Szeredi } 15393be5a52bSMiklos Szeredi 15407078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, 1541b0aa7606SMaxim Patlasov struct inode *inode, 1542b0aa7606SMaxim Patlasov struct fuse_setattr_in *inarg_p, 1543b0aa7606SMaxim Patlasov struct fuse_attr_out *outarg_p) 1544b0aa7606SMaxim Patlasov { 15457078187aSMiklos Szeredi args->in.h.opcode = FUSE_SETATTR; 15467078187aSMiklos Szeredi args->in.h.nodeid = get_node_id(inode); 15477078187aSMiklos Szeredi args->in.numargs = 1; 15487078187aSMiklos Szeredi args->in.args[0].size = sizeof(*inarg_p); 15497078187aSMiklos Szeredi args->in.args[0].value = inarg_p; 15507078187aSMiklos Szeredi args->out.numargs = 1; 15517078187aSMiklos Szeredi args->out.args[0].size = sizeof(*outarg_p); 15527078187aSMiklos Szeredi args->out.args[0].value = outarg_p; 1553b0aa7606SMaxim Patlasov } 1554b0aa7606SMaxim Patlasov 1555b0aa7606SMaxim Patlasov /* 1556b0aa7606SMaxim Patlasov * Flush inode->i_mtime to the server 1557b0aa7606SMaxim Patlasov */ 1558ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff) 1559b0aa7606SMaxim Patlasov { 1560b0aa7606SMaxim Patlasov struct fuse_conn *fc = get_fuse_conn(inode); 15617078187aSMiklos Szeredi FUSE_ARGS(args); 1562b0aa7606SMaxim Patlasov struct fuse_setattr_in inarg; 1563b0aa7606SMaxim Patlasov struct fuse_attr_out outarg; 1564b0aa7606SMaxim Patlasov 1565b0aa7606SMaxim Patlasov memset(&inarg, 0, sizeof(inarg)); 1566b0aa7606SMaxim Patlasov memset(&outarg, 0, sizeof(outarg)); 1567b0aa7606SMaxim Patlasov 1568ab9e13f7SMaxim Patlasov inarg.valid = FATTR_MTIME; 1569b0aa7606SMaxim Patlasov inarg.mtime = inode->i_mtime.tv_sec; 1570b0aa7606SMaxim Patlasov inarg.mtimensec = inode->i_mtime.tv_nsec; 1571ab9e13f7SMaxim Patlasov if (fc->minor >= 23) { 1572ab9e13f7SMaxim Patlasov inarg.valid |= FATTR_CTIME; 1573ab9e13f7SMaxim Patlasov inarg.ctime = inode->i_ctime.tv_sec; 1574ab9e13f7SMaxim Patlasov inarg.ctimensec = inode->i_ctime.tv_nsec; 1575ab9e13f7SMaxim Patlasov } 15761e18bda8SMiklos Szeredi if (ff) { 15771e18bda8SMiklos Szeredi inarg.valid |= FATTR_FH; 15781e18bda8SMiklos Szeredi inarg.fh = ff->fh; 15791e18bda8SMiklos Szeredi } 15807078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 1581b0aa7606SMaxim Patlasov 15827078187aSMiklos Szeredi return fuse_simple_request(fc, &args); 1583b0aa7606SMaxim Patlasov } 1584b0aa7606SMaxim Patlasov 15853be5a52bSMiklos Szeredi /* 15866f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 15876f9f1180SMiklos Szeredi * 15886f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 15896f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 15909ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 15919ffbb916SMiklos Szeredi * and the actual truncation by hand. 15926f9f1180SMiklos Szeredi */ 1593efb9fa9eSMaxim Patlasov int fuse_do_setattr(struct inode *inode, struct iattr *attr, 159449d4914fSMiklos Szeredi struct file *file) 15959e6268dbSMiklos Szeredi { 15969e6268dbSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 159706a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 15987078187aSMiklos Szeredi FUSE_ARGS(args); 15999e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 16009e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 16013be5a52bSMiklos Szeredi bool is_truncate = false; 16028373200bSPavel Emelyanov bool is_wb = fc->writeback_cache; 16033be5a52bSMiklos Szeredi loff_t oldsize; 16049e6268dbSMiklos Szeredi int err; 16053ad22c62SMaxim Patlasov bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode); 16069e6268dbSMiklos Szeredi 1607db78b877SChristoph Hellwig if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 1608db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1609db78b877SChristoph Hellwig 16101e9a4ed9SMiklos Szeredi err = inode_change_ok(inode, attr); 16111e9a4ed9SMiklos Szeredi if (err) 16121e9a4ed9SMiklos Szeredi return err; 16131e9a4ed9SMiklos Szeredi 16148d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 16158d56adddSMiklos Szeredi if (fc->atomic_o_trunc) 16166ff958edSMiklos Szeredi return 0; 16178d56adddSMiklos Szeredi file = NULL; 16188d56adddSMiklos Szeredi } 16196ff958edSMiklos Szeredi 16202c27c65eSChristoph Hellwig if (attr->ia_valid & ATTR_SIZE) 16213be5a52bSMiklos Szeredi is_truncate = true; 16229e6268dbSMiklos Szeredi 162306a7c3c2SMaxim Patlasov if (is_truncate) { 16243be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 162506a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 16263ad22c62SMaxim Patlasov if (trust_local_cmtime && attr->ia_size != inode->i_size) 16273ad22c62SMaxim Patlasov attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; 162806a7c3c2SMaxim Patlasov } 16293be5a52bSMiklos Szeredi 16309e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 16310e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 16323ad22c62SMaxim Patlasov iattr_to_fattr(attr, &inarg, trust_local_cmtime); 163349d4914fSMiklos Szeredi if (file) { 163449d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 163549d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 163649d4914fSMiklos Szeredi inarg.fh = ff->fh; 163749d4914fSMiklos Szeredi } 1638f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1639f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1640f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1641f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 1642f3332114SMiklos Szeredi } 16437078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 16447078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 1645e00d2c2dSMiklos Szeredi if (err) { 1646e00d2c2dSMiklos Szeredi if (err == -EINTR) 1647e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 16483be5a52bSMiklos Szeredi goto error; 1649e00d2c2dSMiklos Szeredi } 1650e00d2c2dSMiklos Szeredi 16519e6268dbSMiklos Szeredi if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { 16529e6268dbSMiklos Szeredi make_bad_inode(inode); 16533be5a52bSMiklos Szeredi err = -EIO; 16543be5a52bSMiklos Szeredi goto error; 16559e6268dbSMiklos Szeredi } 16569e6268dbSMiklos Szeredi 16573be5a52bSMiklos Szeredi spin_lock(&fc->lock); 1658b0aa7606SMaxim Patlasov /* the kernel maintains i_mtime locally */ 16593ad22c62SMaxim Patlasov if (trust_local_cmtime) { 16603ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_MTIME) 1661b0aa7606SMaxim Patlasov inode->i_mtime = attr->ia_mtime; 16623ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_CTIME) 16633ad22c62SMaxim Patlasov inode->i_ctime = attr->ia_ctime; 16641e18bda8SMiklos Szeredi /* FIXME: clear I_DIRTY_SYNC? */ 1665b0aa7606SMaxim Patlasov } 1666b0aa7606SMaxim Patlasov 16673be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 16683be5a52bSMiklos Szeredi attr_timeout(&outarg)); 16693be5a52bSMiklos Szeredi oldsize = inode->i_size; 16708373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 16718373200bSPavel Emelyanov if (!is_wb || is_truncate || !S_ISREG(inode->i_mode)) 16723be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 16733be5a52bSMiklos Szeredi 16743be5a52bSMiklos Szeredi if (is_truncate) { 16753be5a52bSMiklos Szeredi /* NOTE: this may release/reacquire fc->lock */ 16763be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 16773be5a52bSMiklos Szeredi } 16783be5a52bSMiklos Szeredi spin_unlock(&fc->lock); 16793be5a52bSMiklos Szeredi 16803be5a52bSMiklos Szeredi /* 16813be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 16823be5a52bSMiklos Szeredi * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. 16833be5a52bSMiklos Szeredi */ 16848373200bSPavel Emelyanov if ((is_truncate || !is_wb) && 16858373200bSPavel Emelyanov S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 16867caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 16873be5a52bSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 16883be5a52bSMiklos Szeredi } 16893be5a52bSMiklos Szeredi 169006a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 1691e00d2c2dSMiklos Szeredi return 0; 16923be5a52bSMiklos Szeredi 16933be5a52bSMiklos Szeredi error: 16943be5a52bSMiklos Szeredi if (is_truncate) 16953be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 16963be5a52bSMiklos Szeredi 169706a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 16983be5a52bSMiklos Szeredi return err; 16999e6268dbSMiklos Szeredi } 17009e6268dbSMiklos Szeredi 170149d4914fSMiklos Szeredi static int fuse_setattr(struct dentry *entry, struct iattr *attr) 170249d4914fSMiklos Szeredi { 17032b0143b5SDavid Howells struct inode *inode = d_inode(entry); 1704efb9fa9eSMaxim Patlasov 1705efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1706efb9fa9eSMaxim Patlasov return -EACCES; 1707efb9fa9eSMaxim Patlasov 170849d4914fSMiklos Szeredi if (attr->ia_valid & ATTR_FILE) 1709efb9fa9eSMaxim Patlasov return fuse_do_setattr(inode, attr, attr->ia_file); 171049d4914fSMiklos Szeredi else 1711efb9fa9eSMaxim Patlasov return fuse_do_setattr(inode, attr, NULL); 171249d4914fSMiklos Szeredi } 171349d4914fSMiklos Szeredi 1714e5e5558eSMiklos Szeredi static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, 1715e5e5558eSMiklos Szeredi struct kstat *stat) 1716e5e5558eSMiklos Szeredi { 17172b0143b5SDavid Howells struct inode *inode = d_inode(entry); 1718244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1719244f6385SMiklos Szeredi 1720c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1721244f6385SMiklos Szeredi return -EACCES; 1722244f6385SMiklos Szeredi 1723bcb4be80SMiklos Szeredi return fuse_update_attributes(inode, stat, NULL, NULL); 1724e5e5558eSMiklos Szeredi } 1725e5e5558eSMiklos Szeredi 17263767e255SAl Viro static int fuse_setxattr(struct dentry *unused, struct inode *inode, 17273767e255SAl Viro const char *name, const void *value, 17283767e255SAl Viro size_t size, int flags) 172992a8780eSMiklos Szeredi { 173092a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 17317078187aSMiklos Szeredi FUSE_ARGS(args); 173292a8780eSMiklos Szeredi struct fuse_setxattr_in inarg; 173392a8780eSMiklos Szeredi int err; 173492a8780eSMiklos Szeredi 173592a8780eSMiklos Szeredi if (fc->no_setxattr) 173692a8780eSMiklos Szeredi return -EOPNOTSUPP; 173792a8780eSMiklos Szeredi 173892a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 173992a8780eSMiklos Szeredi inarg.size = size; 174092a8780eSMiklos Szeredi inarg.flags = flags; 17417078187aSMiklos Szeredi args.in.h.opcode = FUSE_SETXATTR; 17427078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 17437078187aSMiklos Szeredi args.in.numargs = 3; 17447078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 17457078187aSMiklos Szeredi args.in.args[0].value = &inarg; 17467078187aSMiklos Szeredi args.in.args[1].size = strlen(name) + 1; 17477078187aSMiklos Szeredi args.in.args[1].value = name; 17487078187aSMiklos Szeredi args.in.args[2].size = size; 17497078187aSMiklos Szeredi args.in.args[2].value = value; 17507078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 175192a8780eSMiklos Szeredi if (err == -ENOSYS) { 175292a8780eSMiklos Szeredi fc->no_setxattr = 1; 175392a8780eSMiklos Szeredi err = -EOPNOTSUPP; 175492a8780eSMiklos Szeredi } 175531f3267bSMaxim Patlasov if (!err) { 1756d331a415SAnand Avati fuse_invalidate_attr(inode); 175731f3267bSMaxim Patlasov fuse_update_ctime(inode); 175831f3267bSMaxim Patlasov } 175992a8780eSMiklos Szeredi return err; 176092a8780eSMiklos Szeredi } 176192a8780eSMiklos Szeredi 1762ce23e640SAl Viro static ssize_t fuse_getxattr(struct dentry *entry, struct inode *inode, 1763ce23e640SAl Viro const char *name, void *value, size_t size) 176492a8780eSMiklos Szeredi { 176592a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 17667078187aSMiklos Szeredi FUSE_ARGS(args); 176792a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 176892a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 176992a8780eSMiklos Szeredi ssize_t ret; 177092a8780eSMiklos Szeredi 177192a8780eSMiklos Szeredi if (fc->no_getxattr) 177292a8780eSMiklos Szeredi return -EOPNOTSUPP; 177392a8780eSMiklos Szeredi 177492a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 177592a8780eSMiklos Szeredi inarg.size = size; 17767078187aSMiklos Szeredi args.in.h.opcode = FUSE_GETXATTR; 17777078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 17787078187aSMiklos Szeredi args.in.numargs = 2; 17797078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 17807078187aSMiklos Szeredi args.in.args[0].value = &inarg; 17817078187aSMiklos Szeredi args.in.args[1].size = strlen(name) + 1; 17827078187aSMiklos Szeredi args.in.args[1].value = name; 178392a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 17847078187aSMiklos Szeredi args.out.numargs = 1; 178592a8780eSMiklos Szeredi if (size) { 17867078187aSMiklos Szeredi args.out.argvar = 1; 17877078187aSMiklos Szeredi args.out.args[0].size = size; 17887078187aSMiklos Szeredi args.out.args[0].value = value; 178992a8780eSMiklos Szeredi } else { 17907078187aSMiklos Szeredi args.out.args[0].size = sizeof(outarg); 17917078187aSMiklos Szeredi args.out.args[0].value = &outarg; 179292a8780eSMiklos Szeredi } 17937078187aSMiklos Szeredi ret = fuse_simple_request(fc, &args); 17947078187aSMiklos Szeredi if (!ret && !size) 17957078187aSMiklos Szeredi ret = outarg.size; 179692a8780eSMiklos Szeredi if (ret == -ENOSYS) { 179792a8780eSMiklos Szeredi fc->no_getxattr = 1; 179892a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 179992a8780eSMiklos Szeredi } 180092a8780eSMiklos Szeredi return ret; 180192a8780eSMiklos Szeredi } 180292a8780eSMiklos Szeredi 180392a8780eSMiklos Szeredi static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) 180492a8780eSMiklos Szeredi { 18052b0143b5SDavid Howells struct inode *inode = d_inode(entry); 180692a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 18077078187aSMiklos Szeredi FUSE_ARGS(args); 180892a8780eSMiklos Szeredi struct fuse_getxattr_in inarg; 180992a8780eSMiklos Szeredi struct fuse_getxattr_out outarg; 181092a8780eSMiklos Szeredi ssize_t ret; 181192a8780eSMiklos Szeredi 1812c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1813e57ac683SMiklos Szeredi return -EACCES; 1814e57ac683SMiklos Szeredi 181592a8780eSMiklos Szeredi if (fc->no_listxattr) 181692a8780eSMiklos Szeredi return -EOPNOTSUPP; 181792a8780eSMiklos Szeredi 181892a8780eSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 181992a8780eSMiklos Szeredi inarg.size = size; 18207078187aSMiklos Szeredi args.in.h.opcode = FUSE_LISTXATTR; 18217078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 18227078187aSMiklos Szeredi args.in.numargs = 1; 18237078187aSMiklos Szeredi args.in.args[0].size = sizeof(inarg); 18247078187aSMiklos Szeredi args.in.args[0].value = &inarg; 182592a8780eSMiklos Szeredi /* This is really two different operations rolled into one */ 18267078187aSMiklos Szeredi args.out.numargs = 1; 182792a8780eSMiklos Szeredi if (size) { 18287078187aSMiklos Szeredi args.out.argvar = 1; 18297078187aSMiklos Szeredi args.out.args[0].size = size; 18307078187aSMiklos Szeredi args.out.args[0].value = list; 183192a8780eSMiklos Szeredi } else { 18327078187aSMiklos Szeredi args.out.args[0].size = sizeof(outarg); 18337078187aSMiklos Szeredi args.out.args[0].value = &outarg; 183492a8780eSMiklos Szeredi } 18357078187aSMiklos Szeredi ret = fuse_simple_request(fc, &args); 18367078187aSMiklos Szeredi if (!ret && !size) 18377078187aSMiklos Szeredi ret = outarg.size; 183892a8780eSMiklos Szeredi if (ret == -ENOSYS) { 183992a8780eSMiklos Szeredi fc->no_listxattr = 1; 184092a8780eSMiklos Szeredi ret = -EOPNOTSUPP; 184192a8780eSMiklos Szeredi } 184292a8780eSMiklos Szeredi return ret; 184392a8780eSMiklos Szeredi } 184492a8780eSMiklos Szeredi 184592a8780eSMiklos Szeredi static int fuse_removexattr(struct dentry *entry, const char *name) 184692a8780eSMiklos Szeredi { 18472b0143b5SDavid Howells struct inode *inode = d_inode(entry); 184892a8780eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 18497078187aSMiklos Szeredi FUSE_ARGS(args); 185092a8780eSMiklos Szeredi int err; 185192a8780eSMiklos Szeredi 185292a8780eSMiklos Szeredi if (fc->no_removexattr) 185392a8780eSMiklos Szeredi return -EOPNOTSUPP; 185492a8780eSMiklos Szeredi 18557078187aSMiklos Szeredi args.in.h.opcode = FUSE_REMOVEXATTR; 18567078187aSMiklos Szeredi args.in.h.nodeid = get_node_id(inode); 18577078187aSMiklos Szeredi args.in.numargs = 1; 18587078187aSMiklos Szeredi args.in.args[0].size = strlen(name) + 1; 18597078187aSMiklos Szeredi args.in.args[0].value = name; 18607078187aSMiklos Szeredi err = fuse_simple_request(fc, &args); 186192a8780eSMiklos Szeredi if (err == -ENOSYS) { 186292a8780eSMiklos Szeredi fc->no_removexattr = 1; 186392a8780eSMiklos Szeredi err = -EOPNOTSUPP; 186492a8780eSMiklos Szeredi } 186531f3267bSMaxim Patlasov if (!err) { 1866d331a415SAnand Avati fuse_invalidate_attr(inode); 186731f3267bSMaxim Patlasov fuse_update_ctime(inode); 186831f3267bSMaxim Patlasov } 186992a8780eSMiklos Szeredi return err; 187092a8780eSMiklos Szeredi } 187192a8780eSMiklos Szeredi 1872754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1873e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 18749e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 18759e6268dbSMiklos Szeredi .symlink = fuse_symlink, 18769e6268dbSMiklos Szeredi .unlink = fuse_unlink, 18779e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 18781560c974SMiklos Szeredi .rename2 = fuse_rename2, 18799e6268dbSMiklos Szeredi .link = fuse_link, 18809e6268dbSMiklos Szeredi .setattr = fuse_setattr, 18819e6268dbSMiklos Szeredi .create = fuse_create, 1882c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 18839e6268dbSMiklos Szeredi .mknod = fuse_mknod, 1884e5e5558eSMiklos Szeredi .permission = fuse_permission, 1885e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 188692a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 188792a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 188892a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 188992a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1890e5e5558eSMiklos Szeredi }; 1891e5e5558eSMiklos Szeredi 18924b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 1893b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 1894e5e5558eSMiklos Szeredi .read = generic_read_dir, 1895d9b3dbdcSAl Viro .iterate_shared = fuse_readdir, 1896e5e5558eSMiklos Szeredi .open = fuse_dir_open, 1897e5e5558eSMiklos Szeredi .release = fuse_dir_release, 189882547981SMiklos Szeredi .fsync = fuse_dir_fsync, 1899b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 1900b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 1901e5e5558eSMiklos Szeredi }; 1902e5e5558eSMiklos Szeredi 1903754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 19049e6268dbSMiklos Szeredi .setattr = fuse_setattr, 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 1913754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 19149e6268dbSMiklos Szeredi .setattr = fuse_setattr, 19156b255391SAl Viro .get_link = fuse_get_link, 1916e5e5558eSMiklos Szeredi .readlink = generic_readlink, 1917e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 191892a8780eSMiklos Szeredi .setxattr = fuse_setxattr, 191992a8780eSMiklos Szeredi .getxattr = fuse_getxattr, 192092a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 192192a8780eSMiklos Szeredi .removexattr = fuse_removexattr, 1922e5e5558eSMiklos Szeredi }; 1923e5e5558eSMiklos Szeredi 1924e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 1925e5e5558eSMiklos Szeredi { 1926e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 1927e5e5558eSMiklos Szeredi } 1928e5e5558eSMiklos Szeredi 1929e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 1930e5e5558eSMiklos Szeredi { 1931e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 1932e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 1933e5e5558eSMiklos Szeredi } 1934e5e5558eSMiklos Szeredi 1935e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 1936e5e5558eSMiklos Szeredi { 1937e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 1938e5e5558eSMiklos Szeredi } 1939