Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15a4eab0 authored by Jaegeuk Kim's avatar Jaegeuk Kim
Browse files

Merge remote-tracking branch 'aosp/upstream-f2fs-stable-linux-4.19.y' into android-4.19-stable



This series addressed merge conflicts based on pa/c/1664425/15, mainly
integrated with a patch "f2fs: Handle casefolding with Encryption" for
casefolding support in ACK only.

* aosp/upstream-f2fs-stable-linux-4.19.y:
  f2fs: flush dirty meta pages when flushing them
  f2fs: fix checkpoint=disable:%u%%
  f2fs: rework filename handling
  f2fs: split f2fs_d_compare() from f2fs_match_name()
  f2fs: don't leak filename in f2fs_try_convert_inline_dir()
  f2fs: fix missing check for f2fs_unlock_op

Conflicts:
	fs/f2fs/dir.c
	fs/f2fs/f2fs.h
	fs/f2fs/hash.c
	fs/f2fs/inline.c
	fs/f2fs/namei.c

Change-Id: Ib5ceb0f2f076d6c215d4c0c6262f3c1d41cde7c8
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@google.com>
parents 6b4bac7f 4250e29b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1266,6 +1266,9 @@ void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type)
		if (unlikely(f2fs_cp_error(sbi)))
			break;

		if (type == F2FS_DIRTY_META)
			f2fs_sync_meta_pages(sbi, META, LONG_MAX,
							FS_CP_META_IO);
		io_schedule_timeout(DEFAULT_IO_TIMEOUT);
	}
	finish_wait(&sbi->cp_wait, &wait);
+212 −160
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 *             http://www.samsung.com/
 */
#include <asm/unaligned.h>
#include <linux/fs.h>
#include <linux/f2fs_fs.h>
#include <linux/sched/signal.h>
@@ -70,6 +71,111 @@ unsigned char f2fs_get_de_type(struct f2fs_dir_entry *de)
	return DT_UNKNOWN;
}

/* If @dir is casefolded, initialize @fname->cf_name from @fname->usr_fname. */
int f2fs_init_casefolded_name(const struct inode *dir,
			      struct f2fs_filename *fname)
{
#ifdef CONFIG_UNICODE
	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);

	if (IS_CASEFOLDED(dir)) {
		fname->cf_name.name = f2fs_kmalloc(sbi, F2FS_NAME_LEN,
						   GFP_NOFS);
		if (!fname->cf_name.name)
			return -ENOMEM;
		fname->cf_name.len = utf8_casefold(sbi->sb->s_encoding,
						   fname->usr_fname,
						   fname->cf_name.name,
						   F2FS_NAME_LEN);
		if ((int)fname->cf_name.len <= 0) {
			kfree(fname->cf_name.name);
			fname->cf_name.name = NULL;
			if (sb_has_enc_strict_mode(dir->i_sb))
				return -EINVAL;
			/* fall back to treating name as opaque byte sequence */
		}
	}
#endif
	return 0;
}

static int __f2fs_setup_filename(const struct inode *dir,
				 const struct fscrypt_name *crypt_name,
				 struct f2fs_filename *fname)
{
	int err;

	memset(fname, 0, sizeof(*fname));

	fname->usr_fname = crypt_name->usr_fname;
	fname->disk_name = crypt_name->disk_name;
#ifdef CONFIG_FS_ENCRYPTION
	fname->crypto_buf = crypt_name->crypto_buf;
#endif
	if (crypt_name->is_ciphertext_name) {
		/* hash was decoded from the no-key name */
		fname->hash = cpu_to_le32(crypt_name->hash);
	} else {
		err = f2fs_init_casefolded_name(dir, fname);
		if (err) {
			f2fs_free_filename(fname);
			return err;
		}
		f2fs_hash_filename(dir, fname);
	}
	return 0;
}

/*
 * Prepare to search for @iname in @dir.  This is similar to
 * fscrypt_setup_filename(), but this also handles computing the casefolded name
 * and the f2fs dirhash if needed, then packing all the information about this
 * filename up into a 'struct f2fs_filename'.
 */
int f2fs_setup_filename(struct inode *dir, const struct qstr *iname,
			int lookup, struct f2fs_filename *fname)
{
	struct fscrypt_name crypt_name;
	int err;

	err = fscrypt_setup_filename(dir, iname, lookup, &crypt_name);
	if (err)
		return err;

	return __f2fs_setup_filename(dir, &crypt_name, fname);
}

