Whamcloud - gitweb
a999ea18a4d896d17a7b82b1ac3bb43eefff2b6d
[fs/lustre-release.git] / lustre / llite / symlink.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  *
32  * Copyright (c) 2011, Whamcloud, Inc.
33  */
34 /*
35  * This file is part of Lustre, http://www.lustre.org/
36  * Lustre is a trademark of Sun Microsystems, Inc.
37  */
38
39 #include <linux/fs.h>
40 #include <linux/mm.h>
41 #include <linux/stat.h>
42 #include <linux/smp_lock.h>
43 #include <linux/version.h>
44 #define DEBUG_SUBSYSTEM S_LLITE
45
46 #include <lustre_lite.h>
47 #include "llite_internal.h"
48
49 static int ll_readlink_internal(struct inode *inode,
50                                 struct ptlrpc_request **request, char **symname)
51 {
52         struct ll_inode_info *lli = ll_i2info(inode);
53         struct ll_sb_info *sbi = ll_i2sbi(inode);
54         int rc, symlen = i_size_read(inode) + 1;
55         struct mdt_body *body;
56         struct md_op_data *op_data;
57         ENTRY;
58
59         *request = NULL;
60
61         if (lli->lli_symlink_name) {
62                 *symname = lli->lli_symlink_name;
63                 CDEBUG(D_INODE, "using cached symlink %s\n", *symname);
64                 RETURN(0);
65         }
66
67         op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, symlen,
68                                      LUSTRE_OPC_ANY, NULL);
69         if (IS_ERR(op_data))
70                 RETURN(PTR_ERR(op_data));
71
72         op_data->op_valid = OBD_MD_LINKNAME;
73         rc = md_getattr(sbi->ll_md_exp, op_data, request);
74         ll_finish_md_op_data(op_data);
75         if (rc) {
76                 if (rc != -ENOENT)
77                         CERROR("inode %lu: rc = %d\n", inode->i_ino, rc);
78                 GOTO (failed, rc);
79         }
80
81         body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY);
82         LASSERT(body != NULL);
83         if ((body->valid & OBD_MD_LINKNAME) == 0) {
84                 CERROR("OBD_MD_LINKNAME not set on reply\n");
85                 GOTO(failed, rc = -EPROTO);
86         }
87
88         LASSERT(symlen != 0);
89         if (body->eadatasize != symlen) {
90                 CERROR("inode %lu: symlink length %d not expected %d\n",
91                         inode->i_ino, body->eadatasize - 1, symlen - 1);
92                 GOTO(failed, rc = -EPROTO);
93         }
94
95         *symname = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_MD);
96         if (*symname == NULL ||
97             strnlen(*symname, symlen) != symlen - 1) {
98                 /* not full/NULL terminated */
99                 CERROR("inode %lu: symlink not NULL terminated string"
100                         "of length %d\n", inode->i_ino, symlen - 1);
101                 GOTO(failed, rc = -EPROTO);
102         }
103
104         OBD_ALLOC(lli->lli_symlink_name, symlen);
105         /* do not return an error if we cannot cache the symlink locally */
106         if (lli->lli_symlink_name) {
107                 memcpy(lli->lli_symlink_name, *symname, symlen);
108                 *symname = lli->lli_symlink_name;
109         }
110         RETURN(0);
111
112 failed:
113         RETURN (rc);
114 }
115
116 static int ll_readlink(struct dentry *dentry, char *buffer, int buflen)
117 {
118         struct inode *inode = dentry->d_inode;
119         struct ptlrpc_request *request;
120         char *symname;
121         int rc;
122         ENTRY;
123
124         CDEBUG(D_VFSTRACE, "VFS Op\n");
125         /* on symlinks lli_open_sem protects lli_symlink_name allocation/data */
126         ll_inode_size_lock(inode, 0);
127         rc = ll_readlink_internal(inode, &request, &symname);
128         if (rc)
129                 GOTO(out, rc);
130
131         rc = vfs_readlink(dentry, buffer, buflen, symname);
132  out:
133         ptlrpc_req_finished(request);
134         ll_inode_size_unlock(inode, 0);
135         RETURN(rc);
136 }
137
138 #ifdef HAVE_COOKIE_FOLLOW_LINK
139 # define LL_FOLLOW_LINK_RETURN_TYPE void *
140 #else
141 # define LL_FOLLOW_LINK_RETURN_TYPE int
142 #endif
143
144 static LL_FOLLOW_LINK_RETURN_TYPE ll_follow_link(struct dentry *dentry,
145                                                  struct nameidata *nd)
146 {
147         struct inode *inode = dentry->d_inode;
148         struct ptlrpc_request *request = NULL;
149         int rc;
150         char *symname;
151         ENTRY;
152
153         CDEBUG(D_VFSTRACE, "VFS Op\n");
154         /* Limit the recursive symlink depth to 5 instead of default
155          * 8 links when kernel has 4k stack to prevent stack overflow.
156          * For 8k stacks we need to limit it to 7 for local servers. */
157         if (THREAD_SIZE < 8192 && current->link_count >= 6) {
158                 rc = -ELOOP;
159         } else if (THREAD_SIZE == 8192 && current->link_count >= 8) {
160                 rc = -ELOOP;
161         } else {
162                 ll_inode_size_lock(inode, 0);
163                 rc = ll_readlink_internal(inode, &request, &symname);
164                 ll_inode_size_unlock(inode, 0);
165         }
166         if (rc) {
167                 cfs_path_put(nd); /* Kernel assumes that ->follow_link()
168                                      releases nameidata on error */
169                 GOTO(out, rc);
170         }
171
172 #ifdef HAVE_COOKIE_FOLLOW_LINK
173         nd_set_link(nd, symname);
174         /* @symname may contain a pointer to the request message buffer,
175            we delay request releasing until ll_put_link then. */
176         RETURN(request);
177 #else
178         if (lli->lli_symlink_name == NULL) {
179                 /* falling back to recursive follow link if the request
180                  * needs to be cleaned up still. */
181                 rc = vfs_follow_link(nd, symname);
182                 GOTO(out, rc);
183         }
184         nd_set_link(nd, symname);
185         RETURN(0);
186 #endif
187 out:
188         ptlrpc_req_finished(request);
189 #ifdef HAVE_COOKIE_FOLLOW_LINK
190         RETURN(ERR_PTR(rc));
191 #else
192         RETURN(rc);
193 #endif
194 }
195
196 #ifdef HAVE_COOKIE_FOLLOW_LINK
197 static void ll_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
198 {
199         ptlrpc_req_finished(cookie);
200 }
201 #endif
202
203 struct inode_operations ll_fast_symlink_inode_operations = {
204         .readlink       = ll_readlink,
205         .setattr        = ll_setattr,
206         .follow_link    = ll_follow_link,
207 #ifdef HAVE_COOKIE_FOLLOW_LINK
208         .put_link       = ll_put_link,
209 #endif
210         .getattr        = ll_getattr,
211         .permission     = ll_inode_permission,
212         .setxattr       = ll_setxattr,
213         .getxattr       = ll_getxattr,
214         .listxattr      = ll_listxattr,
215         .removexattr    = ll_removexattr,
216 };