quota: track nwquota usage like NetWare
All checks were successful
Source release / source-package (push) Successful in 1m7s
All checks were successful
Source release / source-package (push) Successful in 1m7s
This commit is contained in:
@@ -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);
|
||||
|
||||
15
src/nwfile.c
15
src/nwfile.c
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user