I'm in the process of revivifying a user space filesystem I wrote for
2.0 kernels several years ago. I have a simple pass through
filesystem basically working. However, if I run a busy loop such as
while true
do
ls -l >/dev/null
done
in a directory within the filesystem and then do a rmdir on that
directory, strange behavior follows. The directory is indeed removed.
I can then create a new directory with the same name as the deleted
directory, but if I then try to create any files or directories within
the new directory I fail. VFS traffic shows that lookups are made for
the files or directories I try to create but no create or mkdir calls.
It appears that some artifacts are left either in the inode cache or
the dentry cache. I'm not sure, but I believe that the problem lies in
my inode_operations::rmdir function which I list below. If I insert a
if (!d_unhashed(entry))
{
return -EBUSY;
}
into the code, as coda does, I am forbidden from deleting a directory
in which processes are active. Any clues as to how to handle rmdir so
that I get ext2 behavior? TIA for any help.
Britt
int uvfs_rmdir(struct inode* dir, struct dentry* entry)
{
int i;
int slot;
int error = 0;
uvfs_rmdir_req_s* request;
uvfs_rmdir_rep_s* reply;
spin_lock(&Uvfs_lock);
/* Grabs a communications slot. */
slot = uvfs_find_accepting_slot();
if (slot < 0)
{
spin_unlock(&Uvfs_lock);
return slot;
}
request = &Uvfs_slots[slot].request.rmdir;
request->type = UVFS_RMDIR;
request->slot = slot;
request->size = sizeof(*request);
request->dir_inode = dir->i_ino;
memcpy(request->name, entry->d_name.name, entry->d_name.len);
request->namelen = entry->d_name.len;
wake_up_interruptible(&Uvfs_slots[slot].driver_queue);
/* This is just an unrolled version of interruptible_sleep_on */
safe_sleep_on(&Uvfs_slots[slot].fs_queue, &Uvfs_lock);
if (signal_pending(current))
{
error = -ERESTARTSYS;
goto out;
}
reply = &Uvfs_slots[slot].reply.rmdir;
error = reply->error;
if (error == 0)
{
entry->d_inode->i_nlink = 0;
d_drop(entry);
}
out:
/* Releases communication slot */
uvfs_empty_slot(slot);
spin_unlock(&Uvfs_lock);
dprintk("<1>Exited uvfs_rmdir. %d\n", error);
return error;
}