X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fbefs%2Flinuxvfs.c;h=de5bb280a82895939c6cd9cce29005b5030689ab;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=05e6005c520253c6115ad2495383c3e45df4e5f8;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 05e6005c5..de5bb280a 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -14,6 +14,7 @@ #include #include #include +#include #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;