Messages in this thread Patch in this message | | | Date | Sat, 26 Jul 1997 16:41:22 +0200 | From | Martin von Loewis <> | Subject | Re: VFAT 2.1.47 |
| |
Andreas Schwab wrote: > There is likely to be one problem that i also tripped along while porting > msdos: you must not return ENOENT from lookup, instead only the fact that > dentry->d_inode is NULL tells the VFS that the file does not exist. Thus > you should change all `return -ENOENT' in vfat_lookup to `return 0'. This > also includes the implicit ENOENT that you may get from vfat_find.
I deliberately ignored those changes, because I found it strange to return success when an error occured. Oh well.
I've included an updated patch below. This also fixes a problem with renaming; it would not update the dcache, but iput the parent directories. As for renaming: In the msdos case, it seems not right to use d_move after a rename. After all, a new inode might be created - at least in the 'different directories' case. Instead, I use d_instantiate for the new inode and d_delete for the old one. Is this correct?
Regards, Martin
diff -u fs/vfat.orig/namei.c fs/vfat/namei.c --- fs/vfat.orig/namei.c Fri Jul 25 06:54:02 1997 +++ fs/vfat/namei.c Sat Jul 26 16:04:34 1997 @@ -69,13 +69,14 @@ static struct super_operations vfat_sops = { vfat_read_inode, - fat_notify_change, fat_write_inode, fat_put_inode, + NULL, /* delete_inode */ + fat_notify_change, vfat_put_super, - NULL, /* added in 0.96c */ + NULL, /* write_super */ fat_statfs, - NULL + NULL /* remount */ }; static int parse_options(char *options, struct fat_mount_options *opts) @@ -910,66 +911,50 @@ return -ENOENT; } -int vfat_lookup(struct inode *dir,const char *name,int len, - struct inode **result) +int vfat_lookup(struct inode *dir,struct dentry *dentry) { - int res, ino; + int res; struct inode *next; struct slot_info sinfo; + struct inode *result; - PRINTK (("vfat_lookup: name=%s, len=%d\n", name, len)); + PRINTK (("vfat_lookup: name=%s, len=%d\n", + dentry->d_name.name, dentry->d_name.len)); - *result = NULL; - if (!dir) return -ENOENT; - if (!S_ISDIR(dir->i_mode)) { - iput(dir); - return -ENOENT; - } - PRINTK (("vfat_lookup 2\n")); - if (len == 1 && name[0] == '.') { - *result = dir; - return 0; - } - if (len == 2 && name[0] == '.' && name[1] == '.') { - ino = fat_parent_ino(dir,0); - iput(dir); - if (ino < 0) return ino; - if (!(*result = iget(dir->i_sb,ino))) return -EACCES; + result = NULL; + if ((res = vfat_find(dir,dentry->d_name.name, + dentry->d_name.len,1,0,0,&sinfo)) < 0) { + d_add(dentry,NULL); return 0; } - PRINTK (("vfat_lookup 3\n")); - if ((res = vfat_find(dir,name,len,1,0,0,&sinfo)) < 0) { - iput(dir); - return res; - } PRINTK (("vfat_lookup 4.5\n")); - if (!(*result = iget(dir->i_sb,sinfo.ino))) { - iput(dir); + if (!(result = iget(dir->i_sb,sinfo.ino))) return -EACCES; - } PRINTK (("vfat_lookup 5\n")); - if (!(*result)->i_sb || - ((*result)->i_sb->s_magic != MSDOS_SUPER_MAGIC)) { + if (!result->i_sb || + (result->i_sb->s_magic != MSDOS_SUPER_MAGIC)) { /* crossed a mount point into a non-msdos fs */ - iput(dir); + d_add(dentry,result); return 0; } - if (MSDOS_I(*result)->i_busy) { /* mkdir in progress */ - iput(*result); - iput(dir); - return -ENOENT; + if (MSDOS_I(result)->i_busy) { /* mkdir in progress */ + iput(result); + d_add(dentry,NULL); + return 0; } PRINTK (("vfat_lookup 6\n")); - while (MSDOS_I(*result)->i_old) { - next = MSDOS_I(*result)->i_old; - iput(*result); - if (!(*result = iget(next->i_sb,next->i_ino))) { + while (MSDOS_I(result)->i_old) { + next = MSDOS_I(result)->i_old; + iput(result); + if (!(result = iget(next->i_sb,next->i_ino))) { fat_fs_panic(dir->i_sb,"vfat_lookup: Can't happen"); iput(dir); return -ENOENT; } } - iput(dir); + PRINTK (("vfat_lookup 7\n")); + d_add(dentry,result); + PRINTK (("vfat_lookup 8\n")); return 0; } @@ -1017,19 +1002,19 @@ return 0; } -int vfat_create(struct inode *dir,const char *name,int len,int mode, - struct inode **result) +int vfat_create(struct inode *dir,struct dentry* dentry,int mode) { int res; + struct inode *result; - if (!dir) return -ENOENT; - + result=NULL; fat_lock_creation(); - res = vfat_create_entry(dir,name,len,0,result); + res = vfat_create_entry(dir,dentry->d_name.name, + dentry->d_name.len,0,&result); if (res < 0) PRINTK(("vfat_create: unable to get new entry\n")); fat_unlock_creation(); - iput(dir); + d_instantiate(dentry,result); return res; } @@ -1271,12 +1256,12 @@ } /***** Remove a directory */ -int vfat_rmdir(struct inode *dir,const char *name,int len) +int vfat_rmdir(struct inode *dir,struct dentry* dentry) { int res; - res = vfat_rmdirx(dir, name, len); - iput(dir); + res = vfat_rmdirx(dir, dentry->d_name.name, dentry->d_name.len); + d_delete(dentry); return res; } @@ -1311,15 +1296,15 @@ } -int vfat_mkdir(struct inode *dir,const char *name,int len,int mode) +int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode) { struct inode *inode; int res; fat_lock_creation(); - if ((res = vfat_create_entry(dir,name,len,1,&inode)) < 0) { + if ((res = vfat_create_entry(dir,dentry->d_name.name, + dentry->d_name.len,1,&inode)) < 0) { fat_unlock_creation(); - iput(dir); return res; } @@ -1330,28 +1315,27 @@ res = vfat_create_dotdirs(inode, dir); fat_unlock_creation(); MSDOS_I(inode)->i_busy = 0; - iput(inode); - iput(dir); + d_instantiate(dentry,inode); if (res < 0) { - if (vfat_rmdir(dir,name,len) < 0) + if (vfat_rmdir(dir,dentry) < 0) fat_fs_panic(dir->i_sb,"rmdir in mkdir failed"); } return res; } /***** Unlink, as called for msdosfs */ -int vfat_unlink(struct inode *dir,const char *name,int len) +int vfat_unlink(struct inode *dir,struct dentry* dentry) { int res; - res = vfat_unlinkx (dir,name,len,1); - iput(dir); + res = vfat_unlinkx (dir,dentry->d_name.name,dentry->d_name.len,1); + d_delete(dentry); return res; } -int vfat_rename(struct inode *old_dir,const char *old_name,int old_len, - struct inode *new_dir,const char *new_name,int new_len) +int vfat_rename(struct inode *old_dir,struct dentry *old_dentry, + struct inode *new_dir,struct dentry *new_dentry) { struct super_block *sb = old_dir->i_sb; struct buffer_head *old_bh,*new_bh,*dotdot_bh; @@ -1364,13 +1348,16 @@ struct slot_info sinfo; PRINTK(("vfat_rename 1\n")); - if (old_dir == new_dir && old_len == new_len && - strncmp(old_name, new_name, old_len) == 0) + if (old_dir == new_dir && + old_dentry->d_name.len == new_dentry->d_name.len && + strncmp(old_dentry->d_name.name, new_dentry->d_name.name, + old_dentry->d_name.len) == 0) return 0; old_bh = new_bh = NULL; old_inode = new_inode = NULL; - res = vfat_find(old_dir,old_name,old_len,1,0,0,&sinfo); + res = vfat_find(old_dir,old_dentry->d_name.name, + old_dentry->d_name.len,1,0,0,&sinfo); PRINTK(("vfat_rename 2\n")); if (res < 0) goto rename_done; @@ -1383,8 +1370,7 @@ if (res < 0) goto rename_done; res = -ENOENT; - if (!(old_inode = iget(old_dir->i_sb,old_ino))) - goto rename_done; + old_inode = old_dentry->d_inode; is_dir = S_ISDIR(old_inode->i_mode); if (is_dir) { if ((old_dir->i_dev != new_dir->i_dev) || @@ -1413,7 +1399,8 @@ iput(walk); } - res = vfat_find(new_dir,new_name,new_len,1,0,is_dir,&sinfo); + res = vfat_find(new_dir,new_dentry->d_name.name, + new_dentry->d_name.len,1,0,is_dir,&sinfo); PRINTK(("vfat_rename 4\n")); if (res > -1) { @@ -1432,12 +1419,14 @@ iput(new_inode); if (new_is_dir) { PRINTK(("vfat_rename 7\n")); - res = vfat_rmdirx(new_dir,new_name,new_len); + res = vfat_rmdirx(new_dir,new_dentry->d_name.name, + new_dentry->d_name.len); PRINTK(("vfat_rename 8\n")); if (res < 0) goto rename_done; } else { PRINTK(("vfat_rename 9\n")); - res = vfat_unlinkx(new_dir,new_name,new_len,1); + res = vfat_unlinkx(new_dir,new_dentry->d_name.name, + new_dentry->d_name.len,1); PRINTK(("vfat_rename 10\n")); if (res < 0) goto rename_done; } @@ -1445,7 +1434,8 @@ PRINTK(("vfat_rename 11\n")); fat_lock_creation(); locked = 1; - res = vfat_find(new_dir,new_name,new_len,1,1,is_dir,&sinfo); + res = vfat_find(new_dir,new_dentry->d_name.name, + new_dentry->d_name.len,1,1,is_dir,&sinfo); PRINTK(("vfat_rename 12\n")); if (res < 0) goto rename_done; @@ -1524,6 +1514,8 @@ } if (res > 0) res = 0; + d_instantiate(new_dentry,new_inode); + d_delete(old_dentry); rename_done: if (locked) @@ -1532,10 +1524,6 @@ fat_brelse(sb, old_bh); if (new_bh) fat_brelse(sb, new_bh); - if (old_inode) - iput(old_inode); - iput(old_dir); - iput(new_dir); return res; } @@ -1554,6 +1542,7 @@ NULL, /* mknod */ vfat_rename, /* rename */ NULL, /* readlink */ + NULL, /* followlink */ NULL, /* readpage */ NULL, /* writepage */ fat_bmap, /* bmap */
| |