xref: /freebsd/sys/contrib/openzfs/module/zfs/zfs_quota.c (revision 87b759f0fa1f7554d50ce640c40138512bbded44)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or https://opensource.org/licenses/CDDL-1.0.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright (c) 2011 Pawel Jakub Dawidek
24  * Copyright (c) 2012, 2015, 2018 by Delphix. All rights reserved.
25  * Copyright (c) 2014 Integros [integros.com]
26  * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
27  */
28 
29 /* Portions Copyright 2010 Robert Milkowski */
30 
31 #include <sys/avl.h>
32 #include <sys/dmu_objset.h>
33 #include <sys/sa.h>
34 #include <sys/sa_impl.h>
35 #include <sys/zap.h>
36 #include <sys/zfs_project.h>
37 #include <sys/zfs_quota.h>
38 #include <sys/zfs_znode.h>
39 
40 int
41 zpl_get_file_info(dmu_object_type_t bonustype, const void *data,
42     zfs_file_info_t *zoi)
43 {
44 	/*
45 	 * Is it a valid type of object to track?
46 	 */
47 	if (bonustype != DMU_OT_ZNODE && bonustype != DMU_OT_SA)
48 		return (SET_ERROR(ENOENT));
49 
50 	zoi->zfi_project = ZFS_DEFAULT_PROJID;
51 
52 	/*
53 	 * If we have a NULL data pointer
54 	 * then assume the id's aren't changing and
55 	 * return EEXIST to the dmu to let it know to
56 	 * use the same ids
57 	 */
58 	if (data == NULL)
59 		return (SET_ERROR(EEXIST));
60 
61 	if (bonustype == DMU_OT_ZNODE) {
62 		const znode_phys_t *znp = data;
63 		zoi->zfi_user = znp->zp_uid;
64 		zoi->zfi_group = znp->zp_gid;
65 		zoi->zfi_generation = znp->zp_gen;
66 		return (0);
67 	}
68 
69 	const sa_hdr_phys_t *sap = data;
70 	if (sap->sa_magic == 0) {
71 		/*
72 		 * This should only happen for newly created files
73 		 * that haven't had the znode data filled in yet.
74 		 */
75 		zoi->zfi_user = 0;
76 		zoi->zfi_group = 0;
77 		zoi->zfi_generation = 0;
78 		return (0);
79 	}
80 
81 	sa_hdr_phys_t sa = *sap;
82 	boolean_t swap = B_FALSE;
83 	if (sa.sa_magic == BSWAP_32(SA_MAGIC)) {
84 		sa.sa_magic = SA_MAGIC;
85 		sa.sa_layout_info = BSWAP_16(sa.sa_layout_info);
86 		swap = B_TRUE;
87 	}
88 	VERIFY3U(sa.sa_magic, ==, SA_MAGIC);
89 
90 	int hdrsize = sa_hdrsize(&sa);
91 	VERIFY3U(hdrsize, >=, sizeof (sa_hdr_phys_t));
92 
93 	uintptr_t data_after_hdr = (uintptr_t)data + hdrsize;
94 	zoi->zfi_user = *((uint64_t *)(data_after_hdr + SA_UID_OFFSET));
95 	zoi->zfi_group = *((uint64_t *)(data_after_hdr + SA_GID_OFFSET));
96 	zoi->zfi_generation = *((uint64_t *)(data_after_hdr + SA_GEN_OFFSET));
97 	uint64_t flags = *((uint64_t *)(data_after_hdr + SA_FLAGS_OFFSET));
98 	if (swap)
99 		flags = BSWAP_64(flags);
100 
101 	if (flags & ZFS_PROJID) {
102 		zoi->zfi_project =
103 		    *((uint64_t *)(data_after_hdr + SA_PROJID_OFFSET));
104 	}
105 
106 	if (swap) {
107 		zoi->zfi_user = BSWAP_64(zoi->zfi_user);
108 		zoi->zfi_group = BSWAP_64(zoi->zfi_group);
109 		zoi->zfi_project = BSWAP_64(zoi->zfi_project);
110 		zoi->zfi_generation = BSWAP_64(zoi->zfi_generation);
111 	}
112 	return (0);
113 }
114 
115 static void
116 fuidstr_to_sid(zfsvfs_t *zfsvfs, const char *fuidstr,
117     char *domainbuf, int buflen, uid_t *ridp)
118 {
119 	uint64_t fuid;
120 	const char *domain;
121 
122 	fuid = zfs_strtonum(fuidstr, NULL);
123 
124 	domain = zfs_fuid_find_by_idx(zfsvfs, FUID_INDEX(fuid));
125 	if (domain)
126 		(void) strlcpy(domainbuf, domain, buflen);
127 	else
128 		domainbuf[0] = '\0';
129 	*ridp = FUID_RID(fuid);
130 }
131 
132 static uint64_t
133 zfs_userquota_prop_to_obj(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type)
134 {
135 	switch (type) {
136 	case ZFS_PROP_USERUSED:
137 	case ZFS_PROP_USEROBJUSED:
138 		return (DMU_USERUSED_OBJECT);
139 	case ZFS_PROP_GROUPUSED:
140 	case ZFS_PROP_GROUPOBJUSED:
141 		return (DMU_GROUPUSED_OBJECT);
142 	case ZFS_PROP_PROJECTUSED:
143 	case ZFS_PROP_PROJECTOBJUSED:
144 		return (DMU_PROJECTUSED_OBJECT);
145 	case ZFS_PROP_USERQUOTA:
146 		return (zfsvfs->z_userquota_obj);
147 	case ZFS_PROP_GROUPQUOTA:
148 		return (zfsvfs->z_groupquota_obj);
149 	case ZFS_PROP_USEROBJQUOTA:
150 		return (zfsvfs->z_userobjquota_obj);
151 	case ZFS_PROP_GROUPOBJQUOTA:
152 		return (zfsvfs->z_groupobjquota_obj);
153 	case ZFS_PROP_PROJECTQUOTA:
154 		return (zfsvfs->z_projectquota_obj);
155 	case ZFS_PROP_PROJECTOBJQUOTA:
156 		return (zfsvfs->z_projectobjquota_obj);
157 	default:
158 		return (ZFS_NO_OBJECT);
159 	}
160 }
161 
162 int
163 zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
164     uint64_t *cookiep, void *vbuf, uint64_t *bufsizep)
165 {
166 	int error;
167 	zap_cursor_t zc;
168 	zap_attribute_t *za;
169 	zfs_useracct_t *buf = vbuf;
170 	uint64_t obj;
171 	int offset = 0;
172 
173 	if (!dmu_objset_userspace_present(zfsvfs->z_os))
174 		return (SET_ERROR(ENOTSUP));
175 
176 	if ((type == ZFS_PROP_PROJECTQUOTA || type == ZFS_PROP_PROJECTUSED ||
177 	    type == ZFS_PROP_PROJECTOBJQUOTA ||
178 	    type == ZFS_PROP_PROJECTOBJUSED) &&
179 	    !dmu_objset_projectquota_present(zfsvfs->z_os))
180 		return (SET_ERROR(ENOTSUP));
181 
182 	if ((type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED ||
183 	    type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA ||
184 	    type == ZFS_PROP_PROJECTOBJUSED ||
185 	    type == ZFS_PROP_PROJECTOBJQUOTA) &&
186 	    !dmu_objset_userobjspace_present(zfsvfs->z_os))
187 		return (SET_ERROR(ENOTSUP));
188 
189 	obj = zfs_userquota_prop_to_obj(zfsvfs, type);
190 	if (obj == ZFS_NO_OBJECT) {
191 		*bufsizep = 0;
192 		return (0);
193 	}
194 
195 	if (type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED ||
196 	    type == ZFS_PROP_PROJECTOBJUSED)
197 		offset = DMU_OBJACCT_PREFIX_LEN;
198 
199 	za = zap_attribute_alloc();
200 	for (zap_cursor_init_serialized(&zc, zfsvfs->z_os, obj, *cookiep);
201 	    (error = zap_cursor_retrieve(&zc, za)) == 0;
202 	    zap_cursor_advance(&zc)) {
203 		if ((uintptr_t)buf - (uintptr_t)vbuf + sizeof (zfs_useracct_t) >
204 		    *bufsizep)
205 			break;
206 
207 		/*
208 		 * skip object quota (with zap name prefix DMU_OBJACCT_PREFIX)
209 		 * when dealing with block quota and vice versa.
210 		 */
211 		if ((offset > 0) != (strncmp(za->za_name, DMU_OBJACCT_PREFIX,
212 		    DMU_OBJACCT_PREFIX_LEN) == 0))
213 			continue;
214 
215 		fuidstr_to_sid(zfsvfs, za->za_name + offset,
216 		    buf->zu_domain, sizeof (buf->zu_domain), &buf->zu_rid);
217 
218 		buf->zu_space = za->za_first_integer;
219 		buf++;
220 	}
221 	if (error == ENOENT)
222 		error = 0;
223 
224 	ASSERT3U((uintptr_t)buf - (uintptr_t)vbuf, <=, *bufsizep);
225 	*bufsizep = (uintptr_t)buf - (uintptr_t)vbuf;
226 	*cookiep = zap_cursor_serialize(&zc);
227 	zap_cursor_fini(&zc);
228 	zap_attribute_free(za);
229 	return (error);
230 }
231 
232 int
233 zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
234     const char *domain, uint64_t rid, uint64_t *valp)
235 {
236 	char buf[20 + DMU_OBJACCT_PREFIX_LEN];
237 	int offset = 0;
238 	int err;
239 	uint64_t obj;
240 
241 	*valp = 0;
242 
243 	if (!dmu_objset_userspace_present(zfsvfs->z_os))
244 		return (SET_ERROR(ENOTSUP));
245 
246 	if ((type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED ||
247 	    type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA ||
248 	    type == ZFS_PROP_PROJECTOBJUSED ||
249 	    type == ZFS_PROP_PROJECTOBJQUOTA) &&
250 	    !dmu_objset_userobjspace_present(zfsvfs->z_os))
251 		return (SET_ERROR(ENOTSUP));
252 
253 	if (type == ZFS_PROP_PROJECTQUOTA || type == ZFS_PROP_PROJECTUSED ||
254 	    type == ZFS_PROP_PROJECTOBJQUOTA ||
255 	    type == ZFS_PROP_PROJECTOBJUSED) {
256 		if (!dmu_objset_projectquota_present(zfsvfs->z_os))
257 			return (SET_ERROR(ENOTSUP));
258 		if (!zpl_is_valid_projid(rid))
259 			return (SET_ERROR(EINVAL));
260 	}
261 
262 	obj = zfs_userquota_prop_to_obj(zfsvfs, type);
263 	if (obj == ZFS_NO_OBJECT)
264 		return (0);
265 
266 	if (type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED ||
267 	    type == ZFS_PROP_PROJECTOBJUSED) {
268 		strlcpy(buf, DMU_OBJACCT_PREFIX, DMU_OBJACCT_PREFIX_LEN + 1);
269 		offset = DMU_OBJACCT_PREFIX_LEN;
270 	}
271 
272 	err = zfs_id_to_fuidstr(zfsvfs, domain, rid, buf + offset,
273 	    sizeof (buf) - offset, B_FALSE);
274 	if (err)
275 		return (err);
276 
277 	err = zap_lookup(zfsvfs->z_os, obj, buf, 8, 1, valp);
278 	if (err == ENOENT)
279 		err = 0;
280 	return (err);
281 }
282 
283 int
284 zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
285     const char *domain, uint64_t rid, uint64_t quota)
286 {
287 	char buf[32];
288 	int err;
289 	dmu_tx_t *tx;
290 	uint64_t *objp;
291 	boolean_t fuid_dirtied;
292 
293 	if (zfsvfs->z_version < ZPL_VERSION_USERSPACE)
294 		return (SET_ERROR(ENOTSUP));
295 
296 	switch (type) {
297 	case ZFS_PROP_USERQUOTA:
298 		objp = &zfsvfs->z_userquota_obj;
299 		break;
300 	case ZFS_PROP_GROUPQUOTA:
301 		objp = &zfsvfs->z_groupquota_obj;
302 		break;
303 	case ZFS_PROP_USEROBJQUOTA:
304 		objp = &zfsvfs->z_userobjquota_obj;
305 		break;
306 	case ZFS_PROP_GROUPOBJQUOTA:
307 		objp = &zfsvfs->z_groupobjquota_obj;
308 		break;
309 	case ZFS_PROP_PROJECTQUOTA:
310 		if (!dmu_objset_projectquota_enabled(zfsvfs->z_os))
311 			return (SET_ERROR(ENOTSUP));
312 		if (!zpl_is_valid_projid(rid))
313 			return (SET_ERROR(EINVAL));
314 
315 		objp = &zfsvfs->z_projectquota_obj;
316 		break;
317 	case ZFS_PROP_PROJECTOBJQUOTA:
318 		if (!dmu_objset_projectquota_enabled(zfsvfs->z_os))
319 			return (SET_ERROR(ENOTSUP));
320 		if (!zpl_is_valid_projid(rid))
321 			return (SET_ERROR(EINVAL));
322 
323 		objp = &zfsvfs->z_projectobjquota_obj;
324 		break;
325 	default:
326 		return (SET_ERROR(EINVAL));
327 	}
328 
329 	err = zfs_id_to_fuidstr(zfsvfs, domain, rid, buf, sizeof (buf), B_TRUE);
330 	if (err)
331 		return (err);
332 	fuid_dirtied = zfsvfs->z_fuid_dirty;
333 
334 	tx = dmu_tx_create(zfsvfs->z_os);
335 	dmu_tx_hold_zap(tx, *objp ? *objp : DMU_NEW_OBJECT, B_TRUE, NULL);
336 	if (*objp == 0) {
337 		dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE,
338 		    zfs_userquota_prop_prefixes[type]);
339 	}
340 	if (fuid_dirtied)
341 		zfs_fuid_txhold(zfsvfs, tx);
342 	err = dmu_tx_assign(tx, TXG_WAIT);
343 	if (err) {
344 		dmu_tx_abort(tx);
345 		return (err);
346 	}
347 
348 	mutex_enter(&zfsvfs->z_lock);
349 	if (*objp == 0) {
350 		*objp = zap_create(zfsvfs->z_os, DMU_OT_USERGROUP_QUOTA,
351 		    DMU_OT_NONE, 0, tx);
352 		VERIFY(0 == zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
353 		    zfs_userquota_prop_prefixes[type], 8, 1, objp, tx));
354 	}
355 	mutex_exit(&zfsvfs->z_lock);
356 
357 	if (quota == 0) {
358 		err = zap_remove(zfsvfs->z_os, *objp, buf, tx);
359 		if (err == ENOENT)
360 			err = 0;
361 	} else {
362 		err = zap_update(zfsvfs->z_os, *objp, buf, 8, 1, &quota, tx);
363 	}
364 	ASSERT(err == 0);
365 	if (fuid_dirtied)
366 		zfs_fuid_sync(zfsvfs, tx);
367 	dmu_tx_commit(tx);
368 	return (err);
369 }
370 
371 boolean_t
372 zfs_id_overobjquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id)
373 {
374 	char buf[20 + DMU_OBJACCT_PREFIX_LEN];
375 	uint64_t used, quota, quotaobj;
376 	int err;
377 
378 	if (!dmu_objset_userobjspace_present(zfsvfs->z_os)) {
379 		if (dmu_objset_userobjspace_upgradable(zfsvfs->z_os)) {
380 			dsl_pool_config_enter(
381 			    dmu_objset_pool(zfsvfs->z_os), FTAG);
382 			dmu_objset_id_quota_upgrade(zfsvfs->z_os);
383 			dsl_pool_config_exit(
384 			    dmu_objset_pool(zfsvfs->z_os), FTAG);
385 		}
386 		return (B_FALSE);
387 	}
388 
389 	if (usedobj == DMU_PROJECTUSED_OBJECT) {
390 		if (!dmu_objset_projectquota_present(zfsvfs->z_os)) {
391 			if (dmu_objset_projectquota_upgradable(zfsvfs->z_os)) {
392 				dsl_pool_config_enter(
393 				    dmu_objset_pool(zfsvfs->z_os), FTAG);
394 				dmu_objset_id_quota_upgrade(zfsvfs->z_os);
395 				dsl_pool_config_exit(
396 				    dmu_objset_pool(zfsvfs->z_os), FTAG);
397 			}
398 			return (B_FALSE);
399 		}
400 		quotaobj = zfsvfs->z_projectobjquota_obj;
401 	} else if (usedobj == DMU_USERUSED_OBJECT) {
402 		quotaobj = zfsvfs->z_userobjquota_obj;
403 	} else if (usedobj == DMU_GROUPUSED_OBJECT) {
404 		quotaobj = zfsvfs->z_groupobjquota_obj;
405 	} else {
406 		return (B_FALSE);
407 	}
408 	if (quotaobj == 0 || zfsvfs->z_replay)
409 		return (B_FALSE);
410 
411 	(void) snprintf(buf, sizeof (buf), "%llx", (longlong_t)id);
412 	err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, &quota);
413 	if (err != 0)
414 		return (B_FALSE);
415 
416 	(void) snprintf(buf, sizeof (buf), DMU_OBJACCT_PREFIX "%llx",
417 	    (longlong_t)id);
418 	err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used);
419 	if (err != 0)
420 		return (B_FALSE);
421 	return (used >= quota);
422 }
423 
424 boolean_t
425 zfs_id_overblockquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id)
426 {
427 	char buf[20];
428 	uint64_t used, quota, quotaobj;
429 	int err;
430 
431 	if (usedobj == DMU_PROJECTUSED_OBJECT) {
432 		if (!dmu_objset_projectquota_present(zfsvfs->z_os)) {
433 			if (dmu_objset_projectquota_upgradable(zfsvfs->z_os)) {
434 				dsl_pool_config_enter(
435 				    dmu_objset_pool(zfsvfs->z_os), FTAG);
436 				dmu_objset_id_quota_upgrade(zfsvfs->z_os);
437 				dsl_pool_config_exit(
438 				    dmu_objset_pool(zfsvfs->z_os), FTAG);
439 			}
440 			return (B_FALSE);
441 		}
442 		quotaobj = zfsvfs->z_projectquota_obj;
443 	} else if (usedobj == DMU_USERUSED_OBJECT) {
444 		quotaobj = zfsvfs->z_userquota_obj;
445 	} else if (usedobj == DMU_GROUPUSED_OBJECT) {
446 		quotaobj = zfsvfs->z_groupquota_obj;
447 	} else {
448 		return (B_FALSE);
449 	}
450 	if (quotaobj == 0 || zfsvfs->z_replay)
451 		return (B_FALSE);
452 
453 	(void) snprintf(buf, sizeof (buf), "%llx", (longlong_t)id);
454 	err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, &quota);
455 	if (err != 0)
456 		return (B_FALSE);
457 
458 	err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used);
459 	if (err != 0)
460 		return (B_FALSE);
461 	return (used >= quota);
462 }
463 
464 boolean_t
465 zfs_id_overquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id)
466 {
467 	return (zfs_id_overblockquota(zfsvfs, usedobj, id) ||
468 	    zfs_id_overobjquota(zfsvfs, usedobj, id));
469 }
470 
471 EXPORT_SYMBOL(zpl_get_file_info);
472 EXPORT_SYMBOL(zfs_userspace_one);
473 EXPORT_SYMBOL(zfs_userspace_many);
474 EXPORT_SYMBOL(zfs_set_userquota);
475 EXPORT_SYMBOL(zfs_id_overblockquota);
476 EXPORT_SYMBOL(zfs_id_overobjquota);
477 EXPORT_SYMBOL(zfs_id_overquota);
478