Messages in this thread Patch in this message | | | Date | Wed, 10 Dec 1997 09:56:23 -0500 | From | Bill Hawes <> | Subject | updated msdos patch for 2.1.72 |
| |
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--- 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); | |