xref: /aosp_15_r20/external/f2fs-tools/fsck/mkquota.c (revision 59bfda1f02d633cd6b8b69f31eee485d40f6eef6)
1*59bfda1fSAndroid Build Coastguard Worker /*
2*59bfda1fSAndroid Build Coastguard Worker  * mkquota.c --- create quota files for a filesystem
3*59bfda1fSAndroid Build Coastguard Worker  *
4*59bfda1fSAndroid Build Coastguard Worker  * Aditya Kali <[email protected]>
5*59bfda1fSAndroid Build Coastguard Worker  * Hyojun Kim <[email protected]> - Ported to f2fs-tools
6*59bfda1fSAndroid Build Coastguard Worker  */
7*59bfda1fSAndroid Build Coastguard Worker 
8*59bfda1fSAndroid Build Coastguard Worker #include <sys/types.h>
9*59bfda1fSAndroid Build Coastguard Worker #include <sys/stat.h>
10*59bfda1fSAndroid Build Coastguard Worker #include <unistd.h>
11*59bfda1fSAndroid Build Coastguard Worker #include <errno.h>
12*59bfda1fSAndroid Build Coastguard Worker #include <string.h>
13*59bfda1fSAndroid Build Coastguard Worker #include <stdlib.h>
14*59bfda1fSAndroid Build Coastguard Worker #include <stdio.h>
15*59bfda1fSAndroid Build Coastguard Worker #include <fcntl.h>
16*59bfda1fSAndroid Build Coastguard Worker 
17*59bfda1fSAndroid Build Coastguard Worker #include "quotaio.h"
18*59bfda1fSAndroid Build Coastguard Worker #include "quotaio_v2.h"
19*59bfda1fSAndroid Build Coastguard Worker #include "quotaio_tree.h"
20*59bfda1fSAndroid Build Coastguard Worker #include "common.h"
21*59bfda1fSAndroid Build Coastguard Worker #include "dict.h"
22*59bfda1fSAndroid Build Coastguard Worker 
23*59bfda1fSAndroid Build Coastguard Worker 
24*59bfda1fSAndroid Build Coastguard Worker /* Needed for architectures where sizeof(int) != sizeof(void *) */
25*59bfda1fSAndroid Build Coastguard Worker #define UINT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
26*59bfda1fSAndroid Build Coastguard Worker #define VOIDPTR_TO_UINT(ptr)  ((unsigned int)(intptr_t)(ptr))
27*59bfda1fSAndroid Build Coastguard Worker 
28*59bfda1fSAndroid Build Coastguard Worker #if DEBUG_QUOTA
print_dquot(const char * desc,struct dquot * dq)29*59bfda1fSAndroid Build Coastguard Worker static void print_dquot(const char *desc, struct dquot *dq)
30*59bfda1fSAndroid Build Coastguard Worker {
31*59bfda1fSAndroid Build Coastguard Worker 	if (desc)
32*59bfda1fSAndroid Build Coastguard Worker 		fprintf(stderr, "%s: ", desc);
33*59bfda1fSAndroid Build Coastguard Worker 	fprintf(stderr, "%u %lld:%lld:%lld %lld:%lld:%lld\n",
34*59bfda1fSAndroid Build Coastguard Worker 		dq->dq_id, (long long) dq->dq_dqb.dqb_curspace,
35*59bfda1fSAndroid Build Coastguard Worker 		(long long) dq->dq_dqb.dqb_bsoftlimit,
36*59bfda1fSAndroid Build Coastguard Worker 		(long long) dq->dq_dqb.dqb_bhardlimit,
37*59bfda1fSAndroid Build Coastguard Worker 		(long long) dq->dq_dqb.dqb_curinodes,
38*59bfda1fSAndroid Build Coastguard Worker 		(long long) dq->dq_dqb.dqb_isoftlimit,
39*59bfda1fSAndroid Build Coastguard Worker 		(long long) dq->dq_dqb.dqb_ihardlimit);
40*59bfda1fSAndroid Build Coastguard Worker }
41*59bfda1fSAndroid Build Coastguard Worker #else
42*59bfda1fSAndroid Build Coastguard Worker #define print_dquot(...)
43*59bfda1fSAndroid Build Coastguard Worker #endif
44*59bfda1fSAndroid Build Coastguard Worker 
write_dquots(dict_t * dict,struct quota_handle * qh)45*59bfda1fSAndroid Build Coastguard Worker static int write_dquots(dict_t *dict, struct quota_handle *qh)
46*59bfda1fSAndroid Build Coastguard Worker {
47*59bfda1fSAndroid Build Coastguard Worker 	dnode_t		*n;
48*59bfda1fSAndroid Build Coastguard Worker 	struct dquot	*dq;
49*59bfda1fSAndroid Build Coastguard Worker 	int retval = 0;
50*59bfda1fSAndroid Build Coastguard Worker 
51*59bfda1fSAndroid Build Coastguard Worker 	for (n = dict_first(dict); n; n = dict_next(dict, n)) {
52*59bfda1fSAndroid Build Coastguard Worker 		dq = dnode_get(n);
53*59bfda1fSAndroid Build Coastguard Worker 		if (dq) {
54*59bfda1fSAndroid Build Coastguard Worker 			print_dquot("write", dq);
55*59bfda1fSAndroid Build Coastguard Worker 			dq->dq_h = qh;
56*59bfda1fSAndroid Build Coastguard Worker 			update_grace_times(dq);
57*59bfda1fSAndroid Build Coastguard Worker 			if (qh->qh_ops->commit_dquot(dq)) {
58*59bfda1fSAndroid Build Coastguard Worker 				retval = -1;
59*59bfda1fSAndroid Build Coastguard Worker 				break;
60*59bfda1fSAndroid Build Coastguard Worker 			}
61*59bfda1fSAndroid Build Coastguard Worker 		}
62*59bfda1fSAndroid Build Coastguard Worker 	}
63*59bfda1fSAndroid Build Coastguard Worker 	return retval;
64*59bfda1fSAndroid Build Coastguard Worker }
65*59bfda1fSAndroid Build Coastguard Worker 
quota_write_inode(struct f2fs_sb_info * sbi,enum quota_type qtype)66*59bfda1fSAndroid Build Coastguard Worker errcode_t quota_write_inode(struct f2fs_sb_info *sbi, enum quota_type qtype)
67*59bfda1fSAndroid Build Coastguard Worker {
68*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
69*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
70*59bfda1fSAndroid Build Coastguard Worker 	quota_ctx_t qctx = fsck->qctx;
71*59bfda1fSAndroid Build Coastguard Worker 	struct quota_handle *h = NULL;
72*59bfda1fSAndroid Build Coastguard Worker 	int retval = 0;
73*59bfda1fSAndroid Build Coastguard Worker 	dict_t *dict;
74*59bfda1fSAndroid Build Coastguard Worker 
75*59bfda1fSAndroid Build Coastguard Worker 	if ((!qctx) || (!sb->qf_ino[qtype]))
76*59bfda1fSAndroid Build Coastguard Worker 		return 0;
77*59bfda1fSAndroid Build Coastguard Worker 
78*59bfda1fSAndroid Build Coastguard Worker 	retval = quota_get_mem(sizeof(struct quota_handle), &h);
79*59bfda1fSAndroid Build Coastguard Worker 	if (retval) {
80*59bfda1fSAndroid Build Coastguard Worker 		log_debug("Unable to allocate quota handle");
81*59bfda1fSAndroid Build Coastguard Worker 		goto out;
82*59bfda1fSAndroid Build Coastguard Worker 	}
83*59bfda1fSAndroid Build Coastguard Worker 
84*59bfda1fSAndroid Build Coastguard Worker 	dict = qctx->quota_dict[qtype];
85*59bfda1fSAndroid Build Coastguard Worker 	if (dict) {
86*59bfda1fSAndroid Build Coastguard Worker 		retval = quota_file_create(sbi, h, qtype);
87*59bfda1fSAndroid Build Coastguard Worker 		if (retval) {
88*59bfda1fSAndroid Build Coastguard Worker 			log_debug("Cannot initialize io on quotafile");
89*59bfda1fSAndroid Build Coastguard Worker 		} else {
90*59bfda1fSAndroid Build Coastguard Worker 			retval = write_dquots(dict, h);
91*59bfda1fSAndroid Build Coastguard Worker 			quota_file_close(sbi, h, 1);
92*59bfda1fSAndroid Build Coastguard Worker 		}
93*59bfda1fSAndroid Build Coastguard Worker 	}
94*59bfda1fSAndroid Build Coastguard Worker out:
95*59bfda1fSAndroid Build Coastguard Worker 	if (h)
96*59bfda1fSAndroid Build Coastguard Worker 		quota_free_mem(&h);
97*59bfda1fSAndroid Build Coastguard Worker 	return retval;
98*59bfda1fSAndroid Build Coastguard Worker }
99*59bfda1fSAndroid Build Coastguard Worker 
100*59bfda1fSAndroid Build Coastguard Worker /******************************************************************/
101*59bfda1fSAndroid Build Coastguard Worker /* Helper functions for computing quota in memory.                */
102*59bfda1fSAndroid Build Coastguard Worker /******************************************************************/
103*59bfda1fSAndroid Build Coastguard Worker 
dict_uint_cmp(const void * a,const void * b)104*59bfda1fSAndroid Build Coastguard Worker static int dict_uint_cmp(const void *a, const void *b)
105*59bfda1fSAndroid Build Coastguard Worker {
106*59bfda1fSAndroid Build Coastguard Worker 	unsigned int	c, d;
107*59bfda1fSAndroid Build Coastguard Worker 
108*59bfda1fSAndroid Build Coastguard Worker 	c = VOIDPTR_TO_UINT(a);
109*59bfda1fSAndroid Build Coastguard Worker 	d = VOIDPTR_TO_UINT(b);
110*59bfda1fSAndroid Build Coastguard Worker 
111*59bfda1fSAndroid Build Coastguard Worker 	if (c == d)
112*59bfda1fSAndroid Build Coastguard Worker 		return 0;
113*59bfda1fSAndroid Build Coastguard Worker 	else if (c > d)
114*59bfda1fSAndroid Build Coastguard Worker 		return 1;
115*59bfda1fSAndroid Build Coastguard Worker 	else
116*59bfda1fSAndroid Build Coastguard Worker 		return -1;
117*59bfda1fSAndroid Build Coastguard Worker }
118*59bfda1fSAndroid Build Coastguard Worker 
get_qid(struct f2fs_inode * inode,enum quota_type qtype)119*59bfda1fSAndroid Build Coastguard Worker static inline qid_t get_qid(struct f2fs_inode *inode, enum quota_type qtype)
120*59bfda1fSAndroid Build Coastguard Worker {
121*59bfda1fSAndroid Build Coastguard Worker 	switch (qtype) {
122*59bfda1fSAndroid Build Coastguard Worker 	case USRQUOTA:
123*59bfda1fSAndroid Build Coastguard Worker 		return inode->i_uid;
124*59bfda1fSAndroid Build Coastguard Worker 	case GRPQUOTA:
125*59bfda1fSAndroid Build Coastguard Worker 		return inode->i_gid;
126*59bfda1fSAndroid Build Coastguard Worker 	case PRJQUOTA:
127*59bfda1fSAndroid Build Coastguard Worker 		return inode->i_projid;
128*59bfda1fSAndroid Build Coastguard Worker 	default:
129*59bfda1fSAndroid Build Coastguard Worker 		return 0;
130*59bfda1fSAndroid Build Coastguard Worker 	}
131*59bfda1fSAndroid Build Coastguard Worker 
132*59bfda1fSAndroid Build Coastguard Worker 	return 0;
133*59bfda1fSAndroid Build Coastguard Worker }
134*59bfda1fSAndroid Build Coastguard Worker 
quota_dnode_free(dnode_t * node,void * UNUSED (context))135*59bfda1fSAndroid Build Coastguard Worker static void quota_dnode_free(dnode_t *node, void *UNUSED(context))
136*59bfda1fSAndroid Build Coastguard Worker {
137*59bfda1fSAndroid Build Coastguard Worker 	void *ptr = node ? dnode_get(node) : 0;
138*59bfda1fSAndroid Build Coastguard Worker 
139*59bfda1fSAndroid Build Coastguard Worker 	quota_free_mem(&ptr);
140*59bfda1fSAndroid Build Coastguard Worker 	free(node);
141*59bfda1fSAndroid Build Coastguard Worker }
142*59bfda1fSAndroid Build Coastguard Worker 
143*59bfda1fSAndroid Build Coastguard Worker /*
144*59bfda1fSAndroid Build Coastguard Worker  * Set up the quota tracking data structures.
145*59bfda1fSAndroid Build Coastguard Worker  */
quota_init_context(struct f2fs_sb_info * sbi)146*59bfda1fSAndroid Build Coastguard Worker errcode_t quota_init_context(struct f2fs_sb_info *sbi)
147*59bfda1fSAndroid Build Coastguard Worker {
148*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
149*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
150*59bfda1fSAndroid Build Coastguard Worker 	errcode_t err;
151*59bfda1fSAndroid Build Coastguard Worker 	dict_t	*dict;
152*59bfda1fSAndroid Build Coastguard Worker 	quota_ctx_t ctx;
153*59bfda1fSAndroid Build Coastguard Worker 	enum quota_type	qtype;
154*59bfda1fSAndroid Build Coastguard Worker 
155*59bfda1fSAndroid Build Coastguard Worker 	err = quota_get_mem(sizeof(struct quota_ctx), &ctx);
156*59bfda1fSAndroid Build Coastguard Worker 	if (err) {
157*59bfda1fSAndroid Build Coastguard Worker 		log_debug("Failed to allocate quota context");
158*59bfda1fSAndroid Build Coastguard Worker 		return err;
159*59bfda1fSAndroid Build Coastguard Worker 	}
160*59bfda1fSAndroid Build Coastguard Worker 
161*59bfda1fSAndroid Build Coastguard Worker 	memset(ctx, 0, sizeof(struct quota_ctx));
162*59bfda1fSAndroid Build Coastguard Worker 	dict_init(&ctx->linked_inode_dict, DICTCOUNT_T_MAX, dict_uint_cmp);
163*59bfda1fSAndroid Build Coastguard Worker 	for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
164*59bfda1fSAndroid Build Coastguard Worker 		ctx->quota_file[qtype] = NULL;
165*59bfda1fSAndroid Build Coastguard Worker 		if (!sb->qf_ino[qtype])
166*59bfda1fSAndroid Build Coastguard Worker 			continue;
167*59bfda1fSAndroid Build Coastguard Worker 		err = quota_get_mem(sizeof(dict_t), &dict);
168*59bfda1fSAndroid Build Coastguard Worker 		if (err) {
169*59bfda1fSAndroid Build Coastguard Worker 			log_debug("Failed to allocate dictionary");
170*59bfda1fSAndroid Build Coastguard Worker 			quota_release_context(&ctx);
171*59bfda1fSAndroid Build Coastguard Worker 			return err;
172*59bfda1fSAndroid Build Coastguard Worker 		}
173*59bfda1fSAndroid Build Coastguard Worker 		ctx->quota_dict[qtype] = dict;
174*59bfda1fSAndroid Build Coastguard Worker 		dict_init(dict, DICTCOUNT_T_MAX, dict_uint_cmp);
175*59bfda1fSAndroid Build Coastguard Worker 		dict_set_allocator(dict, NULL, quota_dnode_free, NULL);
176*59bfda1fSAndroid Build Coastguard Worker 	}
177*59bfda1fSAndroid Build Coastguard Worker 	ctx->sbi = sbi;
178*59bfda1fSAndroid Build Coastguard Worker 	fsck->qctx = ctx;
179*59bfda1fSAndroid Build Coastguard Worker 	return 0;
180*59bfda1fSAndroid Build Coastguard Worker }
181*59bfda1fSAndroid Build Coastguard Worker 
quota_release_context(quota_ctx_t * qctx)182*59bfda1fSAndroid Build Coastguard Worker void quota_release_context(quota_ctx_t *qctx)
183*59bfda1fSAndroid Build Coastguard Worker {
184*59bfda1fSAndroid Build Coastguard Worker 	dict_t	*dict;
185*59bfda1fSAndroid Build Coastguard Worker 	enum quota_type	qtype;
186*59bfda1fSAndroid Build Coastguard Worker 	quota_ctx_t ctx;
187*59bfda1fSAndroid Build Coastguard Worker 
188*59bfda1fSAndroid Build Coastguard Worker 	if (!qctx)
189*59bfda1fSAndroid Build Coastguard Worker 		return;
190*59bfda1fSAndroid Build Coastguard Worker 
191*59bfda1fSAndroid Build Coastguard Worker 	ctx = *qctx;
192*59bfda1fSAndroid Build Coastguard Worker 	for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
193*59bfda1fSAndroid Build Coastguard Worker 		dict = ctx->quota_dict[qtype];
194*59bfda1fSAndroid Build Coastguard Worker 		ctx->quota_dict[qtype] = 0;
195*59bfda1fSAndroid Build Coastguard Worker 		if (dict) {
196*59bfda1fSAndroid Build Coastguard Worker 			dict_free_nodes(dict);
197*59bfda1fSAndroid Build Coastguard Worker 			free(dict);
198*59bfda1fSAndroid Build Coastguard Worker 		}
199*59bfda1fSAndroid Build Coastguard Worker 	}
200*59bfda1fSAndroid Build Coastguard Worker 	dict_free_nodes(&ctx->linked_inode_dict);
201*59bfda1fSAndroid Build Coastguard Worker 	*qctx = NULL;
202*59bfda1fSAndroid Build Coastguard Worker 	free(ctx);
203*59bfda1fSAndroid Build Coastguard Worker }
204*59bfda1fSAndroid Build Coastguard Worker 
get_dq(dict_t * dict,__u32 key)205*59bfda1fSAndroid Build Coastguard Worker static struct dquot *get_dq(dict_t *dict, __u32 key)
206*59bfda1fSAndroid Build Coastguard Worker {
207*59bfda1fSAndroid Build Coastguard Worker 	struct dquot	*dq;
208*59bfda1fSAndroid Build Coastguard Worker 	dnode_t		*n;
209*59bfda1fSAndroid Build Coastguard Worker 
210*59bfda1fSAndroid Build Coastguard Worker 	n = dict_lookup(dict, UINT_TO_VOIDPTR(key));
211*59bfda1fSAndroid Build Coastguard Worker 	if (n)
212*59bfda1fSAndroid Build Coastguard Worker 		dq = dnode_get(n);
213*59bfda1fSAndroid Build Coastguard Worker 	else {
214*59bfda1fSAndroid Build Coastguard Worker 		if (quota_get_mem(sizeof(struct dquot), &dq)) {
215*59bfda1fSAndroid Build Coastguard Worker 			log_err("Unable to allocate dquot");
216*59bfda1fSAndroid Build Coastguard Worker 			return NULL;
217*59bfda1fSAndroid Build Coastguard Worker 		}
218*59bfda1fSAndroid Build Coastguard Worker 		memset(dq, 0, sizeof(struct dquot));
219*59bfda1fSAndroid Build Coastguard Worker 		dict_alloc_insert(dict, UINT_TO_VOIDPTR(key), dq);
220*59bfda1fSAndroid Build Coastguard Worker 		dq->dq_id = key;
221*59bfda1fSAndroid Build Coastguard Worker 	}
222*59bfda1fSAndroid Build Coastguard Worker 	return dq;
223*59bfda1fSAndroid Build Coastguard Worker }
224*59bfda1fSAndroid Build Coastguard Worker 
225*59bfda1fSAndroid Build Coastguard Worker /*
226*59bfda1fSAndroid Build Coastguard Worker  * Called to update the blocks used by a particular inode
227*59bfda1fSAndroid Build Coastguard Worker  */
quota_data_add(quota_ctx_t qctx,struct f2fs_inode * inode,qsize_t space)228*59bfda1fSAndroid Build Coastguard Worker void quota_data_add(quota_ctx_t qctx, struct f2fs_inode *inode, qsize_t space)
229*59bfda1fSAndroid Build Coastguard Worker {
230*59bfda1fSAndroid Build Coastguard Worker 	struct dquot	*dq;
231*59bfda1fSAndroid Build Coastguard Worker 	dict_t		*dict;
232*59bfda1fSAndroid Build Coastguard Worker 	enum quota_type	qtype;
233*59bfda1fSAndroid Build Coastguard Worker 
234*59bfda1fSAndroid Build Coastguard Worker 	if (!qctx)
235*59bfda1fSAndroid Build Coastguard Worker 		return;
236*59bfda1fSAndroid Build Coastguard Worker 
237*59bfda1fSAndroid Build Coastguard Worker 	for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
238*59bfda1fSAndroid Build Coastguard Worker 		dict = qctx->quota_dict[qtype];
239*59bfda1fSAndroid Build Coastguard Worker 		if (dict) {
240*59bfda1fSAndroid Build Coastguard Worker 			dq = get_dq(dict, get_qid(inode, qtype));
241*59bfda1fSAndroid Build Coastguard Worker 			if (dq)
242*59bfda1fSAndroid Build Coastguard Worker 				dq->dq_dqb.dqb_curspace += space;
243*59bfda1fSAndroid Build Coastguard Worker 		}
244*59bfda1fSAndroid Build Coastguard Worker 	}
245*59bfda1fSAndroid Build Coastguard Worker }
246*59bfda1fSAndroid Build Coastguard Worker 
247*59bfda1fSAndroid Build Coastguard Worker /*
248*59bfda1fSAndroid Build Coastguard Worker  * Called to remove some blocks used by a particular inode
249*59bfda1fSAndroid Build Coastguard Worker  */
quota_data_sub(quota_ctx_t qctx,struct f2fs_inode * inode,qsize_t space)250*59bfda1fSAndroid Build Coastguard Worker void quota_data_sub(quota_ctx_t qctx, struct f2fs_inode *inode, qsize_t space)
251*59bfda1fSAndroid Build Coastguard Worker {
252*59bfda1fSAndroid Build Coastguard Worker 	struct dquot	*dq;
253*59bfda1fSAndroid Build Coastguard Worker 	dict_t		*dict;
254*59bfda1fSAndroid Build Coastguard Worker 	enum quota_type	qtype;
255*59bfda1fSAndroid Build Coastguard Worker 
256*59bfda1fSAndroid Build Coastguard Worker 	if (!qctx)
257*59bfda1fSAndroid Build Coastguard Worker 		return;
258*59bfda1fSAndroid Build Coastguard Worker 
259*59bfda1fSAndroid Build Coastguard Worker 	for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
260*59bfda1fSAndroid Build Coastguard Worker 		dict = qctx->quota_dict[qtype];
261*59bfda1fSAndroid Build Coastguard Worker 		if (dict) {
262*59bfda1fSAndroid Build Coastguard Worker 			dq = get_dq(dict, get_qid(inode, qtype));
263*59bfda1fSAndroid Build Coastguard Worker 			dq->dq_dqb.dqb_curspace -= space;
264*59bfda1fSAndroid Build Coastguard Worker 		}
265*59bfda1fSAndroid Build Coastguard Worker 	}
266*59bfda1fSAndroid Build Coastguard Worker }
267*59bfda1fSAndroid Build Coastguard Worker 
268*59bfda1fSAndroid Build Coastguard Worker /*
269*59bfda1fSAndroid Build Coastguard Worker  * Called to count the files used by an inode's user/group
270*59bfda1fSAndroid Build Coastguard Worker  */
quota_data_inodes(quota_ctx_t qctx,struct f2fs_inode * inode,int adjust)271*59bfda1fSAndroid Build Coastguard Worker void quota_data_inodes(quota_ctx_t qctx, struct f2fs_inode *inode, int adjust)
272*59bfda1fSAndroid Build Coastguard Worker {
273*59bfda1fSAndroid Build Coastguard Worker 	struct dquot	*dq;
274*59bfda1fSAndroid Build Coastguard Worker 	dict_t		*dict; enum quota_type	qtype;
275*59bfda1fSAndroid Build Coastguard Worker 
276*59bfda1fSAndroid Build Coastguard Worker 	if (!qctx)
277*59bfda1fSAndroid Build Coastguard Worker 		return;
278*59bfda1fSAndroid Build Coastguard Worker 
279*59bfda1fSAndroid Build Coastguard Worker 	for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
280*59bfda1fSAndroid Build Coastguard Worker 		dict = qctx->quota_dict[qtype];
281*59bfda1fSAndroid Build Coastguard Worker 		if (dict) {
282*59bfda1fSAndroid Build Coastguard Worker 			dq = get_dq(dict, get_qid(inode, qtype));
283*59bfda1fSAndroid Build Coastguard Worker 			dq->dq_dqb.dqb_curinodes += adjust;
284*59bfda1fSAndroid Build Coastguard Worker 		}
285*59bfda1fSAndroid Build Coastguard Worker 	}
286*59bfda1fSAndroid Build Coastguard Worker }
287*59bfda1fSAndroid Build Coastguard Worker 
288*59bfda1fSAndroid Build Coastguard Worker /*
289*59bfda1fSAndroid Build Coastguard Worker  * Called from fsck to count quota.
290*59bfda1fSAndroid Build Coastguard Worker  */
quota_add_inode_usage(quota_ctx_t qctx,f2fs_ino_t ino,struct f2fs_inode * inode)291*59bfda1fSAndroid Build Coastguard Worker void quota_add_inode_usage(quota_ctx_t qctx, f2fs_ino_t ino,
292*59bfda1fSAndroid Build Coastguard Worker 		struct f2fs_inode* inode)
293*59bfda1fSAndroid Build Coastguard Worker {
294*59bfda1fSAndroid Build Coastguard Worker 	if (qctx) {
295*59bfda1fSAndroid Build Coastguard Worker 		/* Handle hard linked inodes */
296*59bfda1fSAndroid Build Coastguard Worker 		if (inode->i_links > 1) {
297*59bfda1fSAndroid Build Coastguard Worker 			if (dict_lookup(&qctx->linked_inode_dict,
298*59bfda1fSAndroid Build Coastguard Worker 				UINT_TO_VOIDPTR(ino))) {
299*59bfda1fSAndroid Build Coastguard Worker 				return;
300*59bfda1fSAndroid Build Coastguard Worker 			}
301*59bfda1fSAndroid Build Coastguard Worker 			dict_alloc_insert(&qctx->linked_inode_dict,
302*59bfda1fSAndroid Build Coastguard Worker 					UINT_TO_VOIDPTR(ino), NULL);
303*59bfda1fSAndroid Build Coastguard Worker 		}
304*59bfda1fSAndroid Build Coastguard Worker 
305*59bfda1fSAndroid Build Coastguard Worker 		qsize_t space = (inode->i_blocks - 1) * F2FS_BLKSIZE;
306*59bfda1fSAndroid Build Coastguard Worker 		quota_data_add(qctx, inode, space);
307*59bfda1fSAndroid Build Coastguard Worker 		quota_data_inodes(qctx, inode, +1);
308*59bfda1fSAndroid Build Coastguard Worker 	}
309*59bfda1fSAndroid Build Coastguard Worker }
310*59bfda1fSAndroid Build Coastguard Worker 
311*59bfda1fSAndroid Build Coastguard Worker struct scan_dquots_data {
312*59bfda1fSAndroid Build Coastguard Worker 	dict_t		*quota_dict;
313*59bfda1fSAndroid Build Coastguard Worker 	int             update_limits; /* update limits from disk */
314*59bfda1fSAndroid Build Coastguard Worker 	int		update_usage;
315*59bfda1fSAndroid Build Coastguard Worker 	int		usage_is_inconsistent;
316*59bfda1fSAndroid Build Coastguard Worker };
317*59bfda1fSAndroid Build Coastguard Worker 
scan_dquots_callback(struct dquot * dquot,void * cb_data)318*59bfda1fSAndroid Build Coastguard Worker static int scan_dquots_callback(struct dquot *dquot, void *cb_data)
319*59bfda1fSAndroid Build Coastguard Worker {
320*59bfda1fSAndroid Build Coastguard Worker 	struct scan_dquots_data *scan_data = cb_data;
321*59bfda1fSAndroid Build Coastguard Worker 	dict_t *quota_dict = scan_data->quota_dict;
322*59bfda1fSAndroid Build Coastguard Worker 	struct dquot *dq;
323*59bfda1fSAndroid Build Coastguard Worker 
324*59bfda1fSAndroid Build Coastguard Worker 	dq = get_dq(quota_dict, dquot->dq_id);
325*59bfda1fSAndroid Build Coastguard Worker 	dq->dq_id = dquot->dq_id;
326*59bfda1fSAndroid Build Coastguard Worker 	dq->dq_flags |= DQF_SEEN;
327*59bfda1fSAndroid Build Coastguard Worker 
328*59bfda1fSAndroid Build Coastguard Worker 	print_dquot("mem", dq);
329*59bfda1fSAndroid Build Coastguard Worker 	print_dquot("dsk", dquot);
330*59bfda1fSAndroid Build Coastguard Worker 	/* Check if there is inconsistency */
331*59bfda1fSAndroid Build Coastguard Worker 	if (dq->dq_dqb.dqb_curspace != dquot->dq_dqb.dqb_curspace ||
332*59bfda1fSAndroid Build Coastguard Worker 	    dq->dq_dqb.dqb_curinodes != dquot->dq_dqb.dqb_curinodes) {
333*59bfda1fSAndroid Build Coastguard Worker 		scan_data->usage_is_inconsistent = 1;
334*59bfda1fSAndroid Build Coastguard Worker 		log_debug("[QUOTA WARNING] Usage inconsistent for ID %u:"
335*59bfda1fSAndroid Build Coastguard Worker 			"actual (%lld, %lld) != expected (%lld, %lld)\n",
336*59bfda1fSAndroid Build Coastguard Worker 				dq->dq_id, (long long) dq->dq_dqb.dqb_curspace,
337*59bfda1fSAndroid Build Coastguard Worker 				(long long) dq->dq_dqb.dqb_curinodes,
338*59bfda1fSAndroid Build Coastguard Worker 				(long long) dquot->dq_dqb.dqb_curspace,
339*59bfda1fSAndroid Build Coastguard Worker 				(long long) dquot->dq_dqb.dqb_curinodes);
340*59bfda1fSAndroid Build Coastguard Worker 	}
341*59bfda1fSAndroid Build Coastguard Worker 
342*59bfda1fSAndroid Build Coastguard Worker 	if (scan_data->update_limits) {
343*59bfda1fSAndroid Build Coastguard Worker 		dq->dq_dqb.dqb_ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
344*59bfda1fSAndroid Build Coastguard Worker 		dq->dq_dqb.dqb_isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
345*59bfda1fSAndroid Build Coastguard Worker 		dq->dq_dqb.dqb_bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
346*59bfda1fSAndroid Build Coastguard Worker 		dq->dq_dqb.dqb_bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
347*59bfda1fSAndroid Build Coastguard Worker 	}
348*59bfda1fSAndroid Build Coastguard Worker 
349*59bfda1fSAndroid Build Coastguard Worker 	if (scan_data->update_usage) {
350*59bfda1fSAndroid Build Coastguard Worker 		dq->dq_dqb.dqb_curspace = dquot->dq_dqb.dqb_curspace;
351*59bfda1fSAndroid Build Coastguard Worker 		dq->dq_dqb.dqb_curinodes = dquot->dq_dqb.dqb_curinodes;
352*59bfda1fSAndroid Build Coastguard Worker 	}
353*59bfda1fSAndroid Build Coastguard Worker 
354*59bfda1fSAndroid Build Coastguard Worker 	return 0;
355*59bfda1fSAndroid Build Coastguard Worker }
356*59bfda1fSAndroid Build Coastguard Worker 
357*59bfda1fSAndroid Build Coastguard Worker /*
358*59bfda1fSAndroid Build Coastguard Worker  * Compares the measured quota in qctx->quota_dict with that in the quota inode
359*59bfda1fSAndroid Build Coastguard Worker  * on disk and updates the limits in qctx->quota_dict. 'usage_inconsistent' is
360*59bfda1fSAndroid Build Coastguard Worker  * set to 1 if the supplied and on-disk quota usage values are not identical.
361*59bfda1fSAndroid Build Coastguard Worker  */
quota_compare_and_update(struct f2fs_sb_info * sbi,enum quota_type qtype,int * usage_inconsistent,int preserve_limits)362*59bfda1fSAndroid Build Coastguard Worker errcode_t quota_compare_and_update(struct f2fs_sb_info *sbi,
363*59bfda1fSAndroid Build Coastguard Worker 		enum quota_type qtype, int *usage_inconsistent,
364*59bfda1fSAndroid Build Coastguard Worker 		int preserve_limits)
365*59bfda1fSAndroid Build Coastguard Worker {
366*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
367*59bfda1fSAndroid Build Coastguard Worker 	quota_ctx_t qctx = fsck->qctx;
368*59bfda1fSAndroid Build Coastguard Worker 	struct quota_handle qh;
369*59bfda1fSAndroid Build Coastguard Worker 	struct scan_dquots_data scan_data;
370*59bfda1fSAndroid Build Coastguard Worker 	struct dquot *dq;
371*59bfda1fSAndroid Build Coastguard Worker 	dnode_t *n;
372*59bfda1fSAndroid Build Coastguard Worker 	dict_t *dict = qctx->quota_dict[qtype];
373*59bfda1fSAndroid Build Coastguard Worker 	errcode_t err = 0;
374*59bfda1fSAndroid Build Coastguard Worker 
375*59bfda1fSAndroid Build Coastguard Worker 	if (!dict)
376*59bfda1fSAndroid Build Coastguard Worker 		goto out;
377*59bfda1fSAndroid Build Coastguard Worker 
378*59bfda1fSAndroid Build Coastguard Worker 	err = quota_file_open(sbi, &qh, qtype, 0);
379*59bfda1fSAndroid Build Coastguard Worker 	if (err) {
380*59bfda1fSAndroid Build Coastguard Worker 		log_debug("Open quota file failed");
381*59bfda1fSAndroid Build Coastguard Worker 		*usage_inconsistent = 1;
382*59bfda1fSAndroid Build Coastguard Worker 		goto out;
383*59bfda1fSAndroid Build Coastguard Worker 	}
384*59bfda1fSAndroid Build Coastguard Worker 
385*59bfda1fSAndroid Build Coastguard Worker 	scan_data.quota_dict = qctx->quota_dict[qtype];
386*59bfda1fSAndroid Build Coastguard Worker 	scan_data.update_limits = preserve_limits;
387*59bfda1fSAndroid Build Coastguard Worker 	scan_data.update_usage = 0;
388*59bfda1fSAndroid Build Coastguard Worker 	scan_data.usage_is_inconsistent = 0;
389*59bfda1fSAndroid Build Coastguard Worker 	err = qh.qh_ops->scan_dquots(&qh, scan_dquots_callback, &scan_data);
390*59bfda1fSAndroid Build Coastguard Worker 	if (err) {
391*59bfda1fSAndroid Build Coastguard Worker 		log_debug("Error scanning dquots");
392*59bfda1fSAndroid Build Coastguard Worker 		goto out;
393*59bfda1fSAndroid Build Coastguard Worker 	}
394*59bfda1fSAndroid Build Coastguard Worker 
395*59bfda1fSAndroid Build Coastguard Worker 	for (n = dict_first(dict); n; n = dict_next(dict, n)) {
396*59bfda1fSAndroid Build Coastguard Worker 		dq = dnode_get(n);
397*59bfda1fSAndroid Build Coastguard Worker 		if (!dq)
398*59bfda1fSAndroid Build Coastguard Worker 			continue;
399*59bfda1fSAndroid Build Coastguard Worker 		if ((dq->dq_flags & DQF_SEEN) == 0) {
400*59bfda1fSAndroid Build Coastguard Worker 			log_debug("[QUOTA WARNING] "
401*59bfda1fSAndroid Build Coastguard Worker 				"Missing quota entry ID %d\n", dq->dq_id);
402*59bfda1fSAndroid Build Coastguard Worker 			scan_data.usage_is_inconsistent = 1;
403*59bfda1fSAndroid Build Coastguard Worker 		}
404*59bfda1fSAndroid Build Coastguard Worker 	}
405*59bfda1fSAndroid Build Coastguard Worker 	*usage_inconsistent = scan_data.usage_is_inconsistent;
406*59bfda1fSAndroid Build Coastguard Worker 
407*59bfda1fSAndroid Build Coastguard Worker out:
408*59bfda1fSAndroid Build Coastguard Worker 	return err;
409*59bfda1fSAndroid Build Coastguard Worker }
410*59bfda1fSAndroid Build Coastguard Worker 
411