/*
 * Prepare to look up @dentry in @dir.  This is similar to
 * fscrypt_prepare_lookup(), but this also handles computing the casefolded name
 * and the f2fs dirhash if needed, then packing all the information about this
 * filename up into a 'struct f2fs_filename'.
 */
int f2fs_prepare_lookup(struct inode *dir, struct dentry *dentry,
			struct f2fs_filename *fname)
{
	struct fscrypt_name crypt_name;
	int err;

	err = fscrypt_prepare_lookup(dir, dentry, &crypt_name);
	if (err)
		return err;

	return __f2fs_setup_filename(dir, &crypt_name, fname);
}

void f2fs_free_filename(struct f2fs_filename *fname)
{
#ifdef CONFIG_FS_ENCRYPTION
	kfree(fname->crypto_buf.name);
	fname->crypto_buf.name = NULL;
#endif
#ifdef CONFIG_UNICODE
	kfree(fname->cf_name.name);
	fname->cf_name.name = NULL;
#endif
}

static unsigned long dir_block_index(unsigned int level,
				int dir_level, unsigned int idx)
{
@@ -84,8 +190,7 @@ static unsigned long dir_block_index(unsigned int level,

static struct f2fs_dir_entry *find_in_block(struct inode *dir,
				struct page *dentry_page,
				struct fscrypt_name *fname,
				f2fs_hash_t namehash,
				const struct f2fs_filename *fname,
				int *max_slots,
				struct page **res_page)
{
@@ -96,7 +201,7 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,
	dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page);

	make_dentry_ptr_block(dir, &d, dentry_blk);
	de = f2fs_find_target_dentry(fname, namehash, max_slots, &d);
	de = f2fs_find_target_dentry(&d, fname, max_slots);
	if (de)
		*res_page = dentry_page;

@@ -107,130 +212,79 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,
/*
 * Test whether a case-insensitive directory entry matches the filename
 * being searched for.
 *
 * Only called for encrypted names if the key is available.
 *
 * Returns: 0 if the directory entry matches, more than 0 if it
 * doesn't match or less than zero on error.
 */
static int f2fs_ci_compare(const struct inode *parent, const struct qstr *name,
			   u8 *de_name, size_t de_name_len, bool quick)
static bool f2fs_match_ci_name(const struct inode *dir, const struct qstr *name,
			       const u8 *de_name, u32 de_name_len)
{
	const struct super_block *sb = parent->i_sb;
	const struct super_block *sb = dir->i_sb;
	const struct unicode_map *um = sb->s_encoding;
	struct fscrypt_str decrypted_name = FSTR_INIT(NULL, de_name_len);
	struct qstr entry = QSTR_INIT(de_name, de_name_len);
	int ret;
	int res;

	if (IS_ENCRYPTED(parent)) {
	if (IS_ENCRYPTED(dir)) {
		const struct fscrypt_str encrypted_name =
				FSTR_INIT(de_name, de_name_len);
			FSTR_INIT((u8 *)de_name, de_name_len);

		if (WARN_ON_ONCE(!fscrypt_has_encryption_key(dir)))
			return false;

		decrypted_name.name = kmalloc(de_name_len, GFP_KERNEL);
		if (!decrypted_name.name)
			return -ENOMEM;
		ret = fscrypt_fname_disk_to_usr(parent, 0, 0, &encrypted_name,
			return false;
		res = fscrypt_fname_disk_to_usr(dir, 0, 0, &encrypted_name,
						&decrypted_name);
		if (ret < 0)
		if (res < 0)
			goto out;
		entry.name = decrypted_name.name;
		entry.len = decrypted_name.len;
	}

	if (quick)
		ret = utf8_strncasecmp_folded(um, name, &entry);
	else
		ret = utf8_strncasecmp(um, name, &entry);
	if (ret < 0) {
		/* Handle invalid character sequence as either an error
		 * or as an opaque byte sequence.
	res = utf8_strncasecmp_folded(um, name, &entry);
	if (res < 0) {
		/*
		 * In strict mode, ignore invalid names.  In non-strict mode,
		 * fall back to treating them as opaque byte sequences.
		 */
		if (sb_has_enc_strict_mode(sb))
			ret = -EINVAL;
		else if (name->len != entry.len)
			ret = 1;
		if (sb_has_enc_strict_mode(sb) || name->len != entry.len)
			res = 1;
		else
			ret = !!memcmp(name->name, entry.name, entry.len);
			res = memcmp(name->name, entry.name, name->len);
	}
out:
	kfree(decrypted_name.name);
	return ret;
	return res == 0;
}
#endif /* CONFIG_UNICODE */

static void f2fs_fname_setup_ci_filename(struct inode *dir,
					const struct qstr *iname,
					struct fscrypt_str *cf_name)
static inline bool f2fs_match_name(const struct inode *dir,
				   const struct f2fs_filename *fname,
				   const u8 *de_name, u32 de_name_len)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);

	if (!IS_CASEFOLDED(dir)) {
		cf_name->name = NULL;
		return;
	}

	cf_name->name = f2fs_kmalloc(sbi, F2FS_NAME_LEN, GFP_NOFS);
	if (!cf_name->name)
		return;

	cf_name->len = utf8_casefold(dir->i_sb->s_encoding,
					iname, cf_name->name,
					F2FS_NAME_LEN);
	if ((int)cf_name->len <= 0) {
		kvfree(cf_name->name);
		cf_name->name = NULL;
	}
}
#endif

static inline bool f2fs_match_name(struct f2fs_dentry_ptr *d,
					struct f2fs_dir_entry *de,
					struct fscrypt_name *fname,
					struct fscrypt_str *cf_str,
					unsigned long bit_pos,
					f2fs_hash_t namehash)
{
#ifdef CONFIG_UNICODE
	struct inode *parent = d->inode;
	u8 *name;
	int len;
#endif

	if (de->hash_code != namehash)
		return false;
	struct fscrypt_name f;

#ifdef CONFIG_UNICODE
	name = d->filename[bit_pos];
	len = le16_to_cpu(de->name_len);
	if (fname->cf_name.name) {
		struct qstr cf = FSTR_TO_QSTR(&fname->cf_name);

	if (needs_casefold(parent)) {
		if (cf_str->name) {
			struct qstr cf = {.name = cf_str->name,
					  .len = cf_str->len};
			return !f2fs_ci_compare(parent, &cf, name, len, true);
		}
		return !f2fs_ci_compare(parent, fname->usr_fname, name, len,
					false);
		return f2fs_match_ci_name(dir, &cf, de_name, de_name_len);
	}
#endif
	if (fscrypt_match_name(fname, d->filename[bit_pos],
				le16_to_cpu(de->name_len)))
		return true;
	return false;
	f.usr_fname = fname->usr_fname;
	f.disk_name = fname->disk_name;
#ifdef CONFIG_FS_ENCRYPTION
	f.crypto_buf = fname->crypto_buf;
#endif
	return fscrypt_match_name(&f, de_name, de_name_len);
}

struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
			f2fs_hash_t namehash, int *max_slots,
			struct f2fs_dentry_ptr *d)
struct f2fs_dir_entry *f2fs_find_target_dentry(const struct f2fs_dentry_ptr *d,
			const struct f2fs_filename *fname, int *max_slots)
{
	struct f2fs_dir_entry *de;
	struct fscrypt_str cf_str = { .name = NULL, .len = 0 };
	unsigned long bit_pos = 0;
	int max_len = 0;

#ifdef CONFIG_UNICODE
	f2fs_fname_setup_ci_filename(d->inode, fname->usr_fname, &cf_str);
#endif

	if (max_slots)
		*max_slots = 0;
	while (bit_pos < d->max) {
@@ -247,7 +301,9 @@ struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
			continue;
		}

		if (f2fs_match_name(d, de, fname, &cf_str, bit_pos, namehash))
		if (de->hash_code == fname->hash &&
		    f2fs_match_name(d->inode, fname, d->filename[bit_pos],
				    le16_to_cpu(de->name_len)))
			goto found;

		if (max_slots && max_len > *max_slots)
@@ -261,33 +317,27 @@ struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
found:
	if (max_slots && max_len > *max_slots)
		*max_slots = max_len;

#ifdef CONFIG_UNICODE
	kvfree(cf_str.name);
#endif
	return de;
}

static struct f2fs_dir_entry *find_in_level(struct inode *dir,
					unsigned int level,
					struct fscrypt_name *fname,
					const struct f2fs_filename *fname,
					struct page **res_page)
{
	struct qstr name = FSTR_TO_QSTR(&fname->disk_name);
	int s = GET_DENTRY_SLOTS(name.len);
	int s = GET_DENTRY_SLOTS(fname->disk_name.len);
	unsigned int nbucket, nblock;
	unsigned int bidx, end_block;
	struct page *dentry_page;
	struct f2fs_dir_entry *de = NULL;
	bool room = false;
	int max_slots;
	f2fs_hash_t namehash = f2fs_dentry_hash(dir, &name, fname);

	nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
	nblock = bucket_blocks(level);

	bidx = dir_block_index(level, F2FS_I(dir)->i_dir_level,
					le32_to_cpu(namehash) % nbucket);
			       le32_to_cpu(fname->hash) % nbucket);
	end_block = bidx + nblock;

	for (; bidx < end_block; bidx++) {
@@ -303,8 +353,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
			}
		}

		de = find_in_block(dir, dentry_page, fname, namehash,
							&max_slots, res_page);
		de = find_in_block(dir, dentry_page, fname, &max_slots,
				   res_page);
		if (de)
			break;

@@ -313,8 +363,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
		f2fs_put_page(dentry_page, 0);
	}

	if (!de && room && F2FS_I(dir)->chash != namehash) {
		F2FS_I(dir)->chash = namehash;
	if (!de && room && F2FS_I(dir)->chash != fname->hash) {
		F2FS_I(dir)->chash = fname->hash;
		F2FS_I(dir)->clevel = level;
	}

@@ -322,7 +372,8 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
}

struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
			struct fscrypt_name *fname, struct page **res_page)
					 const struct f2fs_filename *fname,
					 struct page **res_page)
{
	unsigned long npages = dir_blocks(dir);
	struct f2fs_dir_entry *de = NULL;
@@ -371,18 +422,10 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
			const struct qstr *child, struct page **res_page)
{
	struct f2fs_dir_entry *de = NULL;
	struct fscrypt_name fname;
	struct f2fs_filename fname;
	int err;

#ifdef CONFIG_UNICODE
	if (sb_has_enc_strict_mode(dir->i_sb) && IS_CASEFOLDED(dir) &&
			utf8_validate(dir->i_sb->s_encoding, child)) {
		*res_page = ERR_PTR(-EINVAL);
		return NULL;
	}
#endif

	err = fscrypt_setup_filename(dir, child, 1, &fname);
	err = f2fs_setup_filename(dir, child, 1, &fname);
	if (err) {
		if (err == -ENOENT)
			*res_page = NULL;
@@ -393,7 +436,7 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,

	de = __f2fs_find_entry(dir, &fname, res_page);

	fscrypt_free_filename(&fname);
	f2fs_free_filename(&fname);
	return de;
}

@@ -434,24 +477,47 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
	f2fs_put_page(page, 1);
}

