d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 1) /*
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 2) FUSE: Filesystem in Userspace
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 3) Copyright (C) 2001-2018 Miklos Szeredi <miklos@szeredi.hu>
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 4)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 5) This program can be distributed under the terms of the GNU GPL.
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 6) See the file COPYING.
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 7) */
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 8)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 9)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 10) #include "fuse_i.h"
261aaba72fdba (Miklos Szeredi 2018-10-01 10:07:05 +0200 11) #include <linux/iversion.h>
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 12) #include <linux/posix_acl.h>
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 13) #include <linux/pagemap.h>
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 14) #include <linux/highmem.h>
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 15)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 16) static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 17) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 18) struct fuse_conn *fc = get_fuse_conn(dir);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 19) struct fuse_inode *fi = get_fuse_inode(dir);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 20)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 21) if (!fc->do_readdirplus)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 22) return false;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 23) if (!fc->readdirplus_auto)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 24) return true;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 25) if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 26) return true;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 27) if (ctx->pos == 0)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 28) return true;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 29) return false;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 30) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 31)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 32) static void fuse_add_dirent_to_cache(struct file *file,
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 33) struct fuse_dirent *dirent, loff_t pos)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 34) {
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 35) struct fuse_inode *fi = get_fuse_inode(file_inode(file));
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 36) size_t reclen = FUSE_DIRENT_SIZE(dirent);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 37) pgoff_t index;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 38) struct page *page;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 39) loff_t size;
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 40) u64 version;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 41) unsigned int offset;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 42) void *addr;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 43)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 44) spin_lock(&fi->rdc.lock);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 45) /*
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 46) * Is cache already completed? Or this entry does not go at the end of
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 47) * cache?
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 48) */
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 49) if (fi->rdc.cached || pos != fi->rdc.pos) {
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 50) spin_unlock(&fi->rdc.lock);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 51) return;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 52) }
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 53) version = fi->rdc.version;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 54) size = fi->rdc.size;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 55) offset = size & ~PAGE_MASK;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 56) index = size >> PAGE_SHIFT;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 57) /* Dirent doesn't fit in current page? Jump to next page. */
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 58) if (offset + reclen > PAGE_SIZE) {
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 59) index++;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 60) offset = 0;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 61) }
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 62) spin_unlock(&fi->rdc.lock);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 63)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 64) if (offset) {
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 65) page = find_lock_page(file->f_mapping, index);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 66) } else {
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 67) page = find_or_create_page(file->f_mapping, index,
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 68) mapping_gfp_mask(file->f_mapping));
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 69) }
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 70) if (!page)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 71) return;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 72)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 73) spin_lock(&fi->rdc.lock);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 74) /* Raced with another readdir */
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 75) if (fi->rdc.version != version || fi->rdc.size != size ||
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 76) WARN_ON(fi->rdc.pos != pos))
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 77) goto unlock;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 78)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 79) addr = kmap_atomic(page);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 80) if (!offset)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 81) clear_page(addr);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 82) memcpy(addr + offset, dirent, reclen);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 83) kunmap_atomic(addr);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 84) fi->rdc.size = (index << PAGE_SHIFT) + offset + reclen;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 85) fi->rdc.pos = dirent->off;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 86) unlock:
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 87) spin_unlock(&fi->rdc.lock);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 88) unlock_page(page);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 89) put_page(page);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 90) }
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 91)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 92) static void fuse_readdir_cache_end(struct file *file, loff_t pos)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 93) {
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 94) struct fuse_inode *fi = get_fuse_inode(file_inode(file));
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 95) loff_t end;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 96)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 97) spin_lock(&fi->rdc.lock);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 98) /* does cache end position match current position? */
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 99) if (fi->rdc.pos != pos) {
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 100) spin_unlock(&fi->rdc.lock);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 101) return;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 102) }
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 103)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 104) fi->rdc.cached = true;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 105) end = ALIGN(fi->rdc.size, PAGE_SIZE);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 106) spin_unlock(&fi->rdc.lock);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 107)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 108) /* truncate unused tail of cache */
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 109) truncate_inode_pages(file->f_mapping, end);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 110) }
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 111)
18172b10b674a (Miklos Szeredi 2018-09-28 16:43:23 +0200 112) static bool fuse_emit(struct file *file, struct dir_context *ctx,
18172b10b674a (Miklos Szeredi 2018-09-28 16:43:23 +0200 113) struct fuse_dirent *dirent)
18172b10b674a (Miklos Szeredi 2018-09-28 16:43:23 +0200 114) {
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 115) struct fuse_file *ff = file->private_data;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 116)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 117) if (ff->open_flags & FOPEN_CACHE_DIR)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 118) fuse_add_dirent_to_cache(file, dirent, ctx->pos);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 119)
18172b10b674a (Miklos Szeredi 2018-09-28 16:43:23 +0200 120) return dir_emit(ctx, dirent->name, dirent->namelen, dirent->ino,
18172b10b674a (Miklos Szeredi 2018-09-28 16:43:23 +0200 121) dirent->type);
18172b10b674a (Miklos Szeredi 2018-09-28 16:43:23 +0200 122) }
18172b10b674a (Miklos Szeredi 2018-09-28 16:43:23 +0200 123)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 124) static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 125) struct dir_context *ctx)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 126) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 127) while (nbytes >= FUSE_NAME_OFFSET) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 128) struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 129) size_t reclen = FUSE_DIRENT_SIZE(dirent);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 130) if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 131) return -EIO;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 132) if (reclen > nbytes)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 133) break;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 134) if (memchr(dirent->name, '/', dirent->namelen) != NULL)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 135) return -EIO;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 136)
18172b10b674a (Miklos Szeredi 2018-09-28 16:43:23 +0200 137) if (!fuse_emit(file, ctx, dirent))
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 138) break;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 139)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 140) buf += reclen;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 141) nbytes -= reclen;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 142) ctx->pos = dirent->off;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 143) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 144)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 145) return 0;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 146) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 147)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 148) static int fuse_direntplus_link(struct file *file,
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 149) struct fuse_direntplus *direntplus,
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 150) u64 attr_version)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 151) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 152) struct fuse_entry_out *o = &direntplus->entry_out;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 153) struct fuse_dirent *dirent = &direntplus->dirent;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 154) struct dentry *parent = file->f_path.dentry;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 155) struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 156) struct dentry *dentry;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 157) struct dentry *alias;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 158) struct inode *dir = d_inode(parent);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 159) struct fuse_conn *fc;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 160) struct inode *inode;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 161) DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 162)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 163) if (!o->nodeid) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 164) /*
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 165) * Unlike in the case of fuse_lookup, zero nodeid does not mean
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 166) * ENOENT. Instead, it only means the userspace filesystem did
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 167) * not want to return attributes/handle for this entry.
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 168) *
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 169) * So do nothing.
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 170) */
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 171) return 0;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 172) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 173)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 174) if (name.name[0] == '.') {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 175) /*
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 176) * We could potentially refresh the attributes of the directory
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 177) * and its parent?
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 178) */
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 179) if (name.len == 1)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 180) return 0;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 181) if (name.name[1] == '.' && name.len == 2)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 182) return 0;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 183) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 184)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 185) if (invalid_nodeid(o->nodeid))
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 186) return -EIO;
eb59bd17d2fa6 (Miklos Szeredi 2019-11-12 11:49:04 +0100 187) if (fuse_invalid_attr(&o->attr))
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 188) return -EIO;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 189)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 190) fc = get_fuse_conn(dir);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 191)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 192) name.hash = full_name_hash(parent, name.name, name.len);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 193) dentry = d_lookup(parent, &name);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 194) if (!dentry) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 195) retry:
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 196) dentry = d_alloc_parallel(parent, &name, &wq);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 197) if (IS_ERR(dentry))
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 198) return PTR_ERR(dentry);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 199) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 200) if (!d_in_lookup(dentry)) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 201) struct fuse_inode *fi;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 202) inode = d_inode(dentry);
c09a4ad6251f9 (Amir Goldstein 2021-06-21 14:03:53 +0300 203) if (inode && get_node_id(inode) != o->nodeid)
c09a4ad6251f9 (Amir Goldstein 2021-06-21 14:03:53 +0300 204) inode = NULL;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 205) if (!inode ||
c09a4ad6251f9 (Amir Goldstein 2021-06-21 14:03:53 +0300 206) fuse_stale_inode(inode, o->generation, &o->attr)) {
c09a4ad6251f9 (Amir Goldstein 2021-06-21 14:03:53 +0300 207) if (inode)
c09a4ad6251f9 (Amir Goldstein 2021-06-21 14:03:53 +0300 208) fuse_make_bad(inode);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 209) d_invalidate(dentry);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 210) dput(dentry);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 211) goto retry;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 212) }
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 213) if (fuse_is_bad(inode)) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 214) dput(dentry);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 215) return -EIO;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 216) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 217)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 218) fi = get_fuse_inode(inode);
c9d8f5f0692d5 (Kirill Tkhai 2018-11-09 13:33:27 +0300 219) spin_lock(&fi->lock);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 220) fi->nlookup++;
c9d8f5f0692d5 (Kirill Tkhai 2018-11-09 13:33:27 +0300 221) spin_unlock(&fi->lock);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 222)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 223) forget_all_cached_acls(inode);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 224) fuse_change_attributes(inode, &o->attr,
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 225) entry_attr_timeout(o),
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 226) attr_version);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 227) /*
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 228) * The other branch comes via fuse_iget()
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 229) * which bumps nlookup inside
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 230) */
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 231) } else {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 232) inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 233) &o->attr, entry_attr_timeout(o),
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 234) attr_version);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 235) if (!inode)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 236) inode = ERR_PTR(-ENOMEM);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 237)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 238) alias = d_splice_alias(inode, dentry);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 239) d_lookup_done(dentry);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 240) if (alias) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 241) dput(dentry);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 242) dentry = alias;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 243) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 244) if (IS_ERR(dentry))
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 245) return PTR_ERR(dentry);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 246) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 247) if (fc->readdirplus_auto)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 248) set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 249) fuse_change_entry_timeout(dentry, o);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 250)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 251) dput(dentry);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 252) return 0;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 253) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 254)
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 255) static void fuse_force_forget(struct file *file, u64 nodeid)
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 256) {
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 257) struct inode *inode = file_inode(file);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 258) struct fuse_mount *fm = get_fuse_mount(inode);
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 259) struct fuse_forget_in inarg;
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 260) FUSE_ARGS(args);
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 261)
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 262) memset(&inarg, 0, sizeof(inarg));
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 263) inarg.nlookup = 1;
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 264) args.opcode = FUSE_FORGET;
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 265) args.nodeid = nodeid;
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 266) args.in_numargs = 1;
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 267) args.in_args[0].size = sizeof(inarg);
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 268) args.in_args[0].value = &inarg;
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 269) args.force = true;
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 270) args.noreply = true;
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 271)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 272) fuse_simple_request(fm, &args);
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 273) /* ignore errors */
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 274) }
3545fe2112826 (Miklos Szeredi 2019-09-10 15:04:08 +0200 275)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 276) static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 277) struct dir_context *ctx, u64 attr_version)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 278) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 279) struct fuse_direntplus *direntplus;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 280) struct fuse_dirent *dirent;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 281) size_t reclen;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 282) int over = 0;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 283) int ret;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 284)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 285) while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 286) direntplus = (struct fuse_direntplus *) buf;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 287) dirent = &direntplus->dirent;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 288) reclen = FUSE_DIRENTPLUS_SIZE(direntplus);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 289)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 290) if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 291) return -EIO;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 292) if (reclen > nbytes)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 293) break;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 294) if (memchr(dirent->name, '/', dirent->namelen) != NULL)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 295) return -EIO;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 296)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 297) if (!over) {
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 298) /* We fill entries into dstbuf only as much as
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 299) it can hold. But we still continue iterating
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 300) over remaining entries to link them. If not,
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 301) we need to send a FORGET for each of those
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 302) which we did not link.
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 303) */
18172b10b674a (Miklos Szeredi 2018-09-28 16:43:23 +0200 304) over = !fuse_emit(file, ctx, dirent);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 305) if (!over)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 306) ctx->pos = dirent->off;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 307) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 308)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 309) buf += reclen;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 310) nbytes -= reclen;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 311)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 312) ret = fuse_direntplus_link(file, direntplus, attr_version);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 313) if (ret)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 314) fuse_force_forget(file, direntplus->entry_out.nodeid);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 315) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 316)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 317) return 0;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 318) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 319)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 320) static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 321) {
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 322) int plus;
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 323) ssize_t res;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 324) struct page *page;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 325) struct inode *inode = file_inode(file);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 326) struct fuse_mount *fm = get_fuse_mount(inode);
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 327) struct fuse_io_args ia = {};
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 328) struct fuse_args_pages *ap = &ia.ap;
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 329) struct fuse_page_desc desc = { .length = PAGE_SIZE };
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 330) u64 attr_version = 0;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 331) bool locked;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 332)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 333) page = alloc_page(GFP_KERNEL);
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 334) if (!page)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 335) return -ENOMEM;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 336)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 337) plus = fuse_use_readdirplus(inode, ctx);
cabdb4fa2f666 (zhengbin 2020-01-14 20:39:45 +0800 338) ap->args.out_pages = true;
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 339) ap->num_pages = 1;
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 340) ap->pages = &page;
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 341) ap->descs = &desc;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 342) if (plus) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 343) attr_version = fuse_get_attr_version(fm->fc);
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 344) fuse_read_args_fill(&ia, file, ctx->pos, PAGE_SIZE,
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 345) FUSE_READDIRPLUS);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 346) } else {
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 347) fuse_read_args_fill(&ia, file, ctx->pos, PAGE_SIZE,
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 348) FUSE_READDIR);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 349) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 350) locked = fuse_lock_inode(inode);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 351) res = fuse_simple_request(fm, &ap->args);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 352) fuse_unlock_inode(inode, locked);
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 353) if (res >= 0) {
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 354) if (!res) {
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 355) struct fuse_file *ff = file->private_data;
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 356)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 357) if (ff->open_flags & FOPEN_CACHE_DIR)
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 358) fuse_readdir_cache_end(file, ctx->pos);
69e34551152a2 (Miklos Szeredi 2018-10-01 10:07:04 +0200 359) } else if (plus) {
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 360) res = parse_dirplusfile(page_address(page), res,
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 361) file, ctx, attr_version);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 362) } else {
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 363) res = parse_dirfile(page_address(page), res, file,
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 364) ctx);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 365) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 366) }
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 367)
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 368) __free_page(page);
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 369) fuse_invalidate_atime(inode);
43f5098eb82b1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 370) return res;
d123d8e1833c5 (Miklos Szeredi 2018-09-28 16:43:23 +0200 371) }
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 372)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 373) enum fuse_parse_result {
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 374) FOUND_ERR = -1,
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 375) FOUND_NONE = 0,
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 376) FOUND_SOME,
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 377) FOUND_ALL,
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 378) };
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 379)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 380) static enum fuse_parse_result fuse_parse_cache(struct fuse_file *ff,
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 381) void *addr, unsigned int size,
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 382) struct dir_context *ctx)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 383) {
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 384) unsigned int offset = ff->readdir.cache_off & ~PAGE_MASK;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 385) enum fuse_parse_result res = FOUND_NONE;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 386)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 387) WARN_ON(offset >= size);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 388)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 389) for (;;) {
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 390) struct fuse_dirent *dirent = addr + offset;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 391) unsigned int nbytes = size - offset;
e5854b1cdf6cb (Tejun Heo 2019-09-22 06:19:36 -0700 392) size_t reclen;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 393)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 394) if (nbytes < FUSE_NAME_OFFSET || !dirent->namelen)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 395) break;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 396)
e5854b1cdf6cb (Tejun Heo 2019-09-22 06:19:36 -0700 397) reclen = FUSE_DIRENT_SIZE(dirent); /* derefs ->namelen */
e5854b1cdf6cb (Tejun Heo 2019-09-22 06:19:36 -0700 398)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 399) if (WARN_ON(dirent->namelen > FUSE_NAME_MAX))
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 400) return FOUND_ERR;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 401) if (WARN_ON(reclen > nbytes))
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 402) return FOUND_ERR;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 403) if (WARN_ON(memchr(dirent->name, '/', dirent->namelen) != NULL))
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 404) return FOUND_ERR;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 405)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 406) if (ff->readdir.pos == ctx->pos) {
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 407) res = FOUND_SOME;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 408) if (!dir_emit(ctx, dirent->name, dirent->namelen,
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 409) dirent->ino, dirent->type))
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 410) return FOUND_ALL;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 411) ctx->pos = dirent->off;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 412) }
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 413) ff->readdir.pos = dirent->off;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 414) ff->readdir.cache_off += reclen;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 415)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 416) offset += reclen;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 417) }
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 418)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 419) return res;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 420) }
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 421)
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 422) static void fuse_rdc_reset(struct inode *inode)
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 423) {
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 424) struct fuse_inode *fi = get_fuse_inode(inode);
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 425)
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 426) fi->rdc.cached = false;
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 427) fi->rdc.version++;
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 428) fi->rdc.size = 0;
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 429) fi->rdc.pos = 0;
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 430) }
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 431)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 432) #define UNCACHED 1
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 433)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 434) static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 435) {
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 436) struct fuse_file *ff = file->private_data;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 437) struct inode *inode = file_inode(file);
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 438) struct fuse_conn *fc = get_fuse_conn(inode);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 439) struct fuse_inode *fi = get_fuse_inode(inode);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 440) enum fuse_parse_result res;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 441) pgoff_t index;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 442) unsigned int size;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 443) struct page *page;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 444) void *addr;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 445)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 446) /* Seeked? If so, reset the cache stream */
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 447) if (ff->readdir.pos != ctx->pos) {
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 448) ff->readdir.pos = 0;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 449) ff->readdir.cache_off = 0;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 450) }
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 451)
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 452) /*
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 453) * We're just about to start reading into the cache or reading the
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 454) * cache; both cases require an up-to-date mtime value.
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 455) */
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 456) if (!ctx->pos && fc->auto_inval_data) {
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 457) int err = fuse_update_attributes(inode, file);
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 458)
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 459) if (err)
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 460) return err;
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 461) }
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 462)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 463) retry:
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 464) spin_lock(&fi->rdc.lock);
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 465) retry_locked:
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 466) if (!fi->rdc.cached) {
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 467) /* Starting cache? Set cache mtime. */
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 468) if (!ctx->pos && !fi->rdc.size) {
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 469) fi->rdc.mtime = inode->i_mtime;
261aaba72fdba (Miklos Szeredi 2018-10-01 10:07:05 +0200 470) fi->rdc.iversion = inode_query_iversion(inode);
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 471) }
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 472) spin_unlock(&fi->rdc.lock);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 473) return UNCACHED;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 474) }
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 475) /*
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 476) * When at the beginning of the directory (i.e. just after opendir(3) or
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 477) * rewinddir(3)), then need to check whether directory contents have
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 478) * changed, and reset the cache if so.
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 479) */
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 480) if (!ctx->pos) {
261aaba72fdba (Miklos Szeredi 2018-10-01 10:07:05 +0200 481) if (inode_peek_iversion(inode) != fi->rdc.iversion ||
261aaba72fdba (Miklos Szeredi 2018-10-01 10:07:05 +0200 482) !timespec64_equal(&fi->rdc.mtime, &inode->i_mtime)) {
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 483) fuse_rdc_reset(inode);
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 484) goto retry_locked;
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 485) }
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 486) }
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 487)
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 488) /*
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 489) * If cache version changed since the last getdents() call, then reset
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 490) * the cache stream.
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 491) */
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 492) if (ff->readdir.version != fi->rdc.version) {
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 493) ff->readdir.pos = 0;
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 494) ff->readdir.cache_off = 0;
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 495) }
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 496) /*
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 497) * If at the beginning of the cache, than reset version to
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 498) * current.
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 499) */
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 500) if (ff->readdir.pos == 0)
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 501) ff->readdir.version = fi->rdc.version;
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 502)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 503) WARN_ON(fi->rdc.size < ff->readdir.cache_off);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 504)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 505) index = ff->readdir.cache_off >> PAGE_SHIFT;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 506)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 507) if (index == (fi->rdc.size >> PAGE_SHIFT))
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 508) size = fi->rdc.size & ~PAGE_MASK;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 509) else
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 510) size = PAGE_SIZE;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 511) spin_unlock(&fi->rdc.lock);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 512)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 513) /* EOF? */
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 514) if ((ff->readdir.cache_off & ~PAGE_MASK) == size)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 515) return 0;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 516)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 517) page = find_get_page_flags(file->f_mapping, index,
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 518) FGP_ACCESSED | FGP_LOCK);
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 519) spin_lock(&fi->rdc.lock);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 520) if (!page) {
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 521) /*
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 522) * Uh-oh: page gone missing, cache is useless
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 523) */
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 524) if (fi->rdc.version == ff->readdir.version)
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 525) fuse_rdc_reset(inode);
7118883b44b8e (Miklos Szeredi 2018-10-01 10:07:04 +0200 526) goto retry_locked;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 527) }
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 528)
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 529) /* Make sure it's still the same version after getting the page. */
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 530) if (ff->readdir.version != fi->rdc.version) {
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 531) spin_unlock(&fi->rdc.lock);
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 532) unlock_page(page);
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 533) put_page(page);
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 534) goto retry;
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 535) }
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 536) spin_unlock(&fi->rdc.lock);
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 537)
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 538) /*
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 539) * Contents of the page are now protected against changing by holding
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 540) * the page lock.
3494927e090bf (Miklos Szeredi 2018-10-01 10:07:04 +0200 541) */
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 542) addr = kmap(page);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 543) res = fuse_parse_cache(ff, addr, size, ctx);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 544) kunmap(page);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 545) unlock_page(page);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 546) put_page(page);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 547)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 548) if (res == FOUND_ERR)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 549) return -EIO;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 550)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 551) if (res == FOUND_ALL)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 552) return 0;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 553)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 554) if (size == PAGE_SIZE) {
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 555) /* We hit end of page: skip to next page. */
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 556) ff->readdir.cache_off = ALIGN(ff->readdir.cache_off, PAGE_SIZE);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 557) goto retry;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 558) }
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 559)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 560) /*
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 561) * End of cache reached. If found position, then we are done, otherwise
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 562) * need to fall back to uncached, since the position we were looking for
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 563) * wasn't in the cache.
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 564) */
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 565) return res == FOUND_SOME ? 0 : UNCACHED;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 566) }
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 567)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 568) int fuse_readdir(struct file *file, struct dir_context *ctx)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 569) {
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 570) struct fuse_file *ff = file->private_data;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 571) struct inode *inode = file_inode(file);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 572) int err;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 573)
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 574) if (fuse_is_bad(inode))
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 575) return -EIO;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 576)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 577) mutex_lock(&ff->readdir.lock);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 578)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 579) err = UNCACHED;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 580) if (ff->open_flags & FOPEN_CACHE_DIR)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 581) err = fuse_readdir_cached(file, ctx);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 582) if (err == UNCACHED)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 583) err = fuse_readdir_uncached(file, ctx);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 584)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 585) mutex_unlock(&ff->readdir.lock);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 586)
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 587) return err;
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 588) }