diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-05-03 10:14:29 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-05-29 23:28:40 -0400 |
| commit | ea022dfb3c2a4680483b00eb2fecc9fc4f6091d1 (patch) | |
| tree | a1fc74b921ef4ea32603492f2a500b016e15e377 | |
| parent | 408bd629badbd4353b238ab6f58001529b274d73 (diff) | |
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: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/ocfs2/inode.c | 13 | ||||
| -rw-r--r-- | fs/ocfs2/namei.c | 5 | ||||
| -rw-r--r-- | fs/ocfs2/symlink.c | 115 | ||||
| -rw-r--r-- | fs/ocfs2/symlink.h | 2 |
4 files changed, 31 insertions, 104 deletions
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 735514ca400f..d89e08a81eda 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
| @@ -273,11 +273,13 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
| 273 | inode->i_gid = le32_to_cpu(fe->i_gid); | 273 | inode->i_gid = le32_to_cpu(fe->i_gid); |
| 274 | 274 | ||
| 275 | /* Fast symlinks will have i_size but no allocated clusters. */ | 275 | /* Fast symlinks will have i_size but no allocated clusters. */ |
| 276 | if (S_ISLNK(inode->i_mode) && !fe->i_clusters) | 276 | if (S_ISLNK(inode->i_mode) && !fe->i_clusters) { |
| 277 | inode->i_blocks = 0; | 277 | inode->i_blocks = 0; |
| 278 | else | 278 | inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops; |
| 279 | } else { | ||
| 279 | inode->i_blocks = ocfs2_inode_sector_count(inode); | 280 | inode->i_blocks = ocfs2_inode_sector_count(inode); |
| 280 | inode->i_mapping->a_ops = &ocfs2_aops; | 281 | inode->i_mapping->a_ops = &ocfs2_aops; |
| 282 | } | ||
| 281 | inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); | 283 | inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); |
| 282 | inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); | 284 | inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); |
| 283 | inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); | 285 | inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); |
| @@ -331,10 +333,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
| 331 | OCFS2_I(inode)->ip_dir_lock_gen = 1; | 333 | OCFS2_I(inode)->ip_dir_lock_gen = 1; |
| 332 | break; | 334 | break; |
| 333 | case S_IFLNK: | 335 | case S_IFLNK: |
| 334 | if (ocfs2_inode_is_fast_symlink(inode)) | 336 | inode->i_op = &ocfs2_symlink_inode_operations; |
| 335 | inode->i_op = &ocfs2_fast_symlink_inode_operations; | ||
| 336 | else | ||
| 337 | inode->i_op = &ocfs2_symlink_inode_operations; | ||
| 338 | i_size_write(inode, le64_to_cpu(fe->i_size)); | 337 | i_size_write(inode, le64_to_cpu(fe->i_size)); |
| 339 | break; | 338 | break; |
| 340 | default: | 339 | default: |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index a9856e3eaaf0..9f39c640cddf 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
| @@ -1724,15 +1724,16 @@ static int ocfs2_symlink(struct inode *dir, | |||
| 1724 | fe = (struct ocfs2_dinode *) new_fe_bh->b_data; | 1724 | fe = (struct ocfs2_dinode *) new_fe_bh->b_data; |
| 1725 | inode->i_rdev = 0; | 1725 | inode->i_rdev = 0; |
| 1726 | newsize = l - 1; | 1726 | newsize = l - 1; |
| 1727 | inode->i_op = &ocfs2_symlink_inode_operations; | ||
| 1727 | if (l > ocfs2_fast_symlink_chars(sb)) { | 1728 | if (l > ocfs2_fast_symlink_chars(sb)) { |
| 1728 | u32 offset = 0; | 1729 | u32 offset = 0; |
| 1729 | 1730 | ||
| 1730 | inode->i_op = &ocfs2_symlink_inode_operations; | ||
| 1731 | status = dquot_alloc_space_nodirty(inode, | 1731 | status = dquot_alloc_space_nodirty(inode, |
| 1732 | ocfs2_clusters_to_bytes(osb->sb, 1)); | 1732 | ocfs2_clusters_to_bytes(osb->sb, 1)); |
| 1733 | if (status) | 1733 | if (status) |
| 1734 | goto bail; | 1734 | goto bail; |
| 1735 | did_quota = 1; | 1735 | did_quota = 1; |
| 1736 | inode->i_mapping->a_ops = &ocfs2_aops; | ||
| 1736 | status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0, | 1737 | status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0, |
| 1737 | new_fe_bh, | 1738 | new_fe_bh, |
| 1738 | handle, data_ac, NULL, | 1739 | handle, data_ac, NULL, |
| @@ -1750,7 +1751,7 @@ static int ocfs2_symlink(struct inode *dir, | |||
| 1750 | i_size_write(inode, newsize); | 1751 | i_size_write(inode, newsize); |
| 1751 | inode->i_blocks = ocfs2_inode_sector_count(inode); | 1752 | inode->i_blocks = ocfs2_inode_sector_count(inode); |
| 1752 | } else { | 1753 | } else { |
| 1753 | inode->i_op = &ocfs2_fast_symlink_inode_operations; | 1754 | inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops; |
| 1754 | memcpy((char *) fe->id2.i_symlink, symname, l); | 1755 | memcpy((char *) fe->id2.i_symlink, symname, l); |
| 1755 | i_size_write(inode, newsize); | 1756 | i_size_write(inode, newsize); |
| 1756 | inode->i_blocks = 0; | 1757 | inode->i_blocks = 0; |
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 5d22872e2bb3..f1fbb4b552ad 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c | |||
| @@ -54,101 +54,40 @@ | |||
| 54 | #include "buffer_head_io.h" | 54 | #include "buffer_head_io.h" |
| 55 | 55 | ||
| 56 | 56 | ||
| 57 | static char *ocfs2_fast_symlink_getlink(struct inode *inode, | 57 | static int ocfs2_fast_symlink_readpage(struct file *unused, struct page *page) |
| 58 | struct buffer_head **bh) | ||
| 59 | { | 58 | { |
| 60 | int status; | 59 | struct inode *inode = page->mapping->host; |
| 61 | char *link = NULL; | 60 | struct buffer_head *bh; |
| 61 | int status = ocfs2_read_inode_block(inode, &bh); | ||
| 62 | struct ocfs2_dinode *fe; | 62 | struct ocfs2_dinode *fe; |
| 63 | const char *link; | ||
| 64 | void *kaddr; | ||
| 65 | size_t len; | ||
| 63 | 66 | ||
| 64 | status = ocfs2_read_inode_block(inode, bh); | ||
| 65 | if (status < 0) { | 67 | if (status < 0) { |
| 66 | mlog_errno(status); | 68 | mlog_errno(status); |
| 67 | link = ERR_PTR(status); | 69 | return status; |
| 68 | goto bail; | ||
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | fe = (struct ocfs2_dinode *) (*bh)->b_data; | 72 | fe = (struct ocfs2_dinode *) bh->b_data; |
| 72 | link = (char *) fe->id2.i_symlink; | 73 | link = (char *) fe->id2.i_symlink; |
| 73 | bail: | 74 | /* will be less than a page size */ |
| 74 | 75 | len = strnlen(link, ocfs2_fast_symlink_chars(inode->i_sb)); | |
| 75 | return link; | 76 | kaddr = kmap_atomic(page); |
| 76 | } | 77 | memcpy(kaddr, link, len + 1); |
| 77 | 78 | kunmap_atomic(kaddr); | |
| 78 | static int ocfs2_readlink(struct dentry *dentry, | 79 | SetPageUptodate(page); |
| 79 | char __user *buffer, | 80 | unlock_page(page); |
| 80 | int buflen) | ||
| 81 | { | ||
| 82 | int ret; | ||
| 83 | char *link; | ||
| 84 | struct buffer_head *bh = NULL; | ||
| 85 | struct inode *inode = dentry->d_inode; | ||
| 86 | |||
| 87 | link = ocfs2_fast_symlink_getlink(inode, &bh); | ||
| 88 | if (IS_ERR(link)) { | ||
| 89 | ret = PTR_ERR(link); | ||
| 90 | goto out; | ||
| 91 | } | ||
| 92 | |||
| 93 | /* | ||
| 94 | * Without vfsmount we can't update atime now, | ||
| 95 | * but we will update atime here ultimately. | ||
| 96 | */ | ||
| 97 | ret = vfs_readlink(dentry, buffer, buflen, link); | ||
| 98 | |||
| 99 | brelse(bh); | 81 | brelse(bh); |
| 100 | out: | 82 | return 0; |
| 101 | if (ret < 0) | ||
| 102 | mlog_errno(ret); | ||
| 103 | return ret; | ||
| 104 | } | 83 | } |
| 105 | 84 | ||
| 106 | static void *ocfs2_fast_follow_link(struct dentry *dentry, | 85 | const struct address_space_operations ocfs2_fast_symlink_aops = { |
| 107 | struct nameidata *nd) | 86 | .readpage = ocfs2_fast_symlink_readpage, |
| 108 | { | 87 | }; |
| 109 | int status = 0; | ||
| 110 | int len; | ||
| 111 | char *target, *link = ERR_PTR(-ENOMEM); | ||
| 112 | struct inode *inode = dentry->d_inode; | ||
| 113 | struct buffer_head *bh = NULL; | ||
| 114 | |||
| 115 | BUG_ON(!ocfs2_inode_is_fast_symlink(inode)); | ||
| 116 | target = ocfs2_fast_symlink_getlink(inode, &bh); | ||
| 117 | if (IS_ERR(target)) { | ||
| 118 | status = PTR_ERR(target); | ||
| 119 | mlog_errno(status); | ||
| 120 | goto bail; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Fast symlinks can't be large */ | ||
| 124 | len = strnlen(target, ocfs2_fast_symlink_chars(inode->i_sb)); | ||
| 125 | link = kzalloc(len + 1, GFP_NOFS); | ||
| 126 | if (!link) { | ||
| 127 | status = -ENOMEM; | ||
| 128 | mlog_errno(status); | ||
| 129 | goto bail; | ||
| 130 | } | ||
| 131 | |||
| 132 | memcpy(link, target, len); | ||
| 133 | |||
| 134 | bail: | ||
| 135 | nd_set_link(nd, status ? ERR_PTR(status) : link); | ||
| 136 | brelse(bh); | ||
| 137 | |||
| 138 | if (status) | ||
| 139 | mlog_errno(status); | ||
| 140 | return NULL; | ||
| 141 | } | ||
| 142 | |||
| 143 | static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) | ||
| 144 | { | ||
| 145 | char *link = nd_get_link(nd); | ||
| 146 | if (!IS_ERR(link)) | ||
| 147 | kfree(link); | ||
| 148 | } | ||
| 149 | 88 | ||
| 150 | const struct inode_operations ocfs2_symlink_inode_operations = { | 89 | const struct inode_operations ocfs2_symlink_inode_operations = { |
