diff options
Diffstat (limited to 'fs/ocfs2/symlink.c')
| -rw-r--r-- | fs/ocfs2/symlink.c | 137 |
1 files changed, 31 insertions, 106 deletions
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 7134007ba22..66edce7ecfd 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -38,9 +38,8 @@ #include <linux/types.h> #include <linux/slab.h> #include <linux/pagemap.h> -#include <linux/utsname.h> +#include <linux/namei.h> -#define MLOG_MASK_PREFIX ML_NAMEI #include <cluster/masklog.h> #include "ocfs2.h" @@ -50,126 +49,52 @@ #include "inode.h" #include "journal.h" #include "symlink.h" +#include "xattr.h" #include "buffer_head_io.h" -static char *ocfs2_page_getlink(struct dentry * dentry, - struct page **ppage); -static char *ocfs2_fast_symlink_getlink(struct inode *inode, - struct buffer_head **bh); -/* get the link contents into pagecache */ -static char *ocfs2_page_getlink(struct dentry * dentry, - struct page **ppage) +static int ocfs2_fast_symlink_readpage(struct file *unused, struct page *page) { - struct page * page; - struct address_space *mapping = dentry->d_inode->i_mapping; - page = read_mapping_page(mapping, 0, NULL); - if (IS_ERR(page)) - goto sync_fail; - *ppage = page; - return kmap(page); - -sync_fail: - return (char*)page; -} - -static char *ocfs2_fast_symlink_getlink(struct inode *inode, - struct buffer_head **bh) -{ - int status; - char *link = NULL; + struct inode *inode = page->mapping->host; + struct buffer_head *bh = NULL; + int status = ocfs2_read_inode_block(inode, &bh); struct ocfs2_dinode *fe; + const char *link; + void *kaddr; + size_t len; - mlog_entry_void(); - - status = ocfs2_read_block(OCFS2_SB(inode->i_sb), - OCFS2_I(inode)->ip_blkno, - bh, - OCFS2_BH_CACHED, - inode); if (status < 0) { mlog_errno(status); - link = ERR_PTR(status); - goto bail; + return status; } - fe = (struct ocfs2_dinode *) (*bh)->b_data; + fe = (struct ocfs2_dinode *) bh->b_data; link = (char *) fe->id2.i_symlink; -bail: - mlog_exit(status); - - return link; -} - -static int ocfs2_readlink(struct dentry *dentry, - char __user *buffer, - int buflen) -{ - int ret; - char *link; - struct buffer_head *bh = NULL; - struct inode *inode = dentry->d_inode; - - mlog_entry_void(); - - 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); - + /* will be less than a page size */ + len = strnlen(link, ocfs2_fast_symlink_chars(inode->i_sb)); + kaddr = kmap_atomic(page); + memcpy(kaddr, link, len + 1); + kunmap_atomic(kaddr); + SetPageUptodate(page); + unlock_page(page); brelse(bh); -out: - mlog_exit(ret); - return ret; + return 0; } -static void *ocfs2_follow_link(struct dentry *dentry, - struct nameidata *nd) -{ - int status; - char *link; - struct inode *inode = dentry->d_inode; - struct page *page = NULL; - struct buffer_head *bh = NULL; - - if (ocfs2_inode_is_fast_symlink(inode)) - link = ocfs2_fast_symlink_getlink(inode, &bh); - else - link = ocfs2_page_getlink(dentry, &page); - if (IS_ERR(link)) { - status = PTR_ERR(link); - mlog_errno(status); - goto bail; - } - - status = vfs_follow_link(nd, link); - -bail: - if (page) { - kunmap(page); - page_cache_release(page); - } - if (bh) - brelse(bh); - - return ERR_PTR(status); -} +const struct address_space_operations ocfs2_fast_symlink_aops = { + .readpage = ocfs2_fast_symlink_readpage, +}; const struct inode_operations ocfs2_symlink_inode_operations = { - .readlink = page_readlink, - .follow_link = ocfs2_follow_link, - .getattr = ocfs2_getattr, -}; -const struct inode_operations ocfs2_fast_symlink_inode_operations = { - .readlink = ocfs2_readlink, - .follow_link = ocfs2_follow_link, + .readlink = generic_readlink, + .follow_link = page_follow_link_light, + .put_link = page_put_link, .getattr = ocfs2_getattr, + .setattr = ocfs2_setattr, + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .listxattr = ocfs2_listxattr, + .removexattr = generic_removexattr, + .fiemap = ocfs2_fiemap, }; |
