1*61145dc2SMartin 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 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 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 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 163eda14cbcSMatt Macy int 164eda14cbcSMatt Macy zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 165eda14cbcSMatt Macy uint64_t *cookiep, void *vbuf, uint64_t *bufsizep) 166eda14cbcSMatt Macy { 167eda14cbcSMatt Macy int error; 168eda14cbcSMatt Macy zap_cursor_t zc; 1697a7741afSMartin Matuska zap_attribute_t *za; 170eda14cbcSMatt Macy zfs_useracct_t *buf = vbuf; 171eda14cbcSMatt Macy uint64_t obj; 172eda14cbcSMatt Macy int offset = 0; 173eda14cbcSMatt Macy 174eda14cbcSMatt Macy if (!dmu_objset_userspace_present(zfsvfs->z_os)) 175eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 176eda14cbcSMatt Macy 177eda14cbcSMatt Macy if ((type == ZFS_PROP_PROJECTQUOTA || type == ZFS_PROP_PROJECTUSED || 178eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJQUOTA || 179eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJUSED) && 180eda14cbcSMatt Macy !dmu_objset_projectquota_present(zfsvfs->z_os)) 181eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 182eda14cbcSMatt Macy 183eda14cbcSMatt Macy if ((type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED || 184eda14cbcSMatt Macy type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA || 185eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJUSED || 186eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJQUOTA) && 187eda14cbcSMatt Macy !dmu_objset_userobjspace_present(zfsvfs->z_os)) 188eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 189eda14cbcSMatt Macy 190eda14cbcSMatt Macy obj = zfs_userquota_prop_to_obj(zfsvfs, type); 191eda14cbcSMatt Macy if (obj == ZFS_NO_OBJECT) { 192eda14cbcSMatt Macy *bufsizep = 0; 193eda14cbcSMatt Macy return (0); 194eda14cbcSMatt Macy } 195eda14cbcSMatt Macy 196eda14cbcSMatt Macy if (type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED || 197eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJUSED) 198eda14cbcSMatt Macy offset = DMU_OBJACCT_PREFIX_LEN; 199eda14cbcSMatt Macy 2007a7741afSMartin Matuska za = zap_attribute_alloc(); 201eda14cbcSMatt Macy for (zap_cursor_init_serialized(&zc, zfsvfs->z_os, obj, *cookiep); 2027a7741afSMartin Matuska (error = zap_cursor_retrieve(&zc, za)) == 0; 203eda14cbcSMatt Macy zap_cursor_advance(&zc)) { 204eda14cbcSMatt Macy if ((uintptr_t)buf - (uintptr_t)vbuf + sizeof (zfs_useracct_t) > 205eda14cbcSMatt Macy *bufsizep) 206eda14cbcSMatt Macy break; 207eda14cbcSMatt Macy 208eda14cbcSMatt Macy /* 209eda14cbcSMatt Macy * skip object quota (with zap name prefix DMU_OBJACCT_PREFIX) 210eda14cbcSMatt Macy * when dealing with block quota and vice versa. 211eda14cbcSMatt Macy */ 2127a7741afSMartin Matuska if ((offset > 0) != (strncmp(za->za_name, DMU_OBJACCT_PREFIX, 213eda14cbcSMatt Macy DMU_OBJACCT_PREFIX_LEN) == 0)) 214eda14cbcSMatt Macy continue; 215eda14cbcSMatt Macy 2167a7741afSMartin Matuska fuidstr_to_sid(zfsvfs, za->za_name + offset, 217eda14cbcSMatt Macy buf->zu_domain, sizeof (buf->zu_domain), &buf->zu_rid); 218eda14cbcSMatt Macy 2197a7741afSMartin Matuska buf->zu_space = za->za_first_integer; 220eda14cbcSMatt Macy buf++; 221eda14cbcSMatt Macy } 222eda14cbcSMatt Macy if (error == ENOENT) 223eda14cbcSMatt Macy error = 0; 224eda14cbcSMatt Macy 225eda14cbcSMatt Macy ASSERT3U((uintptr_t)buf - (uintptr_t)vbuf, <=, *bufsizep); 226eda14cbcSMatt Macy *bufsizep = (uintptr_t)buf - (uintptr_t)vbuf; 227eda14cbcSMatt Macy *cookiep = zap_cursor_serialize(&zc); 228eda14cbcSMatt Macy zap_cursor_fini(&zc); 2297a7741afSMartin Matuska zap_attribute_free(za); 230eda14cbcSMatt Macy return (error); 231eda14cbcSMatt Macy } 232eda14cbcSMatt Macy 233eda14cbcSMatt Macy int 234eda14cbcSMatt Macy zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 235eda14cbcSMatt Macy const char *domain, uint64_t rid, uint64_t *valp) 236eda14cbcSMatt Macy { 237eda14cbcSMatt Macy char buf[20 + DMU_OBJACCT_PREFIX_LEN]; 238eda14cbcSMatt Macy int offset = 0; 239eda14cbcSMatt Macy int err; 240eda14cbcSMatt Macy uint64_t obj; 241eda14cbcSMatt Macy 242eda14cbcSMatt Macy *valp = 0; 243eda14cbcSMatt Macy 244eda14cbcSMatt Macy if (!dmu_objset_userspace_present(zfsvfs->z_os)) 245eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 246eda14cbcSMatt Macy 247eda14cbcSMatt Macy if ((type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED || 248eda14cbcSMatt Macy type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA || 249eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJUSED || 250eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJQUOTA) && 251eda14cbcSMatt Macy !dmu_objset_userobjspace_present(zfsvfs->z_os)) 252eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 253eda14cbcSMatt Macy 254eda14cbcSMatt Macy if (type == ZFS_PROP_PROJECTQUOTA || type == ZFS_PROP_PROJECTUSED || 255eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJQUOTA || 256eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJUSED) { 257eda14cbcSMatt Macy if (!dmu_objset_projectquota_present(zfsvfs->z_os)) 258eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 259eda14cbcSMatt Macy if (!zpl_is_valid_projid(rid)) 260eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 261eda14cbcSMatt Macy } 262eda14cbcSMatt Macy 263eda14cbcSMatt Macy obj = zfs_userquota_prop_to_obj(zfsvfs, type); 264eda14cbcSMatt Macy if (obj == ZFS_NO_OBJECT) 265eda14cbcSMatt Macy return (0); 266eda14cbcSMatt Macy 267eda14cbcSMatt Macy if (type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED || 268eda14cbcSMatt Macy type == ZFS_PROP_PROJECTOBJUSED) { 269eda14cbcSMatt Macy strlcpy(buf, DMU_OBJACCT_PREFIX, DMU_OBJACCT_PREFIX_LEN + 1); 270eda14cbcSMatt Macy offset = DMU_OBJACCT_PREFIX_LEN; 271eda14cbcSMatt Macy } 272eda14cbcSMatt Macy 273eda14cbcSMatt Macy err = zfs_id_to_fuidstr(zfsvfs, domain, rid, buf + offset, 274eda14cbcSMatt Macy sizeof (buf) - offset, B_FALSE); 275eda14cbcSMatt Macy if (err) 276eda14cbcSMatt Macy return (err); 277eda14cbcSMatt Macy 278eda14cbcSMatt Macy err = zap_lookup(zfsvfs->z_os, obj, buf, 8, 1, valp); 279eda14cbcSMatt Macy if (err == ENOENT) 280eda14cbcSMatt Macy err = 0; 281eda14cbcSMatt Macy return (err); 282eda14cbcSMatt Macy } 283eda14cbcSMatt Macy 284eda14cbcSMatt Macy int 285eda14cbcSMatt Macy zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, 286eda14cbcSMatt Macy const char *domain, uint64_t rid, uint64_t quota) 287eda14cbcSMatt Macy { 288eda14cbcSMatt Macy char buf[32]; 289eda14cbcSMatt Macy int err; 290eda14cbcSMatt Macy dmu_tx_t *tx; 291eda14cbcSMatt Macy uint64_t *objp; 292eda14cbcSMatt Macy boolean_t fuid_dirtied; 293eda14cbcSMatt Macy 294eda14cbcSMatt Macy if (zfsvfs->z_version < ZPL_VERSION_USERSPACE) 295eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 296eda14cbcSMatt Macy 297eda14cbcSMatt Macy switch (type) { 298eda14cbcSMatt Macy case ZFS_PROP_USERQUOTA: 299eda14cbcSMatt Macy objp = &zfsvfs->z_userquota_obj; 300eda14cbcSMatt Macy break; 301eda14cbcSMatt Macy case ZFS_PROP_GROUPQUOTA: 302eda14cbcSMatt Macy objp = &zfsvfs->z_groupquota_obj; 303eda14cbcSMatt Macy break; 304eda14cbcSMatt Macy case ZFS_PROP_USEROBJQUOTA: 305eda14cbcSMatt Macy objp = &zfsvfs->z_userobjquota_obj; 306eda14cbcSMatt Macy break; 307eda14cbcSMatt Macy case ZFS_PROP_GROUPOBJQUOTA: 308eda14cbcSMatt Macy objp = &zfsvfs->z_groupobjquota_obj; 309eda14cbcSMatt Macy break; 310eda14cbcSMatt Macy case ZFS_PROP_PROJECTQUOTA: 311eda14cbcSMatt Macy if (!dmu_objset_projectquota_enabled(zfsvfs->z_os)) 312eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 313eda14cbcSMatt Macy if (!zpl_is_valid_projid(rid)) 314eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 315eda14cbcSMatt Macy 316eda14cbcSMatt Macy objp = &zfsvfs->z_projectquota_obj; 317eda14cbcSMatt Macy break; 318eda14cbcSMatt Macy case ZFS_PROP_PROJECTOBJQUOTA: 319eda14cbcSMatt Macy if (!dmu_objset_projectquota_enabled(zfsvfs->z_os)) 320eda14cbcSMatt Macy return (SET_ERROR(ENOTSUP)); 321eda14cbcSMatt Macy if (!zpl_is_valid_projid(rid)) 322eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 323eda14cbcSMatt Macy 324eda14cbcSMatt Macy objp = &zfsvfs->z_projectobjquota_obj; 325eda14cbcSMatt Macy break; 326eda14cbcSMatt Macy default: 327eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 328eda14cbcSMatt Macy } 329eda14cbcSMatt Macy 330eda14cbcSMatt Macy err = zfs_id_to_fuidstr(zfsvfs, domain, rid, buf, sizeof (buf), B_TRUE); 331eda14cbcSMatt Macy if (err) 332eda14cbcSMatt Macy return (err); 333eda14cbcSMatt Macy fuid_dirtied = zfsvfs->z_fuid_dirty; 334eda14cbcSMatt Macy 335eda14cbcSMatt Macy tx = dmu_tx_create(zfsvfs->z_os); 336eda14cbcSMatt Macy dmu_tx_hold_zap(tx, *objp ? *objp : DMU_NEW_OBJECT, B_TRUE, NULL); 337eda14cbcSMatt Macy if (*objp == 0) { 338eda14cbcSMatt Macy dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE, 339eda14cbcSMatt Macy zfs_userquota_prop_prefixes[type]); 340eda14cbcSMatt Macy } 341eda14cbcSMatt Macy if (fuid_dirtied) 342eda14cbcSMatt Macy zfs_fuid_txhold(zfsvfs, tx); 343*61145dc2SMartin Matuska err = dmu_tx_assign(tx, DMU_TX_WAIT); 344eda14cbcSMatt Macy if (err) { 345eda14cbcSMatt Macy dmu_tx_abort(tx); 346eda14cbcSMatt Macy return (err); 347eda14cbcSMatt Macy } 348eda14cbcSMatt Macy 349eda14cbcSMatt Macy mutex_enter(&zfsvfs->z_lock); 350eda14cbcSMatt Macy if (*objp == 0) { 351eda14cbcSMatt Macy *objp = zap_create(zfsvfs->z_os, DMU_OT_USERGROUP_QUOTA, 352eda14cbcSMatt Macy DMU_OT_NONE, 0, tx); 3536c1e79dfSMartin Matuska VERIFY(0 == zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, 354eda14cbcSMatt Macy zfs_userquota_prop_prefixes[type], 8, 1, objp, tx)); 355eda14cbcSMatt Macy } 3566c1e79dfSMartin Matuska mutex_exit(&zfsvfs->z_lock); 357eda14cbcSMatt Macy 358eda14cbcSMatt Macy if (quota == 0) { 359eda14cbcSMatt Macy err = zap_remove(zfsvfs->z_os, *objp, buf, tx); 360eda14cbcSMatt Macy if (err == ENOENT) 361eda14cbcSMatt Macy err = 0; 362eda14cbcSMatt Macy } else { 363eda14cbcSMatt Macy err = zap_update(zfsvfs->z_os, *objp, buf, 8, 1, "a, tx); 364eda14cbcSMatt Macy } 365eda14cbcSMatt Macy ASSERT(err == 0); 366eda14cbcSMatt Macy if (fuid_dirtied) 367eda14cbcSMatt Macy zfs_fuid_sync(zfsvfs, tx); 368eda14cbcSMatt Macy dmu_tx_commit(tx); 369eda14cbcSMatt Macy return (err); 370eda14cbcSMatt Macy } 371eda14cbcSMatt Macy 372eda14cbcSMatt Macy boolean_t 373eda14cbcSMatt Macy zfs_id_overobjquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) 374eda14cbcSMatt Macy { 375eda14cbcSMatt Macy char buf[20 + DMU_OBJACCT_PREFIX_LEN]; 376eda14cbcSMatt Macy uint64_t used, quota, quotaobj; 377eda14cbcSMatt Macy int err; 378eda14cbcSMatt Macy 379eda14cbcSMatt Macy if (!dmu_objset_userobjspace_present(zfsvfs->z_os)) { 380eda14cbcSMatt Macy if (dmu_objset_userobjspace_upgradable(zfsvfs->z_os)) { 381eda14cbcSMatt Macy dsl_pool_config_enter( 382eda14cbcSMatt Macy dmu_objset_pool(zfsvfs->z_os), FTAG); 383eda14cbcSMatt Macy dmu_objset_id_quota_upgrade(zfsvfs->z_os); 384eda14cbcSMatt Macy dsl_pool_config_exit( 385eda14cbcSMatt Macy dmu_objset_pool(zfsvfs->z_os), FTAG); 386eda14cbcSMatt Macy } 387eda14cbcSMatt Macy return (B_FALSE); 388eda14cbcSMatt Macy } 389eda14cbcSMatt Macy 390eda14cbcSMatt Macy if (usedobj == DMU_PROJECTUSED_OBJECT) { 391eda14cbcSMatt Macy if (!dmu_objset_projectquota_present(zfsvfs->z_os)) { 392eda14cbcSMatt Macy if (dmu_objset_projectquota_upgradable(zfsvfs->z_os)) { 393eda14cbcSMatt Macy dsl_pool_config_enter( 394eda14cbcSMatt Macy dmu_objset_pool(zfsvfs->z_os), FTAG); 395eda14cbcSMatt Macy dmu_objset_id_quota_upgrade(zfsvfs->z_os); 396eda14cbcSMatt Macy dsl_pool_config_exit( 397eda14cbcSMatt Macy dmu_objset_pool(zfsvfs->z_os), FTAG); 398eda14cbcSMatt Macy } 399eda14cbcSMatt Macy return (B_FALSE); 400eda14cbcSMatt Macy } 401eda14cbcSMatt Macy quotaobj = zfsvfs->z_projectobjquota_obj; 402eda14cbcSMatt Macy } else if (usedobj == DMU_USERUSED_OBJECT) { 403eda14cbcSMatt Macy quotaobj = zfsvfs->z_userobjquota_obj; 404eda14cbcSMatt Macy } else if (usedobj == DMU_GROUPUSED_OBJECT) { 405eda14cbcSMatt Macy quotaobj = zfsvfs->z_groupobjquota_obj; 406eda14cbcSMatt Macy } else { 407eda14cbcSMatt Macy return (B_FALSE); 408eda14cbcSMatt Macy } 409eda14cbcSMatt Macy if (quotaobj == 0 || zfsvfs->z_replay) 410eda14cbcSMatt Macy return (B_FALSE); 411eda14cbcSMatt Macy 412eda14cbcSMatt Macy (void) snprintf(buf, sizeof (buf), "%llx", (longlong_t)id); 413eda14cbcSMatt Macy err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); 414eda14cbcSMatt Macy if (err != 0) 415eda14cbcSMatt Macy return (B_FALSE); 416eda14cbcSMatt Macy 417eda14cbcSMatt Macy (void) snprintf(buf, sizeof (buf), DMU_OBJACCT_PREFIX "%llx", 418eda14cbcSMatt Macy (longlong_t)id); 419eda14cbcSMatt Macy err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used); 420eda14cbcSMatt Macy if (err != 0) 421eda14cbcSMatt Macy return (B_FALSE); 422eda14cbcSMatt Macy return (used >= quota); 423eda14cbcSMatt Macy } 424eda14cbcSMatt Macy 425eda14cbcSMatt Macy boolean_t 426eda14cbcSMatt Macy zfs_id_overblockquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) 427eda14cbcSMatt Macy { 428eda14cbcSMatt Macy char buf[20]; 429eda14cbcSMatt Macy uint64_t used, quota, quotaobj; 430eda14cbcSMatt Macy int err; 431eda14cbcSMatt Macy 432eda14cbcSMatt Macy if (usedobj == DMU_PROJECTUSED_OBJECT) { 433eda14cbcSMatt Macy if (!dmu_objset_projectquota_present(zfsvfs->z_os)) { 434eda14cbcSMatt Macy if (dmu_objset_projectquota_upgradable(zfsvfs->z_os)) { 435eda14cbcSMatt Macy dsl_pool_config_enter( 436eda14cbcSMatt Macy dmu_objset_pool(zfsvfs->z_os), FTAG); 437eda14cbcSMatt Macy dmu_objset_id_quota_upgrade(zfsvfs->z_os); 438eda14cbcSMatt Macy dsl_pool_config_exit( 439eda14cbcSMatt Macy dmu_objset_pool(zfsvfs->z_os), FTAG); 440eda14cbcSMatt Macy } 441eda14cbcSMatt Macy return (B_FALSE); 442eda14cbcSMatt Macy } 443eda14cbcSMatt Macy quotaobj = zfsvfs->z_projectquota_obj; 444eda14cbcSMatt Macy } else if (usedobj == DMU_USERUSED_OBJECT) { 445eda14cbcSMatt Macy quotaobj = zfsvfs->z_userquota_obj; 446eda14cbcSMatt Macy } else if (usedobj == DMU_GROUPUSED_OBJECT) { 447eda14cbcSMatt Macy quotaobj = zfsvfs->z_groupquota_obj; 448eda14cbcSMatt Macy } else { 449eda14cbcSMatt Macy return (B_FALSE); 450eda14cbcSMatt Macy } 451eda14cbcSMatt Macy if (quotaobj == 0 || zfsvfs->z_replay) 452eda14cbcSMatt Macy return (B_FALSE); 453eda14cbcSMatt Macy 454eda14cbcSMatt Macy (void) snprintf(buf, sizeof (buf), "%llx", (longlong_t)id); 455eda14cbcSMatt Macy err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); 456eda14cbcSMatt Macy if (err != 0) 457eda14cbcSMatt Macy return (B_FALSE); 458eda14cbcSMatt Macy 459eda14cbcSMatt Macy err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used); 460eda14cbcSMatt Macy if (err != 0) 461eda14cbcSMatt Macy return (B_FALSE); 462eda14cbcSMatt Macy return (used >= quota); 463eda14cbcSMatt Macy } 464eda14cbcSMatt Macy 465eda14cbcSMatt Macy boolean_t 466eda14cbcSMatt Macy zfs_id_overquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) 467eda14cbcSMatt Macy { 468eda14cbcSMatt Macy return (zfs_id_overblockquota(zfsvfs, usedobj, id) || 469eda14cbcSMatt Macy zfs_id_overobjquota(zfsvfs, usedobj, id)); 470eda14cbcSMatt Macy } 471eda14cbcSMatt Macy 472eda14cbcSMatt Macy EXPORT_SYMBOL(zpl_get_file_info); 473eda14cbcSMatt Macy EXPORT_SYMBOL(zfs_userspace_one); 474eda14cbcSMatt Macy EXPORT_SYMBOL(zfs_userspace_many); 475eda14cbcSMatt Macy EXPORT_SYMBOL(zfs_set_userquota); 476eda14cbcSMatt Macy EXPORT_SYMBOL(zfs_id_overblockquota); 477eda14cbcSMatt Macy EXPORT_SYMBOL(zfs_id_overobjquota); 478eda14cbcSMatt Macy EXPORT_SYMBOL(zfs_id_overquota); 479