static void init_dent_inode(const struct qstr *name, struct page *ipage)
static void init_dent_inode(struct inode *dir, struct inode *inode,
			    const struct f2fs_filename *fname,
			    struct page *ipage)
{
	struct f2fs_inode *ri;

	if (!fname) /* tmpfile case? */
		return;

	f2fs_wait_on_page_writeback(ipage, NODE, true, true);

	/* copy name info. to this inode page */
	ri = F2FS_INODE(ipage);
	ri->i_namelen = cpu_to_le32(name->len);
	memcpy(ri->i_name, name->name, name->len);
	ri->i_namelen = cpu_to_le32(fname->disk_name.len);
	memcpy(ri->i_name, fname->disk_name.name, fname->disk_name.len);
	if (IS_ENCRYPTED(dir)) {
		file_set_enc_name(inode);
		/*
		 * Roll-forward recovery doesn't have encryption keys available,
		 * so it can't compute the dirhash for encrypted+casefolded
		 * filenames.  Append it to i_name if possible.  Else, disable
		 * roll-forward recovery of the dentry (i.e., make fsync'ing the
		 * file force a checkpoint) by setting LOST_PINO.
		 */
		if (IS_CASEFOLDED(dir)) {
			if (fname->disk_name.len + sizeof(f2fs_hash_t) <=
			    F2FS_NAME_LEN)
				put_unaligned(fname->hash, (f2fs_hash_t *)
					&ri->i_name[fname->disk_name.len]);
			else
				file_lost_pino(inode);
		}
	}
	set_page_dirty(ipage);
}

