patch-2.4.0-test3 linux/fs/umsdos/dir.c

Next file: linux/fs/umsdos/emd.c
Previous file: linux/fs/ufs/super.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
@@ -16,8 +16,7 @@
 #include <linux/limits.h>
 #include <linux/umsdos_fs.h>
 #include <linux/malloc.h>
-
-#include <asm/uaccess.h>
+#include <linux/pagemap.h>
 
 #define UMSDOS_SPECIAL_DIRFPOS	3
 extern struct dentry *saved_root;
@@ -96,19 +95,17 @@
  */
  
 static int umsdos_readdir_x (struct inode *dir, struct file *filp,
-				void *dirbuf, int internal_read,
-				struct umsdos_dirent *u_entry,
-				int follow_hlink, filldir_t filldir)
+				void *dirbuf, struct umsdos_dirent *u_entry,
+				filldir_t filldir)
 {
 	struct dentry *demd;
 	off_t start_fpos;
 	int ret = 0;
-	struct file new_filp;
+	loff_t pos;
 
 	umsdos_startlookup (dir);
 
-	if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS &&
-	    dir == pseudo_root && !internal_read) {
+	if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS && dir == pseudo_root) {
 
 		/*
 		 * We don't need to simulate this pseudo directory
@@ -164,24 +161,21 @@
 		goto out_dput;
 	}
 
-	/* set up our private filp ... */
-	fill_new_filp(&new_filp, demd);
-	new_filp.f_pos = filp->f_pos;
+	pos = filp->f_pos;
 	start_fpos = filp->f_pos;
 
-	if (new_filp.f_pos <= UMSDOS_SPECIAL_DIRFPOS + 1)
-		new_filp.f_pos = 0;
-Printk (("f_pos %Ld i_size %ld\n", new_filp.f_pos, demd->d_inode->i_size));
+	if (pos <= UMSDOS_SPECIAL_DIRFPOS + 1)
+		pos = 0;
 	ret = 0;
-	while (new_filp.f_pos < demd->d_inode->i_size) {
-		off_t cur_f_pos = new_filp.f_pos;
+	while (pos < demd->d_inode->i_size) {
+		off_t cur_f_pos = pos;
 		struct dentry *dret;
 		struct inode *inode;
 		struct umsdos_dirent entry;
 		struct umsdos_info info;
 
 		ret = -EIO;
-		if (umsdos_emd_dir_readentry (&new_filp, &entry) != 0)
+		if (umsdos_emd_dir_readentry (demd, &pos, &entry) != 0)
 			break;
 		if (entry.name_len == 0)
 			continue;
@@ -218,7 +212,7 @@
 dret->d_parent->d_name.name, info.fake.fname, dret->d_inode->i_ino,
 entry.flags));
 		/* check whether to resolve a hard-link */
-		if ((entry.flags & UMSDOS_HLINK) && follow_hlink &&
+		if ((entry.flags & UMSDOS_HLINK) &&
 		    !inode->u.umsdos_i.i_is_hlink) {
 			dret = umsdos_solve_hlink (dret);
 			ret = PTR_ERR(dret);
@@ -239,11 +233,10 @@
 		 * infinite recursion (/DOS/linux/DOS/linux/...) while
 		 * walking the file system.
 		 */
-		if (inode != pseudo_root &&
-		    (internal_read || !(entry.flags & UMSDOS_HIDDEN))) {
+		if (inode != pseudo_root && !(entry.flags & UMSDOS_HIDDEN)) {
 			if (filldir (dirbuf, entry.name, entry.name_len,
 				 cur_f_pos, inode->i_ino) < 0) {
-				new_filp.f_pos = cur_f_pos;
+				pos = cur_f_pos;
 			}
 Printk(("umsdos_readdir_x: got %s/%s, ino=%ld\n",
 dret->d_parent->d_name.name, dret->d_name.name, inode->i_ino));
@@ -281,7 +274,7 @@
 	 * (see comments at the beginning), we put back
 	 * the special offset.
 	 */
-	filp->f_pos = new_filp.f_pos;
+	filp->f_pos = pos;
 	if (filp->f_pos == 0)
 		filp->f_pos = start_fpos;
 out_dput:
@@ -317,7 +310,7 @@
 		struct umsdos_dirent entry;
 
 		bufk.count = 0;
-		ret = umsdos_readdir_x (dir, filp, &bufk, 0, &entry, 1, 
+		ret = umsdos_readdir_x (dir, filp, &bufk, &entry, 
 					umsdos_dir_once);
 		if (bufk.count == 0)
 			break;
@@ -650,10 +643,15 @@
  */
 char * umsdos_d_path(struct dentry *dentry, char * buffer, int len)
 {
-	struct dentry * old_root = current->fs->root;
+	struct dentry * old_root;
 	char * path;
 
+	read_lock(&current->fs->lock);
+	old_root = dget(current->fs->root);
+	read_unlock(&current->fs->lock);
+	spin_lock(&dcache_lock);
 	path = __d_path(dentry, NULL, dentry->d_sb->s_root, NULL, buffer, len);
+	spin_unlock(&dcache_lock);
 
 	if (*path == '/')
 		path++; /* skip leading '/' */
@@ -664,6 +662,7 @@
 		path -= (UMSDOS_PSDROOT_LEN+1);
 		memcpy(path, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN);
 	}
+	dput(old_root);
 
 	return path;
 }
@@ -685,28 +684,26 @@
 	struct dentry *dentry_dst;
 	char *path, *pt;
 	int len;
-	struct file filp;
+	struct address_space *mapping = hlink->d_inode->i_mapping;
+	struct page *page;
 
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk("umsdos_solve_hlink: following %s/%s\n", 
-hlink->d_parent->d_name.name, hlink->d_name.name);
-#endif
+	page=read_cache_page(mapping,0,(filler_t *)mapping->a_ops->readpage,NULL);
+	dentry_dst=(struct dentry *)page;
+	if (IS_ERR(page))
+		goto out;
+	wait_on_page(page);
+	if (!Page_Uptodate(page))
+		goto async_fail;
 
-	dentry_dst = ERR_PTR (-ENOMEM);
+	dentry_dst = ERR_PTR(-ENOMEM);
 	path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
 	if (path == NULL)
-		goto out;
+		goto out_release;
+	memcpy(path, (char*)kmap(page), hlink->d_inode->i_size);
+	kunmap(page);
+	page_cache_release(page);
 
-	fill_new_filp (&filp, hlink);
-	filp.f_flags = O_RDONLY;
-
-	len = umsdos_file_read_kmem (&filp, path, hlink->d_inode->i_size);
-	if (len != hlink->d_inode->i_size)
-		goto out_noread;
-#ifdef UMSDOS_DEBUG_VERBOSE
-printk ("umsdos_solve_hlink: %s/%s is path %s\n",
-hlink->d_parent->d_name.name, hlink->d_name.name, path);
-#endif
+	len = hlink->d_inode->i_size;
 
 	/* start at root dentry */
 	dentry_dst = dget(base);
@@ -772,17 +769,17 @@
 	} else
 		printk(KERN_WARNING
 			"umsdos_solve_hlink: err=%ld\n", PTR_ERR(dentry_dst));
-
-out_free:
 	kfree (path);
 
 out:
 	dput(hlink);	/* original hlink no longer needed */
 	return dentry_dst;
 
-out_noread:
-	printk(KERN_WARNING "umsdos_solve_hlink: failed reading pseudolink!\n");
-	goto out_free;
+async_fail:
+	dentry_dst = ERR_PTR(-EIO);
+out_release:
+	page_cache_release(page);
+	goto out;
 }	
 
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)