patch-2.3.32 linux/fs/efs/symlink.c
Next file: linux/fs/ext2/ialloc.c
Previous file: linux/fs/coda/symlink.c
Back to the patch index
Back to the overall index
- Lines: 133
- Date:
Mon Dec 13 16:02:45 1999
- Orig file:
v2.3.31/linux/fs/efs/symlink.c
- Orig date:
Tue Dec 7 09:32:47 1999
diff -u --recursive --new-file v2.3.31/linux/fs/efs/symlink.c linux/fs/efs/symlink.c
@@ -7,97 +7,49 @@
*/
#include <linux/string.h>
-#include <linux/malloc.h>
#include <linux/efs_fs.h>
+#include <linux/pagemap.h>
-static int efs_readlink(struct dentry *, char *, int);
-static struct dentry * efs_follow_link(struct dentry *, struct dentry *, unsigned int);
-
-struct inode_operations efs_symlink_inode_operations = {
- NULL, /* no symlink file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- efs_readlink, /* readlink */
- efs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
-};
-
-static char *efs_linktarget(struct inode *in, int *len) {
- char *name;
+static int efs_symlink_readpage(struct dentry *dentry, struct page *page)
+{
+ char *link = (char*)kmap(page);
struct buffer_head * bh;
- efs_block_t size = in->i_size;
-
- if (size > 2 * EFS_BLOCKSIZE) {
- printk(KERN_ERR "EFS: linktarget(): name too long: %lu\n", in->i_size);
- return NULL;
- }
-
- if (!(name = kmalloc(size + 1, GFP_KERNEL)))
- return NULL;
+ struct inode * inode = dentry->d_inode;
+ efs_block_t size = inode->i_size;
+ int err;
+
+ err = -ENAMETOOLONG;
+ if (size > 2 * EFS_BLOCKSIZE)
+ goto fail;
/* read first 512 bytes of link target */
- bh = bread(in->i_dev, efs_bmap(in, 0), EFS_BLOCKSIZE);
- if (!bh) {
- kfree(name);
- printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 0));
- return NULL;
- }
-
- memcpy(name, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
+ err = -EIO;
+ bh = bread(inode->i_dev, efs_bmap(inode, 0), EFS_BLOCKSIZE);
+ if (!bh)
+ goto fail;
+ memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
brelse(bh);
-
if (size > EFS_BLOCKSIZE) {
- bh = bread(in->i_dev, efs_bmap(in, 1), EFS_BLOCKSIZE);
- if (!bh) {
- kfree(name);
- printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 1));
- return NULL;
- }
- memcpy(name + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
+ bh = bread(inode->i_dev, efs_bmap(inode, 1), EFS_BLOCKSIZE);
+ if (!bh)
+ goto fail;
+ memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
brelse(bh);
}
-
- name[size] = (char) 0;
- if (len) *len = size;
-
- return name;
-}
-
-static struct dentry *efs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) {
- char *name;
- struct inode *inode = dentry->d_inode;
-
- if (!(name = efs_linktarget(inode, NULL))) {
- dput(base);
- return ERR_PTR(-ELOOP);
- }
- base = lookup_dentry(name, base, follow);
- kfree(name);
-
- return base;
-}
-
-static int efs_readlink(struct dentry * dir, char * buf, int bufsiz) {
- int rc;
- char *name;
- struct inode *inode = dir->d_inode;
-
- if (!(name = efs_linktarget(inode, &bufsiz))) return 0;
- rc = copy_to_user(buf, name, bufsiz) ? -EFAULT : bufsiz;
- kfree(name);
-
- return rc;
+ link[size] = '\0';
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return err;
}
+struct inode_operations efs_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: efs_symlink_readpage
+};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)