void f2fs_do_make_empty_dir(struct inode *inode, struct inode *parent,
					struct f2fs_dentry_ptr *d)
{
	struct qstr dot = QSTR_INIT(".", 1);
	struct qstr dotdot = QSTR_INIT("..", 2);
	struct fscrypt_str dot = FSTR_INIT(".", 1);
	struct fscrypt_str dotdot = FSTR_INIT("..", 2);

	/* update dirent of "." */
	f2fs_update_dentry(inode->i_ino, inode->i_mode, d, &dot, 0, 0);
@@ -485,8 +551,7 @@ static int make_empty_dir(struct inode *inode,
}

struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
			const struct qstr *new_name, const struct qstr *orig_name,
			struct page *dpage)
			const struct f2fs_filename *fname, struct page *dpage)
{
	struct page *page;
	int err;
@@ -511,7 +576,8 @@ struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
		if (err)
			goto put_error;

		err = f2fs_init_security(inode, dir, orig_name, page);
		err = f2fs_init_security(inode, dir,
					 fname ? fname->usr_fname : NULL, page);
		if (err)
			goto put_error;

@@ -526,11 +592,7 @@ struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
			return page;
	}

	if (new_name) {
		init_dent_inode(new_name, page);
		if (IS_ENCRYPTED(dir))
			file_set_enc_name(inode);
	}
	init_dent_inode(dir, inode, fname, page);

	/*
	 * This file should be checkpointed during fsync.
@@ -595,11 +657,11 @@ int f2fs_room_for_filename(const void *bitmap, int slots, int max_slots)
}

bool f2fs_has_enough_room(struct inode *dir, struct page *ipage,
					struct fscrypt_name *fname)
			  const struct f2fs_filename *fname)
{
	struct f2fs_dentry_ptr d;
	unsigned int bit_pos;
	int slots = GET_DENTRY_SLOTS(fname_len(fname));
	int slots = GET_DENTRY_SLOTS(fname->disk_name.len);

	make_dentry_ptr_inline(dir, &d, inline_data_addr(dir, ipage));

@@ -609,7 +671,7 @@ bool f2fs_has_enough_room(struct inode *dir, struct page *ipage,
}

void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d,
				const struct qstr *name, f2fs_hash_t name_hash,
			const struct fscrypt_str *name, f2fs_hash_t name_hash,
			unsigned int bit_pos)
{
	struct f2fs_dir_entry *de;
@@ -630,9 +692,7 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d,
	}
}

int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
				const struct qstr *orig_name,
				f2fs_hash_t dentry_hash,
int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname,
			   struct inode *inode, nid_t ino, umode_t mode)
{
	unsigned int bit_pos;
@@ -647,10 +707,10 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
	int slots, err = 0;

	level = 0;
	slots = GET_DENTRY_SLOTS(new_name->len);
	slots = GET_DENTRY_SLOTS(fname->disk_name.len);

	current_depth = F2FS_I(dir)->i_current_depth;
	if (F2FS_I(dir)->chash == dentry_hash) {
	if (F2FS_I(dir)->chash == fname->hash) {
		level = F2FS_I(dir)->clevel;
		F2FS_I(dir)->chash = 0;
	}
@@ -672,7 +732,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
	nblock = bucket_blocks(level);

	bidx = dir_block_index(level, F2FS_I(dir)->i_dir_level,
				(le32_to_cpu(dentry_hash) % nbucket));
				(le32_to_cpu(fname->hash) % nbucket));

	for (block = bidx; block <= (bidx + nblock - 1); block++) {
		dentry_page = f2fs_get_new_data_page(dir, NULL, block, true);
@@ -696,8 +756,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,

	if (inode) {
		down_write(&F2FS_I(inode)->i_sem);
		page = f2fs_init_inode_metadata(inode, dir, new_name,
						orig_name, NULL);
		page = f2fs_init_inode_metadata(inode, dir, fname, NULL);
		if (IS_ERR(page)) {
			err = PTR_ERR(page);
			goto fail;
@@ -705,7 +764,8 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
	}

	make_dentry_ptr_block(NULL, &d, dentry_blk);
	f2fs_update_dentry(ino, mode, &d, new_name, dentry_hash, bit_pos);
	f2fs_update_dentry(ino, mode, &d, &fname->disk_name, fname->hash,
			   bit_pos);

	set_page_dirty(dentry_page);

@@ -729,23 +789,15 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
	return err;
}

int f2fs_add_dentry(struct inode *dir, struct fscrypt_name *fname,
int f2fs_add_dentry(struct inode *dir, const struct f2fs_filename *fname,
		    struct inode *inode, nid_t ino, umode_t mode)
{
	struct qstr new_name;
	f2fs_hash_t dentry_hash;
	int err = -EAGAIN;

	new_name.name = fname_name(fname);
	new_name.len = fname_len(fname);

	if (f2fs_has_inline_dentry(dir))
		err = f2fs_add_inline_entry(dir, &new_name, fname,
							inode, ino, mode);
	dentry_hash = f2fs_dentry_hash(dir, &new_name, fname);
		err = f2fs_add_inline_entry(dir, fname, inode, ino, mode);
	if (err == -EAGAIN)
		err = f2fs_add_regular_entry(dir, &new_name, fname->usr_fname,
						dentry_hash, inode, ino, mode);
		err = f2fs_add_regular_entry(dir, fname, inode, ino, mode);

	f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
	return err;
@@ -758,12 +810,12 @@ int f2fs_add_dentry(struct inode *dir, struct fscrypt_name *fname,
int f2fs_do_add_link(struct inode *dir, const struct qstr *name,
				struct inode *inode, nid_t ino, umode_t mode)
{
	struct fscrypt_name fname;
	struct f2fs_filename fname;
	struct page *page = NULL;
	struct f2fs_dir_entry *de = NULL;
	int err;

	err = fscrypt_setup_filename(dir, name, 0, &fname);
	err = f2fs_setup_filename(dir, name, 0, &fname);
	if (err)
		return err;

@@ -786,7 +838,7 @@ int f2fs_do_add_link(struct inode *dir, const struct qstr *name,
	} else {
		err = f2fs_add_dentry(dir, &fname, inode, ino, mode);
	}
	fscrypt_free_filename(&fname);
	f2fs_free_filename(&fname);
	return err;
}

@@ -796,7 +848,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
	int err = 0;

	down_write(&F2FS_I(inode)->i_sem);
	page = f2fs_init_inode_metadata(inode, dir, NULL, NULL, NULL);
	page = f2fs_init_inode_metadata(inode, dir, NULL, NULL);
	if (IS_ERR(page)) {
		err = PTR_ERR(page);
		goto fail;
+62 −19
Original line number Diff line number Diff line
@@ -141,6 +141,7 @@ struct f2fs_mount_info {
#ifdef CONFIG_FS_ENCRYPTION
	bool inlinecrypt;		/* inline encryption enabled */
