#include <linux/buffer_head.h>
#include <linux/vfs.h>
#include <linux/parser.h>
+#include <linux/namei.h>
#include "befs.h"
#include "btree.h"
static void befs_destroy_inode(struct inode *inode);
static int befs_init_inodecache(void);
static void befs_destroy_inodecache(void);
-static int befs_readlink(struct dentry *, char __user *, int);
-static int befs_follow_link(struct dentry *, struct nameidata *nd);
+static int befs_follow_link(struct dentry *, struct nameidata *);
+static void befs_put_link(struct dentry *, struct nameidata *);
static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
char **out, int *out_len);
static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
/* slab cache for befs_inode_info objects */
static kmem_cache_t *befs_inode_cachep;
-struct file_operations befs_dir_operations = {
+static struct file_operations befs_dir_operations = {
.read = generic_read_dir,
.readdir = befs_readdir,
};
-struct inode_operations befs_dir_inode_operations = {
+static struct inode_operations befs_dir_inode_operations = {
.lookup = befs_lookup,
};
-struct file_operations befs_file_operations = {
+static struct file_operations befs_file_operations = {
.llseek = default_llseek,
.read = generic_file_read,
.mmap = generic_file_readonly_mmap,
};
-struct address_space_operations befs_aops = {
+static struct address_space_operations befs_aops = {
.readpage = befs_readpage,
.sync_page = block_sync_page,
.bmap = befs_bmap,
};
static struct inode_operations befs_symlink_inode_operations = {
- .readlink = befs_readlink,
+ .readlink = generic_readlink,
.follow_link = befs_follow_link,
+ .put_link = befs_put_link,
};
/*
{
befs_inode_cachep = kmem_cache_create("befs_inode_cache",
sizeof (struct befs_inode_info),
- 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+ 0, SLAB_RECLAIM_ACCOUNT,
init_once, NULL);
if (befs_inode_cachep == NULL) {
printk(KERN_ERR "befs_init_inodecache: "
static int
befs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
- struct super_block *sb = dentry->d_sb;
befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
char *link;
- int res;
if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
+ struct super_block *sb = dentry->d_sb;
befs_data_stream *data = &befs_ino->i_data.ds;
- befs_off_t linklen = data->size;
+ befs_off_t len = data->size;
befs_debug(sb, "Follow long symlink");
- link = kmalloc(linklen, GFP_NOFS);
- if (link == NULL)
- return -ENOMEM;
-
- if (befs_read_lsymlink(sb, data, link, linklen) != linklen) {
+ link = kmalloc(len, GFP_NOFS);
+ if (!link) {
+ link = ERR_PTR(-ENOMEM);
+ } else if (befs_read_lsymlink(sb, data, link, len) != len) {
kfree(link);
befs_error(sb, "Failed to read entire long symlink");
- return -EIO;
+ link = ERR_PTR(-EIO);
}
-
- res = vfs_follow_link(nd, link);
-
- kfree(link);
} else {
link = befs_ino->i_data.symlink;
- res = vfs_follow_link(nd, link);
}
- return res;
+ nd_set_link(nd, link);
+ return 0;
}
-static int
-befs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+static void befs_put_link(struct dentry *dentry, struct nameidata *nd)
{
- struct super_block *sb = dentry->d_sb;
befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
- char *link;
- int res;
-
if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
- befs_data_stream *data = &befs_ino->i_data.ds;
- befs_off_t linklen = data->size;
-
- befs_debug(sb, "Read long symlink");
-
- link = kmalloc(linklen, GFP_NOFS);
- if (link == NULL)
- return -ENOMEM;
-
- if (befs_read_lsymlink(sb, data, link, linklen) != linklen) {
- kfree(link);
- befs_error(sb, "Failed to read entire long symlink");
- return -EIO;
- }
-
- res = vfs_readlink(dentry, buffer, buflen, link);
-
- kfree(link);
- } else {
- link = befs_ino->i_data.symlink;
- res = vfs_readlink(dentry, buffer, buflen, link);
+ char *p = nd_get_link(nd);
+ if (!IS_ERR(p))
+ kfree(p);
}
-
- return res;
}
/*
befs_sb->nls = load_nls(befs_sb->mount_opts.iocharset);
if (!befs_sb->nls) {
befs_warning(sb, "Cannot load nls %s"
- "loding default nls",
- befs_sb->mount_opts.iocharset);
+ " loading default nls",
+ befs_sb->mount_opts.iocharset);
befs_sb->nls = load_nls_default();
}
+ /* load default nls if none is specified in mount options */
+ } else {
+ befs_debug(sb, "Loading default nls");
+ befs_sb->nls = load_nls_default();
}
return 0;