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