#endif
	block_t unusable_cap_perc;	/* percentage for cap */
	block_t unusable_cap;		/* Amount of space allowed to be
					 * unusable when disabling checkpoint
					 */
@@ -508,6 +509,44 @@ static inline int get_inline_xattr_addrs(struct inode *inode);
 * For INODE and NODE manager
 */
/* for directory operations */

struct f2fs_filename {
	/*
	 * The filename the user specified.  This is NULL for some
	 * filesystem-internal operations, e.g. converting an inline directory
	 * to a non-inline one, or roll-forward recovering an encrypted dentry.
	 */
	const struct qstr *usr_fname;

	/*
	 * The on-disk filename.  For encrypted directories, this is encrypted.
	 * This may be NULL for lookups in an encrypted dir without the key.
	 */
	struct fscrypt_str disk_name;

	/* The dirhash of this filename */
	f2fs_hash_t hash;

#ifdef CONFIG_FS_ENCRYPTION
	/*
	 * For lookups in encrypted directories: either the buffer backing
	 * disk_name, or a buffer that holds the decoded no-key name.
	 */
	struct fscrypt_str crypto_buf;
#endif
#ifdef CONFIG_UNICODE
	/*
	 * For casefolded directories: the casefolded name, but it's left NULL
	 * if the original name is not valid Unicode, if the directory is both
	 * casefolded and encrypted and its encryption key is unavailable, or if
	 * the filesystem is doing an internal operation where usr_fname is also
	 * NULL.  In all these cases we fall back to treating the name as an
	 * opaque byte sequence.
	 */
	struct fscrypt_str cf_name;
#endif
};

struct f2fs_dentry_ptr {
	struct inode *inode;
	void *bitmap;
@@ -2919,12 +2958,12 @@ static inline bool f2fs_cp_error(struct f2fs_sb_info *sbi)
	return is_set_ckpt_flags(sbi, CP_ERROR_FLAG);
}

