diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
commit | db7d4daea91e105e3859cf461d7e53b9b77454b2 (patch) | |
tree | 9bb65b95440af09e8aca63abe56970dd3360cc57 /fs/umsdos | |
parent | 9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff) |
Merge with Linux 2.2.8.
Diffstat (limited to 'fs/umsdos')
-rw-r--r-- | fs/umsdos/dir.c | 72 | ||||
-rw-r--r-- | fs/umsdos/emd.c | 4 | ||||
-rw-r--r-- | fs/umsdos/inode.c | 13 | ||||
-rw-r--r-- | fs/umsdos/namei.c | 305 | ||||
-rw-r--r-- | fs/umsdos/rdir.c | 13 |
5 files changed, 104 insertions, 303 deletions
diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index 6ab276ac4..799f685de 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -30,7 +30,7 @@ extern struct inode *pseudo_root; */ /* nothing for now ... */ -static int umsdos_dentry_validate(struct dentry *dentry) +static int umsdos_dentry_validate(struct dentry *dentry, int flags) { return 1; } @@ -46,7 +46,7 @@ static void umsdos_dentry_dput(struct dentry *dentry) struct dentry_operations umsdos_dentry_operations = { - umsdos_dentry_validate, /* d_validate(struct dentry *) */ + umsdos_dentry_validate, /* d_revalidate(struct dentry *, int) */ NULL, /* d_hash */ NULL, /* d_compare */ umsdos_dentry_dput, /* d_delete(struct dentry *) */ @@ -210,8 +210,8 @@ filp->f_dentry->d_name.name, entry.name); /* * Do a real lookup on the short name. */ - dret = umsdos_lookup_dentry(filp->f_dentry, info.fake.fname, - info.fake.len, 1); + dret = umsdos_covered(filp->f_dentry, info.fake.fname, + info.fake.len); ret = PTR_ERR(dret); if (IS_ERR(dret)) break; @@ -459,7 +459,7 @@ int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry) * entry from the EMD file, and return ENOENT. */ -int umsdos_lookup_x (struct inode *dir, struct dentry *dentry, int nopseudo) +struct dentry *umsdos_lookup_x (struct inode *dir, struct dentry *dentry, int nopseudo) { struct dentry *dret = NULL; struct inode *inode; @@ -500,8 +500,7 @@ Printk (("lookup %.*s pos %lu ret %d len %d ", info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len)); /* do a real lookup to get the short name ... */ - dret = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname, - info.fake.len, 1); + dret = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); ret = PTR_ERR(dret); if (IS_ERR(dret)) { printk("umsdos_lookup_x: %s/%s real lookup failed, ret=%d\n", @@ -563,7 +562,7 @@ out_dput: dput(dret); out: umsdos_endlookup (dir); - return ret; + return ERR_PTR(ret); out_remove: printk(KERN_WARNING "UMSDOS: entry %s/%s out of sync, erased\n", @@ -581,23 +580,48 @@ out_remove: * Called by VFS; should fill dentry->d_inode via d_add. */ -int UMSDOS_lookup (struct inode *dir, struct dentry *dentry) +struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry) { - int ret; + struct dentry *ret; ret = umsdos_lookup_x (dir, dentry, 0); /* Create negative dentry if not found. */ - if (ret == -ENOENT) { + if (ret == ERR_PTR(-ENOENT)) { Printk ((KERN_DEBUG "UMSDOS_lookup: converting -ENOENT to negative\n")); d_add (dentry, NULL); dentry->d_op = &umsdos_dentry_operations; - ret = 0; + ret = NULL; } return ret; } +struct dentry *umsdos_covered(struct dentry *parent, char *name, int len) +{ + struct dentry *result, *dentry; + struct qstr qstr; + + qstr.name = name; + qstr.len = len; + qstr.hash = full_name_hash(name, len); + result = ERR_PTR(-ENOMEM); + dentry = d_alloc(parent, &qstr); + if (dentry) { + /* XXXXXXXXXXXXXXXXXXX Race alert! */ + result = UMSDOS_rlookup(parent->d_inode, dentry); + d_drop(dentry); + if (result) + goto out_fail; + return dentry; + } +out: + return result; + +out_fail: + dput(dentry); + goto out; +} /* * Lookup or create a dentry from within the filesystem. @@ -609,7 +633,6 @@ struct dentry *umsdos_lookup_dentry(struct dentry *parent, char *name, int len, int real) { struct dentry *result, *dentry; - int error; struct qstr qstr; qstr.name = name; @@ -620,20 +643,19 @@ struct dentry *umsdos_lookup_dentry(struct dentry *parent, char *name, int len, result = ERR_PTR(-ENOMEM); dentry = d_alloc(parent, &qstr); if (dentry) { - result = dentry; - error = real ? - UMSDOS_rlookup(parent->d_inode, result) : - UMSDOS_lookup(parent->d_inode, result); - if (error) + result = real ? + UMSDOS_rlookup(parent->d_inode, dentry) : + UMSDOS_lookup(parent->d_inode, dentry); + if (result) goto out_fail; + return dentry; } } out: return result; out_fail: - dput(result); - result = ERR_PTR(error); + dput(dentry); goto out; } @@ -706,11 +728,6 @@ hlink->d_parent->d_name.name, hlink->d_name.name, path); len = (int) (pt - start); if (*pt == '/') *pt++ = '\0'; - real = (dir->d_inode->u.umsdos_i.i_emd_dir == 0); - /* - * Hack alert! inode->u.umsdos_i.i_emd_dir isn't reliable, - * so just check whether there's an EMD file ... - */ real = 1; demd = umsdos_get_emd_dentry(dir); if (!IS_ERR(demd)) { @@ -720,9 +737,8 @@ hlink->d_parent->d_name.name, hlink->d_name.name, path); } #ifdef UMSDOS_DEBUG_VERBOSE -printk ("umsdos_solve_hlink: dir %s/%s, name=%s, emd_dir=%ld, real=%d\n", -dir->d_parent->d_name.name, dir->d_name.name, start, -dir->d_inode->u.umsdos_i.i_emd_dir, real); +printk ("umsdos_solve_hlink: dir %s/%s, name=%s, real=%d\n", +dir->d_parent->d_name.name, dir->d_name.name, start, real); #endif dentry_dst = umsdos_lookup_dentry(dir, start, len, real); if (real) diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c index 6a4e99c04..d5a7a9578 100644 --- a/fs/umsdos/emd.c +++ b/fs/umsdos/emd.c @@ -250,12 +250,8 @@ parent->d_name.name, demd->d_name.name)); printk (KERN_WARNING "umsdos_make_emd: create %s/%s failed, err=%d\n", parent->d_name.name, demd->d_name.name, err); - goto out_dput; } out_set: - parent->d_inode->u.umsdos_i.i_emd_dir = demd->d_inode->i_ino; - -out_dput: dput(demd); out: return err; diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c index ef6e56dc3..c7c94b558 100644 --- a/fs/umsdos/inode.c +++ b/fs/umsdos/inode.c @@ -50,10 +50,10 @@ void fill_new_filp (struct file *filp, struct dentry *dentry) void UMSDOS_put_inode (struct inode *inode) { PRINTK ((KERN_DEBUG - "put inode %p (%lu) owner %lu pos %lu dir %lu count=%d\n" + "put inode %p (%lu) pos %lu count=%d\n" ,inode, inode->i_ino - ,inode->u.umsdos_i.i_emd_owner, inode->u.umsdos_i.pos - ,inode->u.umsdos_i.i_emd_dir, inode->i_count)); + ,inode->u.umsdos_i.pos + ,inode->i_count)); if (inode == pseudo_root) { printk (KERN_ERR "Umsdos: Oops releasing pseudo_root." @@ -94,7 +94,6 @@ void umsdos_setup_dir(struct dentry *dir) printk(KERN_ERR "umsdos_setup_dir: %s/%s not a dir!\n", dir->d_parent->d_name.name, dir->d_name.name); - inode->u.umsdos_i.i_emd_dir = 0; inode->i_op = &umsdos_rdir_inode_operations; if (umsdos_have_emd(dir)) { Printk((KERN_DEBUG "umsdos_setup_dir: %s/%s using EMD\n", @@ -112,14 +111,11 @@ void umsdos_set_dirinfo_new (struct dentry *dentry, off_t f_pos) struct inode *inode = dentry->d_inode; struct dentry *demd; - inode->u.umsdos_i.i_emd_owner = 0; inode->u.umsdos_i.pos = f_pos; /* now check the EMD file */ demd = umsdos_get_emd_dentry(dentry->d_parent); if (!IS_ERR(demd)) { - if (demd->d_inode) - inode->u.umsdos_i.i_emd_owner = demd->d_inode->i_ino; dput(demd); } return; @@ -149,7 +145,6 @@ PRINTK (("umsdos_patch_inode: call umsdos_set_dirinfo_new(%p,%lu)\n", dentry, f_pos)); umsdos_set_dirinfo_new(dentry, f_pos); - inode->u.umsdos_i.i_emd_dir = 0; if (S_ISREG (inode->i_mode)) { if (MSDOS_SB (inode->i_sb)->cvf_format) { if (MSDOS_SB (inode->i_sb)->cvf_format->flags & CVF_USE_READPAGE) { @@ -327,8 +322,6 @@ void UMSDOS_write_inode (struct inode *inode) { struct iattr newattrs; - PRINTK (("UMSDOS_write_inode emd %d (FIXME: missing notify_change)\n", - inode->u.umsdos_i.i_emd_owner)); fat_write_inode (inode); newattrs.ia_mtime = inode->i_mtime; newattrs.ia_atime = inode->i_atime; diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c index 8e7780395..444e9ffae 100644 --- a/fs/umsdos/namei.c +++ b/fs/umsdos/namei.c @@ -6,6 +6,10 @@ * * Maintain and access the --linux alternate directory file. */ + /* + * You are in the maze of twisted functions - half of them shouldn't + * be here... + */ #include <linux/errno.h> #include <linux/kernel.h> @@ -171,18 +175,6 @@ void umsdos_endlookup (struct inode *dir) #endif -/* - * Check whether we can delete from the directory. - */ -static int is_sticky(struct inode *dir, int uid) -{ - return !((dir->i_mode & S_ISVTX) == 0 || - current->fsuid == uid || - current->fsuid == dir->i_uid || - capable (CAP_FOWNER)); -} - - static int umsdos_nevercreat (struct inode *dir, struct dentry *dentry, int errcod) { @@ -258,16 +250,11 @@ static int umsdos_create_any (struct inode *dir, struct dentry *dentry, goto out; /* do a real lookup to get the short name dentry */ - fake = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname, - info.fake.len, 1); + fake = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); ret = PTR_ERR(fake); if (IS_ERR(fake)) goto out_remove; - /* keep the short name anonymous ... */ - if (dentry != fake) - d_drop(fake); - /* should not exist yet ... */ ret = -EEXIST; if (fake->d_inode) @@ -278,14 +265,8 @@ static int umsdos_create_any (struct inode *dir, struct dentry *dentry, goto out_remove_dput; inode = fake->d_inode; - /* - * Note! The long and short name might be the same, - * so check first before doing the instantiate ... - */ - if (dentry != fake) { - inode->i_count++; - d_instantiate (dentry, inode); - } + inode->i_count++; + d_instantiate (dentry, inode); dput(fake); if (inode->i_count > 1) { printk(KERN_WARNING @@ -363,7 +344,7 @@ static int umsdos_rename_f (struct inode *old_dir, struct dentry *old_dentry, { struct inode *old_inode = old_dentry->d_inode; struct dentry *old, *new, *old_emd; - int err, ret, rehash = 0; + int err, ret; struct umsdos_info old_info; struct umsdos_info new_info; @@ -386,34 +367,11 @@ static int umsdos_rename_f (struct inode *old_dir, struct dentry *old_dentry, umsdos_lockcreate2 (old_dir, new_dir); ret = umsdos_findentry(old_emd->d_parent, &old_info, 0); - if (ret) { - printk(KERN_ERR - "umsdos_rename_f: old entry %s/%s not in EMD, ret=%d\n", - old_dentry->d_parent->d_name.name, old_info.entry.name, - ret); - goto out_unlock; - } - - /* check sticky bit on old_dir */ - ret = -EPERM; - if (is_sticky(old_dir, old_info.entry.uid)) { -printk("umsdos_rename_f: %s/%s old sticky bit, fsuid=%d, uid=%d, dir=%d\n", -old_dentry->d_parent->d_name.name, old_info.entry.name, -current->fsuid, old_info.entry.uid, old_dir->i_uid); + if (ret) goto out_unlock; - } - /* - * Check whether the new_name already exists, and - * if so whether we're allowed to replace it. - */ err = umsdos_findentry(new_dentry->d_parent, &new_info, 0); if (err == 0) { - /* Are we allowed to replace it? */ - if (is_sticky(new_dir, new_info.entry.uid)) { -Printk (("sticky set on new ")); - goto out_unlock; - } /* check whether it _really_ exists ... */ ret = -EEXIST; if (new_dentry->d_inode) @@ -427,108 +385,41 @@ Printk (("sticky set on new ")); S_ISDIR(new_info.entry.mode)); } -Printk (("new newentry ")); - /* create the new entry ... */ umsdos_ren_init (&new_info, &old_info); if (flags) new_info.entry.flags = flags; ret = umsdos_newentry (new_dentry->d_parent, &new_info); - if (ret) { - printk(KERN_WARNING - "umsdos_rename_f: newentry %s/%s failed, ret=%d\n", - new_dentry->d_parent->d_name.name, new_info.entry.name, - ret); + if (ret) goto out_unlock; - } /* If we're moving a hardlink, drop it first */ if (old_info.entry.flags & UMSDOS_HLINK) { - rehash = !list_empty(&old_dentry->d_hash); d_drop(old_dentry); -printk("umsdos_rename_f: moving hardlink %s/%s, rehash=%d\n", -old_dentry->d_parent->d_name.name, old_info.entry.name, rehash); } - /* Do a real lookup to get the old short name dentry */ - old = umsdos_lookup_dentry(old_dentry->d_parent, old_info.fake.fname, - old_info.fake.len, 1); + old = umsdos_covered(old_dentry->d_parent, old_info.fake.fname, + old_info.fake.len); ret = PTR_ERR(old); - if (IS_ERR(old)) { - printk(KERN_WARNING - "umsdos_rename_f: lookup old dentry %s/%s, ret=%d\n", - old_dentry->d_parent->d_name.name, old_info.fake.fname, - ret); + if (IS_ERR(old)) goto out_unlock; - } - /* short and long name dentries match? */ - if (old == old_dentry) - dput(old); - else { - /* make sure it's the same inode! */ - ret = -ENOENT; - if (old->d_inode != old_inode) - goto out_dput; - /* - * A cross-directory move with different short and long - * names has nasty complications: msdos-fs will need to - * change inodes, so we must check whether the original - * dentry is busy, and if the rename succeeds the short - * dentry will come back with a different inode. - * - * To handle this, we drop the dentry and free the inode, - * and then pick up the new inode after the rename. - */ - if (old_dir != new_dir) { - ret = -EBUSY; - if (old_dentry->d_count > 1) { -printk("umsdos_rename_f: old dentry %s/%s busy, d_count=%d\n", -old_dentry->d_parent->d_name.name, old_dentry->d_name.name,old_dentry->d_count); - goto out_dput; - } - d_drop(old_dentry); - d_delete(old_dentry); -printk("umsdos_rename_f: cross-dir move, %s/%s dropped\n", -old_dentry->d_parent->d_name.name, old_dentry->d_name.name); - } - } + /* make sure it's the same inode! */ + ret = -ENOENT; + if (old->d_inode != old_inode) + goto out_dput; - new = umsdos_lookup_dentry(new_dentry->d_parent, new_info.fake.fname, - new_info.fake.len, 1); + new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname, + new_info.fake.len); ret = PTR_ERR(new); - if (IS_ERR(new)) { - printk(KERN_WARNING - "umsdos_rename_f: lookup new dentry %s/%s, ret=%d\n", - new_dentry->d_parent->d_name.name, new_info.fake.fname, - ret); + if (IS_ERR(new)) goto out_dput; - } -#ifdef UMSDOS_PARANOIA -if (new->d_inode != new_dentry->d_inode) -printk("umsdos_rename_f: new %s/%s, inode %p!=%p??\n", -new->d_parent->d_name.name, new->d_name.name, new->d_inode,new_dentry->d_inode); -#endif - /* short and long name dentries match? */ - if (new == new_dentry) - dput(new); -#ifdef UMSDOS_DEBUG_VERBOSE -printk("umsdos_rename_f: msdos_rename %s/%s(%ld) to %s/%s(%ld)\n", -old->d_parent->d_name.name, old->d_name.name, old->d_inode->i_ino, -new->d_parent->d_name.name, new->d_name.name, -new->d_inode ? new->d_inode->i_ino : 0); -#endif /* Do the msdos-level rename */ ret = msdos_rename (old_dir, old, new_dir, new); -Printk(("umsdos_rename_f: now %s/%s, ret=%d\n", -old->d_parent->d_name.name, old->d_name.name, ret)); - if (new != new_dentry) - dput(new); + dput(new); /* If the rename failed, remove the new EMD entry */ if (ret != 0) { -Printk(("umsdos_rename_f: rename failed, ret=%d, removing %s/%s\n", -ret, new_dentry->d_parent->d_name.name, new_info.entry.name)); umsdos_delentry (new_dentry->d_parent, &new_info, S_ISDIR (new_info.entry.mode)); goto out_dput; @@ -550,33 +441,6 @@ ret, new_dentry->d_parent->d_name.name, new_info.entry.name)); } /* - * Check whether to update the dcache ... if both - * old and new dentries match, it's already correct. - * If the targets were aliases, the old short-name - * dentry has the original target name. - */ - if (old_dentry != old) { - if (!old_dentry->d_inode) { - struct inode *inode = old->d_inode; - inode->i_count++; - d_instantiate(old_dentry, inode); -printk("umsdos_rename_f: %s/%s gets new ino=%ld\n", -old_dentry->d_parent->d_name.name, old_dentry->d_name.name, inode->i_ino); - } - if (new_dentry == new) - new_dentry = old; - goto move_it; - } else if (new_dentry != new) { - move_it: - /* this will rehash the dentry ... */ - d_move(old_dentry, new_dentry); - } - /* Check whether the old inode changed ... */ - if (old_dentry->d_inode != old_inode) { - umsdos_lookup_patch_new(old_dentry, &new_info); - } - - /* * Update f_pos so notify_change will succeed * if the file was already in use. */ @@ -584,8 +448,7 @@ old_dentry->d_parent->d_name.name, old_dentry->d_name.name, inode->i_ino); /* dput() the dentry if we haven't already */ out_dput: - if (old_dentry != old) - dput(old); + dput(old); out_unlock: dput(old_emd); @@ -614,6 +477,9 @@ out: extern struct inode_operations umsdos_symlink_inode_operations; +/* + * AV. Should be called with dir->i_sem down. + */ static int umsdos_symlink_x (struct inode *dir, struct dentry *dentry, const char *symname, int mode, char flags) { @@ -745,8 +611,9 @@ dentry->d_parent->d_name.name, hid_info.entry.name, ret); goto cleanup; } /* rename the link to the hidden location ... */ - ret = umsdos_rename_f (olddir, olddentry, olddir, temp, + ret = umsdos_rename_f(olddir, olddentry, olddir, temp, UMSDOS_HIDDEN); + d_move(olddentry, temp); dput(temp); if (ret) { printk("umsdos_link: rename to %s/%s failed, ret=%d\n", @@ -817,9 +684,8 @@ Printk(("UMSDOS_link: hard link %s/%s, fake=%s\n", olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.fake.fname)); /* Do a real lookup to get the short name dentry */ - temp = umsdos_lookup_dentry(olddentry->d_parent, - old_info.fake.fname, - old_info.fake.len, 1); + temp = umsdos_covered(olddentry->d_parent, old_info.fake.fname, + old_info.fake.len); ret = PTR_ERR(temp); if (IS_ERR(temp)) goto out_unlock; @@ -905,16 +771,11 @@ int UMSDOS_mkdir (struct inode *dir, struct dentry *dentry, int mode) goto out; /* lookup the short name dentry */ - temp = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname, - info.fake.len, 1); + temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); ret = PTR_ERR(temp); if (IS_ERR(temp)) goto out_remove; - /* Keep the short name dentry anonymous */ - if (temp != dentry) - d_drop(temp); - /* Make sure the short name doesn't exist */ ret = -EEXIST; if (temp->d_inode) { @@ -933,16 +794,9 @@ dentry->d_parent->d_name.name, info.fake.fname); inode = temp->d_inode; down(&inode->i_sem); - /* - * Note! The long and short name might be the same, - * so check first before doing the instantiate ... - */ - if (dentry != temp) { -if (dentry->d_inode) -printk("umsdos_mkdir: dentry not negative!\n"); - inode->i_count++; - d_instantiate(dentry, inode); - } + inode->i_count++; + d_instantiate(dentry, inode); + /* N.B. this should have an option to create the EMD ... */ umsdos_lookup_patch_new(dentry, &info); @@ -1042,21 +896,11 @@ demd->d_parent->d_name.name, demd->d_name.name, err); umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info); /* Call findentry to complete the mangling */ umsdos_findentry (dentry->d_parent, &info, 2); - temp = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname, - info.fake.len, 1); + temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); ret = PTR_ERR(temp); if (IS_ERR(temp)) goto out; /* - * If the short name is an alias, dput() it now; - * otherwise d_drop() it to keep it anonymous. - */ - if (temp == dentry) - dput(temp); - else - d_drop(temp); - - /* * Attempt to remove the msdos name. */ ret = msdos_rmdir (dir, temp); @@ -1072,8 +916,7 @@ printk("umsdos_rmdir: delentry %s failed, ret=%d\n", info.entry.name, ret); /* dput() temp if we didn't do it above */ out_dput: - if (temp != dentry) - dput(temp); + dput(temp); out: Printk (("umsdos_rmdir %d\n", ret)); @@ -1096,7 +939,7 @@ int UMSDOS_unlink (struct inode *dir, struct dentry *dentry) { struct dentry *temp, *link = NULL; struct inode *inode; - int ret, rehash = 0; + int ret; struct umsdos_info info; Printk(("UMSDOS_unlink: entering %s/%s\n", @@ -1120,14 +963,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name, ret); Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname)); - ret = -EPERM; - /* check sticky bit */ - if (is_sticky(dir, info.entry.uid)) { -printk("umsdos_unlink: %s/%s is sticky\n", -dentry->d_parent->d_name.name, dentry->d_name.name); - goto out_unlock; - } - /* * Note! If this is a hardlink and the names are aliased, * the short-name lookup will return the hardlink dentry. @@ -1135,15 +970,11 @@ dentry->d_parent->d_name.name, dentry->d_name.name); * the original dentry. */ if (info.entry.flags & UMSDOS_HLINK) { - rehash = !list_empty(&dentry->d_hash); d_drop(dentry); -Printk(("UMSDOS_unlink: hard link %s/%s, fake=%s, rehash=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname, rehash)); } /* Do a real lookup to get the short name dentry */ - temp = umsdos_lookup_dentry(dentry->d_parent, info.fake.fname, - info.fake.len, 1); + temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len); ret = PTR_ERR(temp); if (IS_ERR(temp)) goto out_unlock; @@ -1155,13 +986,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname, rehash)); link = umsdos_solve_hlink(dget(temp)); } - /* - * If the short and long names are aliased, - * dput() it now so the dentry isn't busy. - */ - if (temp == dentry) - dput(temp); - /* Delete the EMD entry */ ret = umsdos_delentry (dentry->d_parent, &info, 0); if (ret && ret != -ENOENT) { @@ -1170,7 +994,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname, rehash)); goto out_dput; } - ret = msdos_unlink_umsdos (dir, temp); + ret = msdos_unlink(dir, temp); #ifdef UMSDOS_PARANOIA if (ret) printk("umsdos_unlink: %s/%s unlink failed, ret=%d\n", @@ -1179,12 +1003,9 @@ temp->d_parent->d_name.name, temp->d_name.name, ret); /* dput() temp if we didn't do it above */ out_dput: - if (temp != dentry) { - d_drop(temp); - dput(temp); - if (!ret) - d_delete (dentry); - } + dput(temp); + if (!ret) + d_delete (dentry); out_unlock: umsdos_unlockcreate (dir); @@ -1247,57 +1068,31 @@ out: return ret; } - /* * Rename (move) a file. */ int UMSDOS_rename (struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { - struct dentry *new_target; int ret; -#ifdef UMSDOS_DEBUG_VERBOSE -printk("umsdos_rename: enter, %s/%s(%ld) to %s/%s(%ld)\n", -old_dentry->d_parent->d_name.name, old_dentry->d_name.name, -old_dentry->d_inode->i_ino, -new_dentry->d_parent->d_name.name, new_dentry->d_name.name, -new_dentry->d_inode ? new_dentry->d_inode->i_ino : 0); -#endif ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST); if (ret) - goto out; + return ret; - /* - * If the target already exists, delete it first. - */ + /* + * If the target already exists, delete it first. + */ if (new_dentry->d_inode) { - if (S_ISDIR(new_dentry->d_inode->i_mode)) + new_dentry->d_count++; + if (S_ISDIR(old_dentry->d_inode->i_mode)) ret = UMSDOS_rmdir (new_dir, new_dentry); else ret = UMSDOS_unlink (new_dir, new_dentry); + dput(new_dentry); if (ret) - goto out; + return ret; } - - /* - * If we didn't get a negative dentry, make a copy and hash it. - */ - new_target = new_dentry; - if (new_dentry->d_inode) { -printk("umsdos_rename: %s/%s not negative, hash=%d\n", -new_dentry->d_parent->d_name.name, new_dentry->d_name.name, -!list_empty(&new_dentry->d_hash)); - ret = -ENOMEM; - new_target = d_alloc(new_dentry->d_parent, &new_dentry->d_name); - if (!new_target) - goto out; - d_add(new_target, NULL); - } - ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_target, 0); - if (new_target != new_dentry) - dput(new_target); - -out: + ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_dentry, 0); return ret; } diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c index 10ff145b7..3f5d10953 100644 --- a/fs/umsdos/rdir.c +++ b/fs/umsdos/rdir.c @@ -79,9 +79,9 @@ static int UMSDOS_rreaddir (struct file *filp, void *dirbuf, filldir_t filldir) * In the real root directory (c:\), the directory .. * is the pseudo root (c:\linux). */ -int umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo) +struct dentry *umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo) { - int ret; + struct dentry *ret; if (saved_root && dir == saved_root->d_inode && !nopseudo && dentry->d_name.len == UMSDOS_PSDROOT_LEN && @@ -91,15 +91,16 @@ int umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo) * /linux won't show */ - ret = -ENOENT; + ret = ERR_PTR(-ENOENT); goto out; } ret = msdos_lookup (dir, dentry); if (ret) { printk(KERN_WARNING - "umsdos_rlookup_x: %s/%s failed, ret=%d\n", - dentry->d_parent->d_name.name, dentry->d_name.name,ret); + "umsdos_rlookup_x: %s/%s failed, ret=%ld\n", + dentry->d_parent->d_name.name, dentry->d_name.name, + PTR_ERR(ret)); goto out; } if (dentry->d_inode) { @@ -119,7 +120,7 @@ out: } -int UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry) +struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry) { return umsdos_rlookup_x (dir, dentry, 0); } |