updated msdos patch for 2.1.72

Bill Hawes (whawes@star.net)
Wed, 10 Dec 1997 09:56:23 -0500


This is a multi-part message in MIME format.
--------------A0AC2F3AC6D5ABB48018CA02
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I've made a couple of minor improvements to the msdos patch that should
more closely follow the old semantics with respect to invalid file
names.

Instead of returning an error from the d_hash operation for invalid file
names, the code now leaves the hash unchanged. This allows the dentry to
be created, and then the msdos fs operations can return the appropriate
error when the dentry is used. (I.e. ENOENT for searches, EINVAL for
creation.) The d_compare operation falls back to the standard compare to
avoid creating multiple copies of the dentry.

In addition to preserving error semantics, leaving the negative dentry
in place will speed up operations if for some reason the invalid name is
used a lot. This might be the case with certain wild-card names like
*.bak or whatever.

Regards,
Bill
--------------A0AC2F3AC6D5ABB48018CA02
Content-Type: text/plain; charset=us-ascii; name="fat_72-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="fat_72-patch"

--- linux-2.1.72/fs/fat/inode.c.old Sun Nov 30 11:26:00 1997
+++ linux-2.1.72/fs/fat/inode.c Wed Dec 10 10:23:01 1997
@@ -117,6 +117,16 @@

void fat_delete_inode(struct inode *inode)
{
+ /*
+ * Make sure there are no active dependencies ...
+ */
+ if (MSDOS_I(inode)->i_old)
+ printk("fat_delete_inode: inode %ld, old=%p??\n",
+ inode->i_ino, MSDOS_I(inode)->i_old);
+ if (MSDOS_I(inode)->i_oldlink)
+ printk("fat_delete_inode: inode %ld, oldlink=%p??\n",
+ inode->i_ino, MSDOS_I(inode)->i_oldlink);
+
fat_cache_inval_inode(inode);
inode->i_size = 0;
fat_truncate(inode);
--- linux-2.1.72/fs/msdos/namei.c.old Sun Nov 30 11:26:00 1997
+++ linux-2.1.72/fs/msdos/namei.c Wed Dec 10 10:23:01 1997
@@ -173,56 +173,60 @@
return fat_scan(dir,msdos_name,bh,de,ino,scantype);
}

-
+/*
+ * Compute the hash for the msdos name corresponding to the dentry.
+ * Note: if the name is invalid, we leave the hash code unchanged so
+ * that the existing dentry can be used. The msdos fs routines will
+ * return ENOENT or EINVAL as appropriate.
+ */
static int msdos_hash(struct dentry *dentry, struct qstr *qstr)
{
- unsigned long hash;
- char msdos_name[MSDOS_NAME];
+ struct fat_mount_options *options = & (MSDOS_SB(dentry->d_sb)->options);
int error;
- int i;
- struct fat_mount_options *options =
- & (MSDOS_SB(dentry->d_inode->i_sb)->options);
+ char msdos_name[MSDOS_NAME];

- error = msdos_format_name(options->name_check,
- qstr->name, qstr->len, msdos_name,1,
- options->dotsOK);
- if(error)
- return error;
- hash = init_name_hash();
- for(i=0; i< MSDOS_NAME; i++)
- hash = partial_name_hash(msdos_name[i], hash);
- qstr->hash = end_name_hash(hash);
+ error = msdos_format_name(options->name_check, qstr->name, qstr->len,
+ msdos_name, 1, options->dotsOK);
+ if (!error)
+ qstr->hash = full_name_hash(msdos_name, MSDOS_NAME);
return 0;
}

-
-static int msdos_cmp(struct dentry *dentry,
- struct qstr *a, struct qstr *b)
+/*
+ * Compare two msdos names. If either of the names are invalid,
+ * we fall back to doing the standard name comparison.
+ */
+static int msdos_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
{
- char a_msdos_name[MSDOS_NAME],b_msdos_name[MSDOS_NAME];
+ struct fat_mount_options *options = & (MSDOS_SB(dentry->d_sb)->options);
int error;
- struct fat_mount_options *options =
- & (MSDOS_SB(dentry->d_inode->i_sb)->options);
+ char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];

- error = msdos_format_name(options->name_check,
- a->name, a->len, a_msdos_name,1,
- options->dotsOK);
- if(error)
- return error;
- error = msdos_format_name(options->name_check,
- b->name, b->len, b_msdos_name,1,
- options->dotsOK);
- if(error)
- return error;
-
- return memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
+ error = msdos_format_name(options->name_check, a->name, a->len,
+ a_msdos_name, 1, options->dotsOK);
+ if (error)
+ goto old_compare;
+ error = msdos_format_name(options->name_check, b->name, b->len,
+ b_msdos_name, 1, options->dotsOK);
+ if (error)
+ goto old_compare;
+ error = memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
+out:
+ return error;
+
+old_compare:
+ error = 1;
+ if (a->len == b->len)
+ error = memcmp(a->name, b->name, a->len);
+ goto out;
}


static struct dentry_operations msdos_dentry_operations = {
- 0, /* d_revalidate */
+ NULL, /* d_revalidate */
msdos_hash,
- msdos_cmp
+ msdos_cmp,
+ NULL /* d_delete */
};

struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent)
@@ -233,14 +237,16 @@

MSDOS_SB(sb)->options.isvfat = 0;
sb->s_op = &msdos_sops;
- res = fat_read_super(sb, data, silent);
- if (res == NULL) {
- sb->s_dev = 0;
- MOD_DEC_USE_COUNT;
- return NULL;
- }
+ res = fat_read_super(sb, data, silent);
+ if (res == NULL)
+ goto out_fail;
sb->s_root->d_op = &msdos_dentry_operations;
return res;
+
+out_fail:
+ sb->s_dev = 0;
+ MOD_DEC_USE_COUNT;
+ return NULL;
}


@@ -290,11 +296,14 @@
PRINTK (("msdos_lookup 6\n"));
while (MSDOS_I(inode)->i_old) {
next = MSDOS_I(inode)->i_old;
+#ifdef MSDOS_PARANOIA
+printk("msdos_lookup: ino %ld, old ino=%ld\n", inode->i_ino, next->i_ino);
+if (MSDOS_I(next)->i_depend != inode)
+printk("msdos_lookup: depend=%p, inode=%p??\n", MSDOS_I(next)->i_depend, inode);
+#endif
+ next->i_count++;
iput(inode);
- if (!(inode = iget(next->i_sb,next->i_ino))) {
- fat_fs_panic(dir->i_sb,"msdos_lookup: Can't happen");
- return -ENOENT; /* N.B. Maybe ENOMEM is better? */
- }
+ inode = next;
}
PRINTK (("msdos_lookup 7\n"));
d_add(dentry, inode);

--------------A0AC2F3AC6D5ABB48018CA02--