Commit ea022dfb authored by Al Viro's avatar Al Viro

ocfs: simplify symlink handling

seeing that "fast" symlinks still get allocation + copy, we might as
well simply switch them to pagecache-based variant of ->follow_link();
just need an appropriate ->readpage() for them...
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 408bd629
...@@ -273,11 +273,13 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, ...@@ -273,11 +273,13 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
inode->i_gid = le32_to_cpu(fe->i_gid); inode->i_gid = le32_to_cpu(fe->i_gid);
/* Fast symlinks will have i_size but no allocated clusters. */ /* Fast symlinks will have i_size but no allocated clusters. */
if (S_ISLNK(inode->i_mode) && !fe->i_clusters) if (S_ISLNK(inode->i_mode) && !fe->i_clusters) {
inode->i_blocks = 0; inode->i_blocks = 0;
else inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops;
} else {
inode->i_blocks = ocfs2_inode_sector_count(inode); inode->i_blocks = ocfs2_inode_sector_count(inode);
inode->i_mapping->a_ops = &ocfs2_aops; inode->i_mapping->a_ops = &ocfs2_aops;
}
inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);
inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);
...@@ -331,9 +333,6 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, ...@@ -331,9 +333,6 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
OCFS2_I(inode)->ip_dir_lock_gen = 1; OCFS2_I(inode)->ip_dir_lock_gen = 1;
break; break;
case S_IFLNK: case S_IFLNK:
if (ocfs2_inode_is_fast_symlink(inode))
inode->i_op = &ocfs2_fast_symlink_inode_operations;
else
inode->i_op = &ocfs2_symlink_inode_operations; inode->i_op = &ocfs2_symlink_inode_operations;
i_size_write(inode, le64_to_cpu(fe->i_size)); i_size_write(inode, le64_to_cpu(fe->i_size));
break; break;
......
...@@ -1724,15 +1724,16 @@ static int ocfs2_symlink(struct inode *dir, ...@@ -1724,15 +1724,16 @@ static int ocfs2_symlink(struct inode *dir,
fe = (struct ocfs2_dinode *) new_fe_bh->b_data; fe = (struct ocfs2_dinode *) new_fe_bh->b_data;
inode->i_rdev = 0; inode->i_rdev = 0;
newsize = l - 1; newsize = l - 1;
inode->i_op = &ocfs2_symlink_inode_operations;
if (l > ocfs2_fast_symlink_chars(sb)) { if (l > ocfs2_fast_symlink_chars(sb)) {
u32 offset = 0; u32 offset = 0;
inode->i_op = &ocfs2_symlink_inode_operations;
status = dquot_alloc_space_nodirty(inode, status = dquot_alloc_space_nodirty(inode,
ocfs2_clusters_to_bytes(osb->sb, 1)); ocfs2_clusters_to_bytes(osb->sb, 1));
if (status) if (status)
goto bail; goto bail;
did_quota = 1; did_quota = 1;
inode->i_mapping->a_ops = &ocfs2_aops;
status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0, status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
new_fe_bh, new_fe_bh,
handle, data_ac, NULL, handle, data_ac, NULL,
...@@ -1750,7 +1751,7 @@ static int ocfs2_symlink(struct inode *dir, ...@@ -1750,7 +1751,7 @@ static int ocfs2_symlink(struct inode *dir,
i_size_write(inode, newsize); i_size_write(inode, newsize);
inode->i_blocks = ocfs2_inode_sector_count(inode); inode->i_blocks = ocfs2_inode_sector_count(inode);
} else { } else {
inode->i_op = &ocfs2_fast_symlink_inode_operations; inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops;
memcpy((char *) fe->id2.i_symlink, symname, l); memcpy((char *) fe->id2.i_symlink, symname, l);
i_size_write(inode, newsize); i_size_write(inode, newsize);
inode->i_blocks = 0; inode->i_blocks = 0;
......
...@@ -54,101 +54,40 @@ ...@@ -54,101 +54,40 @@
#include "buffer_head_io.h" #include "buffer_head_io.h"
static char *ocfs2_fast_symlink_getlink(struct inode *inode, static int ocfs2_fast_symlink_readpage(struct file *unused, struct page *page)
struct buffer_head **bh)
{ {
int status; struct inode *inode = page->mapping->host;
char *link = NULL; struct buffer_head *bh;
int status = ocfs2_read_inode_block(inode, &bh);
struct ocfs2_dinode *fe; struct ocfs2_dinode *fe;
const char *link;
void *kaddr;
size_t len;
status = ocfs2_read_inode_block(inode, bh);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
link = ERR_PTR(status); return status;
goto bail;
} }
fe = (struct ocfs2_dinode *) (*bh)->b_data; fe = (struct ocfs2_dinode *) bh->b_data;
link = (char *) fe->id2.i_symlink; link = (char *) fe->id2.i_symlink;
bail: /* will be less than a page size */
len = strnlen(link, ocfs2_fast_symlink_chars(inode->i_sb));
return link; kaddr = kmap_atomic(page);
} memcpy(kaddr, link, len + 1);
kunmap_atomic(kaddr);
static int ocfs2_readlink(struct dentry *dentry, SetPageUptodate(page);
char __user *buffer, unlock_page(page);
int buflen)
{
int ret;
char *link;
struct buffer_head *bh = NULL;
struct inode *inode = dentry->d_inode;
link = ocfs2_fast_symlink_getlink(inode, &bh);
if (IS_ERR(link)) {
ret = PTR_ERR(link);
goto out;
}
/*
* Without vfsmount we can't update atime now,
* but we will update atime here ultimately.
*/
ret = vfs_readlink(dentry, buffer, buflen, link);
brelse(bh);
out:
if (ret < 0)
mlog_errno(ret);
return ret;
}
static void *ocfs2_fast_follow_link(struct dentry *dentry,
struct nameidata *nd)
{
int status = 0;
int len;
char *target, *link = ERR_PTR(-ENOMEM);
struct inode *inode = dentry->d_inode;
struct buffer_head *bh = NULL;
BUG_ON(!ocfs2_inode_is_fast_symlink(inode));
target = ocfs2_fast_symlink_getlink(inode, &bh);
if (IS_ERR(target)) {
status = PTR_ERR(target);
mlog_errno(status);
goto bail;
}
/* Fast symlinks can't be large */
len = strnlen(target, ocfs2_fast_symlink_chars(inode->i_sb));
link = kzalloc(len + 1, GFP_NOFS);
if (!link) {
status = -ENOMEM;
mlog_errno(status);
goto bail;
}
memcpy(link, target, len);
bail:
nd_set_link(nd, status ? ERR_PTR(status) : link);
brelse(bh); brelse(bh);
return 0;
if (status)
mlog_errno(status);
return NULL;
} }
static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) const struct address_space_operations ocfs2_fast_symlink_aops = {
{ .readpage = ocfs2_fast_symlink_readpage,
char *link = nd_get_link(nd); };
if (!IS_ERR(link))
kfree(link);
}
const struct inode_operations ocfs2_symlink_inode_operations = { const struct inode_operations ocfs2_symlink_inode_operations = {
.readlink = page_readlink, .readlink = generic_readlink,
.follow_link = page_follow_link_light, .follow_link = page_follow_link_light,
.put_link = page_put_link, .put_link = page_put_link,
.getattr = ocfs2_getattr, .getattr = ocfs2_getattr,
...@@ -159,15 +98,3 @@ const struct inode_operations ocfs2_symlink_inode_operations = { ...@@ -159,15 +98,3 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
.removexattr = generic_removexattr, .removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap, .fiemap = ocfs2_fiemap,
}; };
const struct inode_operations ocfs2_fast_symlink_inode_operations = {
.readlink = ocfs2_readlink,
.follow_link = ocfs2_fast_follow_link,
.put_link = ocfs2_fast_put_link,
.getattr = ocfs2_getattr,
.setattr = ocfs2_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ocfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap,
};
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#define OCFS2_SYMLINK_H #define OCFS2_SYMLINK_H
extern const struct inode_operations ocfs2_symlink_inode_operations; extern const struct inode_operations ocfs2_symlink_inode_operations;
extern const struct inode_operations ocfs2_fast_symlink_inode_operations; extern const struct address_space_operations ocfs2_fast_symlink_aops;
/* /*
* Test whether an inode is a fast symlink. * Test whether an inode is a fast symlink.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment