server: recycle stale temporary directory handles
All checks were successful
Source release / source-package (push) Successful in 47s
All checks were successful
Source release / source-package (push) Successful in 47s
Novell NCOPY can allocate temporary directory handles while checking
effective directory rights before copying. On long-running test runs the
temporary directory handle table may already contain stale entries, causing
Allocate Temporary Directory Handle to fail with -0x9d / "no directory
handles". NCOPY then falls back to relative GetEffectiveRights requests that
fail and reports:
NWGetEffectiveDirectoryRights returned an error.
Restore recycling of stale temporary directory handles in xinsert_new_dir().
Free slots are still preferred. If none are available and the caller requests
a temporary handle, recycle the oldest temporary handle for the same task first,
then the oldest temporary handle globally. Permanent directory handles are not
recycled.
This matches the expected NetWare-style behaviour for temporary handles and
allows NCOPY-style allocate-temp-handle / get-effective-rights flows to keep
working after repeated tests.
This commit is contained in:
@@ -2485,26 +2485,55 @@ int xinsert_new_dir(int volume, uint8 *path, int dev, int inode, int drive, int
|
||||
{
|
||||
int j = 0;
|
||||
int freehandle = 0;
|
||||
#if 0
|
||||
time_t lowtime = time(NULL);
|
||||
int timedhandle = 0;
|
||||
#endif
|
||||
/* first look, whether drive is allready in use */
|
||||
int timedhandle_same_task = 0;
|
||||
int timedhandle_any_task = 0;
|
||||
time_t lowtime_same_task = time(NULL);
|
||||
time_t lowtime_any_task = time(NULL);
|
||||
|
||||
/*
|
||||
* Temporary directory handles are supposed to be freed automatically at
|
||||
* End Of Job. Some DOS requesters/tools, notably Novell NCOPY through
|
||||
* Client32, can allocate temp handles without sending EOJ often enough for
|
||||
* MARS-NWE's small dir-handle table. The old code only reused empty slots
|
||||
* and returned 0x9d (no directory handles) once the table had filled with
|
||||
* stale temp handles. That makes NCOPY fail before the actual copy with
|
||||
* "NWGetEffectiveDirectoryRights returned an error."
|
||||
*
|
||||
* Prefer a genuinely free slot. If the table is full and this is another
|
||||
* temp-handle allocation, recycle the oldest temp handle from the same task;
|
||||
* only if none exists, recycle the oldest temp handle from any task.
|
||||
* Permanent handles are never recycled here.
|
||||
*/
|
||||
for (j = (used_dirs) ? 1 : 0; j < (int)used_dirs; j++) {
|
||||
NW_DIR *d = &(dirs[j]);
|
||||
if (!d->inode)
|
||||
if (!d->inode) {
|
||||
freehandle = j+1;
|
||||
#if 0
|
||||
} else if (d->is_temp && d->timestamp < lowtime) {
|
||||
timedhandle = j+1;
|
||||
lowtime = d->timestamp;
|
||||
} else if (is_temp && d->is_temp) {
|
||||
if (d->task == (uint8)task && d->timestamp <= lowtime_same_task) {
|
||||
timedhandle_same_task = j+1;
|
||||
lowtime_same_task = d->timestamp;
|
||||
}
|
||||
if (d->timestamp <= lowtime_any_task) {
|
||||
timedhandle_any_task = j+1;
|
||||
lowtime_any_task = d->timestamp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!freehandle && used_dirs < MAX_NW_DIRS) freehandle = ++used_dirs;
|
||||
#if 0
|
||||
if (!freehandle) freehandle = timedhandle;
|
||||
#endif
|
||||
if (!freehandle && is_temp) {
|
||||
freehandle = timedhandle_same_task ? timedhandle_same_task : timedhandle_any_task;
|
||||
if (freehandle) {
|
||||
NW_DIR *d = &(dirs[freehandle-1]);
|
||||
XDPRINTF((3,0,"Recycle stale temp dhandle:%d old='%d:%s' oldtask=%d newtask=%d",
|
||||
freehandle, d->volume, d->path ? (char*)d->path : "",
|
||||
d->task, task));
|
||||
if (d->path) {
|
||||
xfree(d->path);
|
||||
d->path = NULL;
|
||||
}
|
||||
d->inode = 0;
|
||||
}
|
||||
}
|
||||
if (freehandle){
|
||||
(void)change_dir_entry(&(dirs[freehandle-1]),
|
||||
volume, path, dev, inode,
|
||||
|
||||
Reference in New Issue
Block a user