quota: track nwquota usage like NetWare
All checks were successful
Source release / source-package (push) Successful in 1m7s

This commit is contained in:
OpenAI
2026-06-11 10:10:54 +00:00
committed by Mario Fetka
parent 9a3890c7b1
commit 3455b3e7b2
3 changed files with 107 additions and 4 deletions

View File

@@ -130,6 +130,8 @@ extern int nw_set_vol_restrictions(uint8 volnr, int uid, uint32 quota);
extern int nw_get_vol_restrictions(uint8 volnr, int uid, uint32 *quota, uint32 *inuse);
extern int nw_check_vol_user_space(uint8 volnr, int uid, const char *unixname,
off_t old_size, off_t new_size);
extern int nw_adjust_vol_user_space(uint8 volnr, int uid,
off_t old_size, off_t new_size);
extern uint32 nw_vol_inode_to_handle(int volume, ino_t inode,
DEV_NAMESPACE_MAP *dnm);

View File

@@ -1018,9 +1018,15 @@ int nw_write_file(int fhandle, uint8 *data, int size, uint32 offset)
if (qresult < 0) {
size = qresult;
} else {
int requested = size;
size = write(fh->fd, data, size);
if (size > -1)
if (size > -1) {
off_t written_end = (off_t)offset + (off_t)size;
if (requested > 0 && written_end > old_size)
(void)nw_adjust_vol_user_space((uint8)fh->volume, act_uid,
old_size, written_end);
fh->fh_flags &= ~FH_CREATED_NEW;
}
fh->offd+=(long)size;
if (!fh->modified)
fh->modified++;
@@ -1035,8 +1041,13 @@ int nw_write_file(int fhandle, uint8 *data, int size, uint32 offset)
result = nw_check_vol_user_space((uint8)fh->volume, act_uid,
fh->fname, qst.st_size,
(off_t)offset);
if (!result)
if (!result) {
off_t old_size = qst.st_size;
result = unx_ftruncate(fh->fd, offset);
if (!result)
(void)nw_adjust_vol_user_space((uint8)fh->volume, act_uid,
old_size, (off_t)offset);
}
XDPRINTF((5,0,"File %s is truncated, result=%d", fh->fname, result));
fh->offd = -1L;
if (!result && !fh->modified)

View File

@@ -1097,11 +1097,14 @@ static uint32 nw_volume_uid_usage_4k(uint8 volnr, int uid)
static int nw_set_vol_restrictions_metadata(uint8 volnr, int uid, uint32 quota)
{
zNW_user_quota_s userquota;
uint32 inuse;
int i;
if (read_userquota_from_volume(volnr, &userquota))
nwfs_userquota_init(&userquota);
inuse = nw_volume_uid_usage_4k(volnr, uid);
for (i = 0; i < userquota.nwuq_num_users; i++) {
if (nwfs_guid_to_mars_uid(&userquota.nwuq_user[i].nwur_user) == uid) {
if (quota == 0) {
@@ -1112,6 +1115,7 @@ static int nw_set_vol_restrictions_metadata(uint8 volnr, int uid, uint32 quota)
userquota.nwuq_num_users--;
} else {
userquota.nwuq_user[i].nwur_restriction = (SQUAD)quota;
userquota.nwuq_user[i].nwur_reserved_2 = (QUAD)inuse;
}
return(write_userquota_to_volume(volnr, &userquota) ? -0xfb : 0);
}
@@ -1124,11 +1128,32 @@ static int nw_set_vol_restrictions_metadata(uint8 volnr, int uid, uint32 quota)
mars_uid_to_nwfs_guid(uid, &userquota.nwuq_user[userquota.nwuq_num_users].nwur_user);
userquota.nwuq_user[userquota.nwuq_num_users].nwur_restriction = (SQUAD)quota;
userquota.nwuq_user[userquota.nwuq_num_users].nwur_reserved_2 = 0;
userquota.nwuq_user[userquota.nwuq_num_users].nwur_reserved_2 = (QUAD)inuse;
userquota.nwuq_num_users++;
return(write_userquota_to_volume(volnr, &userquota) ? -0xfb : 0);
}
static uint32 nw_userquota_used_4k(zNW_user_restriction_s *entry, uint32 scanned)
{
uint32 stored;
if (!entry)
return(scanned);
if (entry->nwur_reserved_2 > (QUAD)0xffffffffU)
stored = 0xffffffffU;
else
stored = (uint32)entry->nwur_reserved_2;
/*
* NetWare/NSS does not derive live usage from POSIX uid ownership. It
* stores per-owner usage in the volume user-space-restriction tree and
* adjusts it on writes/deletes/owner changes. Keep the metadata backend in
* that model: use the stored amount for online accounting, but never let it
* go below a full scan of existing host-owned data.
*/
return(stored > scanned ? stored : scanned);
}
static int nw_get_vol_restrictions_metadata(uint8 volnr, int uid, uint32 *quota, uint32 *inuse)
{
zNW_user_quota_s userquota;
@@ -1141,17 +1166,51 @@ static int nw_get_vol_restrictions_metadata(uint8 volnr, int uid, uint32 *quota,
for (i = 0; i < userquota.nwuq_num_users; i++) {
if (nwfs_guid_to_mars_uid(&userquota.nwuq_user[i].nwur_user) == uid) {
uint32 scanned = nw_volume_uid_usage_4k(volnr, uid);
if (userquota.nwuq_user[i].nwur_restriction <= 0)
*quota = 0x40000000;
else
*quota = (uint32)userquota.nwuq_user[i].nwur_restriction;
*inuse = nw_volume_uid_usage_4k(volnr, uid);
*inuse = nw_userquota_used_4k(&userquota.nwuq_user[i], scanned);
return(0);
}
}
return(0);
}
static int nw_adjust_vol_user_space_metadata(uint8 volnr, int uid, int delta4k)
{
zNW_user_quota_s userquota;
int i;
if (delta4k == 0)
return(0);
if (read_userquota_from_volume(volnr, &userquota))
return(0);
for (i = 0; i < userquota.nwuq_num_users; i++) {
if (nwfs_guid_to_mars_uid(&userquota.nwuq_user[i].nwur_user) == uid) {
uint32 scanned = nw_volume_uid_usage_4k(volnr, uid);
uint32 used = nw_userquota_used_4k(&userquota.nwuq_user[i], scanned);
if (delta4k < 0) {
uint32 dec = (uint32)(-delta4k);
used = (used > dec) ? (used - dec) : 0;
} else if (used <= 0xffffffffU - (uint32)delta4k) {
used += (uint32)delta4k;
} else {
used = 0xffffffffU;
}
userquota.nwuq_user[i].nwur_reserved_2 = (QUAD)used;
XDPRINTF((2,0,
"VOL_AdjustUsedUserSpace vol=%d uid=%d delta4k=%d used4k=%u",
volnr, uid, delta4k, used));
return(write_userquota_to_volume(volnr, &userquota) ? -0xfb : 0);
}
}
return(0);
}
/* NOTE: The error numbers in here are probably wrong */
int nw_set_vol_restrictions(uint8 volnr, int uid, uint32 quota)
{
@@ -1353,6 +1412,32 @@ int nw_check_vol_user_space(uint8 volnr, int uid, const char *unixname,
return(0);
}
int nw_adjust_vol_user_space(uint8 volnr, int uid, off_t old_size, off_t new_size)
{
uint32 old_blocks;
uint32 new_blocks;
int backend = nwfs_quota_backend_current();
if (new_size == old_size)
return(0);
if (backend != NWFS_QUOTA_BACKEND_ID_METADATAONLY &&
backend != NWFS_QUOTA_BACKEND_ID_NWQUOTA) {
const char *device;
if (volnr >= used_nw_volumes || nw_volumes == (NW_VOL *) NULL)
return(0);
device = find_device_file(nw_volumes[volnr].unixname);
if (device != (char *) NULL)
return(0);
}
old_blocks = quota_blocks_for_size(old_size);
new_blocks = quota_blocks_for_size(new_size);
return(nw_adjust_vol_user_space_metadata(volnr, uid,
(int)new_blocks - (int)old_blocks));
}
#else
int nw_set_vol_restrictions(uint8 volnr, int uid, uint32 quota)
{
@@ -1371,4 +1456,9 @@ int nw_check_vol_user_space(uint8 volnr, int uid, const char *unixname,
{
return(0);
}
int nw_adjust_vol_user_space(uint8 volnr, int uid, off_t old_size, off_t new_size)
{
return(0);
}
#endif