summaryrefslogtreecommitdiffstats
path: root/fs/umsdos
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
commitdb7d4daea91e105e3859cf461d7e53b9b77454b2 (patch)
tree9bb65b95440af09e8aca63abe56970dd3360cc57 /fs/umsdos
parent9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff)
Merge with Linux 2.2.8.
Diffstat (limited to 'fs/umsdos')
-rw-r--r--fs/umsdos/dir.c72
-rw-r--r--fs/umsdos/emd.c4
-rw-r--r--fs/umsdos/inode.c13
-rw-r--r--fs/umsdos/namei.c305
-rw-r--r--fs/umsdos/rdir.c13
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);
}