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

Commit 46a53cca authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: look for acls during btrfs_read_locked_inode



This changes btrfs_read_locked_inode() to peek ahead in the btree for acl items.
If it is certain a given inode has no acls, it will set the in memory acl
fields to null to avoid acl lookups completely.

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 7b1a14bb
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
@@ -2015,6 +2015,57 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
	btrfs_free_path(path);
}

/*
 * very simple check to peek ahead in the leaf looking for xattrs.  If we
 * don't find any xattrs, we know there can't be any acls.
 *
 * slot is the slot the inode is in, objectid is the objectid of the inode
 */
static noinline int acls_after_inode_item(struct extent_buffer *leaf,
					  int slot, u64 objectid)
{
	u32 nritems = btrfs_header_nritems(leaf);
	struct btrfs_key found_key;
	int scanned = 0;

	slot++;
	while (slot < nritems) {
		btrfs_item_key_to_cpu(leaf, &found_key, slot);

		/* we found a different objectid, there must not be acls */
		if (found_key.objectid != objectid)
			return 0;

		/* we found an xattr, assume we've got an acl */
		if (found_key.type == BTRFS_XATTR_ITEM_KEY)
			return 1;

		/*
		 * we found a key greater than an xattr key, there can't
		 * be any acls later on
		 */
		if (found_key.type > BTRFS_XATTR_ITEM_KEY)
			return 0;

		slot++;
		scanned++;

		/*
		 * it goes inode, inode backrefs, xattrs, extents,
		 * so if there are a ton of hard links to an inode there can
		 * be a lot of backrefs.  Don't waste time searching too hard,
		 * this is just an optimization
		 */
		if (scanned >= 8)
			break;
	}
	/* we hit the end of the leaf before we found an xattr or
	 * something larger than an xattr.  We have to assume the inode
	 * has acls
	 */
	return 1;
}

/*
 * read an inode from the btree into the in-memory inode
 */
@@ -2026,6 +2077,7 @@ void btrfs_read_locked_inode(struct inode *inode)
	struct btrfs_timespec *tspec;
	struct btrfs_root *root = BTRFS_I(inode)->root;
	struct btrfs_key location;
	int maybe_acls;
	u64 alloc_group_block;
	u32 rdev;
	int ret;
@@ -2072,6 +2124,16 @@ void btrfs_read_locked_inode(struct inode *inode)

	alloc_group_block = btrfs_inode_block_group(leaf, inode_item);

	/*
	 * try to precache a NULL acl entry for files that don't have
	 * any xattrs or acls
	 */
	maybe_acls = acls_after_inode_item(leaf, path->slots[0], inode->i_ino);
	if (!maybe_acls) {
		BTRFS_I(inode)->i_acl = NULL;
		BTRFS_I(inode)->i_default_acl = NULL;
	}

	BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0,
						alloc_group_block, 0);
	btrfs_free_path(path);