Re: dcache questions

Gordon Chaffee (chaffee@CS.Berkeley.EDU)
Wed, 31 Dec 1997 02:48:33 -0800 (PST)


Martin von Loewis writes:
> Strange. When you remove longfi~1, I'm sure you also remove LongFileName
> physically from the disk. At that time, couldn't you also instantiate
> a negative dentry for it, or rather d_delete the existing one?

This is the problem of determining all the dentries that exist for a
given inode. Since there are many different directory name combinations
that can end up in the same place, some might still exist.

Even for the simple case that I thought should have worked, it didn't.
LongFileName has an alias longfi~1. When LongFileName got deleted, I did
a d_lookup using the same parent of LongFileName with the name set to
the alias longfi~1. I never got a match on the dentry even if I had
looked it up with longfi~1 before.

Here is the routine I was using. fninfo holds the longname and the
shortname. dentry is the dentry that was passed to vfat_unlink()
or vfat_create(). I called this routine in both cases to try to
remove no longer valid dentries. I don't know why it wouldn't work
for the case I was trying, but it would fail for more complex cases
anyway (i.e. parent dentry of alias different than parent dentry of
longname).

- Gordon

/*
* This cleans up any dentries that refer to the same file as dentry.
* These will usually be vfat aliases.
*/
static void
vfat_delete_dalias(struct dentry *dentry, struct vfat_fname_info *fninfo)
{
struct dentry *dalias;
struct qstr qstr;
int deleted;

if (fninfo->msdos_name == NULL || fninfo->longname == NULL)
return;

PRINTK(("vfat_delete_dalias 1: name=%s\n", fninfo->msdos_name));
deleted = 0;
qstr.name = fninfo->msdos_name;
qstr.len = strlen(qstr.name);
qstr.hash = dentry->d_op->d_hash(dentry->d_parent, &qstr);
dalias = d_lookup(dentry->d_parent, &qstr);
if (dalias) {
PRINTK(("vfat_delete_dalias 2\n"));
if (dalias != dentry) {
PRINTK(("vfat_delete_dalias 2a\n"));
d_delete(dalias);
deleted = 1;
}
dput(dalias);
}
if (!deleted) {
PRINTK(("vfat_delete_dalias 3\n"));
qstr.name = fninfo->longname;
qstr.len = strlen(qstr.name);
qstr.hash = dentry->d_op->d_hash(dentry->d_parent, &qstr);
dalias = d_lookup(dentry->d_parent, &qstr);
if (dalias) {
PRINTK(("vfat_delete_dalias 3a\n"));
if (dalias != dentry) {
PRINTK(("vfat_delete_dalias 3b\n"));
d_delete(dalias);
}
dput(dalias);
}
}
PRINTK(("vfat_delete_dalias 4\n"));
}