1603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim/**
2603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim * xattr.c
3603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim *
4603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim * Many parts of codes are copied from Linux kernel/fs/f2fs.
5603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim *
6603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim * Copyright (C) 2015 Huawei Ltd.
7603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim * Witten by:
8603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim *   Hou Pengyang <houpengyang@huawei.com>
9603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim *   Liu Shuoran <liushuoran@huawei.com>
10603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim *   Jaegeuk Kim <jaegeuk@kernel.org>
11603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim *
12603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim * This program is free software; you can redistribute it and/or modify
13603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim * it under the terms of the GNU General Public License version 2 as
14603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim * published by the Free Software Foundation.
15603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim */
16603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim#include "fsck.h"
17603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim#include "node.h"
18603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim#include "xattr.h"
19603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
20603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim#define XATTR_CREATE 0x1
21603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim#define XATTR_REPLACE 0x2
22603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
23603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kimstatic void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode)
24603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim{
25603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	struct f2fs_xattr_header *header;
26603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	void *txattr_addr;
27603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	u64 inline_size = inline_xattr_size(&inode->i);
28603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
29603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	txattr_addr = calloc(inline_size + BLOCK_SZ, 1);
30603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ASSERT(txattr_addr);
31603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
32603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (inline_size)
33603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		memcpy(txattr_addr, inline_xattr_addr(&inode->i), inline_size);
34603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
35603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	/* Read from xattr node block. */
36603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (inode->i.i_xattr_nid) {
37603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		struct node_info ni;
38603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		int ret;
39603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
40603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		get_node_info(sbi, le32_to_cpu(inode->i.i_xattr_nid), &ni);
41603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		ret = dev_read_block(txattr_addr + inline_size, ni.blk_addr);
42603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		ASSERT(ret >= 0);
43603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	}
44603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
45603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	header = XATTR_HDR(txattr_addr);
46603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
47603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	/* Never been allocated xattrs */
48603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) {
49603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);
50603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		header->h_refcount = cpu_to_le32(1);
51603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	}
52603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	return txattr_addr;
53603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim}
54603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
55603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kimstatic struct f2fs_xattr_entry *__find_xattr(void *base_addr, int index,
56603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		size_t len, const char *name)
57603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim{
58603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	struct f2fs_xattr_entry *entry;
59603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	list_for_each_xattr(entry, base_addr) {
60603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		if (entry->e_name_index != index)
61603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim			continue;
62603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		if (entry->e_name_len != len)
63603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim			continue;
64603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		if (!memcmp(entry->e_name, name, len))
65603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim			break;
66603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	}
67603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	return entry;
68603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim}
69603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
70603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kimstatic void write_all_xattrs(struct f2fs_sb_info *sbi,
71603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		struct f2fs_node *inode, __u32 hsize, void *txattr_addr)
72603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim{
73603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	void *xattr_addr;
74603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	struct dnode_of_data dn;
75603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	struct node_info ni;
76603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	struct f2fs_node *xattr_node;
77603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	nid_t new_nid = 0;
78603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	block_t blkaddr;
79603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	nid_t xnid = le32_to_cpu(inode->i.i_xattr_nid);
80603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	u64 inline_size = inline_xattr_size(&inode->i);
81603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	int ret;
82603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
83603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ASSERT(inode->i.i_inline & F2FS_INLINE_XATTR);
84603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	memcpy(inline_xattr_addr(&inode->i), txattr_addr, inline_size);
85603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
86603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (hsize <= inline_size)
87603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		return;
88603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
89603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (!xnid) {
90603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		f2fs_alloc_nid(sbi, &new_nid, 0);
91603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
92603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		set_new_dnode(&dn, inode, NULL, new_nid);
93603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		/* NAT entry would be updated by new_node_page. */
94603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		blkaddr = new_node_block(sbi, &dn, XATTR_NODE_OFFSET);
95603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		ASSERT(dn.node_blk);
96603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		xattr_node = dn.node_blk;
97603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		inode->i.i_xattr_nid = cpu_to_le32(new_nid);
98603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	} else {
99603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		set_new_dnode(&dn, inode, NULL, xnid);
100603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		get_node_info(sbi, xnid, &ni);
101603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		blkaddr = ni.blk_addr;
102603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		xattr_node = calloc(BLOCK_SZ, 1);
103603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		ASSERT(xattr_node);
104603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		ret = dev_read_block(xattr_node, ni.blk_addr);
105603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		ASSERT(ret >= 0);
106603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	}
107603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
108603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	/* write to xattr node block */
109603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	xattr_addr = (void *)xattr_node;
110603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	memcpy(xattr_addr, txattr_addr + inline_size,
111603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim			PAGE_SIZE - sizeof(struct node_footer));
112603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
113603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ret = dev_write_block(xattr_node, blkaddr);
114603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ASSERT(ret >= 0);
115603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim}
116603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
117603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kimint f2fs_setxattr(struct f2fs_sb_info *sbi, nid_t ino, int index, const char *name,
118603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		const void *value, size_t size, int flags)
119603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim{
120603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	struct f2fs_node *inode;
121603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	void *base_addr;
122603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	struct f2fs_xattr_entry *here, *last;
123603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	struct node_info ni;
124603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	int error = 0;
125603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	int len;
126603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	int found, newsize;
127603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	__u32 new_hsize;
128603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	int ret;
129603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
130603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (name == NULL)
131603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		return -EINVAL;
132603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
133603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (value == NULL)
134603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		return -EINVAL;
135603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
136603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	len = strlen(name);
137603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
138603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (len > F2FS_NAME_LEN || size > MAX_VALUE_LEN)
139603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		return -ERANGE;
140603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
141603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (ino < 3)
142603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		return -EINVAL;
143603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
144603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	/* Now We just support selinux */
145603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ASSERT(index == F2FS_XATTR_INDEX_SECURITY);
146603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
147603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	get_node_info(sbi, ino, &ni);
148603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	inode = calloc(BLOCK_SZ, 1);
149603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ASSERT(inode);
150603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ret = dev_read_block(inode, ni.blk_addr);
151603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ASSERT(ret >= 0);
152603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
153603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	base_addr = read_all_xattrs(sbi, inode);
154603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ASSERT(base_addr);
155603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
156603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	here = __find_xattr(base_addr, index, len, name);
157603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
158603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	found = IS_XATTR_LAST_ENTRY(here) ? 0 : 1;
159603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
160603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if ((flags & XATTR_REPLACE) && !found) {
161603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		error = -ENODATA;
162603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		goto exit;
163603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	} else if ((flags & XATTR_CREATE) && found) {
164603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		error = -EEXIST;
165603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		goto exit;
166603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	}
167603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
168603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	last = here;
169603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	while (!IS_XATTR_LAST_ENTRY(last))
170603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		last = XATTR_NEXT_ENTRY(last);
171603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
172603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + len + size);
173603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
174603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	/* 1. Check space */
175603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (value) {
176603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		int free;
177603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		/*
178603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		 * If value is NULL, it is remove operation.
179603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		 * In case of update operation, we calculate free.
180603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		 */
181603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		free = MIN_OFFSET - ((char *)last - (char *)base_addr);
182603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		if (found)
183603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim			free = free + ENTRY_SIZE(here);
184603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		if (free < newsize) {
185603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim			error = -ENOSPC;
186603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim			goto exit;
187603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		}
188603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	}
189603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
190603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	/* 2. Remove old entry */
191603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (found) {
192603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		/*
193603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		 * If entry if sound, remove old entry.
194603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		 * If not found, remove operation is not needed
195603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		 */
196603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here);
197603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		int oldsize = ENTRY_SIZE(here);
198603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
199603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		memmove(here, next, (char *)last - (char *)next);
200603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		last = (struct f2fs_xattr_entry *)((char *)last - oldsize);
201603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		memset(last, 0, oldsize);
202603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
203603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	}
204603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
205603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	new_hsize = (char *)last - (char *)base_addr;
206603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
207603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	/* 3. Write new entry */
208603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (value) {
209603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		char *pval;
210603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		/*
211603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		 * Before we come here, old entry is removed.
212603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		 * We just write new entry.
213603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		 */
214603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		memset(last, 0, newsize);
215603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		last->e_name_index = index;
216603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		last->e_name_len = len;
217603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		memcpy(last->e_name, name, len);
218603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		pval = last->e_name + len;
219603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		memcpy(pval, value, size);
220603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		last->e_value_size = cpu_to_le16(size);
221603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		new_hsize += newsize;
222603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	}
223603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
224603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	write_all_xattrs(sbi, inode, new_hsize, base_addr);
225603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
226603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	/* inode need update */
227603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ret = dev_write_block(inode, ni.blk_addr);
228603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	ASSERT(ret >= 0);
229603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kimexit:
230603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	free(base_addr);
231603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	return error;
232603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim}
233603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
234603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kimint inode_set_selinux(struct f2fs_sb_info *sbi, u32 ino, const char *secon)
235603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim{
236603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	if (!secon)
237603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		return 0;
238603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim
239603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim	return f2fs_setxattr(sbi, ino, F2FS_XATTR_INDEX_SECURITY,
240603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim			XATTR_SELINUX_SUFFIX, secon, strlen(secon), 1);
241603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim}
242