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