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