vserver 1.9.3
[linux-2.6.git] / fs / befs / linuxvfs.c
index 05e6005..de5bb28 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/parser.h>
+#include <linux/namei.h>
 
 #include "befs.h"
 #include "btree.h"
@@ -40,8 +41,8 @@ static struct inode *befs_alloc_inode(struct super_block *sb);
 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,
@@ -63,30 +64,31 @@ static const struct super_operations befs_sops = {
 /* 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,
 };
 
 /* 
@@ -325,7 +327,7 @@ befs_read_inode(struct inode *inode)
                   befs_ino->i_inode_num.allocation_group,
                   befs_ino->i_inode_num.start, befs_ino->i_inode_num.len);
 
-       bh = befs_bread_iaddr(sb, befs_ino->i_inode_num);
+       bh = befs_bread(sb, inode->i_ino);
        if (!bh) {
                befs_error(sb, "unable to read inode block - "
                           "inode = %lu", inode->i_ino);
@@ -376,7 +378,7 @@ befs_read_inode(struct inode *inode)
        befs_ino->i_attribute = fsrun_to_cpu(sb, raw_inode->attributes);
        befs_ino->i_flags = fs32_to_cpu(sb, raw_inode->flags);
 
-       if (S_ISLNK(inode->i_mode) && !(inode->i_flags & BEFS_LONG_SYMLINK)) {
+       if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){
                inode->i_size = 0;
                inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE;
                strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink,
@@ -431,7 +433,7 @@ befs_init_inodecache(void)
 {
        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: "
@@ -462,71 +464,40 @@ befs_destroy_inodecache(void)
 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;
 }
 
 /*
@@ -571,7 +542,7 @@ befs_utf2nls(struct super_block *sb, const char *in,
                }
 
                /* convert from Unicode to nls */
-               unilen = nls->uni2char(uni, &result[o], 1);
+               unilen = nls->uni2char(uni, &result[o], in_len - o);
                if (unilen < 0) {
                        goto conv_err;
                }
@@ -584,7 +555,7 @@ befs_utf2nls(struct super_block *sb, const char *in,
        return o;
 
       conv_err:
-       befs_error(sb, "Name using charecter set %s contains a charecter that "
+       befs_error(sb, "Name using character set %s contains a character that "
                   "cannot be converted to unicode.", nls->charset);
        befs_debug(sb, "<--- utf2nls()");
        kfree(result);
@@ -856,6 +827,13 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
        if (befs_check_sb(sb) != BEFS_OK)
                goto unaquire_priv_sbp;
 
+       if( befs_sb->num_blocks > ~((sector_t)0) ) {
+               befs_error(sb, "blocks count: %Lu "
+                       "is larger than the host can use",
+                       befs_sb->num_blocks);
+               goto unaquire_priv_sbp;
+       }
+
        /*
         * set up enough so that it can read an inode
         * Fill in kernel superblock fields from private sb
@@ -879,10 +857,14 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
                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;