patch-2.3.32 linux/fs/affs/symlink.c

Next file: linux/fs/autofs/symlink.c
Previous file: linux/fs/Config.in
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.31/linux/fs/affs/symlink.c linux/fs/affs/symlink.c
@@ -9,101 +9,19 @@
  */
 
 #include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/malloc.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/affs_fs.h>
 #include <linux/amigaffs.h>
-#include <asm/uaccess.h>
+#include <linux/pagemap.h>
 
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-
-static int		 affs_readlink(struct dentry *, char *, int);
-static struct dentry	*affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int);
-
-struct inode_operations affs_symlink_inode_operations = {
-	NULL,			/* no file-operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	affs_readlink,		/* readlink */
-	affs_follow_link,	/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
-};
-
-static int
-affs_readlink(struct dentry *dentry, char *buffer, int buflen)
+static int affs_symlink_readpage(struct dentry *dentry, struct page *page)
 {
+	struct buffer_head *bh;
 	struct inode *inode = dentry->d_inode;
-	struct buffer_head	*bh;
-	struct slink_front	*lf;
-	int			 i, j;
-	char			 c;
-	char			 lc;
-	char			*pf;
-
-	pr_debug("AFFS: readlink(ino=%lu,buflen=%d)\n",inode->i_ino,buflen);
-
-	bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
-	if (!bh) {
-		affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
-				inode->i_ino);
-		return -EIO;
-	}
-	lf = (struct slink_front *)bh->b_data;
-	lc = 0;
-	i  = 0;
-	j  = 0;
-	pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
-	
-	if (strchr(lf->symname,':')) {		/* Handle assign or volume name */
-		while (i < buflen && (c = pf[i])) {
-			put_user(c,buffer++);
-			i++;
-		}
-		while (i < buflen && (c = lf->symname[j]) != ':') {
-			put_user(c,buffer++);
-			i++, j++;
-		}
-		if (i < buflen) {
-			put_user('/',buffer++);
-			i++, j++;
-		}
-		lc = '/';
-	}
-	while (i < buflen && (c = lf->symname[j])) {
-		if (c == '/' && lc == '/' && (i + 3 < buflen)) {	/* parent dir */
-			put_user('.',buffer++);
-			put_user('.',buffer++);
-			i += 2;
-		}
-		put_user(c,buffer++);
-		lc = c;
-		i++, j++;
-	}
-	affs_brelse(bh);
-	return i;
-}
-
-static struct dentry *
-affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
-{
-	struct inode *inode = dentry->d_inode;
-	struct buffer_head	*bh;
-	struct slink_front	*lf;
-	char			*buffer;
+	char *link = (char*)kmap(page);
+	struct slink_front *lf;
+	int err;
 	int			 i, j;
 	char			 c;
 	char			 lc;
@@ -111,47 +29,50 @@
 
 	pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
 
-	if (!(buffer = kmalloc(1024,GFP_KERNEL))) {
-		dput(base);
-		return ERR_PTR(-ENOSPC);
-	}
+	err = -EIO;
 	bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
-	if (!bh) {
-		affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
-				inode->i_ino);
-		kfree(buffer);
-		dput(base);
-		return ERR_PTR(-EIO);
-	}
+	if (!bh)
+		goto fail;
 	i  = 0;
 	j  = 0;
 	lf = (struct slink_front *)bh->b_data;
 	lc = 0;
 	pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
 
-	if (strchr(lf->symname,':')) {		/* Handle assign or volume name */
+	if (strchr(lf->symname,':')) {	/* Handle assign or volume name */
 		while (i < 1023 && (c = pf[i]))
-			buffer[i++] = c;
+			link[i++] = c;
 		while (i < 1023 && lf->symname[j] != ':')
-			buffer[i++] = lf->symname[j++];
+			link[i++] = lf->symname[j++];
 		if (i < 1023)
-			 buffer[i++] = '/';
+			link[i++] = '/';
 		j++;
 		lc = '/';
 	}
 	while (i < 1023 && (c = lf->symname[j])) {
 		if (c == '/' && lc == '/' && i < 1020) {	/* parent dir */
-			buffer[i++] = '.';
-			buffer[i++] = '.';
+			link[i++] = '.';
+			link[i++] = '.';
 		}
-		buffer[i++] = c;
+		link[i++] = c;
 		lc = c;
 		j++;
 	}
-	buffer[i] = '\0';
+	link[i] = '\0';
 	affs_brelse(bh);
-	base = lookup_dentry(buffer,base,follow);
-	kfree(buffer);
-	return base;
+	SetPageUptodate(page);
+	kunmap(page);
+	UnlockPage(page);
+	return 0;
+fail:
+	SetPageError(page);
+	kunmap(page);
+	UnlockPage(page);
+	return err;
 }
 
+struct inode_operations affs_symlink_inode_operations = {
+	readlink:	page_readlink,
+	follow_link:	page_follow_link,
+	readpage:	affs_symlink_readpage,
+};

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