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