static inline bool is_dot_dotdot(const struct qstr *str)
static inline bool is_dot_dotdot(const u8 *name, size_t len)
{
	if (str->len == 1 && str->name[0] == '.')
	if (len == 1 && name[0] == '.')
		return true;

	if (str->len == 2 && str->name[0] == '.' && str->name[1] == '.')
	if (len == 2 && name[0] == '.' && name[1] == '.')
		return true;

	return false;
@@ -3143,22 +3182,28 @@ struct dentry *f2fs_get_parent(struct dentry *child);
 * dir.c
 */
unsigned char f2fs_get_de_type(struct f2fs_dir_entry *de);
struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
			f2fs_hash_t namehash, int *max_slots,
			struct f2fs_dentry_ptr *d);
int f2fs_init_casefolded_name(const struct inode *dir,
			      struct f2fs_filename *fname);
int f2fs_setup_filename(struct inode *dir, const struct qstr *iname,
			int lookup, struct f2fs_filename *fname);
int f2fs_prepare_lookup(struct inode *dir, struct dentry *dentry,
			struct f2fs_filename *fname);
void f2fs_free_filename(struct f2fs_filename *fname);
struct f2fs_dir_entry *f2fs_find_target_dentry(const struct f2fs_dentry_ptr *d,
			const struct f2fs_filename *fname, int *max_slots);
int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
			unsigned int start_pos, struct fscrypt_str *fstr);
void f2fs_do_make_empty_dir(struct inode *inode, struct inode *parent,
			struct f2fs_dentry_ptr *d);
struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
			const struct qstr *new_name,
			const struct qstr *orig_name, struct page *dpage);
			const struct f2fs_filename *fname, struct page *dpage);
void f2fs_update_parent_metadata(struct inode *dir, struct inode *inode,
			unsigned int current_depth);
int f2fs_room_for_filename(const void *bitmap, int slots, int max_slots);
void f2fs_drop_nlink(struct inode *dir, struct inode *inode);
struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
			struct fscrypt_name *fname, struct page **res_page);
					 const struct f2fs_filename *fname,
					 struct page **res_page);
struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
			const struct qstr *child, struct page **res_page);
struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p);
@@ -3167,14 +3212,13 @@ ino_t f2fs_inode_by_name(struct inode *dir, const struct qstr *qstr,
void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
			struct page *page, struct inode *inode);
bool f2fs_has_enough_room(struct inode *dir, struct page *ipage,
			struct fscrypt_name *fname);
			  const struct f2fs_filename *fname);
void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d,
			const struct qstr *name, f2fs_hash_t name_hash,
			const struct fscrypt_str *name, f2fs_hash_t name_hash,
			unsigned int bit_pos);
int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
			const struct qstr *orig_name, f2fs_hash_t dentry_hash,
int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname,
			struct inode *inode, nid_t ino, umode_t mode);
int f2fs_add_dentry(struct inode *dir, struct fscrypt_name *fname,
int f2fs_add_dentry(struct inode *dir, const struct f2fs_filename *fname,
			struct inode *inode, nid_t ino, umode_t mode);
int f2fs_do_add_link(struct inode *dir, const struct qstr *name,
			struct inode *inode, nid_t ino, umode_t mode);
@@ -3204,8 +3248,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
/*
 * hash.c
 */
f2fs_hash_t f2fs_dentry_hash(const struct inode *dir,
		const struct qstr *name_info, const struct fscrypt_name *fname);
void f2fs_hash_filename(const struct inode *dir, struct f2fs_filename *fname);

/*
 * node.c
@@ -3711,11 +3754,11 @@ int f2fs_try_convert_inline_dir(struct inode *dir, struct dentry *dentry);
int f2fs_write_inline_data(struct inode *inode, struct page *page);
bool f2fs_recover_inline_data(struct inode *inode, struct page *npage);
struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir,
			struct fscrypt_name *fname, struct page **res_page);
					const struct f2fs_filename *fname,
					struct page **res_page);
int f2fs_make_empty_inline_dir(struct inode *inode, struct inode *parent,
			struct page *ipage);
int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,
			const struct fscrypt_name *fname,
int f2fs_add_inline_entry(struct inode *dir, const struct f2fs_filename *fname,
			struct inode *inode, nid_t ino, umode_t mode);
void f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry,
				struct page *page, struct inode *dir,
+42 −54

File changed.

Preview size limit exceeded, changes collapsed.

+25 −25

File changed.

Preview size limit exceeded, changes collapsed.

Loading