| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 1 | /* -*- mode: c; c-basic-offset: 8; -*- | 
|  | 2 | * vim: noexpandtab sw=8 ts=8 sts=0: | 
|  | 3 | * | 
|  | 4 | *  linux/cluster/ssi/cfs/symlink.c | 
|  | 5 | * | 
|  | 6 | *	This program is free software; you can redistribute it and/or | 
|  | 7 | *	modify it under the terms of the GNU General Public License as | 
|  | 8 | *	published by the Free Software Foundation; either version 2 of | 
|  | 9 | *	the License, or (at your option) any later version. | 
|  | 10 | * | 
|  | 11 | *	This program is distributed in the hope that it will be useful, | 
|  | 12 | *	but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 13 | *	MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE | 
|  | 14 | *	or NON INFRINGEMENT.  See the GNU General Public License for more | 
|  | 15 | *	details. | 
|  | 16 | * | 
|  | 17 | * 	You should have received a copy of the GNU General Public License | 
|  | 18 | * 	along with this program; if not, write to the Free Software | 
|  | 19 | * 	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | 20 | * | 
|  | 21 | *	Questions/Comments/Bugfixes to ssic-linux-devel@lists.sourceforge.net | 
|  | 22 | * | 
|  | 23 | *  Copyright (C) 1992  Rick Sladkey | 
|  | 24 | * | 
|  | 25 | *  Optimization changes Copyright (C) 1994 Florian La Roche | 
|  | 26 | * | 
|  | 27 | *  Jun 7 1999, cache symlink lookups in the page cache.  -DaveM | 
|  | 28 | * | 
|  | 29 | *  Portions Copyright (C) 2001 Compaq Computer Corporation | 
|  | 30 | * | 
|  | 31 | *  ocfs2 symlink handling code. | 
|  | 32 | * | 
|  | 33 | *  Copyright (C) 2004, 2005 Oracle. | 
|  | 34 | * | 
|  | 35 | */ | 
|  | 36 |  | 
|  | 37 | #include <linux/fs.h> | 
|  | 38 | #include <linux/types.h> | 
|  | 39 | #include <linux/slab.h> | 
|  | 40 | #include <linux/pagemap.h> | 
| Joel Becker | a731d12 | 2009-04-06 16:43:42 -0700 | [diff] [blame] | 41 | #include <linux/namei.h> | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 42 |  | 
|  | 43 | #define MLOG_MASK_PREFIX ML_NAMEI | 
|  | 44 | #include <cluster/masklog.h> | 
|  | 45 |  | 
|  | 46 | #include "ocfs2.h" | 
|  | 47 |  | 
|  | 48 | #include "alloc.h" | 
|  | 49 | #include "file.h" | 
|  | 50 | #include "inode.h" | 
|  | 51 | #include "journal.h" | 
|  | 52 | #include "symlink.h" | 
| Tiger Yang | cf1d6c7 | 2008-08-18 17:11:00 +0800 | [diff] [blame] | 53 | #include "xattr.h" | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 54 |  | 
|  | 55 | #include "buffer_head_io.h" | 
|  | 56 |  | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 57 |  | 
|  | 58 | static char *ocfs2_fast_symlink_getlink(struct inode *inode, | 
|  | 59 | struct buffer_head **bh) | 
|  | 60 | { | 
|  | 61 | int status; | 
|  | 62 | char *link = NULL; | 
|  | 63 | struct ocfs2_dinode *fe; | 
|  | 64 |  | 
|  | 65 | mlog_entry_void(); | 
|  | 66 |  | 
| Joel Becker | b657c95 | 2008-11-13 14:49:11 -0800 | [diff] [blame] | 67 | status = ocfs2_read_inode_block(inode, bh); | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 68 | if (status < 0) { | 
|  | 69 | mlog_errno(status); | 
|  | 70 | link = ERR_PTR(status); | 
|  | 71 | goto bail; | 
|  | 72 | } | 
|  | 73 |  | 
|  | 74 | fe = (struct ocfs2_dinode *) (*bh)->b_data; | 
|  | 75 | link = (char *) fe->id2.i_symlink; | 
|  | 76 | bail: | 
|  | 77 | mlog_exit(status); | 
|  | 78 |  | 
|  | 79 | return link; | 
|  | 80 | } | 
|  | 81 |  | 
|  | 82 | static int ocfs2_readlink(struct dentry *dentry, | 
|  | 83 | char __user *buffer, | 
|  | 84 | int buflen) | 
|  | 85 | { | 
|  | 86 | int ret; | 
|  | 87 | char *link; | 
|  | 88 | struct buffer_head *bh = NULL; | 
|  | 89 | struct inode *inode = dentry->d_inode; | 
|  | 90 |  | 
|  | 91 | mlog_entry_void(); | 
|  | 92 |  | 
|  | 93 | link = ocfs2_fast_symlink_getlink(inode, &bh); | 
|  | 94 | if (IS_ERR(link)) { | 
|  | 95 | ret = PTR_ERR(link); | 
|  | 96 | goto out; | 
|  | 97 | } | 
|  | 98 |  | 
| Tiger Yang | 25899de | 2006-11-15 15:49:02 +0800 | [diff] [blame] | 99 | /* | 
|  | 100 | * Without vfsmount we can't update atime now, | 
|  | 101 | * but we will update atime here ultimately. | 
|  | 102 | */ | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 103 | ret = vfs_readlink(dentry, buffer, buflen, link); | 
|  | 104 |  | 
|  | 105 | brelse(bh); | 
|  | 106 | out: | 
|  | 107 | mlog_exit(ret); | 
|  | 108 | return ret; | 
|  | 109 | } | 
|  | 110 |  | 
| Joel Becker | a731d12 | 2009-04-06 16:43:42 -0700 | [diff] [blame] | 111 | static void *ocfs2_fast_follow_link(struct dentry *dentry, | 
|  | 112 | struct nameidata *nd) | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 113 | { | 
| Joel Becker | a731d12 | 2009-04-06 16:43:42 -0700 | [diff] [blame] | 114 | int status = 0; | 
|  | 115 | int len; | 
|  | 116 | char *target, *link = ERR_PTR(-ENOMEM); | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 117 | struct inode *inode = dentry->d_inode; | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 118 | struct buffer_head *bh = NULL; | 
| Joel Becker | a731d12 | 2009-04-06 16:43:42 -0700 | [diff] [blame] | 119 |  | 
|  | 120 | mlog_entry_void(); | 
|  | 121 |  | 
|  | 122 | BUG_ON(!ocfs2_inode_is_fast_symlink(inode)); | 
|  | 123 | target = ocfs2_fast_symlink_getlink(inode, &bh); | 
|  | 124 | if (IS_ERR(target)) { | 
|  | 125 | status = PTR_ERR(target); | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 126 | mlog_errno(status); | 
|  | 127 | goto bail; | 
|  | 128 | } | 
|  | 129 |  | 
| Joel Becker | a731d12 | 2009-04-06 16:43:42 -0700 | [diff] [blame] | 130 | /* Fast symlinks can't be large */ | 
|  | 131 | len = strlen(target); | 
|  | 132 | link = kzalloc(len + 1, GFP_NOFS); | 
|  | 133 | if (!link) { | 
|  | 134 | status = -ENOMEM; | 
|  | 135 | mlog_errno(status); | 
|  | 136 | goto bail; | 
|  | 137 | } | 
|  | 138 |  | 
|  | 139 | memcpy(link, target, len); | 
|  | 140 | nd_set_link(nd, link); | 
| Mark Fasheh | 72bce50 | 2007-01-03 17:25:40 -0800 | [diff] [blame] | 141 |  | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 142 | bail: | 
| Mark Fasheh | a81cb88 | 2008-10-07 14:25:16 -0700 | [diff] [blame] | 143 | brelse(bh); | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 144 |  | 
| Joel Becker | a731d12 | 2009-04-06 16:43:42 -0700 | [diff] [blame] | 145 | mlog_exit(status); | 
|  | 146 | return status ? ERR_PTR(status) : link; | 
|  | 147 | } | 
|  | 148 |  | 
|  | 149 | static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) | 
|  | 150 | { | 
|  | 151 | char *link = cookie; | 
|  | 152 |  | 
|  | 153 | kfree(link); | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 154 | } | 
|  | 155 |  | 
| Arjan van de Ven | 92e1d5b | 2007-02-12 00:55:39 -0800 | [diff] [blame] | 156 | const struct inode_operations ocfs2_symlink_inode_operations = { | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 157 | .readlink	= page_readlink, | 
| Joel Becker | a731d12 | 2009-04-06 16:43:42 -0700 | [diff] [blame] | 158 | .follow_link	= page_follow_link_light, | 
|  | 159 | .put_link	= page_put_link, | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 160 | .getattr	= ocfs2_getattr, | 
| Sunil Mushran | bc53580 | 2008-04-18 10:23:53 -0700 | [diff] [blame] | 161 | .setattr	= ocfs2_setattr, | 
| Tiger Yang | cf1d6c7 | 2008-08-18 17:11:00 +0800 | [diff] [blame] | 162 | .setxattr	= generic_setxattr, | 
|  | 163 | .getxattr	= generic_getxattr, | 
|  | 164 | .listxattr	= ocfs2_listxattr, | 
|  | 165 | .removexattr	= generic_removexattr, | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 166 | }; | 
| Arjan van de Ven | 92e1d5b | 2007-02-12 00:55:39 -0800 | [diff] [blame] | 167 | const struct inode_operations ocfs2_fast_symlink_inode_operations = { | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 168 | .readlink	= ocfs2_readlink, | 
| Joel Becker | a731d12 | 2009-04-06 16:43:42 -0700 | [diff] [blame] | 169 | .follow_link	= ocfs2_fast_follow_link, | 
|  | 170 | .put_link	= ocfs2_fast_put_link, | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 171 | .getattr	= ocfs2_getattr, | 
| Sunil Mushran | bc53580 | 2008-04-18 10:23:53 -0700 | [diff] [blame] | 172 | .setattr	= ocfs2_setattr, | 
| Tiger Yang | cf1d6c7 | 2008-08-18 17:11:00 +0800 | [diff] [blame] | 173 | .setxattr	= generic_setxattr, | 
|  | 174 | .getxattr	= generic_getxattr, | 
|  | 175 | .listxattr	= ocfs2_listxattr, | 
|  | 176 | .removexattr	= generic_removexattr, | 
| Mark Fasheh | ccd979b | 2005-12-15 14:31:24 -0800 | [diff] [blame] | 177 | }; |