• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2 /*
3  * Copyright (C) 2018-2019 HUAWEI, Inc.
4  *             http://www.huawei.com/
5  * Created by Li Guifu <bluce.liguifu@huawei.com>
6  * with heavy changes by Gao Xiang <xiang@kernel.org>
7  */
8 #define _GNU_SOURCE
9 #ifdef EROFS_MT_ENABLED
10 #include <pthread.h>
11 #endif
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <sys/stat.h>
16 #include <config.h>
17 #if defined(HAVE_SYS_SYSMACROS_H)
18 #include <sys/sysmacros.h>
19 #endif
20 #include <dirent.h>
21 #include "erofs/print.h"
22 #include "erofs/diskbuf.h"
23 #include "erofs/inode.h"
24 #include "erofs/cache.h"
25 #include "erofs/compress.h"
26 #include "erofs/xattr.h"
27 #include "erofs/exclude.h"
28 #include "erofs/block_list.h"
29 #include "erofs/compress_hints.h"
30 #include "erofs/blobchunk.h"
31 #include "erofs/fragments.h"
32 #include "liberofs_private.h"
33 
34 #define S_SHIFT                 12
35 static unsigned char erofs_ftype_by_mode[S_IFMT >> S_SHIFT] = {
36 	[S_IFREG >> S_SHIFT]  = EROFS_FT_REG_FILE,
37 	[S_IFDIR >> S_SHIFT]  = EROFS_FT_DIR,
38 	[S_IFCHR >> S_SHIFT]  = EROFS_FT_CHRDEV,
39 	[S_IFBLK >> S_SHIFT]  = EROFS_FT_BLKDEV,
40 	[S_IFIFO >> S_SHIFT]  = EROFS_FT_FIFO,
41 	[S_IFSOCK >> S_SHIFT] = EROFS_FT_SOCK,
42 	[S_IFLNK >> S_SHIFT]  = EROFS_FT_SYMLINK,
43 };
44 
erofs_mode_to_ftype(umode_t mode)45 unsigned char erofs_mode_to_ftype(umode_t mode)
46 {
47 	return erofs_ftype_by_mode[(mode & S_IFMT) >> S_SHIFT];
48 }
49 
50 static const unsigned char erofs_dtype_by_ftype[EROFS_FT_MAX] = {
51 	[EROFS_FT_UNKNOWN]	= DT_UNKNOWN,
52 	[EROFS_FT_REG_FILE]	= DT_REG,
53 	[EROFS_FT_DIR]		= DT_DIR,
54 	[EROFS_FT_CHRDEV]	= DT_CHR,
55 	[EROFS_FT_BLKDEV]	= DT_BLK,
56 	[EROFS_FT_FIFO]		= DT_FIFO,
57 	[EROFS_FT_SOCK]		= DT_SOCK,
58 	[EROFS_FT_SYMLINK]	= DT_LNK
59 };
60 
61 static const umode_t erofs_dtype_by_umode[EROFS_FT_MAX] = {
62 	[EROFS_FT_UNKNOWN]	= S_IFMT,
63 	[EROFS_FT_REG_FILE]	= S_IFREG,
64 	[EROFS_FT_DIR]		= S_IFDIR,
65 	[EROFS_FT_CHRDEV]	= S_IFCHR,
66 	[EROFS_FT_BLKDEV]	= S_IFBLK,
67 	[EROFS_FT_FIFO]		= S_IFIFO,
68 	[EROFS_FT_SOCK]		= S_IFSOCK,
69 	[EROFS_FT_SYMLINK]	= S_IFLNK
70 };
71 
erofs_ftype_to_mode(unsigned int ftype,unsigned int perm)72 umode_t erofs_ftype_to_mode(unsigned int ftype, unsigned int perm)
73 {
74 	if (ftype >= EROFS_FT_MAX)
75 		ftype = EROFS_FT_UNKNOWN;
76 
77 	return erofs_dtype_by_umode[ftype] | perm;
78 }
79 
erofs_ftype_to_dtype(unsigned int filetype)80 unsigned char erofs_ftype_to_dtype(unsigned int filetype)
81 {
82 	if (filetype >= EROFS_FT_MAX)
83 		return DT_UNKNOWN;
84 
85 	return erofs_dtype_by_ftype[filetype];
86 }
87 
88 #define NR_INODE_HASHTABLE	16384
89 
90 struct list_head inode_hashtable[NR_INODE_HASHTABLE];
91 
erofs_inode_manager_init(void)92 void erofs_inode_manager_init(void)
93 {
94 	unsigned int i;
95 
96 	for (i = 0; i < NR_INODE_HASHTABLE; ++i)
97 		init_list_head(&inode_hashtable[i]);
98 }
99 
erofs_insert_ihash(struct erofs_inode * inode)100 void erofs_insert_ihash(struct erofs_inode *inode)
101 {
102 	unsigned int nr = (inode->i_ino[1] ^ inode->dev) % NR_INODE_HASHTABLE;
103 
104 	list_add(&inode->i_hash, &inode_hashtable[nr]);
105 }
106 
107 /* get the inode from the (source) inode # */
erofs_iget(dev_t dev,ino_t ino)108 struct erofs_inode *erofs_iget(dev_t dev, ino_t ino)
109 {
110 	struct list_head *head =
111 		&inode_hashtable[(ino ^ dev) % NR_INODE_HASHTABLE];
112 	struct erofs_inode *inode;
113 
114 	list_for_each_entry(inode, head, i_hash)
115 		if (inode->i_ino[1] == ino && inode->dev == dev)
116 			return erofs_igrab(inode);
117 	return NULL;
118 }
119 
erofs_iget_by_nid(erofs_nid_t nid)120 struct erofs_inode *erofs_iget_by_nid(erofs_nid_t nid)
121 {
122 	struct list_head *head =
123 		&inode_hashtable[nid % NR_INODE_HASHTABLE];
124 	struct erofs_inode *inode;
125 
126 	list_for_each_entry(inode, head, i_hash)
127 		if (inode->nid == nid)
128 			return erofs_igrab(inode);
129 	return NULL;
130 }
131 
erofs_iput(struct erofs_inode * inode)132 unsigned int erofs_iput(struct erofs_inode *inode)
133 {
134 	struct erofs_dentry *d, *t;
135 	unsigned long got = erofs_atomic_dec_return(&inode->i_count);
136 
137 	if (got >= 1)
138 		return got;
139 
140 	list_for_each_entry_safe(d, t, &inode->i_subdirs, d_child)
141 		free(d);
142 
143 	free(inode->compressmeta);
144 	if (inode->eof_tailraw)
145 		free(inode->eof_tailraw);
146 	list_del(&inode->i_hash);
147 	if (inode->i_srcpath)
148 		free(inode->i_srcpath);
149 
150 	if (inode->datasource == EROFS_INODE_DATA_SOURCE_DISKBUF) {
151 		erofs_diskbuf_close(inode->i_diskbuf);
152 		free(inode->i_diskbuf);
153 	} else if (inode->i_link) {
154 		free(inode->i_link);
155 	}
156 	free(inode);
157 	return 0;
158 }
159 
erofs_d_alloc(struct erofs_inode * parent,const char * name)160 struct erofs_dentry *erofs_d_alloc(struct erofs_inode *parent,
161 				   const char *name)
162 {
163 	struct erofs_dentry *d = malloc(sizeof(*d));
164 
165 	if (!d)
166 		return ERR_PTR(-ENOMEM);
167 
168 	strncpy(d->name, name, EROFS_NAME_LEN - 1);
169 	d->name[EROFS_NAME_LEN - 1] = '\0';
170 	d->inode = NULL;
171 	d->type = EROFS_FT_UNKNOWN;
172 	d->validnid = false;
173 	list_add_tail(&d->d_child, &parent->i_subdirs);
174 	return d;
175 }
176 
177 /* allocate main data for an inode */
erofs_allocate_inode_bh_data(struct erofs_inode * inode,erofs_blk_t nblocks)178 int erofs_allocate_inode_bh_data(struct erofs_inode *inode, erofs_blk_t nblocks)
179 {
180 	struct erofs_bufmgr *bmgr = inode->sbi->bmgr;
181 	struct erofs_buffer_head *bh;
182 	int ret, type;
183 
184 	if (!nblocks) {
185 		/* it has only tail-end data */
186 		inode->u.i_blkaddr = NULL_ADDR;
187 		return 0;
188 	}
189 
190 	/* allocate main data buffer */
191 	type = S_ISDIR(inode->i_mode) ? DIRA : DATA;
192 	bh = erofs_balloc(bmgr, type, erofs_pos(inode->sbi, nblocks), 0, 0);
193 	if (IS_ERR(bh))
194 		return PTR_ERR(bh);
195 
196 	bh->op = &erofs_skip_write_bhops;
197 	inode->bh_data = bh;
198 
199 	/* get blkaddr of the bh */
200 	ret = erofs_mapbh(NULL, bh->block);
201 	DBG_BUGON(ret < 0);
202 
203 	/* write blocks except for the tail-end block */
204 	inode->u.i_blkaddr = bh->block->blkaddr;
205 	return 0;
206 }
207 
comp_subdir(const void * a,const void * b)208 static int comp_subdir(const void *a, const void *b)
209 {
210 	const struct erofs_dentry *da, *db;
211 
212 	da = *((const struct erofs_dentry **)a);
213 	db = *((const struct erofs_dentry **)b);
214 	return strcmp(da->name, db->name);
215 }
216 
erofs_init_empty_dir(struct erofs_inode * dir)217 int erofs_init_empty_dir(struct erofs_inode *dir)
218 {
219 	struct erofs_dentry *d;
220 
221 	/* dot is pointed to the current dir inode */
222 	d = erofs_d_alloc(dir, ".");
223 	if (IS_ERR(d))
224 		return PTR_ERR(d);
225 	d->inode = erofs_igrab(dir);
226 	d->type = EROFS_FT_DIR;
227 
228 	/* dotdot is pointed to the parent dir */
229 	d = erofs_d_alloc(dir, "..");
230 	if (IS_ERR(d))
231 		return PTR_ERR(d);
232 	d->inode = erofs_igrab(erofs_parent_inode(dir));
233 	d->type = EROFS_FT_DIR;
234 
235 	dir->i_nlink = 2;
236 	return 0;
237 }
238 
erofs_prepare_dir_file(struct erofs_inode * dir,unsigned int nr_subdirs)239 static int erofs_prepare_dir_file(struct erofs_inode *dir,
240 				  unsigned int nr_subdirs)
241 {
242 	struct erofs_sb_info *sbi = dir->sbi;
243 	struct erofs_dentry *d, *n, **sorted_d;
244 	unsigned int i;
245 	unsigned int d_size = 0;
246 
247 	sorted_d = malloc(nr_subdirs * sizeof(d));
248 	if (!sorted_d)
249 		return -ENOMEM;
250 	i = 0;
251 	list_for_each_entry_safe(d, n, &dir->i_subdirs, d_child) {
252 		list_del(&d->d_child);
253 		sorted_d[i++] = d;
254 	}
255 	DBG_BUGON(i != nr_subdirs);
256 	qsort(sorted_d, nr_subdirs, sizeof(d), comp_subdir);
257 	for (i = 0; i < nr_subdirs; i++)
258 		list_add_tail(&sorted_d[i]->d_child, &dir->i_subdirs);
259 	free(sorted_d);
260 
261 	/* let's calculate dir size */
262 	list_for_each_entry(d, &dir->i_subdirs, d_child) {
263 		int len = strlen(d->name) + sizeof(struct erofs_dirent);
264 
265 		if (erofs_blkoff(sbi, d_size) + len > erofs_blksiz(sbi))
266 			d_size = round_up(d_size, erofs_blksiz(sbi));
267 		d_size += len;
268 	}
269 	dir->i_size = d_size;
270 
271 	/* no compression for all dirs */
272 	dir->datalayout = EROFS_INODE_FLAT_INLINE;
273 
274 	/* it will be used in erofs_prepare_inode_buffer */
275 	dir->idata_size = d_size % erofs_blksiz(sbi);
276 	return 0;
277 }
278 
fill_dirblock(char * buf,unsigned int size,unsigned int q,struct erofs_dentry * head,struct erofs_dentry * end)279 static void fill_dirblock(char *buf, unsigned int size, unsigned int q,
280 			  struct erofs_dentry *head, struct erofs_dentry *end)
281 {
282 	unsigned int p = 0;
283 
284 	/* write out all erofs_dirents + filenames */
285 	while (head != end) {
286 		const unsigned int namelen = strlen(head->name);
287 		struct erofs_dirent d = {
288 			.nid = cpu_to_le64(head->nid),
289 			.nameoff = cpu_to_le16(q),
290 			.file_type = head->type,
291 		};
292 
293 		memcpy(buf + p, &d, sizeof(d));
294 		memcpy(buf + q, head->name, namelen);
295 		p += sizeof(d);
296 		q += namelen;
297 
298 		head = list_next_entry(head, d_child);
299 	}
300 	memset(buf + q, 0, size - q);
301 }
302 
write_dirblock(struct erofs_sb_info * sbi,unsigned int q,struct erofs_dentry * head,struct erofs_dentry * end,erofs_blk_t blkaddr)303 static int write_dirblock(struct erofs_sb_info *sbi,
304 			  unsigned int q, struct erofs_dentry *head,
305 			  struct erofs_dentry *end, erofs_blk_t blkaddr)
306 {
307 	char buf[EROFS_MAX_BLOCK_SIZE];
308 
309 	fill_dirblock(buf, erofs_blksiz(sbi), q, head, end);
310 	return erofs_blk_write(sbi, buf, blkaddr, 1);
311 }
312 
erofs_lookupnid(struct erofs_inode * inode)313 erofs_nid_t erofs_lookupnid(struct erofs_inode *inode)
314 {
315 	struct erofs_buffer_head *const bh = inode->bh;
316 	struct erofs_sb_info *sbi = inode->sbi;
317 	erofs_off_t off, meta_offset;
318 
319 	if (bh && (long long)inode->nid <= 0) {
320 		erofs_mapbh(NULL, bh->block);
321 		off = erofs_btell(bh, false);
322 
323 		meta_offset = erofs_pos(sbi, sbi->meta_blkaddr);
324 		DBG_BUGON(off < meta_offset);
325 		inode->nid = (off - meta_offset) >> EROFS_ISLOTBITS;
326 		erofs_dbg("Assign nid %llu to file %s (mode %05o)",
327 			  inode->nid, inode->i_srcpath, inode->i_mode);
328 	}
329 	if (__erofs_unlikely(IS_ROOT(inode)) && inode->nid > 0xffff)
330 		return sbi->root_nid;
331 	return inode->nid;
332 }
333 
erofs_d_invalidate(struct erofs_dentry * d)334 static void erofs_d_invalidate(struct erofs_dentry *d)
335 {
336 	struct erofs_inode *const inode = d->inode;
337 
338 	if (d->validnid)
339 		return;
340 	d->nid = erofs_lookupnid(inode);
341 	d->validnid = true;
342 	erofs_iput(inode);
343 }
344 
erofs_rebuild_inode_fix_pnid(struct erofs_inode * parent,erofs_nid_t nid)345 static int erofs_rebuild_inode_fix_pnid(struct erofs_inode *parent,
346 					erofs_nid_t nid)
347 {
348 	struct erofs_inode dir = {
349 		.sbi = parent->sbi,
350 		.nid = nid
351 	};
352 	unsigned int bsz = erofs_blksiz(dir.sbi);
353 	unsigned int err, isz;
354 	erofs_off_t boff, off;
355 	erofs_nid_t pnid;
356 	bool fixed = false;
357 
358 	err = erofs_read_inode_from_disk(&dir);
359 	if (err)
360 		return err;
361 
362 	if (!S_ISDIR(dir.i_mode))
363 		return -ENOTDIR;
364 
365 	if (dir.datalayout != EROFS_INODE_FLAT_INLINE &&
366 	    dir.datalayout != EROFS_INODE_FLAT_PLAIN)
367 		return -EOPNOTSUPP;
368 
369 	pnid = erofs_lookupnid(parent);
370 	isz = dir.inode_isize + dir.xattr_isize;
371 	boff = erofs_pos(dir.sbi, dir.u.i_blkaddr);
372 	for (off = 0; off < dir.i_size; off += bsz) {
373 		char buf[EROFS_MAX_BLOCK_SIZE];
374 		struct erofs_dirent *de = (struct erofs_dirent *)buf;
375 		unsigned int nameoff, count, de_nameoff;
376 
377 		count = min_t(erofs_off_t, bsz, dir.i_size - off);
378 		err = erofs_pread(&dir, buf, count, off);
379 		if (err)
380 			return err;
381 
382 		nameoff = le16_to_cpu(de->nameoff);
383 		if (nameoff < sizeof(struct erofs_dirent) ||
384 		    nameoff >= count) {
385 			erofs_err("invalid de[0].nameoff %u @ nid %llu, offset %llu",
386 				  nameoff, dir.nid | 0ULL, off | 0ULL);
387 			return -EFSCORRUPTED;
388 		}
389 
390 		while ((char *)de < buf + nameoff) {
391 			de_nameoff = le16_to_cpu(de->nameoff);
392 			if (((char *)(de + 1) >= buf + nameoff ?
393 				strnlen(buf + de_nameoff, count - de_nameoff) == 2 :
394 				le16_to_cpu(de[1].nameoff) == de_nameoff + 2) &&
395 			   !memcmp(buf + de_nameoff, "..", 2)) {
396 				if (de->nid == cpu_to_le64(pnid))
397 					return 0;
398 				de->nid = cpu_to_le64(pnid);
399 				fixed = true;
400 				break;
401 			}
402 			++de;
403 		}
404 
405 		if (!fixed)
406 			continue;
407 		err = erofs_dev_write(dir.sbi, buf,
408 			(off + bsz > dir.i_size &&
409 				dir.datalayout == EROFS_INODE_FLAT_INLINE ?
410 				erofs_iloc(&dir) + isz : boff + off), count);
411 		erofs_dbg("directory %llu pNID is updated to %llu",
412 			  nid | 0ULL, pnid | 0ULL);
413 		break;
414 	}
415 	if (err || fixed)
416 		return err;
417 
418 	erofs_err("directory data %llu is corrupted (\"..\" not found)",
419 		  nid | 0ULL);
420 	return -EFSCORRUPTED;
421 }
422 
erofs_write_dir_file(struct erofs_inode * dir)423 static int erofs_write_dir_file(struct erofs_inode *dir)
424 {
425 	struct erofs_dentry *head = list_first_entry(&dir->i_subdirs,
426 						     struct erofs_dentry,
427 						     d_child);
428 	struct erofs_sb_info *sbi = dir->sbi;
429 	struct erofs_dentry *d;
430 	int ret;
431 	unsigned int q, used, blkno;
432 
433 	q = used = blkno = 0;
434 
435 	/* allocate dir main data */
436 	ret = erofs_allocate_inode_bh_data(dir, erofs_blknr(sbi, dir->i_size));
437 	if (ret)
438 		return ret;
439 
440 	list_for_each_entry(d, &dir->i_subdirs, d_child) {
441 		const unsigned int len = strlen(d->name) +
442 			sizeof(struct erofs_dirent);
443 
444 		/* XXX: a bit hacky, but to avoid another traversal */
445 		if (d->validnid && d->type == EROFS_FT_DIR) {
446 			ret = erofs_rebuild_inode_fix_pnid(dir, d->nid);
447 			if (ret)
448 				return ret;
449 		}
450 
451 		erofs_d_invalidate(d);
452 		if (used + len > erofs_blksiz(sbi)) {
453 			ret = write_dirblock(sbi, q, head, d,
454 					     dir->u.i_blkaddr + blkno);
455 			if (ret)
456 				return ret;
457 
458 			head = d;
459 			q = used = 0;
460 			++blkno;
461 		}
462 		used += len;
463 		q += sizeof(struct erofs_dirent);
464 	}
465 
466 	DBG_BUGON(used > erofs_blksiz(sbi));
467 	if (used == erofs_blksiz(sbi)) {
468 		DBG_BUGON(dir->i_size % erofs_blksiz(sbi));
469 		DBG_BUGON(dir->idata_size);
470 		return write_dirblock(sbi, q, head, d, dir->u.i_blkaddr + blkno);
471 	}
472 	DBG_BUGON(used != dir->i_size % erofs_blksiz(sbi));
473 	if (used) {
474 		/* fill tail-end dir block */
475 		dir->idata = malloc(used);
476 		if (!dir->idata)
477 			return -ENOMEM;
478 		DBG_BUGON(used != dir->idata_size);
479 		fill_dirblock(dir->idata, dir->idata_size, q, head, d);
480 	}
481 	return 0;
482 }
483 
erofs_write_file_from_buffer(struct erofs_inode * inode,char * buf)484 int erofs_write_file_from_buffer(struct erofs_inode *inode, char *buf)
485 {
486 	struct erofs_sb_info *sbi = inode->sbi;
487 	const unsigned int nblocks = erofs_blknr(sbi, inode->i_size);
488 	int ret;
489 
490 	inode->datalayout = EROFS_INODE_FLAT_INLINE;
491 
492 	ret = erofs_allocate_inode_bh_data(inode, nblocks);
493 	if (ret)
494 		return ret;
495 
496 	if (nblocks)
497 		erofs_blk_write(sbi, buf, inode->u.i_blkaddr, nblocks);
498 	inode->idata_size = inode->i_size % erofs_blksiz(sbi);
499 	if (inode->idata_size) {
500 		inode->idata = malloc(inode->idata_size);
501 		if (!inode->idata)
502 			return -ENOMEM;
503 		memcpy(inode->idata, buf + erofs_pos(sbi, nblocks),
504 		       inode->idata_size);
505 	}
506 	return 0;
507 }
508 
509 /* rules to decide whether a file could be compressed or not */
erofs_file_is_compressible(struct erofs_inode * inode)510 static bool erofs_file_is_compressible(struct erofs_inode *inode)
511 {
512 	if (cfg.c_compress_hints_file)
513 		return z_erofs_apply_compress_hints(inode);
514 	return true;
515 }
516 
write_uncompressed_file_from_fd(struct erofs_inode * inode,int fd)517 static int write_uncompressed_file_from_fd(struct erofs_inode *inode, int fd)
518 {
519 	struct erofs_sb_info *sbi = inode->sbi;
520 	erofs_blk_t nblocks, i;
521 	unsigned int len;
522 	int ret;
523 
524 	inode->datalayout = EROFS_INODE_FLAT_INLINE;
525 	nblocks = inode->i_size >> sbi->blkszbits;
526 
527 	ret = erofs_allocate_inode_bh_data(inode, nblocks);
528 	if (ret)
529 		return ret;
530 
531 	for (i = 0; i < nblocks; i += (len >> sbi->blkszbits)) {
532 		len = min_t(u64, round_down(UINT_MAX, 1U << sbi->blkszbits),
533 			    erofs_pos(sbi, nblocks - i));
534 		ret = erofs_io_xcopy(&sbi->bdev,
535 				     erofs_pos(sbi, inode->u.i_blkaddr + i),
536 				     &((struct erofs_vfile){ .fd = fd }), len,
537 			inode->datasource == EROFS_INODE_DATA_SOURCE_DISKBUF);
538 		if (ret)
539 			return ret;
540 	}
541 
542 	/* read the tail-end data */
543 	inode->idata_size = inode->i_size % erofs_blksiz(sbi);
544 	if (inode->idata_size) {
545 		inode->idata = malloc(inode->idata_size);
546 		if (!inode->idata)
547 			return -ENOMEM;
548 
549 		ret = read(fd, inode->idata, inode->idata_size);
550 		if (ret < inode->idata_size) {
551 			free(inode->idata);
552 			inode->idata = NULL;
553 			return -EIO;
554 		}
555 	}
556 	erofs_droid_blocklist_write(inode, inode->u.i_blkaddr, nblocks);
557 	return 0;
558 }
559 
erofs_write_unencoded_file(struct erofs_inode * inode,int fd,u64 fpos)560 int erofs_write_unencoded_file(struct erofs_inode *inode, int fd, u64 fpos)
561 {
562 	if (cfg.c_chunkbits) {
563 		inode->u.chunkbits = cfg.c_chunkbits;
564 		/* chunk indexes when explicitly specified */
565 		inode->u.chunkformat = 0;
566 		if (cfg.c_force_chunkformat == FORCE_INODE_CHUNK_INDEXES)
567 			inode->u.chunkformat = EROFS_CHUNK_FORMAT_INDEXES;
568 		return erofs_blob_write_chunked_file(inode, fd, fpos);
569 	}
570 
571 	/* fallback to all data uncompressed */
572 	return write_uncompressed_file_from_fd(inode, fd);
573 }
574 
erofs_iflush(struct erofs_inode * inode)575 int erofs_iflush(struct erofs_inode *inode)
576 {
577 	const u16 icount = EROFS_INODE_XATTR_ICOUNT(inode->xattr_isize);
578 	struct erofs_sb_info *sbi = inode->sbi;
579 	erofs_off_t off;
580 	union {
581 		struct erofs_inode_compact dic;
582 		struct erofs_inode_extended die;
583 	} u = {};
584 	int ret;
585 
586 	if (inode->bh)
587 		off = erofs_btell(inode->bh, false);
588 	else
589 		off = erofs_iloc(inode);
590 
591 	switch (inode->inode_isize) {
592 	case sizeof(struct erofs_inode_compact):
593 		u.dic.i_format = cpu_to_le16(0 | (inode->datalayout << 1));
594 		u.dic.i_xattr_icount = cpu_to_le16(icount);
595 		u.dic.i_mode = cpu_to_le16(inode->i_mode);
596 		u.dic.i_nlink = cpu_to_le16(inode->i_nlink);
597 		u.dic.i_size = cpu_to_le32((u32)inode->i_size);
598 
599 		u.dic.i_ino = cpu_to_le32(inode->i_ino[0]);
600 
601 		u.dic.i_uid = cpu_to_le16((u16)inode->i_uid);
602 		u.dic.i_gid = cpu_to_le16((u16)inode->i_gid);
603 
604 		switch (inode->i_mode & S_IFMT) {
605 		case S_IFCHR:
606 		case S_IFBLK:
607 		case S_IFIFO:
608 		case S_IFSOCK:
609 			u.dic.i_u.rdev = cpu_to_le32(inode->u.i_rdev);
610 			break;
611 
612 		default:
613 			if (is_inode_layout_compression(inode))
614 				u.dic.i_u.compressed_blocks =
615 					cpu_to_le32(inode->u.i_blocks);
616 			else if (inode->datalayout ==
617 					EROFS_INODE_CHUNK_BASED)
618 				u.dic.i_u.c.format =
619 					cpu_to_le16(inode->u.chunkformat);
620 			else
621 				u.dic.i_u.raw_blkaddr =
622 					cpu_to_le32(inode->u.i_blkaddr);
623 			break;
624 		}
625 		break;
626 	case sizeof(struct erofs_inode_extended):
627 		u.die.i_format = cpu_to_le16(1 | (inode->datalayout << 1));
628 		u.die.i_xattr_icount = cpu_to_le16(icount);
629 		u.die.i_mode = cpu_to_le16(inode->i_mode);
630 		u.die.i_nlink = cpu_to_le32(inode->i_nlink);
631 		u.die.i_size = cpu_to_le64(inode->i_size);
632 
633 		u.die.i_ino = cpu_to_le32(inode->i_ino[0]);
634 
635 		u.die.i_uid = cpu_to_le32(inode->i_uid);
636 		u.die.i_gid = cpu_to_le32(inode->i_gid);
637 
638 		u.die.i_mtime = cpu_to_le64(inode->i_mtime);
639 		u.die.i_mtime_nsec = cpu_to_le32(inode->i_mtime_nsec);
640 
641 		switch (inode->i_mode & S_IFMT) {
642 		case S_IFCHR:
643 		case S_IFBLK:
644 		case S_IFIFO:
645 		case S_IFSOCK:
646 			u.die.i_u.rdev = cpu_to_le32(inode->u.i_rdev);
647 			break;
648 
649 		default:
650 			if (is_inode_layout_compression(inode))
651 				u.die.i_u.compressed_blocks =
652 					cpu_to_le32(inode->u.i_blocks);
653 			else if (inode->datalayout ==
654 					EROFS_INODE_CHUNK_BASED)
655 				u.die.i_u.c.format =
656 					cpu_to_le16(inode->u.chunkformat);
657 			else
658 				u.die.i_u.raw_blkaddr =
659 					cpu_to_le32(inode->u.i_blkaddr);
660 			break;
661 		}
662 		break;
663 	default:
664 		erofs_err("unsupported on-disk inode version of nid %llu",
665 			  (unsigned long long)inode->nid);
666 		BUG_ON(1);
667 	}
668 
669 	ret = erofs_dev_write(sbi, &u, off, inode->inode_isize);
670 	if (ret)
671 		return ret;
672 	off += inode->inode_isize;
673 
674 	if (inode->xattr_isize) {
675 		char *xattrs = erofs_export_xattr_ibody(inode);
676 
677 		if (IS_ERR(xattrs))
678 			return PTR_ERR(xattrs);
679 
680 		ret = erofs_dev_write(sbi, xattrs, off, inode->xattr_isize);
681 		free(xattrs);
682 		if (ret)
683 			return ret;
684 
685 		off += inode->xattr_isize;
686 	}
687 
688 	if (inode->extent_isize) {
689 		if (inode->datalayout == EROFS_INODE_CHUNK_BASED) {
690 			ret = erofs_blob_write_chunk_indexes(inode, off);
691 			if (ret)
692 				return ret;
693 		} else {
694 			/* write compression metadata */
695 			off = roundup(off, 8);
696 			ret = erofs_dev_write(sbi, inode->compressmeta, off,
697 					      inode->extent_isize);
698 			if (ret)
699 				return ret;
700 		}
701 	}
702 	return 0;
703 }
704 
erofs_bh_flush_write_inode(struct erofs_buffer_head * bh)705 static int erofs_bh_flush_write_inode(struct erofs_buffer_head *bh)
706 {
707 	struct erofs_inode *inode = bh->fsprivate;
708 	int ret;
709 
710 	DBG_BUGON(inode->bh != bh);
711 	ret = erofs_iflush(inode);
712 	if (ret)
713 		return ret;
714 	inode->bh = NULL;
715 	erofs_iput(inode);
716 	return erofs_bh_flush_generic_end(bh);
717 }
718 
719 static struct erofs_bhops erofs_write_inode_bhops = {
720 	.flush = erofs_bh_flush_write_inode,
721 };
722 
erofs_prepare_tail_block(struct erofs_inode * inode)723 static int erofs_prepare_tail_block(struct erofs_inode *inode)
724 {
725 	struct erofs_sb_info *sbi = inode->sbi;
726 	struct erofs_buffer_head *bh;
727 	int ret;
728 
729 	if (!inode->idata_size)
730 		return 0;
731 
732 	bh = inode->bh_data;
733 	if (bh) {
734 		/* expend a block as the tail block (should be successful) */
735 		ret = erofs_bh_balloon(bh, erofs_blksiz(sbi));
736 		if (ret != erofs_blksiz(sbi)) {
737 			DBG_BUGON(1);
738 			return -EIO;
739 		}
740 	} else {
741 		inode->lazy_tailblock = true;
742 	}
743 	if (is_inode_layout_compression(inode))
744 		inode->u.i_blocks += 1;
745 	return 0;
746 }
747 
erofs_prepare_inode_buffer(struct erofs_inode * inode)748 static int erofs_prepare_inode_buffer(struct erofs_inode *inode)
749 {
750 	struct erofs_bufmgr *bmgr = inode->sbi->bmgr;
751 	unsigned int inodesize;
752 	struct erofs_buffer_head *bh, *ibh;
753 
754 	DBG_BUGON(inode->bh || inode->bh_inline);
755 
756 	inodesize = inode->inode_isize + inode->xattr_isize;
757 	if (inode->extent_isize)
758 		inodesize = roundup(inodesize, 8) + inode->extent_isize;
759 
760 	if (inode->datalayout == EROFS_INODE_FLAT_PLAIN)
761 		goto noinline;
762 
763 	/* TODO: tailpacking inline of chunk-based format isn't finalized */
764 	if (inode->datalayout == EROFS_INODE_CHUNK_BASED)
765 		goto noinline;
766 
767 	if (!is_inode_layout_compression(inode)) {
768 		if (!cfg.c_inline_data && S_ISREG(inode->i_mode)) {
769 			inode->datalayout = EROFS_INODE_FLAT_PLAIN;
770 			goto noinline;
771 		}
772 		/*
773 		 * If the file sizes of uncompressed files are block-aligned,
774 		 * should use the EROFS_INODE_FLAT_PLAIN data layout.
775 		 */
776 		if (!inode->idata_size)
777 			inode->datalayout = EROFS_INODE_FLAT_PLAIN;
778 	}
779 
780 	bh = erofs_balloc(bmgr, INODE, inodesize, 0, inode->idata_size);
781 	if (bh == ERR_PTR(-ENOSPC)) {
782 		int ret;
783 
784 		if (is_inode_layout_compression(inode))
785 			z_erofs_drop_inline_pcluster(inode);
786 		else
787 			inode->datalayout = EROFS_INODE_FLAT_PLAIN;
788 noinline:
789 		/* expend an extra block for tail-end data */
790 		ret = erofs_prepare_tail_block(inode);
791 		if (ret)
792 			return ret;
793 		bh = erofs_balloc(bmgr, INODE, inodesize, 0, 0);
794 		if (IS_ERR(bh))
795 			return PTR_ERR(bh);
796 		DBG_BUGON(inode->bh_inline);
797 	} else if (IS_ERR(bh)) {
798 		return PTR_ERR(bh);
799 	} else if (inode->idata_size) {
800 		if (is_inode_layout_compression(inode)) {
801 			DBG_BUGON(!cfg.c_ztailpacking);
802 			erofs_dbg("Inline %scompressed data (%u bytes) to %s",
803 				  inode->compressed_idata ? "" : "un",
804 				  inode->idata_size, inode->i_srcpath);
805 			erofs_sb_set_ztailpacking(inode->sbi);
806 		} else {
807 			inode->datalayout = EROFS_INODE_FLAT_INLINE;
808 			erofs_dbg("Inline tail-end data (%u bytes) to %s",
809 				  inode->idata_size, inode->i_srcpath);
810 		}
811 
812 		/* allocate inline buffer */
813 		ibh = erofs_battach(bh, META, inode->idata_size);
814 		if (IS_ERR(ibh))
815 			return PTR_ERR(ibh);
816 
817 		ibh->op = &erofs_skip_write_bhops;
818 		inode->bh_inline = ibh;
819 	}
820 
821 	bh->fsprivate = erofs_igrab(inode);
822 	bh->op = &erofs_write_inode_bhops;
823 	inode->bh = bh;
824 	inode->i_ino[0] = ++inode->sbi->inos;  /* inode serial number */
825 	return 0;
826 }
827 
erofs_bh_flush_write_inline(struct erofs_buffer_head * bh)828 static int erofs_bh_flush_write_inline(struct erofs_buffer_head *bh)
829 {
830 	struct erofs_inode *const inode = bh->fsprivate;
831 	const erofs_off_t off = erofs_btell(bh, false);
832 	int ret;
833 
834 	ret = erofs_dev_write(inode->sbi, inode->idata, off, inode->idata_size);
835 	if (ret)
836 		return ret;
837 
838 	free(inode->idata);
839 	inode->idata = NULL;
840 
841 	erofs_iput(inode);
842 	return erofs_bh_flush_generic_end(bh);
843 }
844 
845 static struct erofs_bhops erofs_write_inline_bhops = {
846 	.flush = erofs_bh_flush_write_inline,
847 };
848 
erofs_write_tail_end(struct erofs_inode * inode)849 static int erofs_write_tail_end(struct erofs_inode *inode)
850 {
851 	struct erofs_sb_info *sbi = inode->sbi;
852 	struct erofs_buffer_head *bh, *ibh;
853 
854 	bh = inode->bh_data;
855 
856 	if (!inode->idata_size)
857 		goto out;
858 
859 	DBG_BUGON(!inode->idata);
860 	/* have enough room to inline data */
861 	if (inode->bh_inline) {
862 		ibh = inode->bh_inline;
863 
864 		ibh->fsprivate = erofs_igrab(inode);
865 		ibh->op = &erofs_write_inline_bhops;
866 
867 		erofs_droid_blocklist_write_tail_end(inode, NULL_ADDR);
868 	} else {
869 		int ret;
870 		erofs_off_t pos, zero_pos;
871 
872 		if (!bh) {
873 			bh = erofs_balloc(sbi->bmgr, DATA,
874 					  erofs_blksiz(sbi), 0, 0);
875 			if (IS_ERR(bh))
876 				return PTR_ERR(bh);
877 			bh->op = &erofs_skip_write_bhops;
878 
879 			/* get blkaddr of bh */
880 			ret = erofs_mapbh(NULL, bh->block);
881 			inode->u.i_blkaddr = bh->block->blkaddr;
882 			inode->bh_data = bh;
883 		} else {
884 			if (inode->lazy_tailblock) {
885 				/* expend a tail block (should be successful) */
886 				ret = erofs_bh_balloon(bh, erofs_blksiz(sbi));
887 				if (ret != erofs_blksiz(sbi)) {
888 					DBG_BUGON(1);
889 					return -EIO;
890 				}
891 				inode->lazy_tailblock = false;
892 			}
893 			ret = erofs_mapbh(NULL, bh->block);
894 		}
895 		DBG_BUGON(ret < 0);
896 		pos = erofs_btell(bh, true) - erofs_blksiz(sbi);
897 
898 		/* 0'ed data should be padded at head for 0padding conversion */
899 		if (erofs_sb_has_lz4_0padding(sbi) && inode->compressed_idata) {
900 			zero_pos = pos;
901 			pos += erofs_blksiz(sbi) - inode->idata_size;
902 		} else {
903 			/* pad 0'ed data for the other cases */
904 			zero_pos = pos + inode->idata_size;
905 		}
906 		ret = erofs_dev_write(sbi, inode->idata, pos, inode->idata_size);
907 		if (ret)
908 			return ret;
909 
910 		DBG_BUGON(inode->idata_size > erofs_blksiz(sbi));
911 		if (inode->idata_size < erofs_blksiz(sbi)) {
912 			ret = erofs_dev_fillzero(sbi, zero_pos,
913 					   erofs_blksiz(sbi) - inode->idata_size,
914 					   false);
915 			if (ret)
916 				return ret;
917 		}
918 		inode->idata_size = 0;
919 		free(inode->idata);
920 		inode->idata = NULL;
921 
922 		erofs_droid_blocklist_write_tail_end(inode, erofs_blknr(sbi, pos));
923 	}
924 out:
925 	/* now bh_data can drop directly */
926 	if (bh) {
927 		/*
928 		 * Don't leave DATA buffers which were written in the global
929 		 * buffer list. It will make balloc() slowly.
930 		 */
931 		erofs_bdrop(bh, false);
932 		inode->bh_data = NULL;
933 	}
934 	return 0;
935 }
936 
erofs_should_use_inode_extended(struct erofs_inode * inode)937 static bool erofs_should_use_inode_extended(struct erofs_inode *inode)
938 {
939 	if (cfg.c_force_inodeversion == FORCE_INODE_EXTENDED)
940 		return true;
941 	if (inode->i_size > UINT_MAX)
942 		return true;
943 	if (erofs_is_packed_inode(inode))
944 		return false;
945 	if (inode->i_uid > USHRT_MAX)
946 		return true;
947 	if (inode->i_gid > USHRT_MAX)
948 		return true;
949 	if (inode->i_nlink > USHRT_MAX)
950 		return true;
951 	if ((inode->i_mtime != inode->sbi->build_time ||
952 	     inode->i_mtime_nsec != inode->sbi->build_time_nsec) &&
953 	    !cfg.c_ignore_mtime)
954 		return true;
955 	return false;
956 }
957 
erofs_new_encode_dev(dev_t dev)958 u32 erofs_new_encode_dev(dev_t dev)
959 {
960 	const unsigned int major = major(dev);
961 	const unsigned int minor = minor(dev);
962 
963 	return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
964 }
965 
966 #ifdef WITH_ANDROID
erofs_droid_inode_fsconfig(struct erofs_inode * inode,struct stat * st,const char * path)967 int erofs_droid_inode_fsconfig(struct erofs_inode *inode,
968 			       struct stat *st,
969 			       const char *path)
970 {
971 	/* filesystem_config does not preserve file type bits */
972 	mode_t stat_file_type_mask = st->st_mode & S_IFMT;
973 	unsigned int uid = 0, gid = 0, mode = 0;
974 	const char *fspath;
975 	char *decorated = NULL;
976 
977 	inode->capabilities = 0;
978 	if (!cfg.fs_config_file && !cfg.mount_point)
979 		return 0;
980 	/* avoid loading special inodes */
981 	if (path == EROFS_PACKED_INODE)
982 		return 0;
983 
984 	if (!cfg.mount_point ||
985 	/* have to drop the mountpoint for rootdir of canned fsconfig */
986 	    (cfg.fs_config_file && erofs_fspath(path)[0] == '\0')) {
987 		fspath = erofs_fspath(path);
988 	} else {
989 		if (asprintf(&decorated, "%s/%s", cfg.mount_point,
990 			     erofs_fspath(path)) <= 0)
991 			return -ENOMEM;
992 		fspath = decorated;
993 	}
994 
995 	if (cfg.fs_config_file)
996 		canned_fs_config(fspath, S_ISDIR(st->st_mode),
997 				 cfg.target_out_path,
998 				 &uid, &gid, &mode, &inode->capabilities);
999 	else
1000 		fs_config(fspath, S_ISDIR(st->st_mode),
1001 			  cfg.target_out_path,
1002 			  &uid, &gid, &mode, &inode->capabilities);
1003 
1004 	erofs_dbg("/%s -> mode = 0x%x, uid = 0x%x, gid = 0x%x, capabilities = 0x%" PRIx64,
1005 		  fspath, mode, uid, gid, inode->capabilities);
1006 
1007 	if (decorated)
1008 		free(decorated);
1009 	st->st_uid = uid;
1010 	st->st_gid = gid;
1011 	st->st_mode = mode | stat_file_type_mask;
1012 	return 0;
1013 }
1014 #else
erofs_droid_inode_fsconfig(struct erofs_inode * inode,struct stat * st,const char * path)1015 static int erofs_droid_inode_fsconfig(struct erofs_inode *inode,
1016 				      struct stat *st,
1017 				      const char *path)
1018 {
1019 	return 0;
1020 }
1021 #endif
1022 
__erofs_fill_inode(struct erofs_inode * inode,struct stat * st,const char * path)1023 int __erofs_fill_inode(struct erofs_inode *inode, struct stat *st,
1024 		       const char *path)
1025 {
1026 	int err = erofs_droid_inode_fsconfig(inode, st, path);
1027 	struct erofs_sb_info *sbi = inode->sbi;
1028 
1029 	if (err)
1030 		return err;
1031 
1032 	inode->i_uid = cfg.c_uid == -1 ? st->st_uid : cfg.c_uid;
1033 	inode->i_gid = cfg.c_gid == -1 ? st->st_gid : cfg.c_gid;
1034 
1035 	if (inode->i_uid + cfg.c_uid_offset < 0)
1036 		erofs_err("uid overflow @ %s", path);
1037 	inode->i_uid += cfg.c_uid_offset;
1038 
1039 	if (inode->i_gid + cfg.c_gid_offset < 0)
1040 		erofs_err("gid overflow @ %s", path);
1041 	inode->i_gid += cfg.c_gid_offset;
1042 
1043 	inode->i_mtime = st->st_mtime;
1044 	inode->i_mtime_nsec = ST_MTIM_NSEC(st);
1045 
1046 	switch (cfg.c_timeinherit) {
1047 	case TIMESTAMP_CLAMPING:
1048 		if (inode->i_mtime < sbi->build_time)
1049 			break;
1050 	case TIMESTAMP_FIXED:
1051 		inode->i_mtime = sbi->build_time;
1052 		inode->i_mtime_nsec = sbi->build_time_nsec;
1053 	default:
1054 		break;
1055 	}
1056 
1057 	return 0;
1058 }
1059 
erofs_fill_inode(struct erofs_inode * inode,struct stat * st,const char * path)1060 static int erofs_fill_inode(struct erofs_inode *inode, struct stat *st,
1061 			    const char *path)
1062 {
1063 	int err = __erofs_fill_inode(inode, st, path);
1064 
1065 	if (err)
1066 		return err;
1067 
1068 	inode->i_mode = st->st_mode;
1069 	inode->i_nlink = 1;	/* fix up later if needed */
1070 
1071 	switch (inode->i_mode & S_IFMT) {
1072 	case S_IFCHR:
1073 	case S_IFBLK:
1074 	case S_IFIFO:
1075 	case S_IFSOCK:
1076 		inode->u.i_rdev = erofs_new_encode_dev(st->st_rdev);
1077 	case S_IFDIR:
1078 		inode->i_size = 0;
1079 		break;
1080 	case S_IFREG:
1081 	case S_IFLNK:
1082 		inode->i_size = st->st_size;
1083 		break;
1084 	default:
1085 		return -EINVAL;
1086 	}
1087 
1088 	inode->i_srcpath = strdup(path);
1089 	if (!inode->i_srcpath)
1090 		return -ENOMEM;
1091 
1092 	if (erofs_should_use_inode_extended(inode)) {
1093 		if (cfg.c_force_inodeversion == FORCE_INODE_COMPACT) {
1094 			erofs_err("file %s cannot be in compact form",
1095 				  inode->i_srcpath);
1096 			return -EINVAL;
1097 		}
1098 		inode->inode_isize = sizeof(struct erofs_inode_extended);
1099 	} else {
1100 		inode->inode_isize = sizeof(struct erofs_inode_compact);
1101 	}
1102 
1103 	inode->dev = st->st_dev;
1104 	inode->i_ino[1] = st->st_ino;
1105 	erofs_insert_ihash(inode);
1106 	return 0;
1107 }
1108 
erofs_new_inode(struct erofs_sb_info * sbi)1109 struct erofs_inode *erofs_new_inode(struct erofs_sb_info *sbi)
1110 {
1111 	struct erofs_inode *inode;
1112 
1113 	inode = calloc(1, sizeof(struct erofs_inode));
1114 	if (!inode)
1115 		return ERR_PTR(-ENOMEM);
1116 
1117 	inode->sbi = sbi;
1118 	inode->i_count = 1;
1119 	inode->datalayout = EROFS_INODE_FLAT_PLAIN;
1120 
1121 	init_list_head(&inode->i_hash);
1122 	init_list_head(&inode->i_subdirs);
1123 	init_list_head(&inode->i_xattrs);
1124 	return inode;
1125 }
1126 
1127 /* get the inode from the source path */
erofs_iget_from_srcpath(struct erofs_sb_info * sbi,const char * path)1128 static struct erofs_inode *erofs_iget_from_srcpath(struct erofs_sb_info *sbi,
1129 						   const char *path)
1130 {
1131 	struct stat st;
1132 	struct erofs_inode *inode;
1133 	int ret;
1134 
1135 	ret = lstat(path, &st);
1136 	if (ret)
1137 		return ERR_PTR(-errno);
1138 
1139 	/*
1140 	 * lookup in hash table first, if it already exists we have a
1141 	 * hard-link, just return it. Also don't lookup for directories
1142 	 * since hard-link directory isn't allowed.
1143 	 */
1144 	if (!S_ISDIR(st.st_mode) && (!cfg.c_hard_dereference)) {
1145 		inode = erofs_iget(st.st_dev, st.st_ino);
1146 		if (inode)
1147 			return inode;
1148 	}
1149 
1150 	/* cannot find in the inode cache */
1151 	inode = erofs_new_inode(sbi);
1152 	if (IS_ERR(inode))
1153 		return inode;
1154 
1155 	ret = erofs_fill_inode(inode, &st, path);
1156 	if (ret) {
1157 		erofs_iput(inode);
1158 		return ERR_PTR(ret);
1159 	}
1160 	return inode;
1161 }
1162 
erofs_fixup_meta_blkaddr(struct erofs_inode * rootdir)1163 static void erofs_fixup_meta_blkaddr(struct erofs_inode *rootdir)
1164 {
1165 	const erofs_off_t rootnid_maxoffset = 0xffff << EROFS_ISLOTBITS;
1166 	struct erofs_buffer_head *const bh = rootdir->bh;
1167 	struct erofs_sb_info *sbi = rootdir->sbi;
1168 	erofs_off_t off, meta_offset;
1169 
1170 	erofs_mapbh(NULL, bh->block);
1171 	off = erofs_btell(bh, false);
1172 
1173 	if (off > rootnid_maxoffset)
1174 		meta_offset = round_up(off - rootnid_maxoffset, erofs_blksiz(sbi));
1175 	else
1176 		meta_offset = 0;
1177 	sbi->meta_blkaddr = erofs_blknr(sbi, meta_offset);
1178 	rootdir->nid = (off - meta_offset) >> EROFS_ISLOTBITS;
1179 }
1180 
erofs_inode_reserve_data_blocks(struct erofs_inode * inode)1181 static int erofs_inode_reserve_data_blocks(struct erofs_inode *inode)
1182 {
1183 	struct erofs_sb_info *sbi = inode->sbi;
1184 	erofs_off_t alignedsz = round_up(inode->i_size, erofs_blksiz(sbi));
1185 	erofs_blk_t nblocks = alignedsz >> sbi->blkszbits;
1186 	struct erofs_buffer_head *bh;
1187 
1188 	/* allocate data blocks */
1189 	bh = erofs_balloc(sbi->bmgr, DATA, alignedsz, 0, 0);
1190 	if (IS_ERR(bh))
1191 		return PTR_ERR(bh);
1192 
1193 	/* get blkaddr of the bh */
1194 	(void)erofs_mapbh(NULL, bh->block);
1195 
1196 	/* write blocks except for the tail-end block */
1197 	inode->u.i_blkaddr = bh->block->blkaddr;
1198 	erofs_bdrop(bh, false);
1199 
1200 	inode->datalayout = EROFS_INODE_FLAT_PLAIN;
1201 	tarerofs_blocklist_write(inode->u.i_blkaddr, nblocks, inode->i_ino[1],
1202 				 alignedsz - inode->i_size);
1203 	return 0;
1204 }
1205 
1206 struct erofs_mkfs_job_ndir_ctx {
1207 	struct erofs_inode *inode;
1208 	void *ictx;
1209 	int fd;
1210 	u64 fpos;
1211 };
1212 
erofs_mkfs_job_write_file(struct erofs_mkfs_job_ndir_ctx * ctx)1213 static int erofs_mkfs_job_write_file(struct erofs_mkfs_job_ndir_ctx *ctx)
1214 {
1215 	struct erofs_inode *inode = ctx->inode;
1216 	int ret;
1217 
1218 	if (inode->datasource == EROFS_INODE_DATA_SOURCE_DISKBUF &&
1219 	    lseek(ctx->fd, ctx->fpos, SEEK_SET) < 0) {
1220 		ret = -errno;
1221 		goto out;
1222 	}
1223 
1224 	if (ctx->ictx) {
1225 		ret = erofs_write_compressed_file(ctx->ictx);
1226 		if (ret != -ENOSPC)
1227 			goto out;
1228 		if (lseek(ctx->fd, ctx->fpos, SEEK_SET) < 0) {
1229 			ret = -errno;
1230 			goto out;
1231 		}
1232 	}
1233 	/* fallback to all data uncompressed */
1234 	ret = erofs_write_unencoded_file(inode, ctx->fd, ctx->fpos);
1235 out:
1236 	if (inode->datasource == EROFS_INODE_DATA_SOURCE_DISKBUF) {
1237 		erofs_diskbuf_close(inode->i_diskbuf);
1238 		free(inode->i_diskbuf);
1239 		inode->i_diskbuf = NULL;
1240 		inode->datasource = EROFS_INODE_DATA_SOURCE_NONE;
1241 	} else {
1242 		close(ctx->fd);
1243 	}
1244 	return ret;
1245 }
1246 
erofs_mkfs_handle_nondirectory(struct erofs_mkfs_job_ndir_ctx * ctx)1247 static int erofs_mkfs_handle_nondirectory(struct erofs_mkfs_job_ndir_ctx *ctx)
1248 {
1249 	struct erofs_inode *inode = ctx->inode;
1250 	int ret = 0;
1251 
1252 	if (S_ISLNK(inode->i_mode)) {
1253 		char *symlink = inode->i_link;
1254 
1255 		if (!symlink) {
1256 			symlink = malloc(inode->i_size);
1257 			if (!symlink)
1258 				return -ENOMEM;
1259 			ret = readlink(inode->i_srcpath, symlink, inode->i_size);
1260 			if (ret < 0) {
1261 				free(symlink);
1262 				return -errno;
1263 			}
1264 		}
1265 		ret = erofs_write_file_from_buffer(inode, symlink);
1266 		free(symlink);
1267 		inode->i_link = NULL;
1268 	} else if (inode->i_size) {
1269 		if (inode->datasource == EROFS_INODE_DATA_SOURCE_RESVSP)
1270 			ret = erofs_inode_reserve_data_blocks(inode);
1271 		else if (ctx->fd >= 0)
1272 			ret = erofs_mkfs_job_write_file(ctx);
1273 	}
1274 	if (ret)
1275 		return ret;
1276 	erofs_prepare_inode_buffer(inode);
1277 	erofs_write_tail_end(inode);
1278 	return 0;
1279 }
1280 
1281 enum erofs_mkfs_jobtype {	/* ordered job types */
1282 	EROFS_MKFS_JOB_NDIR,
1283 	EROFS_MKFS_JOB_DIR,
1284 	EROFS_MKFS_JOB_DIR_BH,
1285 	EROFS_MKFS_JOB_MAX
1286 };
1287 
1288 struct erofs_mkfs_jobitem {
1289 	enum erofs_mkfs_jobtype type;
1290 	union {
1291 		struct erofs_inode *inode;
1292 		struct erofs_mkfs_job_ndir_ctx ndir;
1293 	} u;
1294 };
1295 
erofs_mkfs_jobfn(struct erofs_mkfs_jobitem * item)1296 static int erofs_mkfs_jobfn(struct erofs_mkfs_jobitem *item)
1297 {
1298 	struct erofs_inode *inode = item->u.inode;
1299 	int ret;
1300 
1301 	if (item->type == EROFS_MKFS_JOB_NDIR)
1302 		return erofs_mkfs_handle_nondirectory(&item->u.ndir);
1303 
1304 	if (item->type == EROFS_MKFS_JOB_DIR) {
1305 		ret = erofs_prepare_inode_buffer(inode);
1306 		if (ret)
1307 			return ret;
1308 		inode->bh->op = &erofs_skip_write_bhops;
1309 		return 0;
1310 	}
1311 
1312 	if (item->type == EROFS_MKFS_JOB_DIR_BH) {
1313 		ret = erofs_write_dir_file(inode);
1314 		if (ret)
1315 			return ret;
1316 		erofs_write_tail_end(inode);
1317 		inode->bh->op = &erofs_write_inode_bhops;
1318 		erofs_iput(inode);
1319 		return 0;
1320 	}
1321 	return -EINVAL;
1322 }
1323 
1324 #ifdef EROFS_MT_ENABLED
1325 
1326 struct erofs_mkfs_dfops {
1327 	pthread_t worker;
1328 	pthread_mutex_t lock;
1329 	pthread_cond_t full, empty, drain;
1330 	struct erofs_mkfs_jobitem *queue;
1331 	unsigned int entries, head, tail;
1332 	bool idle;	/* initialize as false before the dfops worker runs */
1333 };
1334 
1335 #define EROFS_MT_QUEUE_SIZE 128
1336 
erofs_mkfs_flushjobs(struct erofs_sb_info * sbi)1337 static void erofs_mkfs_flushjobs(struct erofs_sb_info *sbi)
1338 {
1339 	struct erofs_mkfs_dfops *q = sbi->mkfs_dfops;
1340 
1341 	pthread_mutex_lock(&q->lock);
1342 	if (!q->idle)
1343 		pthread_cond_wait(&q->drain, &q->lock);
1344 	pthread_mutex_unlock(&q->lock);
1345 }
1346 
erofs_mkfs_pop_jobitem(struct erofs_mkfs_dfops * q)1347 static void *erofs_mkfs_pop_jobitem(struct erofs_mkfs_dfops *q)
1348 {
1349 	struct erofs_mkfs_jobitem *item;
1350 
1351 	pthread_mutex_lock(&q->lock);
1352 	while (q->head == q->tail) {
1353 		/* the worker has handled everything only if sleeping here */
1354 		q->idle = true;
1355 		pthread_cond_signal(&q->drain);
1356 		pthread_cond_wait(&q->empty, &q->lock);
1357 	}
1358 
1359 	item = q->queue + q->head;
1360 	q->head = (q->head + 1) & (q->entries - 1);
1361 
1362 	pthread_cond_signal(&q->full);
1363 	pthread_mutex_unlock(&q->lock);
1364 	return item;
1365 }
1366 
z_erofs_mt_dfops_worker(void * arg)1367 static void *z_erofs_mt_dfops_worker(void *arg)
1368 {
1369 	struct erofs_sb_info *sbi = arg;
1370 	int ret = 0;
1371 
1372 	while (1) {
1373 		struct erofs_mkfs_jobitem *item;
1374 
1375 		item = erofs_mkfs_pop_jobitem(sbi->mkfs_dfops);
1376 		if (item->type >= EROFS_MKFS_JOB_MAX)
1377 			break;
1378 		ret = erofs_mkfs_jobfn(item);
1379 		if (ret)
1380 			break;
1381 	}
1382 	pthread_exit((void *)(uintptr_t)ret);
1383 }
1384 
erofs_mkfs_go(struct erofs_sb_info * sbi,enum erofs_mkfs_jobtype type,void * elem,int size)1385 static int erofs_mkfs_go(struct erofs_sb_info *sbi,
1386 			 enum erofs_mkfs_jobtype type, void *elem, int size)
1387 {
1388 	struct erofs_mkfs_jobitem *item;
1389 	struct erofs_mkfs_dfops *q = sbi->mkfs_dfops;
1390 
1391 	pthread_mutex_lock(&q->lock);
1392 
1393 	while (((q->tail + 1) & (q->entries - 1)) == q->head)
1394 		pthread_cond_wait(&q->full, &q->lock);
1395 
1396 	item = q->queue + q->tail;
1397 	item->type = type;
1398 	if (size)
1399 		memcpy(&item->u, elem, size);
1400 	q->tail = (q->tail + 1) & (q->entries - 1);
1401 	q->idle = false;
1402 
1403 	pthread_cond_signal(&q->empty);
1404 	pthread_mutex_unlock(&q->lock);
1405 	return 0;
1406 }
1407 #else
erofs_mkfs_go(struct erofs_sb_info * sbi,enum erofs_mkfs_jobtype type,void * elem,int size)1408 static int erofs_mkfs_go(struct erofs_sb_info *sbi,
1409 			 enum erofs_mkfs_jobtype type, void *elem, int size)
1410 {
1411 	struct erofs_mkfs_jobitem item;
1412 
1413 	item.type = type;
1414 	memcpy(&item.u, elem, size);
1415 	return erofs_mkfs_jobfn(&item);
1416 }
erofs_mkfs_flushjobs(struct erofs_sb_info * sbi)1417 static void erofs_mkfs_flushjobs(struct erofs_sb_info *sbi)
1418 {
1419 }
1420 #endif
1421 
erofs_mkfs_handle_directory(struct erofs_inode * dir)1422 static int erofs_mkfs_handle_directory(struct erofs_inode *dir)
1423 {
1424 	struct erofs_sb_info *sbi = dir->sbi;
1425 	DIR *_dir;
1426 	struct dirent *dp;
1427 	struct erofs_dentry *d;
1428 	unsigned int nr_subdirs, i_nlink;
1429 	int ret;
1430 
1431 	_dir = opendir(dir->i_srcpath);
1432 	if (!_dir) {
1433 		erofs_err("failed to opendir at %s: %s",
1434 			  dir->i_srcpath, erofs_strerror(-errno));
1435 		return -errno;
1436 	}
1437 
1438 	nr_subdirs = 0;
1439 	i_nlink = 0;
1440 	while (1) {
1441 		char buf[PATH_MAX];
1442 		struct erofs_inode *inode;
1443 
1444 		/*
1445 		 * set errno to 0 before calling readdir() in order to
1446 		 * distinguish end of stream and from an error.
1447 		 */
1448 		errno = 0;
1449 		dp = readdir(_dir);
1450 		if (!dp) {
1451 			if (!errno)
1452 				break;
1453 			ret = -errno;
1454 			goto err_closedir;
1455 		}
1456 
1457 		if (is_dot_dotdot(dp->d_name)) {
1458 			++i_nlink;
1459 			continue;
1460 		}
1461 
1462 		/* skip if it's a exclude file */
1463 		if (erofs_is_exclude_path(dir->i_srcpath, dp->d_name))
1464 			continue;
1465 
1466 		d = erofs_d_alloc(dir, dp->d_name);
1467 		if (IS_ERR(d)) {
1468 			ret = PTR_ERR(d);
1469 			goto err_closedir;
1470 		}
1471 
1472 		ret = snprintf(buf, PATH_MAX, "%s/%s", dir->i_srcpath, d->name);
1473 		if (ret < 0 || ret >= PATH_MAX)
1474 			goto err_closedir;
1475 
1476 		inode = erofs_iget_from_srcpath(sbi, buf);
1477 		if (IS_ERR(inode)) {
1478 			ret = PTR_ERR(inode);
1479 			goto err_closedir;
1480 		}
1481 		d->inode = inode;
1482 		d->type = erofs_mode_to_ftype(inode->i_mode);
1483 		i_nlink += S_ISDIR(inode->i_mode);
1484 		erofs_dbg("file %s added (type %u)", buf, d->type);
1485 		nr_subdirs++;
1486 	}
1487 	closedir(_dir);
1488 
1489 	ret = erofs_init_empty_dir(dir);
1490 	if (ret)
1491 		return ret;
1492 
1493 	ret = erofs_prepare_dir_file(dir, nr_subdirs + 2); /* sort subdirs */
1494 	if (ret)
1495 		return ret;
1496 
1497 	/*
1498 	 * if there're too many subdirs as compact form, set nlink=1
1499 	 * rather than upgrade to use extented form instead.
1500 	 */
1501 	if (i_nlink > USHRT_MAX &&
1502 	    dir->inode_isize == sizeof(struct erofs_inode_compact))
1503 		dir->i_nlink = 1;
1504 	else
1505 		dir->i_nlink = i_nlink;
1506 
1507 	return erofs_mkfs_go(sbi, EROFS_MKFS_JOB_DIR, &dir, sizeof(dir));
1508 
1509 err_closedir:
1510 	closedir(_dir);
1511 	return ret;
1512 }
1513 
1514 int erofs_rebuild_load_basedir(struct erofs_inode *dir);
1515 
erofs_dentry_is_wht(struct erofs_sb_info * sbi,struct erofs_dentry * d)1516 bool erofs_dentry_is_wht(struct erofs_sb_info *sbi, struct erofs_dentry *d)
1517 {
1518 	if (!d->validnid)
1519 		return erofs_inode_is_whiteout(d->inode);
1520 	if (d->type == EROFS_FT_CHRDEV) {
1521 		struct erofs_inode ei = { .sbi = sbi, .nid = d->nid };
1522 		int ret;
1523 
1524 		ret = erofs_read_inode_from_disk(&ei);
1525 		if (ret) {
1526 			erofs_err("failed to check DT_WHT: %s",
1527 				  erofs_strerror(ret));
1528 			DBG_BUGON(1);
1529 			return false;
1530 		}
1531 		return erofs_inode_is_whiteout(&ei);
1532 	}
1533 	return false;
1534 }
1535 
erofs_rebuild_handle_directory(struct erofs_inode * dir,bool incremental)1536 static int erofs_rebuild_handle_directory(struct erofs_inode *dir,
1537 					  bool incremental)
1538 {
1539 	struct erofs_sb_info *sbi = dir->sbi;
1540 	struct erofs_dentry *d, *n;
1541 	unsigned int nr_subdirs, i_nlink;
1542 	bool delwht = cfg.c_ovlfs_strip && dir->whiteouts;
1543 	int ret;
1544 
1545 	nr_subdirs = 0;
1546 	i_nlink = 0;
1547 
1548 	list_for_each_entry_safe(d, n, &dir->i_subdirs, d_child) {
1549 		if (delwht && erofs_dentry_is_wht(sbi, d)) {
1550 			erofs_dbg("remove whiteout %s", d->inode->i_srcpath);
1551 			list_del(&d->d_child);
1552 			erofs_d_invalidate(d);
1553 			free(d);
1554 			continue;
1555 		}
1556 		i_nlink += (d->type == EROFS_FT_DIR);
1557 		++nr_subdirs;
1558 	}
1559 
1560 	DBG_BUGON(i_nlink < 2);		/* should have `.` and `..` */
1561 	DBG_BUGON(nr_subdirs < i_nlink);
1562 	ret = erofs_prepare_dir_file(dir, nr_subdirs);
1563 	if (ret)
1564 		return ret;
1565 
1566 	if (IS_ROOT(dir) && incremental)
1567 		dir->datalayout = EROFS_INODE_FLAT_PLAIN;
1568 
1569 	/*
1570 	 * if there're too many subdirs as compact form, set nlink=1
1571 	 * rather than upgrade to use extented form instead.
1572 	 */
1573 	if (i_nlink > USHRT_MAX &&
1574 	    dir->inode_isize == sizeof(struct erofs_inode_compact))
1575 		dir->i_nlink = 1;
1576 	else
1577 		dir->i_nlink = i_nlink;
1578 
1579 	return erofs_mkfs_go(sbi, EROFS_MKFS_JOB_DIR, &dir, sizeof(dir));
1580 }
1581 
erofs_mkfs_handle_inode(struct erofs_inode * inode)1582 static int erofs_mkfs_handle_inode(struct erofs_inode *inode)
1583 {
1584 	const char *relpath = erofs_fspath(inode->i_srcpath);
1585 	char *trimmed;
1586 	int ret;
1587 
1588 	trimmed = erofs_trim_for_progressinfo(relpath[0] ? relpath : "/",
1589 					      sizeof("Processing  ...") - 1);
1590 	erofs_update_progressinfo("Processing %s ...", trimmed);
1591 	free(trimmed);
1592 
1593 	ret = erofs_scan_file_xattrs(inode);
1594 	if (ret < 0)
1595 		return ret;
1596 
1597 	ret = erofs_prepare_xattr_ibody(inode, false);
1598 	if (ret < 0)
1599 		return ret;
1600 
1601 	if (!S_ISDIR(inode->i_mode)) {
1602 		struct erofs_mkfs_job_ndir_ctx ctx = { .inode = inode };
1603 
1604 		if (!S_ISLNK(inode->i_mode) && inode->i_size) {
1605 			ctx.fd = open(inode->i_srcpath, O_RDONLY | O_BINARY);
1606 			if (ctx.fd < 0)
1607 				return -errno;
1608 
1609 			if (cfg.c_compr_opts[0].alg &&
1610 			    erofs_file_is_compressible(inode)) {
1611 				ctx.ictx = erofs_begin_compressed_file(inode,
1612 								ctx.fd, 0);
1613 				if (IS_ERR(ctx.ictx))
1614 					return PTR_ERR(ctx.ictx);
1615 			}
1616 		}
1617 		ret = erofs_mkfs_go(inode->sbi, EROFS_MKFS_JOB_NDIR,
1618 				    &ctx, sizeof(ctx));
1619 	} else {
1620 		ret = erofs_mkfs_handle_directory(inode);
1621 	}
1622 	erofs_info("file /%s dumped (mode %05o)", relpath, inode->i_mode);
1623 	return ret;
1624 }
1625 
erofs_rebuild_handle_inode(struct erofs_inode * inode,bool incremental)1626 static int erofs_rebuild_handle_inode(struct erofs_inode *inode,
1627 				      bool incremental)
1628 {
1629 	char *trimmed;
1630 	int ret;
1631 
1632 	trimmed = erofs_trim_for_progressinfo(erofs_fspath(inode->i_srcpath),
1633 					      sizeof("Processing  ...") - 1);
1634 	erofs_update_progressinfo("Processing %s ...", trimmed);
1635 	free(trimmed);
1636 
1637 	if (erofs_should_use_inode_extended(inode)) {
1638 		if (cfg.c_force_inodeversion == FORCE_INODE_COMPACT) {
1639 			erofs_err("file %s cannot be in compact form",
1640 				  inode->i_srcpath);
1641 			return -EINVAL;
1642 		}
1643 		inode->inode_isize = sizeof(struct erofs_inode_extended);
1644 	} else {
1645 		inode->inode_isize = sizeof(struct erofs_inode_compact);
1646 	}
1647 
1648 	if (incremental && S_ISDIR(inode->i_mode) &&
1649 	    inode->dev == inode->sbi->dev && !inode->opaque) {
1650 		ret = erofs_rebuild_load_basedir(inode);
1651 		if (ret)
1652 			return ret;
1653 	}
1654 
1655 	/* strip all unnecessary overlayfs xattrs when ovlfs_strip is enabled */
1656 	if (cfg.c_ovlfs_strip)
1657 		erofs_clear_opaque_xattr(inode);
1658 	else if (inode->whiteouts)
1659 		erofs_set_origin_xattr(inode);
1660 
1661 	ret = erofs_prepare_xattr_ibody(inode, incremental && IS_ROOT(inode));
1662 	if (ret < 0)
1663 		return ret;
1664 
1665 	if (!S_ISDIR(inode->i_mode)) {
1666 		struct erofs_mkfs_job_ndir_ctx ctx =
1667 			{ .inode = inode, .fd = -1 };
1668 
1669 		if (S_ISREG(inode->i_mode) && inode->i_size &&
1670 		    inode->datasource == EROFS_INODE_DATA_SOURCE_DISKBUF) {
1671 			ctx.fd = erofs_diskbuf_getfd(inode->i_diskbuf, &ctx.fpos);
1672 			if (ctx.fd < 0)
1673 				return ret;
1674 
1675 			if (cfg.c_compr_opts[0].alg &&
1676 			    erofs_file_is_compressible(inode)) {
1677 				ctx.ictx = erofs_begin_compressed_file(inode,
1678 							ctx.fd, ctx.fpos);
1679 				if (IS_ERR(ctx.ictx))
1680 					return PTR_ERR(ctx.ictx);
1681 			}
1682 		}
1683 		ret = erofs_mkfs_go(inode->sbi, EROFS_MKFS_JOB_NDIR,
1684 				    &ctx, sizeof(ctx));
1685 	} else {
1686 		ret = erofs_rebuild_handle_directory(inode, incremental);
1687 	}
1688 	erofs_info("file %s dumped (mode %05o)", erofs_fspath(inode->i_srcpath),
1689 		   inode->i_mode);
1690 	return ret;
1691 }
1692 
erofs_inode_visited(struct erofs_inode * inode)1693 static bool erofs_inode_visited(struct erofs_inode *inode)
1694 {
1695 	return (unsigned long)inode->i_parent & 1UL;
1696 }
1697 
erofs_mark_parent_inode(struct erofs_inode * inode,struct erofs_inode * dir)1698 static void erofs_mark_parent_inode(struct erofs_inode *inode,
1699 				    struct erofs_inode *dir)
1700 {
1701 	inode->i_parent = (void *)((unsigned long)dir | 1);
1702 }
1703 
erofs_mkfs_dump_tree(struct erofs_inode * root,bool rebuild,bool incremental)1704 static int erofs_mkfs_dump_tree(struct erofs_inode *root, bool rebuild,
1705 				bool incremental)
1706 {
1707 	struct erofs_sb_info *sbi = root->sbi;
1708 	struct erofs_inode *dumpdir = erofs_igrab(root);
1709 	int err, err2;
1710 
1711 	erofs_mark_parent_inode(root, root);	/* rootdir mark */
1712 	root->next_dirwrite = NULL;
1713 	/* update dev/i_ino[1] to keep track of the base image */
1714 	if (incremental) {
1715 		root->dev = root->sbi->dev;
1716 		root->i_ino[1] = sbi->root_nid;
1717 		list_del(&root->i_hash);
1718 		erofs_insert_ihash(root);
1719 	} else if (cfg.c_root_xattr_isize) {
1720 		if (cfg.c_root_xattr_isize > EROFS_XATTR_ALIGN(
1721 				UINT16_MAX - sizeof(struct erofs_xattr_entry))) {
1722 			erofs_err("Invalid configuration for c_root_xattr_isize: %u (too large)",
1723 				  cfg.c_root_xattr_isize);
1724 			return -EINVAL;
1725 		}
1726 		root->xattr_isize = cfg.c_root_xattr_isize;
1727 	}
1728 
1729 	err = !rebuild ? erofs_mkfs_handle_inode(root) :
1730 			erofs_rebuild_handle_inode(root, incremental);
1731 	if (err)
1732 		return err;
1733 
1734 	/* assign root NID immediately for non-incremental builds */
1735 	if (!incremental) {
1736 		erofs_mkfs_flushjobs(sbi);
1737 		erofs_fixup_meta_blkaddr(root);
1738 		sbi->root_nid = root->nid;
1739 	}
1740 
1741 	do {
1742 		struct erofs_inode *dir = dumpdir;
1743 		/* used for adding sub-directories in reverse order due to FIFO */
1744 		struct erofs_inode *head, **last = &head;
1745 		struct erofs_dentry *d;
1746 
1747 		dumpdir = dir->next_dirwrite;
1748 		list_for_each_entry(d, &dir->i_subdirs, d_child) {
1749 			struct erofs_inode *inode = d->inode;
1750 
1751 			if (is_dot_dotdot(d->name) || d->validnid)
1752 				continue;
1753 
1754 			if (!erofs_inode_visited(inode)) {
1755 				DBG_BUGON(rebuild && (inode->i_nlink == 1 ||
1756 					  S_ISDIR(inode->i_mode)) &&
1757 					  erofs_parent_inode(inode) != dir);
1758 				erofs_mark_parent_inode(inode, dir);
1759 
1760 				if (!rebuild)
1761 					err = erofs_mkfs_handle_inode(inode);
1762 				else
1763 					err = erofs_rebuild_handle_inode(inode,
1764 								incremental);
1765 				if (err)
1766 					break;
1767 				if (S_ISDIR(inode->i_mode)) {
1768 					*last = inode;
1769 					last = &inode->next_dirwrite;
1770 					(void)erofs_igrab(inode);
1771 				}
1772 			} else if (!rebuild) {
1773 				++inode->i_nlink;
1774 			}
1775 		}
1776 		*last = dumpdir;	/* fixup the last (or the only) one */
1777 		dumpdir = head;
1778 		err2 = erofs_mkfs_go(sbi, EROFS_MKFS_JOB_DIR_BH,
1779 				    &dir, sizeof(dir));
1780 		if (err || err2)
1781 			return err ? err : err2;
1782 	} while (dumpdir);
1783 
1784 	return err;
1785 }
1786 
1787 struct erofs_mkfs_buildtree_ctx {
1788 	struct erofs_sb_info *sbi;
1789 	union {
1790 		const char *path;
1791 		struct erofs_inode *root;
1792 	} u;
1793 	bool incremental;
1794 };
1795 #ifndef EROFS_MT_ENABLED
1796 #define __erofs_mkfs_build_tree erofs_mkfs_build_tree
1797 #endif
1798 
__erofs_mkfs_build_tree(struct erofs_mkfs_buildtree_ctx * ctx)1799 static int __erofs_mkfs_build_tree(struct erofs_mkfs_buildtree_ctx *ctx)
1800 {
1801 	bool from_path = !!ctx->sbi;
1802 	struct erofs_inode *root;
1803 	int err;
1804 
1805 	if (from_path) {
1806 		root = erofs_iget_from_srcpath(ctx->sbi, ctx->u.path);
1807 		if (IS_ERR(root))
1808 			return PTR_ERR(root);
1809 	} else {
1810 		root = ctx->u.root;
1811 	}
1812 
1813 	err = erofs_mkfs_dump_tree(root, !from_path, ctx->incremental);
1814 	if (err) {
1815 		if (from_path)
1816 			erofs_iput(root);
1817 		return err;
1818 	}
1819 	ctx->u.root = root;
1820 	return 0;
1821 }
1822 
1823 #ifdef EROFS_MT_ENABLED
erofs_mkfs_build_tree(struct erofs_mkfs_buildtree_ctx * ctx)1824 static int erofs_mkfs_build_tree(struct erofs_mkfs_buildtree_ctx *ctx)
1825 {
1826 	struct erofs_mkfs_dfops *q;
1827 	int err, err2;
1828 	struct erofs_sb_info *sbi = ctx->sbi ? ctx->sbi : ctx->u.root->sbi;
1829 
1830 	q = calloc(1, sizeof(*q));
1831 	if (!q)
1832 		return -ENOMEM;
1833 
1834 	q->entries = EROFS_MT_QUEUE_SIZE;
1835 	q->queue = malloc(q->entries * sizeof(*q->queue));
1836 	if (!q->queue) {
1837 		free(q);
1838 		return -ENOMEM;
1839 	}
1840 	pthread_mutex_init(&q->lock, NULL);
1841 	pthread_cond_init(&q->empty, NULL);
1842 	pthread_cond_init(&q->full, NULL);
1843 	pthread_cond_init(&q->drain, NULL);
1844 
1845 	sbi->mkfs_dfops = q;
1846 	err = pthread_create(&sbi->dfops_worker, NULL,
1847 			     z_erofs_mt_dfops_worker, sbi);
1848 	if (err)
1849 		goto fail;
1850 
1851 	err = __erofs_mkfs_build_tree(ctx);
1852 	erofs_mkfs_go(sbi, ~0, NULL, 0);
1853 	err2 = pthread_join(sbi->dfops_worker, NULL);
1854 	if (!err)
1855 		err = err2;
1856 
1857 fail:
1858 	pthread_cond_destroy(&q->empty);
1859 	pthread_cond_destroy(&q->full);
1860 	pthread_cond_destroy(&q->drain);
1861 	pthread_mutex_destroy(&q->lock);
1862 	free(q->queue);
1863 	free(q);
1864 	return err;
1865 }
1866 #endif
1867 
erofs_mkfs_build_tree_from_path(struct erofs_sb_info * sbi,const char * path)1868 struct erofs_inode *erofs_mkfs_build_tree_from_path(struct erofs_sb_info *sbi,
1869 						    const char *path)
1870 {
1871 	struct erofs_mkfs_buildtree_ctx ctx = {
1872 		.sbi = sbi,
1873 		.u.path = path,
1874 	};
1875 	int err;
1876 
1877 	if (!sbi)
1878 		return ERR_PTR(-EINVAL);
1879 	err = erofs_mkfs_build_tree(&ctx);
1880 	if (err)
1881 		return ERR_PTR(err);
1882 	return ctx.u.root;
1883 }
1884 
erofs_rebuild_dump_tree(struct erofs_inode * root,bool incremental)1885 int erofs_rebuild_dump_tree(struct erofs_inode *root, bool incremental)
1886 {
1887 	return erofs_mkfs_build_tree(&((struct erofs_mkfs_buildtree_ctx) {
1888 		.sbi = NULL,
1889 		.u.root = root,
1890 		.incremental = incremental,
1891 	}));
1892 }
1893 
erofs_mkfs_build_special_from_fd(struct erofs_sb_info * sbi,int fd,const char * name)1894 struct erofs_inode *erofs_mkfs_build_special_from_fd(struct erofs_sb_info *sbi,
1895 						     int fd, const char *name)
1896 {
1897 	struct stat st;
1898 	struct erofs_inode *inode;
1899 	void *ictx;
1900 	int ret;
1901 
1902 	ret = lseek(fd, 0, SEEK_SET);
1903 	if (ret < 0)
1904 		return ERR_PTR(-errno);
1905 
1906 	ret = fstat(fd, &st);
1907 	if (ret)
1908 		return ERR_PTR(-errno);
1909 
1910 	inode = erofs_new_inode(sbi);
1911 	if (IS_ERR(inode))
1912 		return inode;
1913 
1914 	if (name == EROFS_PACKED_INODE) {
1915 		st.st_uid = st.st_gid = 0;
1916 		st.st_nlink = 0;
1917 	}
1918 
1919 	ret = erofs_fill_inode(inode, &st, name);
1920 	if (ret) {
1921 		free(inode);
1922 		return ERR_PTR(ret);
1923 	}
1924 
1925 	if (name == EROFS_PACKED_INODE) {
1926 		inode->sbi->packed_nid = EROFS_PACKED_NID_UNALLOCATED;
1927 		inode->nid = inode->sbi->packed_nid;
1928 	}
1929 
1930 	if (cfg.c_compr_opts[0].alg &&
1931 	    erofs_file_is_compressible(inode)) {
1932 		ictx = erofs_begin_compressed_file(inode, fd, 0);
1933 		if (IS_ERR(ictx))
1934 			return ERR_CAST(ictx);
1935 
1936 		DBG_BUGON(!ictx);
1937 		ret = erofs_write_compressed_file(ictx);
1938 		if (!ret)
1939 			goto out;
1940 		if (ret != -ENOSPC)
1941 			 return ERR_PTR(ret);
1942 
1943 		ret = lseek(fd, 0, SEEK_SET);
1944 		if (ret < 0)
1945 			return ERR_PTR(-errno);
1946 	}
1947 	ret = write_uncompressed_file_from_fd(inode, fd);
1948 	if (ret)
1949 		return ERR_PTR(ret);
1950 out:
1951 	erofs_prepare_inode_buffer(inode);
1952 	erofs_write_tail_end(inode);
1953 	return inode;
1954 }
1955 
erofs_fixup_root_inode(struct erofs_inode * root)1956 int erofs_fixup_root_inode(struct erofs_inode *root)
1957 {
1958 	struct erofs_sb_info *sbi = root->sbi;
1959 	struct erofs_inode oi;
1960 	unsigned int ondisk_capacity, ondisk_size;
1961 	char *ibuf;
1962 	int err;
1963 
1964 	if (sbi->root_nid == root->nid)		/* for most mkfs cases */
1965 		return 0;
1966 
1967 	if (root->nid <= 0xffff) {
1968 		sbi->root_nid = root->nid;
1969 		return 0;
1970 	}
1971 
1972 	oi = (struct erofs_inode){ .sbi = sbi, .nid = sbi->root_nid };
1973 	err = erofs_read_inode_from_disk(&oi);
1974 	if (err) {
1975 		erofs_err("failed to read root inode: %s",
1976 			  erofs_strerror(err));
1977 		return err;
1978 	}
1979 
1980 	if (oi.datalayout != EROFS_INODE_FLAT_INLINE &&
1981 	    oi.datalayout != EROFS_INODE_FLAT_PLAIN)
1982 		return -EOPNOTSUPP;
1983 
1984 	ondisk_capacity = oi.inode_isize + oi.xattr_isize;
1985 	if (oi.datalayout == EROFS_INODE_FLAT_INLINE)
1986 		ondisk_capacity += erofs_blkoff(sbi, oi.i_size);
1987 
1988 	ondisk_size = root->inode_isize + root->xattr_isize;
1989 	if (root->extent_isize)
1990 		ondisk_size = roundup(ondisk_size, 8) + root->extent_isize;
1991 	ondisk_size += root->idata_size;
1992 
1993 	if (ondisk_size > ondisk_capacity) {
1994 		erofs_err("no enough room for the root inode from nid %llu",
1995 			  root->nid);
1996 		return -ENOSPC;
1997 	}
1998 
1999 	ibuf = malloc(ondisk_size);
2000 	if (!ibuf)
2001 		return -ENOMEM;
2002 	err = erofs_dev_read(sbi, 0, ibuf, erofs_iloc(root), ondisk_size);
2003 	if (err >= 0)
2004 		err = erofs_dev_write(sbi, ibuf, erofs_iloc(&oi), ondisk_size);
2005 	free(ibuf);
2006 	return err;
2007 }
2008 
erofs_rebuild_make_root(struct erofs_sb_info * sbi)2009 struct erofs_inode *erofs_rebuild_make_root(struct erofs_sb_info *sbi)
2010 {
2011 	struct erofs_inode *root;
2012 
2013 	root = erofs_new_inode(sbi);
2014 	if (IS_ERR(root))
2015 		return root;
2016 	root->i_srcpath = strdup("/");
2017 	root->i_mode = S_IFDIR | 0777;
2018 	root->i_parent = root;
2019 	root->i_mtime = root->sbi->build_time;
2020 	root->i_mtime_nsec = root->sbi->build_time_nsec;
2021 	erofs_init_empty_dir(root);
2022 	return root;
2023 }
2024