This bug is years old. Just now sending it in. We created the following patch to mainly fix ZFS quotas in the case the quota is set to NONE (which is the default). What started the issue is 0 quota normally means unlimited. In the case of ZFS the quota is set to NONE. The following patch fixes this problem: *** ./smbd/quotas.c.orig Thu Oct 7 12:41:16 2010 --- ./smbd/quotas.c Tue Nov 30 17:29:16 2010 *************** *** 392,397 **** --- 392,398 ---- #include <sys/param.h> #if defined(SUNOS5) #include <sys/fs/ufs_quota.h> + #include <libzfs.h> #include <sys/mnttab.h> #include <sys/mntent.h> #else /* defined(SUNOS4) */ *************** *** 432,457 **** } gqr->status = quotastat; ! if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) { ! DEBUG(6,("nfs_quotas: Block size bad or zero\n")); ! return 0; } - if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) { - DEBUG(6,("nfs_quotas: Active bad or zero\n")); - return 0; - } - if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) { - DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n")); - return 0; - } - if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) { - DEBUG(6,("nfs_quotas: Softlimit bad or zero\n")); - return 0; - } - if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) { - DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n")); - return 0; - } return (1); } --- 433,461 ---- } gqr->status = quotastat; ! if (quotastat == Q_OK) { ! if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) { ! DEBUG(6,("nfs_quotas: Block size bad or zero\n")); ! return 0; ! } ! if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) { ! DEBUG(6,("nfs_quotas: Active bad or zero\n")); ! return 0; ! } ! if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) { ! DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n")); ! return 0; ! } ! if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) { ! DEBUG(6,("nfs_quotas: Softlimit bad or zero\n")); ! return 0; ! } ! if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) { ! DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n")); ! return 0; ! } ! } return (1); } *************** *** 511,518 **** */ switch (gqr.status) { ! case 0: ! DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr.status)); ret = False; goto out; --- 515,522 ---- */ switch (gqr.status) { ! default: ! DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr.status )); ret = False; goto out; *************** *** 521,538 **** D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; break; - - case 2: - case 3: - D.dqb_bsoftlimit = 1; - D.dqb_curblocks = 1; - DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr.status)); - break; - - default: - DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr.status )); - break; } DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n", --- 525,536 ---- D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; + if (D.dqb_bsoftlimit == 0) { + DEBUG(9,("nfs_quotas: soft quota is zero - change to no quota \n", gqr.status )); + ret = False; + goto out; + } break; } DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n", *************** *** 569,574 **** --- 567,639 ---- DEBUG(10,("nfs_quotas: End of nfs_quotas\n" )); return ret; } + + /* Get ZFS quota for user */ + static bool zfs_quotas(char *zfspath, uid_t euser_id, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize) + { + libzfs_handle_t * zfs; + zfs_handle_t * zhp; + uint64_t userquota; + uint64_t userused; + char property[ /* "userquota@" + 12 + 1 */ 24 ]; + + *bsize = *dfree = *dsize = (uint64_t)0; + + zfs = libzfs_init(); + if (zfs == NULL) { + DEBUG(10,("zfs_quotas: Cannot initialize libzfs\n")); + return False; + } + + zhp = zfs_open(zfs, zfspath, ZFS_TYPE_DATASET); + if (zhp == NULL) { + DEBUG(10,("zfs_quotas: Cannot open zfs \"%s\" handle\n", zfspath)); + libzfs_fini(zfs); + return False; + } + + /* Format request */ + snprintf(property, sizeof(property), "userquota@%u", euser_id); + + /* Get quota */ + if (zfs_prop_get_userquota_int(zhp, property, &userquota)) { + DEBUG(10,("zfs_quotas: Cannot open zfs property \"%s\"\n", property)); + zfs_close(zhp); + libzfs_fini(zfs); + return False; + } + + /* Format request */ + snprintf(property, sizeof(property), "userused@%u", euser_id); + + /* Get used */ + if (zfs_prop_get_userquota_int(zhp, property, &userused)) { + DEBUG(10,("zfs_quotas: Cannot open zfs property \"%s\"\n", property)); + zfs_close(zhp); + libzfs_fini(zfs); + return False; + } + + /* Close handles */ + zfs_close(zhp); + libzfs_fini(zfs); + + /* No quota? */ + if (userquota == 0) + return False; + + /* Update results */ + *bsize = DEV_BSIZE; + *dsize = userquota / DEV_BSIZE; + if (userused > userquota) { + *dfree = 0; + *dsize = userused / DEV_BSIZE; + } else + *dfree = (userquota - userused) / DEV_BSIZE; + DEBUG(5,("zfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",zfspath,(double)*bsize,(double)*dfree,(double)*dsize)); + DEBUG(10,("zfs_quotas: End of zfs_quotas\n")); + return True; + } #endif /**************************************************************************** *************** *** 619,627 **** DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt.mnt_mountp, (unsigned int)devno)); ! /* quotas are only on vxfs, UFS or NFS */ if ((sbuf.st_ex_dev == devno) && ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || strcmp( mnt.mnt_fstype, "nfs" ) == 0 || strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) { found = true; --- 684,693 ---- DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt.mnt_mountp, (unsigned int)devno)); ! /* quotas are only on vxfs, UFS, ZFS or NFS */ if ((sbuf.st_ex_dev == devno) && ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || + strcmp( mnt.mnt_fstype, MNTTYPE_ZFS ) == 0 || strcmp( mnt.mnt_fstype, "nfs" ) == 0 || strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) { found = true; *************** *** 672,677 **** --- 738,753 ---- retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize); unbecome_root(); + return retval; + } + + if (strcmp(mnt.mnt_fstype, MNTTYPE_ZFS) == 0) { + bool retval; + DEBUG(5,("disk_quotas: looking for mountpath (ZFS) \"%s\"\n", + mnt.mnt_special)); + retval = zfs_quotas(mnt.mnt_special, + euser_id, bsize, dfree, dsize); + unbecome_root(); return retval; }
Would it be possible that you re-do the patch as "diff -u" and upload it as an attachment? This makes it easier to apply, the Linux patch program seems to have problems applying this patch cleanly. Thanks, Volker
(In reply to comment #1) Will do ... --mike
Created attachment 11755 [details] zfs_dfree vfs module for 3.6 on Solaris Hi! A few years ago I've produced a vfs module based on the work of Mike Moya (in the bug description). As far as I remember the attached module works fine on Solaris with Samba 3.6. Best regards Björn