Commit | Line | Data |
---|---|---|
d7e09d03 PT |
1 | /* |
2 | * GPL HEADER START | |
3 | * | |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 only, | |
8 | * as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License version 2 for more details (a copy is included | |
14 | * in the LICENSE file that accompanied this code). | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * version 2 along with this program; If not, see | |
18 | * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf | |
19 | * | |
20 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
21 | * CA 95054 USA or visit www.sun.com if you need additional information or | |
22 | * have any questions. | |
23 | * | |
24 | * GPL HEADER END | |
25 | */ | |
26 | /* | |
27 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | |
28 | * Use is subject to license terms. | |
29 | * | |
30 | * Copyright (c) 2011, 2012, Intel Corporation. | |
31 | */ | |
32 | /* | |
33 | * This file is part of Lustre, http://www.lustre.org/ | |
34 | * Lustre is a trademark of Sun Microsystems, Inc. | |
35 | */ | |
36 | ||
37 | #include <linux/fs.h> | |
38 | #include <linux/mm.h> | |
39 | #include <linux/stat.h> | |
d7e09d03 PT |
40 | #define DEBUG_SUBSYSTEM S_LLITE |
41 | ||
67a235f5 | 42 | #include "../include/lustre_lite.h" |
d7e09d03 PT |
43 | #include "llite_internal.h" |
44 | ||
45 | static int ll_readlink_internal(struct inode *inode, | |
46 | struct ptlrpc_request **request, char **symname) | |
47 | { | |
48 | struct ll_inode_info *lli = ll_i2info(inode); | |
49 | struct ll_sb_info *sbi = ll_i2sbi(inode); | |
50 | int rc, symlen = i_size_read(inode) + 1; | |
51 | struct mdt_body *body; | |
52 | struct md_op_data *op_data; | |
d7e09d03 PT |
53 | |
54 | *request = NULL; | |
55 | ||
56 | if (lli->lli_symlink_name) { | |
57 | int print_limit = min_t(int, PAGE_SIZE - 128, symlen); | |
58 | ||
59 | *symname = lli->lli_symlink_name; | |
60 | /* If the total CDEBUG() size is larger than a page, it | |
61 | * will print a warning to the console, avoid this by | |
62 | * printing just the last part of the symlink. */ | |
63 | CDEBUG(D_INODE, "using cached symlink %s%.*s, len = %d\n", | |
64 | print_limit < symlen ? "..." : "", print_limit, | |
65 | (*symname) + symlen - print_limit, symlen); | |
0a3bdb00 | 66 | return 0; |
d7e09d03 PT |
67 | } |
68 | ||
69 | op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, symlen, | |
70 | LUSTRE_OPC_ANY, NULL); | |
71 | if (IS_ERR(op_data)) | |
0a3bdb00 | 72 | return PTR_ERR(op_data); |
d7e09d03 PT |
73 | |
74 | op_data->op_valid = OBD_MD_LINKNAME; | |
75 | rc = md_getattr(sbi->ll_md_exp, op_data, request); | |
76 | ll_finish_md_op_data(op_data); | |
77 | if (rc) { | |
78 | if (rc != -ENOENT) | |
79 | CERROR("inode %lu: rc = %d\n", inode->i_ino, rc); | |
34e1f2bb | 80 | goto failed; |
d7e09d03 PT |
81 | } |
82 | ||
83 | body = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_BODY); | |
84 | LASSERT(body != NULL); | |
85 | if ((body->valid & OBD_MD_LINKNAME) == 0) { | |
86 | CERROR("OBD_MD_LINKNAME not set on reply\n"); | |
34e1f2bb JL |
87 | rc = -EPROTO; |
88 | goto failed; | |
d7e09d03 PT |
89 | } |
90 | ||
91 | LASSERT(symlen != 0); | |
92 | if (body->eadatasize != symlen) { | |
93 | CERROR("inode %lu: symlink length %d not expected %d\n", | |
94 | inode->i_ino, body->eadatasize - 1, symlen - 1); | |
34e1f2bb JL |
95 | rc = -EPROTO; |
96 | goto failed; | |
d7e09d03 PT |
97 | } |
98 | ||
99 | *symname = req_capsule_server_get(&(*request)->rq_pill, &RMF_MDT_MD); | |
100 | if (*symname == NULL || | |
101 | strnlen(*symname, symlen) != symlen - 1) { | |
102 | /* not full/NULL terminated */ | |
2d00bd17 JP |
103 | CERROR("inode %lu: symlink not NULL terminated string of length %d\n", |
104 | inode->i_ino, symlen - 1); | |
34e1f2bb JL |
105 | rc = -EPROTO; |
106 | goto failed; | |
d7e09d03 PT |
107 | } |
108 | ||
496a51bd | 109 | lli->lli_symlink_name = kzalloc(symlen, GFP_NOFS); |
d7e09d03 PT |
110 | /* do not return an error if we cannot cache the symlink locally */ |
111 | if (lli->lli_symlink_name) { | |
112 | memcpy(lli->lli_symlink_name, *symname, symlen); | |
113 | *symname = lli->lli_symlink_name; | |
114 | } | |
0a3bdb00 | 115 | return 0; |
d7e09d03 PT |
116 | |
117 | failed: | |
0a3bdb00 | 118 | return rc; |
d7e09d03 PT |
119 | } |
120 | ||
d7e09d03 PT |
121 | static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd) |
122 | { | |
2b0143b5 | 123 | struct inode *inode = d_inode(dentry); |
d7e09d03 PT |
124 | struct ptlrpc_request *request = NULL; |
125 | int rc; | |
1da4f83c | 126 | char *symname = NULL; |
d7e09d03 PT |
127 | |
128 | CDEBUG(D_VFSTRACE, "VFS Op\n"); | |
129 | /* Limit the recursive symlink depth to 5 instead of default | |
130 | * 8 links when kernel has 4k stack to prevent stack overflow. | |
131 | * For 8k stacks we need to limit it to 7 for local servers. */ | |
132 | if (THREAD_SIZE < 8192 && current->link_count >= 6) { | |
133 | rc = -ELOOP; | |
134 | } else if (THREAD_SIZE == 8192 && current->link_count >= 8) { | |
135 | rc = -ELOOP; | |
136 | } else { | |
137 | ll_inode_size_lock(inode); | |
138 | rc = ll_readlink_internal(inode, &request, &symname); | |
139 | ll_inode_size_unlock(inode); | |
140 | } | |
141 | if (rc) { | |
142 | ptlrpc_req_finished(request); | |
143 | request = NULL; | |
144 | symname = ERR_PTR(rc); | |
145 | } | |
146 | ||
147 | nd_set_link(nd, symname); | |
148 | /* symname may contain a pointer to the request message buffer, | |
149 | * we delay request releasing until ll_put_link then. | |
150 | */ | |
0a3bdb00 | 151 | return request; |
d7e09d03 PT |
152 | } |
153 | ||
154 | static void ll_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) | |
155 | { | |
156 | ptlrpc_req_finished(cookie); | |
157 | } | |
158 | ||
159 | struct inode_operations ll_fast_symlink_inode_operations = { | |
4efcc9ff | 160 | .readlink = generic_readlink, |
d7e09d03 PT |
161 | .setattr = ll_setattr, |
162 | .follow_link = ll_follow_link, | |
163 | .put_link = ll_put_link, | |
164 | .getattr = ll_getattr, | |
165 | .permission = ll_inode_permission, | |
166 | .setxattr = ll_setxattr, | |
167 | .getxattr = ll_getxattr, | |
168 | .listxattr = ll_listxattr, | |
169 | .removexattr = ll_removexattr, | |
170 | }; |