Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 3f49381

Browse files
ANDROID: Incremental fs: Create mapped file
Bug: 160634482 Test: incfs_test passes Signed-off-by: Paul Lawrence <[email protected]> Change-Id: Ic2ac8dfccd60f6c9c72c38bf323997fce7546c1c
1 parent 7c02f94 commit 3f49381

File tree

7 files changed

+571
-55
lines changed

7 files changed

+571
-55
lines changed

fs/incfs/data_mgmt.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/ktime.h>
99
#include <linux/lz4.h>
1010
#include <linux/mm.h>
11+
#include <linux/namei.h>
1112
#include <linux/pagemap.h>
1213
#include <linux/slab.h>
1314
#include <linux/types.h>
@@ -123,6 +124,86 @@ static void data_file_segment_init(struct data_file_segment *segment)
123124
INIT_LIST_HEAD(&segment->reads_list_head);
124125
}
125126

127+
char *file_id_to_str(incfs_uuid_t id)
128+
{
129+
char *result = kmalloc(1 + sizeof(id.bytes) * 2, GFP_NOFS);
130+
char *end;
131+
132+
if (!result)
133+
return NULL;
134+
135+
end = bin2hex(result, id.bytes, sizeof(id.bytes));
136+
*end = 0;
137+
return result;
138+
}
139+
140+
struct dentry *incfs_lookup_dentry(struct dentry *parent, const char *name)
141+
{
142+
struct inode *inode;
143+
struct dentry *result = NULL;
144+
145+
if (!parent)
146+
return ERR_PTR(-EFAULT);
147+
148+
inode = d_inode(parent);
149+
inode_lock_nested(inode, I_MUTEX_PARENT);
150+
result = lookup_one_len(name, parent, strlen(name));
151+
inode_unlock(inode);
152+
153+
if (IS_ERR(result))
154+
pr_warn("%s err:%ld\n", __func__, PTR_ERR(result));
155+
156+
return result;
157+
}
158+
159+
static struct data_file *handle_mapped_file(struct mount_info *mi,
160+
struct data_file *df)
161+
{
162+
char *file_id_str;
163+
struct dentry *index_file_dentry;
164+
struct path path;
165+
struct file *bf;
166+
struct data_file *result = NULL;
167+
168+
file_id_str = file_id_to_str(df->df_id);
169+
if (!file_id_str)
170+
return ERR_PTR(-ENOENT);
171+
172+
index_file_dentry = incfs_lookup_dentry(mi->mi_index_dir,
173+
file_id_str);
174+
kfree(file_id_str);
175+
if (!index_file_dentry)
176+
return ERR_PTR(-ENOENT);
177+
if (IS_ERR(index_file_dentry))
178+
return (struct data_file *)index_file_dentry;
179+
if (!d_really_is_positive(index_file_dentry)) {
180+
result = ERR_PTR(-ENOENT);
181+
goto out;
182+
}
183+
184+
path = (struct path) {
185+
.mnt = mi->mi_backing_dir_path.mnt,
186+
.dentry = index_file_dentry
187+
};
188+
189+
bf = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner);
190+
if (IS_ERR(bf)) {
191+
result = (struct data_file *)bf;
192+
goto out;
193+
}
194+
195+
result = incfs_open_data_file(mi, bf);
196+
fput(bf);
197+
if (IS_ERR(result))
198+
goto out;
199+
200+
result->df_mapped_offset = df->df_metadata_off;
201+
202+
out:
203+
dput(index_file_dentry);
204+
return result;
205+
}
206+
126207
struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
127208
{
128209
struct data_file *df = NULL;
@@ -167,6 +248,13 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
167248
if (size > 0)
168249
df->df_data_block_count = get_blocks_count_for_size(size);
169250

251+
if (df->df_header_flags & INCFS_FILE_MAPPED) {
252+
struct data_file *mapped_df = handle_mapped_file(mi, df);
253+
254+
incfs_free_data_file(df);
255+
return mapped_df;
256+
}
257+
170258
md_records = incfs_scan_metadata_chain(df);
171259
if (md_records < 0)
172260
error = md_records;

fs/incfs/data_mgmt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ struct data_file {
235235
/* Total number of blocks, data + hash */
236236
int df_total_block_count;
237237

238+
/* For mapped files, the offset into the actual file */
239+
loff_t df_mapped_offset;
240+
238241
struct file_attr n_attr;
239242

240243
struct mtree *df_hash_tree;
@@ -271,6 +274,8 @@ int incfs_realloc_mount_info(struct mount_info *mi,
271274

272275
void incfs_free_mount_info(struct mount_info *mi);
273276

277+
char *file_id_to_str(incfs_uuid_t id);
278+
struct dentry *incfs_lookup_dentry(struct dentry *parent, const char *name);
274279
struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf);
275280
void incfs_free_data_file(struct data_file *df);
276281

fs/incfs/format.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,7 @@ int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags)
233233
return -EFAULT;
234234

235235
return write_to_bf(bfc, &flags, sizeof(flags),
236-
offsetof(struct incfs_file_header,
237-
fh_file_header_flags));
236+
offsetof(struct incfs_file_header, fh_flags));
238237
}
239238

