inline_data.c revision 97581d448127f95dcc968c0785f7ab3413bf0222
1416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu/*
2416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * inline_data.c --- data in inode
3416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu *
4416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * Copyright (C) 2012 Zheng Liu <wenqing.lz@taobao.com>
5416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu *
6416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * %Begin-Header%
7416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * This file may be redistributed under the terms of the GNU library
8416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * General Public License, version 2.
9416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu * %End-Header%
10416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu */
11416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
12416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "config.h"
13416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include <stdio.h>
14416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include <time.h>
15416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
16416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "ext2_fs.h"
17416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "ext2_ext_attr.h"
18416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
19416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "ext2fs.h"
20416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#include "ext2fsP.h"
21416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
22416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liustruct ext2_inline_data {
23416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ext2_filsys fs;
24416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ext2_ino_t ino;
25416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	size_t ea_size;	/* the size of inline data in ea area */
26416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	void *ea_data;
27416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu};
28416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
29416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liustatic errcode_t ext2fs_inline_data_ea_set(struct ext2_inline_data *data)
30416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu{
31416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	struct ext2_xattr_handle *handle;
32416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	errcode_t retval;
33416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
34416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
35416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (retval)
36416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		return retval;
37416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
38416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	retval = ext2fs_xattrs_read(handle);
39416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (retval)
40416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto err;
41416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
42416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	retval = ext2fs_xattr_set(handle, "system.data",
43416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu				  data->ea_data, data->ea_size);
44416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (retval)
45416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto err;
46416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
47416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	retval = ext2fs_xattrs_write(handle);
48416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
49416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuerr:
50416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	(void) ext2fs_xattrs_close(&handle);
51416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	return retval;
52416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu}
53416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
54416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liustatic errcode_t ext2fs_inline_data_ea_get(struct ext2_inline_data *data)
55416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu{
56416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	struct ext2_xattr_handle *handle;
57416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	errcode_t retval;
58416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
59416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	data->ea_size = 0;
60416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	data->ea_data = 0;
61416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
62416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
63416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (retval)
64416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		return retval;
65416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
66416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	retval = ext2fs_xattrs_read(handle);
67416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (retval)
68416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto err;
69416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
70416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	retval = ext2fs_xattr_get(handle, "system.data",
71416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu				  (void **)&data->ea_data, &data->ea_size);
72416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (retval)
73416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto err;
74416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
75416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuerr:
76416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	(void) ext2fs_xattrs_close(&handle);
77416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	return retval;
78416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu}
79416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
8082e77d07ee6c9e2414233d4428887a22bf755609Zheng Liuerrcode_t ext2fs_inline_data_init(ext2_filsys fs, ext2_ino_t ino)
8182e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu{
8282e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu	struct ext2_inline_data data;
8382e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu
8482e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu	data.fs = fs;
8582e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu	data.ino = ino;
8682e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu	data.ea_size = 0;
8782e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu	data.ea_data = "";
8882e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu	return ext2fs_inline_data_ea_set(&data);
8982e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu}
9082e77d07ee6c9e2414233d4428887a22bf755609Zheng Liu
91133e94627b01823d2555450ddd1d95401ff2227aZheng Liuerrcode_t ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino, size_t *size)
92133e94627b01823d2555450ddd1d95401ff2227aZheng Liu{
93133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	struct ext2_inode inode;
94133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	struct ext2_inline_data data;
95133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	errcode_t retval;
96133e94627b01823d2555450ddd1d95401ff2227aZheng Liu
97133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	retval = ext2fs_read_inode(fs, ino, &inode);
98133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	if (retval)
99133e94627b01823d2555450ddd1d95401ff2227aZheng Liu		return retval;
100133e94627b01823d2555450ddd1d95401ff2227aZheng Liu
101133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	if (!(inode.i_flags & EXT4_INLINE_DATA_FL))
102133e94627b01823d2555450ddd1d95401ff2227aZheng Liu		return EXT2_ET_NO_INLINE_DATA;
103133e94627b01823d2555450ddd1d95401ff2227aZheng Liu
104133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	data.fs = fs;
105133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	data.ino = ino;
106133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	retval = ext2fs_inline_data_ea_get(&data);
107133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	if (retval)
108133e94627b01823d2555450ddd1d95401ff2227aZheng Liu		return retval;
109133e94627b01823d2555450ddd1d95401ff2227aZheng Liu
110133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	*size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size;
111133e94627b01823d2555450ddd1d95401ff2227aZheng Liu	return ext2fs_free_mem(&data.ea_data);
112133e94627b01823d2555450ddd1d95401ff2227aZheng Liu}
113416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
114416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuint ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino,
115416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu				   void *priv_data)
116416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu{
117416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	struct dir_context *ctx;
118416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	struct ext2_inode inode;
119416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	struct ext2_dir_entry dirent;
120416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	struct ext2_inline_data data;
121416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	int ret = BLOCK_ABORT;
122416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	e2_blkcnt_t blockcnt = 0;
123416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
124416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx = (struct dir_context *)priv_data;
125416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
126416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->errcode = ext2fs_read_inode(fs, ino, &inode);
127416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ctx->errcode)
128416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
129416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
130416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) {
131416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ctx->errcode = EXT2_ET_NO_INLINE_DATA;
132416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
133416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	}
134416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
135416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (!LINUX_S_ISDIR(inode.i_mode)) {
136416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ctx->errcode = EXT2_ET_NO_DIRECTORY;
137416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
138416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	}
139416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ret = 0;
140416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
141416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	/* we first check '.' and '..' dir */
142416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	dirent.inode = ino;
143416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	dirent.name_len = 1;
144416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent);
145416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	dirent.name[0] = '.';
146416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	dirent.name[1] = '\0';
147416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->buf = (char *)&dirent;
148416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
149416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
150416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ret & BLOCK_ABORT)
151416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
152416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
153416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]);
154416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	dirent.name_len = 2;
155416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent);
156416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	dirent.name[0] = '.';
157416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	dirent.name[1] = '.';
158416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	dirent.name[2] = '\0';
159416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->buf = (char *)&dirent;
160416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
161416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
162416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ret & BLOCK_INLINE_DATA_CHANGED) {
163416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		errcode_t err;
164416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
165416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode);
166416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		err = ext2fs_write_inode(fs, ino, &inode);
167416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		if (err)
168416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu			goto out;
169416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ret &= ~BLOCK_INLINE_DATA_CHANGED;
170416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	}
171416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ret & BLOCK_ABORT)
172416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
173416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
174416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE;
175416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
176416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#ifdef WORDS_BIGENDIAN
177416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
178416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ctx->errcode) {
179416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ret |= BLOCK_ABORT;
180416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
181416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	}
182416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#endif
183416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
184416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ret & BLOCK_INLINE_DATA_CHANGED) {
185416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#ifdef WORDS_BIGENDIAN
186416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
187416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu						       ctx->buflen, 0);
188416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		if (ctx->errcode) {
189416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu			ret |= BLOCK_ABORT;
190416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu			goto out;
191416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		}
192416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#endif
193416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ctx->errcode = ext2fs_write_inode(fs, ino, &inode);
194416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		if (ctx->errcode)
195416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu			ret |= BLOCK_ABORT;
196416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ret &= ~BLOCK_INLINE_DATA_CHANGED;
197416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	}
198416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ret & BLOCK_ABORT)
199416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
200416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
201416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	data.fs = fs;
202416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	data.ino = ino;
203416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->errcode = ext2fs_inline_data_ea_get(&data);
204416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ctx->errcode) {
205416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ret |= BLOCK_ABORT;
206416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
207416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	}
208416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (data.ea_size <= 0)
209416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
210416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
211416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->buf = data.ea_data;
212416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->buflen = data.ea_size;
213416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#ifdef WORDS_BIGENDIAN
214416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx.errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
215416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ctx.errcode) {
216416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ret |= BLOCK_ABORT;
217416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		goto out;
218416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	}
219416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#endif
220416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
221416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
222416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	if (ret & BLOCK_INLINE_DATA_CHANGED) {
223416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#ifdef WORDS_BIGENDIAN
224416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
225416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu						      ctx->buflen, 0);
226416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		if (ctx->errcode) {
227416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu			ret |= BLOCK_ABORT;
228416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu			goto out1;
229416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		}
230416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu#endif
231416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		ctx->errcode = ext2fs_inline_data_ea_set(&data);
232416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu		if (ctx->errcode)
233416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu			ret |= BLOCK_ABORT;
234416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	}
235416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
236416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuout1:
237416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ext2fs_free_mem(&data.ea_data);
238416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ctx->buf = 0;
239416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu
240416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liuout:
241416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED);
242416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu	return ret;
243416c1de94ddf7199aedaf7b039292a36b92699fbZheng Liu}
24446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
24597581d448127f95dcc968c0785f7ab3413bf0222Zheng Liuerrcode_t ext2fs_inline_data_ea_remove(ext2_filsys fs, ext2_ino_t ino)
24646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu{
24746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	struct ext2_xattr_handle *handle;
24846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	errcode_t retval;
24946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
25046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_xattrs_open(fs, ino, &handle);
25146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
25246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		return retval;
25346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
25446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_xattrs_read(handle);
25546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
25646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto err;
25746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
25846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_xattr_remove(handle, "system.data");
25946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
26046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto err;
26146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
26246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_xattrs_write(handle);
26346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
26446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liuerr:
26546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	(void) ext2fs_xattrs_close(&handle);
26646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	return retval;
26746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu}
26846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
26946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liustatic errcode_t ext2fs_inline_data_convert_dir(ext2_filsys fs, ext2_ino_t ino,
27046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu						char *bbuf, char *ibuf, int size)
27146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu{
27246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	struct ext2_dir_entry *dir, *dir2;
27346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	struct ext2_dir_entry_tail *t;
27446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	errcode_t retval;
27546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	unsigned int offset;
27646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	int csum_size = 0;
27746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	int filetype = 0;
27846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	int rec_len;
27946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
28046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
28146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
28246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		csum_size = sizeof(struct ext2_dir_entry_tail);
28346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
28446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	/* Create '.' and '..' */
28546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
28646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu				      EXT2_FEATURE_INCOMPAT_FILETYPE))
28746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		filetype = EXT2_FT_DIR;
28846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
28946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	/*
29046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	 * Set up entry for '.'
29146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	 */
29246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir = (struct ext2_dir_entry *) bbuf;
29346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir->inode = ino;
29446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	ext2fs_dirent_set_name_len(dir, 1);
29546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	ext2fs_dirent_set_file_type(dir, filetype);
29646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir->name[0] = '.';
29746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1);
29846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir->rec_len = EXT2_DIR_REC_LEN(1);
29946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
30046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	/*
30146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	 * Set up entry for '..'
30246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	 */
30346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir = (struct ext2_dir_entry *) (bbuf + dir->rec_len);
30446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir->rec_len = EXT2_DIR_REC_LEN(2);
30546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir->inode = ext2fs_le32_to_cpu(((__u32 *)ibuf)[0]);
30646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	ext2fs_dirent_set_name_len(dir, 2);
30746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	ext2fs_dirent_set_file_type(dir, filetype);
30846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir->name[0] = '.';
30946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir->name[1] = '.';
31046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
31146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	/*
31246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	 * Ajust the last rec_len
31346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	 */
31446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	offset = EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2);
31546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	dir = (struct ext2_dir_entry *) (bbuf + offset);
31646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	memcpy(bbuf + offset, ibuf + EXT4_INLINE_DATA_DOTDOT_SIZE,
31746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	       size - EXT4_INLINE_DATA_DOTDOT_SIZE);
31846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	size += EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) -
31946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		EXT4_INLINE_DATA_DOTDOT_SIZE;
32046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
32146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	do {
32246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		dir2 = dir;
32346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		retval = ext2fs_get_rec_len(fs, dir, &rec_len);
32446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		if (retval)
32546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu			goto err;
32646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		offset += rec_len;
32746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		dir = (struct ext2_dir_entry *) (bbuf + offset);
32846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	} while (offset < size);
32946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	rec_len += fs->blocksize - csum_size - offset;
33046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_set_rec_len(fs, rec_len, dir2);
33146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
33246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto err;
33346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
33446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (csum_size) {
33546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		t = EXT2_DIRENT_TAIL(bbuf, fs->blocksize);
33646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		ext2fs_initialize_dirent_tail(fs, t);
33746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	}
33846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
33946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liuerr:
34046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	return retval;
34146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu}
34246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
34346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liuerrcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino)
34446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu{
34546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	struct ext2_inode inode;
34646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	struct ext2_inline_data data;
34746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	errcode_t retval;
34846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	blk64_t blk;
34946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	char *inline_buf = 0;
35046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	char *blk_buf = 0;
35146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
35246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
35346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
35446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_read_inode(fs, ino, &inode);
35546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
35646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		return retval;
35746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
35846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (!(inode.i_flags & EXT4_INLINE_DATA_FL))
35946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		return EXT2_ET_NO_INLINE_DATA;
36046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
36146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	/* Get inline data first */
36246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	data.fs = fs;
36346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	data.ino = ino;
36446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_inline_data_ea_get(&data);
36546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
36646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		return retval;
36746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_get_mem(EXT4_MIN_INLINE_DATA_SIZE + data.ea_size,
36846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu				&inline_buf);
36946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
37046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto errout;
37146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
37246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	memcpy(inline_buf, (void *)inode.i_block, EXT4_MIN_INLINE_DATA_SIZE);
37346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (data.ea_size > 0) {
37446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		memcpy(inline_buf + EXT4_MIN_INLINE_DATA_SIZE,
37546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		       data.ea_data, data.ea_size);
37646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	}
37746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
37846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu#ifdef WORDS_BIGENDIAN
37946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_dirent_swab_in2(fs, inline_buf,
38046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu			data.ea_size + EXT4_MIN_INLINE_DATA_SIZE);
38146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
38246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto errout;
38346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu#endif
38446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
38546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	memset((void *)inode.i_block, 0, EXT4_MIN_INLINE_DATA_SIZE);
38646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_inline_data_ea_remove(fs, ino);
38746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
38846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto errout;
38946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
39046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_get_mem(fs->blocksize, &blk_buf);
39146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
39246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto errout;
39346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
39446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	/* Adjust the rec_len */
39546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf, inline_buf,
39646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu						EXT4_MIN_INLINE_DATA_SIZE +
39746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu							data.ea_size);
39846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
39946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto errout;
40046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
40146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	/* Allocate a new block */
40246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_new_block2(fs, 0, 0, &blk);
40346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
40446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto errout;
40546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino);
40646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
40746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto errout;
40846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
40946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	/* Update inode */
41046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT3_FEATURE_INCOMPAT_EXTENTS))
41146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		inode.i_flags |= EXT4_EXTENTS_FL;
41246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	inode.i_flags &= ~EXT4_INLINE_DATA_FL;
41346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	ext2fs_iblk_set(fs, &inode, 1);
41446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	inode.i_size = fs->blocksize;
41546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_bmap2(fs, ino, &inode, 0, BMAP_SET, 0, 0, &blk);
41646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
41746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto errout;
41846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	retval = ext2fs_write_inode(fs, ino, &inode);
41946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (retval)
42046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		goto errout;
42146bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	ext2fs_block_alloc_stats2(fs, blk, +1);
42246bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu
42346bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liuerrout:
42446bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (blk_buf)
42546bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		ext2fs_free_mem(&blk_buf);
42646bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	if (inline_buf)
42746bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu		ext2fs_free_mem(&inline_buf);
42846bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	ext2fs_free_mem(&data.ea_data);
42946bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu	return retval;
43046bd6bdfc8c2e79336267f639b7963bea4487c42Zheng Liu}
431