VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
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) }