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