240239
/*
@@ -385,7 +384,7 @@ int incfs_write_signature_to_backing_file(struct backing_file_context *bfc,
385384
/*
386385
* Write a backing file header
387386
* It should always be called only on empty file.
388-
* incfs_super_block.s_first_md_offset is 0 for now, but will be updated
387+
* fh.fh_first_md_offset is 0 for now, but will be updated
389388
* once first metadata record is added.
390389
*/
391390
int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
@@ -415,6 +414,38 @@ int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
415414
return write_to_bf(bfc, &fh, sizeof(fh), file_pos);
416415
}
417416

417+
/*
418+
* Write a backing file header for a mapping file
419+
* It should always be called only on empty file.
420+
*/
421+
int incfs_write_mapping_fh_to_backing_file(struct backing_file_context *bfc,
422+
incfs_uuid_t *uuid, u64 file_size, u64 offset)
423+
{
424+
struct incfs_file_header fh = {};
425+
loff_t file_pos = 0;
426+
427+
if (!bfc)
428+
return -EFAULT;
429+
430+
fh.fh_magic = cpu_to_le64(INCFS_MAGIC_NUMBER);
431+
fh.fh_version = cpu_to_le64(INCFS_FORMAT_CURRENT_VER);
432+
fh.fh_header_size = cpu_to_le16(sizeof(fh));
433+
fh.fh_original_offset = cpu_to_le64(offset);
434+
fh.fh_data_block_size = cpu_to_le16(INCFS_DATA_FILE_BLOCK_SIZE);
435+
436+
fh.fh_mapped_file_size = cpu_to_le64(file_size);
437+
fh.fh_original_uuid = *uuid;
438+
fh.fh_flags = INCFS_FILE_MAPPED;
439+
440+
LOCK_REQUIRED(bfc->bc_mutex);
441+
442+
file_pos = incfs_get_end_offset(bfc->bc_file);
443+
if (file_pos != 0)
444+
return -EEXIST;
445+
446+
return write_to_bf(bfc, &fh, sizeof(fh), file_pos);
447+
}
448+
418449
/* Write a given data block and update file's blockmap to point it. */
419450
int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc,
420451
struct mem_range block, int block_index,
@@ -598,7 +629,7 @@ int incfs_read_file_header(struct backing_file_context *bfc,
598629
if (file_size)
599630
*file_size = le64_to_cpu(fh.fh_file_size);
600631
if (flags)
601-
*flags = le32_to_cpu(fh.fh_file_header_flags);
632+
*flags = le32_to_cpu(fh.fh_flags);
602633
return 0;
603634
}
604635

fs/incfs/format.h

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
*
7373
*
7474
* +-------------------------------------------+
75-
* | incfs_super_block |]---+
75+
* | incfs_file_header |]---+
7676
* +-------------------------------------------+ |
7777
* | metadata |<---+
7878
* | incfs_file_signature |]---+
@@ -123,6 +123,7 @@ enum incfs_metadata_type {
123123

124124
enum incfs_file_header_flags {
125125
INCFS_FILE_COMPLETE = 1 << 0,
126+
INCFS_FILE_MAPPED = 1 << 1,
126127
};
127128

128129
/* Header included at the beginning of all metadata records on the disk. */
@@ -164,20 +165,33 @@ struct incfs_file_header {
164165
__le16 fh_data_block_size;
165166

166167
/* File flags, from incfs_file_header_flags */
167-
__le32 fh_file_header_flags;
168+
__le32 fh_flags;
168169

169-
/* Offset of the first metadata record */
170-
__le64 fh_first_md_offset;
171-
172-
/*
173-
* Put file specific information after this point
174-
*/
175-
176-
/* Full size of the file's content */
177-
__le64 fh_file_size;
178-
179-
/* File uuid */
180-
incfs_uuid_t fh_uuid;
170+
union {
171+
/* Standard incfs file */
172+
struct {
173+
/* Offset of the first metadata record */
174+
__le64 fh_first_md_offset;
175+
176+
/* Full size of the file's content */
177+
__le64 fh_file_size;
178+
179+
/* File uuid */
180+
incfs_uuid_t fh_uuid;
181+
};
182+
183+
/* Mapped file - INCFS_FILE_MAPPED set in fh_flags */
184+
struct {
185+
/* Offset in original file */
186+
__le64 fh_original_offset;
187+
188+
/* Full size of the file's content */
189+
__le64 fh_mapped_file_size;
190+
191+
/* Original file's uuid */
192+
incfs_uuid_t fh_original_uuid;
193+
};
194+
};
181195
} __packed;
182196

183197
enum incfs_block_map_entry_flags {
@@ -294,6 +308,9 @@ int incfs_write_blockmap_to_backing_file(struct backing_file_context *bfc,
294308
int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
295309
incfs_uuid_t *uuid, u64 file_size);
296310

311+
int incfs_write_mapping_fh_to_backing_file(struct backing_file_context *bfc,
312+
incfs_uuid_t *uuid, u64 file_size, u64 offset);
313+
297314
int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc,
298315
struct mem_range block,
299316
int block_index, loff_t bm_base_off,

0 commit comments

Comments
 (0)