2 * inline_data.c --- data in inode
4 * Copyright (C) 2012 Zheng Liu <wenqing.lz@taobao.com>
7 * This file may be redistributed under the terms of the GNU library
8 * General Public License, version 2.
17 #include "ext2_ext_attr.h"
22 struct ext2_inline_data {
25 size_t ea_size; /* the size of inline data in ea area */
29 static errcode_t ext2fs_inline_data_ea_set(struct ext2_inline_data *data)
31 struct ext2_xattr_handle *handle;
34 retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
38 retval = ext2fs_xattrs_read(handle);
42 retval = ext2fs_xattr_set(handle, "system.data",
43 data->ea_data, data->ea_size);
47 retval = ext2fs_xattrs_write(handle);
50 (void) ext2fs_xattrs_close(&handle);
54 static errcode_t ext2fs_inline_data_ea_get(struct ext2_inline_data *data)
56 struct ext2_xattr_handle *handle;
62 retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
66 retval = ext2fs_xattrs_read(handle);
70 retval = ext2fs_xattr_get(handle, "system.data",
71 (void **)&data->ea_data, &data->ea_size);
76 (void) ext2fs_xattrs_close(&handle);
80 errcode_t ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino, size_t *size)
82 struct ext2_inode inode;
83 struct ext2_inline_data data;
86 retval = ext2fs_read_inode(fs, ino, &inode);
90 if (!(inode.i_flags & EXT4_INLINE_DATA_FL))
91 return EXT2_ET_NO_INLINE_DATA;
95 retval = ext2fs_inline_data_ea_get(&data);
99 *size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size;
100 return ext2fs_free_mem(&data.ea_data);
103 int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino,
106 struct dir_context *ctx;
107 struct ext2_inode inode;
108 struct ext2_dir_entry dirent;
109 struct ext2_inline_data data;
110 int ret = BLOCK_ABORT;
111 e2_blkcnt_t blockcnt = 0;
113 ctx = (struct dir_context *)priv_data;
115 ctx->errcode = ext2fs_read_inode(fs, ino, &inode);
119 if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) {
120 ctx->errcode = EXT2_ET_NO_INLINE_DATA;
124 if (!LINUX_S_ISDIR(inode.i_mode)) {
125 ctx->errcode = EXT2_ET_NO_DIRECTORY;
130 /* we first check '.' and '..' dir */
133 ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent);
134 dirent.name[0] = '.';
135 dirent.name[1] = '\0';
136 ctx->buf = (char *)&dirent;
137 ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
138 ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
139 if (ret & BLOCK_ABORT)
142 dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]);
144 ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent);
145 dirent.name[0] = '.';
146 dirent.name[1] = '.';
147 dirent.name[2] = '\0';
148 ctx->buf = (char *)&dirent;
149 ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
150 ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
151 if (ret & BLOCK_INLINE_DATA_CHANGED) {
154 inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode);
155 err = ext2fs_write_inode(fs, ino, &inode);
158 ret &= ~BLOCK_INLINE_DATA_CHANGED;
160 if (ret & BLOCK_ABORT)
163 ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE;
164 ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
165 #ifdef WORDS_BIGENDIAN
166 ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
172 ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
173 if (ret & BLOCK_INLINE_DATA_CHANGED) {
174 #ifdef WORDS_BIGENDIAN
175 ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
182 ctx->errcode = ext2fs_write_inode(fs, ino, &inode);
185 ret &= ~BLOCK_INLINE_DATA_CHANGED;
187 if (ret & BLOCK_ABORT)
192 ctx->errcode = ext2fs_inline_data_ea_get(&data);
197 if (data.ea_size <= 0)
200 ctx->buf = data.ea_data;
201 ctx->buflen = data.ea_size;
202 #ifdef WORDS_BIGENDIAN
203 ctx.errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
210 ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
211 if (ret & BLOCK_INLINE_DATA_CHANGED) {
212 #ifdef WORDS_BIGENDIAN
213 ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
220 ctx->errcode = ext2fs_inline_data_ea_set(&data);
226 ext2fs_free_mem(&data.ea_data);
230 ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED);