static int ocfs2_fast_symlink_readpage(struct file *unused, struct page *page) { 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; if (status < 0) { mlog_errno(status); return status; } fe = (struct ocfs2_dinode *) bh->b_data; link = (char *) fe->id2.i_symlink; /* 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); return 0; }
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; mlog_entry_void(); 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); nd_set_link(nd, link); bail: brelse(bh); mlog_exit(status); return status ? ERR_PTR(status) : link; }