From: Andy P. <at...@us...> - 2002-04-09 15:08:17
|
Update of /cvsroot/linux-vax/kernel-2.4/fs/umsdos In directory usw-pr-cvs1:/tmp/cvs-serv32005/umsdos Modified Files: README-WIP.txt dir.c emd.c inode.c ioctl.c namei.c rdir.c Log Message: synch 2.4.15 commit 14 Index: README-WIP.txt =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/umsdos/README-WIP.txt,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- README-WIP.txt 14 Jan 2001 16:27:24 -0000 1.1.1.1 +++ README-WIP.txt 9 Apr 2002 13:30:19 -0000 1.2 @@ -5,18 +5,11 @@ There is no warning any more. Both read-only and read-write stuff is fixed, both in msdos-compatibile mode, and in umsdos EMD mode, and it seems stable. -There are still few hardlink nuisances, but those are not fatal. - -I'd call it pre-release, and ask for as many people as possible to -come and test it! See notes below for some more information, or if -you are trying to use UMSDOS as root partition. Userland NOTE: new umsdos_progs (umssync, umssetup, udosctl & friends) that -will compile and work on 2.2.x kernels and glibc based systems may be found -at http://cvs.linux.hr/ - -Also look at the quick-hack "homepage" for umsdos filesystem at -http://www.voyager.hr/~mnalis/umsdos +will compile and work on 2.2.x+ kernels and glibc based systems, as well as +kernel patches and other umsdos related information may be found at +http://linux.voyager.hr/umsdos/ Information below is getting outdated slowly -- I'll fix it one day when I get enough time - there are more important things to fix right now. @@ -24,7 +17,7 @@ Legend: those lines marked with '+' on the beggining of line indicates it passed all of my tests, and performed perfect in all of them. -Current status (990202) - UMSDOS 0.85: +Current status (010125) - UMSDOS 0.86j: (1) pure MSDOS (no --linux-.--- EMD file): @@ -35,7 +28,7 @@ WRITE: + creat file - works -+ delete file - works ++ unlink file - works + write file - works + rename file (same dir) - works + rename file (dif. dir) - works @@ -66,21 +59,22 @@ WRITE: + create symlink - works -- create hardlink - works ++ create hardlink - works + create file - works + create special file - works + write to file - works + rename file (same dir) - works + rename file (dif. dir) - works -- rename hardlink (same dir) - -- rename hardlink (dif. dir) - ++ rename hardlink (same dir) - works +- rename hardlink (dif. dir) - works, but see notes below. + rename symlink (same dir) - works + rename symlink (dif. dir) - works + rename dir (same dir) - works + rename dir (dif. dir) - works -+ delete file - works ++ unlink file - works + notify_change (chown,perms) - works -+ delete hardlink - works ++ notify_change for hardlinks - works ++ unlink hardlink - works + mkdir - works + rmdir - works + umssyncing (many ioctls) - works @@ -99,24 +93,11 @@ example is specs file about it. Specifically, moving directory which contains hardlinks will break them. -Note: (about pseudoroot) If you are currently trying to use UMSDOS as root -partition (with linux installed in c:\linux) it will boot, but there may be -some problems. Volunteers ready to test pseudoroot are needed (preferably -ones with working backups or unimportant data). For example, '/DOS' pseudo -directory is only partially re-implemented and buggy. It works most of the -time, though. Update: should work ok in 0.84, although it still does not -work correctly in combination with initrd featere. Working on this! - Note: (about creating hardlinks in pseudoroot mode) - hardlinks created in pseudoroot mode are now again compatibile with 'normal' hardlinks, and vice versa. Thanks to Sorin Iordachescu <so...@ro...> for providing fix. - -Warning: (about hardlinks) - modifying hardlinks (esp. if they are in -different directories) are currently somewhat broken, I'm working on it. -Problem seems to be that code uses and updates EMD of directory where 'real -hardlink' is stored, not EMD of directory where our pseudo-hardlink is -located! I'm looking for ideas how to work around this in clean way, since -without it modifying hardlinks in any but most simple ways is broken! +See http://linux.voyager.hr/umsdos/hlbug.html for more info and upgrade +procedure if you used broken versions... ------------------------------------------------------------------------------ @@ -130,6 +111,4 @@ I'm unfortunately somewhat out of time to read linux-kernel@vger, but I do check for messages having "UMSDOS" in the subject, and read them. I might miss some in all that volume, though. I should reply to any direct e-mail -in few days. If I don't, probably I never got your message. You can try -mn...@vo...; however mn...@ja... is preferable. - +in few days. If I don't, probably I never got your message. Index: dir.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/umsdos/dir.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- dir.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ dir.c 9 Apr 2002 13:30:19 -0000 1.2 @@ -67,7 +67,7 @@ static int umsdos_dir_once ( void *buf, const char *name, int len, - off_t offset, + loff_t offset, ino_t ino, unsigned type) { @@ -651,13 +651,13 @@ old_root = dget(current->fs->root); read_unlock(¤t->fs->lock); spin_lock(&dcache_lock); - path = __d_path(dentry, NULL, dentry->d_sb->s_root, NULL, buffer, len); + path = __d_path(dentry, current->fs->rootmnt, dentry->d_sb->s_root, current->fs->rootmnt, buffer, len); /* FIXME: current->fs->rootmnt */ spin_unlock(&dcache_lock); if (*path == '/') path++; /* skip leading '/' */ - if (old_root->d_inode == pseudo_root) + if (current->fs->root->d_inode == pseudo_root) { *(path-1) = '/'; path -= (UMSDOS_PSDROOT_LEN+1); Index: emd.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/umsdos/emd.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- emd.c 14 Jan 2001 16:27:14 -0000 1.1.1.1 +++ emd.c 9 Apr 2002 13:30:19 -0000 1.2 @@ -16,10 +16,23 @@ #include <linux/umsdos_fs.h> #include <linux/dcache.h> #include <linux/pagemap.h> +#include <linux/delay.h> -#include <asm/delay.h> +void put_entry (struct umsdos_dirent *p, struct umsdos_dirent *q) +{ + p->name_len = q->name_len; + p->flags = q->flags; + p->nlink = cpu_to_le16(q->nlink); + p->uid = cpu_to_le16(q->uid); + p->gid = cpu_to_le16(q->gid); + p->atime = cpu_to_le32(q->atime); + p->mtime = cpu_to_le32(q->mtime); + p->ctime = cpu_to_le32(q->ctime); + p->rdev = cpu_to_le16(q->rdev); + p->mode = cpu_to_le16(q->mode); +} -static void copy_entry(struct umsdos_dirent *p, struct umsdos_dirent *q) +static void get_entry(struct umsdos_dirent *p, struct umsdos_dirent *q) { p->name_len = q->name_len; p->name[p->name_len]='\0'; @@ -137,6 +150,7 @@ printk (KERN_WARNING "Ignoring invalid EMD entry with size %d\n", entry->name_len); p->name_len = 0; ret = -ENAMETOOLONG; /* notify umssync(8) code that something is wrong */ + /* FIXME: does not work if we did 'ls -l' before 'udosctl uls' ?! */ } recsize = umsdos_evalrecsize(p->name_len); @@ -164,7 +178,7 @@ page_cache_release(page2); } else memcpy(entry->spare,p->spare,((char*)p+recsize)-p->spare); - copy_entry(entry, p); + get_entry(entry, p); kunmap(page); page_cache_release(page); *pos += recsize; @@ -250,20 +264,11 @@ offs+info->recsize-PAGE_CACHE_SIZE); if (ret) goto out_unlock3; - p->name_len = entry->name_len; - p->flags = entry->flags; - p->nlink = cpu_to_le16(entry->nlink); - p->uid = cpu_to_le16(entry->uid); - p->gid = cpu_to_le16(entry->gid); - p->atime = cpu_to_le32(entry->atime); - p->mtime = cpu_to_le32(entry->mtime); - p->ctime = cpu_to_le32(entry->ctime); - p->rdev = cpu_to_le16(entry->rdev); - p->mode = cpu_to_le16(entry->mode); - memcpy(p->name,entry->name, + put_entry (p, entry); + memcpy(p->spare,entry->spare, (char *)(page_address(page) + PAGE_CACHE_SIZE) - p->spare); memcpy(page_address(page2), - entry->spare+PAGE_CACHE_SIZE-offs, + ((char*)entry)+PAGE_CACHE_SIZE-offs, offs+info->recsize-PAGE_CACHE_SIZE); ret = mapping->a_ops->commit_write(NULL,page2,0, offs+info->recsize-PAGE_CACHE_SIZE); @@ -280,16 +285,7 @@ offs + info->recsize); if (ret) goto out_unlock; - p->name_len = entry->name_len; - p->flags = entry->flags; - p->nlink = cpu_to_le16(entry->nlink); - p->uid = cpu_to_le16(entry->uid); - p->gid = cpu_to_le16(entry->gid); - p->atime = cpu_to_le32(entry->atime); - p->mtime = cpu_to_le32(entry->mtime); - p->ctime = cpu_to_le32(entry->ctime); - p->rdev = cpu_to_le16(entry->rdev); - p->mode = cpu_to_le16(entry->mode); + put_entry (p, entry); memcpy(p->spare,entry->spare,((char*)p+info->recsize)-p->spare); ret = mapping->a_ops->commit_write(NULL,page,offs, offs + info->recsize); @@ -464,7 +460,7 @@ goto skip_it; info->f_pos = pos; - copy_entry(entry, rentry); + get_entry(entry, rentry); ret = 0; break; skip_it: Index: inode.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/umsdos/inode.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- inode.c 14 Jan 2001 16:27:11 -0000 1.1.1.1 +++ inode.c 9 Apr 2002 13:30:19 -0000 1.2 @@ -38,7 +38,7 @@ ,atomic_read(&inode->i_count))); if (inode == pseudo_root) { - printk (KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, atomic_read(&inode->i_count)); + Printk ((KERN_ERR "Umsdos: debug: releasing pseudo_root - ino=%lu count=%d\n", inode->i_ino, atomic_read(&inode->i_count))); } if (atomic_read(&inode->i_count) == 1) @@ -49,7 +49,7 @@ void UMSDOS_put_super (struct super_block *sb) { Printk ((KERN_DEBUG "UMSDOS_put_super: entering\n")); - if (saved_root) { + if (saved_root && pseudo_root && sb->s_dev == ROOT_DEV) { shrink_dcache_parent(saved_root); dput(saved_root); saved_root = NULL; @@ -153,16 +153,56 @@ } -int umsdos_notify_change_locked(struct dentry *, struct iattr *); /* * lock the parent dir before starting ... + * also handles hardlink converting */ int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr) { - struct inode *dir = dentry->d_parent->d_inode; - struct inode *inode = dentry->d_inode; + struct inode *dir, *inode; + struct umsdos_info info; + struct dentry *temp, *old_dentry = NULL; int ret; + ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, + &info); + if (ret) + goto out; + ret = umsdos_findentry (dentry->d_parent, &info, 0); + if (ret) { +printk("UMSDOS_notify_change: %s/%s not in EMD, ret=%d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, ret); + goto out; + } + + if (info.entry.flags & UMSDOS_HLINK) { + /* + * In order to get the correct (real) inode, we just drop + * the original dentry. + */ + d_drop(dentry); +Printk(("UMSDOS_notify_change: hard link %s/%s, fake=%s\n", +dentry->d_parent->d_name.name, dentry->d_name.name, info.fake.fname)); + + /* Do a real lookup to get the short name dentry */ + temp = umsdos_covered(dentry->d_parent, info.fake.fname, + info.fake.len); + ret = PTR_ERR(temp); + if (IS_ERR(temp)) + goto out; + + /* now resolve the link ... */ + temp = umsdos_solve_hlink(temp); + ret = PTR_ERR(temp); + if (IS_ERR(temp)) + goto out; + old_dentry = dentry; + dentry = temp; /* so umsdos_notify_change_locked will operate on that */ + } + + dir = dentry->d_parent->d_inode; + inode = dentry->d_inode; + ret = inode_change_ok (inode, attr); if (ret) goto out; @@ -171,11 +211,14 @@ ret = umsdos_notify_change_locked(dentry, attr); up(&dir->i_sem); if (ret == 0) - inode_setattr (inode, attr); + ret = inode_setattr (inode, attr); out: + if (old_dentry) + dput (dentry); /* if we had to use fake dentry for hardlinks, dput() it now */ return ret; } + /* * Must be called with the parent lock held. */ @@ -316,16 +359,16 @@ struct super_block *res; struct dentry *new_root; - MSDOS_SB(sb)->options.isvfat = 0; /* * Call msdos-fs to mount the disk. * Note: this returns res == sb or NULL */ res = msdos_read_super (sb, data, silent); + if (!res) goto out_fail; - printk (KERN_INFO "UMSDOS 0.86i " + printk (KERN_INFO "UMSDOS 0.86k " "(compatibility level %d.%d, fast msdos)\n", UMSDOS_VERSION, UMSDOS_RELEASE); @@ -334,6 +377,7 @@ /* install our dentry operations ... */ sb->s_root->d_op = &umsdos_dentry_operations; + umsdos_patch_dentry_inode(sb->s_root, 0); /* Check whether to change to the /linux root */ @@ -345,10 +389,9 @@ printk("umsdos_read_super: pseudo-root wrong ops!\n"); pseudo_root = new_root->d_inode; - saved_root = sb->s_root; - sb->s_root = new_root; printk(KERN_INFO "UMSDOS: changed to alternate root\n"); + dget (sb->s_root); sb->s_root = dget(new_root); } return sb; @@ -378,21 +421,23 @@ * lookup_dentry needs a (so far non-existent) root. */ printk(KERN_INFO "check_pseudo_root: mounted as root\n"); - root = lookup_one(UMSDOS_PSDROOT_NAME, sb->s_root); + root = lookup_one_len(UMSDOS_PSDROOT_NAME, sb->s_root,UMSDOS_PSDROOT_LEN); if (IS_ERR(root)) goto out_noroot; + if (!root->d_inode || !S_ISDIR(root->d_inode->i_mode)) goto out_dput; - printk(KERN_INFO "check_pseudo_root: found %s/%s\n", root->d_parent->d_name.name, root->d_name.name); +printk(KERN_INFO "check_pseudo_root: found %s/%s\n", +root->d_parent->d_name.name, root->d_name.name); /* look for /sbin/init */ - sbin = lookup_one("sbin", root); + sbin = lookup_one_len("sbin", root, 4); if (IS_ERR(sbin)) goto out_dput; if (!sbin->d_inode || !S_ISDIR(sbin->d_inode->i_mode)) goto out_dput_sbin; - init = lookup_one("init", sbin); + init = lookup_one_len("init", sbin, 4); if (IS_ERR(init)) goto out_dput_sbin; if (!init->d_inode) @@ -430,3 +475,4 @@ module_init(init_umsdos_fs) module_exit(exit_umsdos_fs) +MODULE_LICENSE("GPL"); Index: ioctl.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/umsdos/ioctl.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- ioctl.c 14 Jan 2001 16:27:15 -0000 1.1.1.1 +++ ioctl.c 9 Apr 2002 13:30:19 -0000 1.2 @@ -28,7 +28,7 @@ void *buf, const char *name, int name_len, - off_t offset, + loff_t offset, ino_t ino, unsigned type) { @@ -95,7 +95,7 @@ && cmd != UMSDOS_DOS_SETUP) return fat_dir_ioctl (dir, filp, cmd, data_ptr); - /* #Specification: ioctl / acces + /* #Specification: ioctl / access * Only root (effective id) is allowed to do IOCTL on directory * in UMSDOS. EPERM is returned for other user. */ Index: namei.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/umsdos/namei.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- namei.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ namei.c 9 Apr 2002 13:30:19 -0000 1.2 @@ -405,8 +405,15 @@ goto out_unlock; /* make sure it's the same inode! */ ret = -ENOENT; - if (old->d_inode != old_inode) - goto out_dput; + /* + * note: for hardlinks they will be different! + * old_inode will contain inode of .LINKxxx file containing data, and + * old->d_inode will contain inode of file containing path to .LINKxxx file + */ + if (!(old_info.entry.flags & UMSDOS_HLINK)) { + if (old->d_inode != old_inode) + goto out_dput; + } new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname, new_info.fake.len); @@ -491,7 +498,7 @@ goto out; } - len = strlen (symname); + len = strlen (symname) + 1; ret = block_symlink(dentry->d_inode, symname, len); if (ret < 0) goto out_unlink; @@ -531,7 +538,7 @@ struct umsdos_info hid_info; #ifdef UMSDOS_DEBUG_VERBOSE -printk("umsdos_link: new %s%s -> %s/%s\n", +printk("umsdos_link: new %s/%s -> %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name, olddentry->d_parent->d_name.name, olddentry->d_name.name); #endif @@ -698,17 +705,36 @@ if (ret == 0) { struct iattr newattrs; + /* Do a real lookup to get the short name dentry */ + temp = umsdos_covered(olddentry->d_parent, + old_info.fake.fname, + old_info.fake.len); + ret = PTR_ERR(temp); + if (IS_ERR(temp)) + goto out_unlock2; + + /* now resolve the link ... */ + temp = umsdos_solve_hlink(temp); + ret = PTR_ERR(temp); + if (IS_ERR(temp)) + goto out_unlock2; + + #ifdef UMSDOS_PARANOIA if (!oldinode->u.umsdos_i.i_is_hlink) printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n", olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino); #endif - oldinode->i_nlink++; + temp->d_inode->i_nlink++; Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n", olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino, oldinode->i_nlink)); newattrs.ia_valid = 0; - ret = umsdos_notify_change_locked(olddentry, &newattrs); + ret = umsdos_notify_change_locked(temp, &newattrs); + if (ret == 0) + mark_inode_dirty(temp->d_inode); + dput(temp); +out_unlock2: if (ret == 0) mark_inode_dirty(olddentry->d_inode); } Index: rdir.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/fs/umsdos/rdir.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- rdir.c 25 Feb 2001 23:14:46 -0000 1.1.1.2 +++ rdir.c 9 Apr 2002 13:30:19 -0000 1.2 @@ -32,7 +32,7 @@ static int rdir_filldir ( void *buf, const char *name, int name_len, - off_t offset, + loff_t offset, ino_t ino, unsigned int d_type) { @@ -111,6 +111,9 @@ */ Printk ((KERN_DEBUG "umsdos_rlookup_x: patch_dentry_inode %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name)); +/* only patch if needed (because we get called even for lookup + (not only rlookup) stuff sometimes, like in umsdos_covered() */ + if (dentry->d_inode->u.umsdos_i.i_patched == 0) umsdos_patch_dentry_inode(dentry, 0); } |