1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#define DEBUG_SUBSYSTEM S_LMV
38#include <linux/slab.h>
39#include <linux/module.h>
40#include <linux/pagemap.h>
41#include <asm/div64.h>
42#include <linux/seq_file.h>
43#include <linux/namei.h>
44#include "../include/lustre_intent.h"
45#include "../include/obd_support.h"
46#include "../include/lustre/lustre_idl.h"
47#include "../include/lustre_lib.h"
48#include "../include/lustre_net.h"
49#include "../include/lustre_dlm.h"
50#include "../include/obd_class.h"
51#include "../include/lprocfs_status.h"
52#include "lmv_internal.h"
53
54static int lmv_intent_remote(struct obd_export *exp, void *lmm,
55 int lmmsize, struct lookup_intent *it,
56 const struct lu_fid *parent_fid, int flags,
57 struct ptlrpc_request **reqp,
58 ldlm_blocking_callback cb_blocking,
59 __u64 extra_lock_flags)
60{
61 struct obd_device *obd = exp->exp_obd;
62 struct lmv_obd *lmv = &obd->u.lmv;
63 struct ptlrpc_request *req = NULL;
64 struct lustre_handle plock;
65 struct md_op_data *op_data;
66 struct lmv_tgt_desc *tgt;
67 struct mdt_body *body;
68 int pmode;
69 int rc = 0;
70
71 body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
72 if (body == NULL)
73 return -EPROTO;
74
75 LASSERT((body->valid & OBD_MD_MDS));
76
77
78
79
80
81 if (it->it_op & IT_LOOKUP)
82 it->it_op = IT_GETATTR;
83
84
85
86
87 pmode = it->d.lustre.it_lock_mode;
88 if (pmode) {
89 plock.cookie = it->d.lustre.it_lock_handle;
90 it->d.lustre.it_lock_mode = 0;
91 it->d.lustre.it_data = NULL;
92 }
93
94 LASSERT(fid_is_sane(&body->fid1));
95
96 tgt = lmv_find_target(lmv, &body->fid1);
97 if (IS_ERR(tgt)) {
98 rc = PTR_ERR(tgt);
99 goto out;
100 }
101
102 OBD_ALLOC_PTR(op_data);
103 if (op_data == NULL) {
104 rc = -ENOMEM;
105 goto out;
106 }
107
108 op_data->op_fid1 = body->fid1;
109
110 if (parent_fid != NULL) {
111
112
113
114 LASSERT(it->it_op & IT_OPEN);
115 op_data->op_fid2 = *parent_fid;
116
117
118 op_data->op_fid3 = body->fid1;
119 }
120
121 op_data->op_bias = MDS_CROSS_REF;
122 CDEBUG(D_INODE, "REMOTE_INTENT with fid="DFID" -> mds #%d\n",
123 PFID(&body->fid1), tgt->ltd_idx);
124
125 rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it,
126 flags, &req, cb_blocking, extra_lock_flags);
127 if (rc)
128 goto out_free_op_data;
129
130
131
132
133
134
135 if (it->d.lustre.it_lock_mode != 0) {
136 it->d.lustre.it_remote_lock_handle =
137 it->d.lustre.it_lock_handle;
138 it->d.lustre.it_remote_lock_mode = it->d.lustre.it_lock_mode;
139 }
140
141 it->d.lustre.it_lock_handle = plock.cookie;
142 it->d.lustre.it_lock_mode = pmode;
143
144out_free_op_data:
145 OBD_FREE_PTR(op_data);
146out:
147 if (rc && pmode)
148 ldlm_lock_decref(&plock, pmode);
149
150 ptlrpc_req_finished(*reqp);
151 *reqp = req;
152 return rc;
153}
154
155
156
157
158
159int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data,
160 void *lmm, int lmmsize, struct lookup_intent *it,
161 int flags, struct ptlrpc_request **reqp,
162 ldlm_blocking_callback cb_blocking,
163 __u64 extra_lock_flags)
164{
165 struct obd_device *obd = exp->exp_obd;
166 struct lmv_obd *lmv = &obd->u.lmv;
167 struct lmv_tgt_desc *tgt;
168 struct mdt_body *body;
169 int rc;
170
171 tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
172 if (IS_ERR(tgt))
173 return PTR_ERR(tgt);
174
175
176
177 if ((it->it_op & IT_CREAT) &&
178 !(it->it_flags & MDS_OPEN_BY_FID)) {
179
180
181
182
183 op_data->op_fid3 = op_data->op_fid2;
184 rc = lmv_fid_alloc(exp, &op_data->op_fid2, op_data);
185 if (rc != 0)
186 return rc;
187 }
188
189 CDEBUG(D_INODE, "OPEN_INTENT with fid1=" DFID ", fid2=" DFID ", name='%s' -> mds #%d\n",
190 PFID(&op_data->op_fid1),
191 PFID(&op_data->op_fid2), op_data->op_name, tgt->ltd_idx);
192
193 rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it, flags,
194 reqp, cb_blocking, extra_lock_flags);
195 if (rc != 0)
196 return rc;
197
198
199
200
201 if ((it->d.lustre.it_disposition & DISP_LOOKUP_NEG) &&
202 !(it->d.lustre.it_disposition & DISP_OPEN_CREATE) &&
203 !(it->d.lustre.it_disposition & DISP_OPEN_OPEN))
204 return rc;
205
206 body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
207 if (body == NULL)
208 return -EPROTO;
209
210
211
212 if (likely(!(body->valid & OBD_MD_MDS)))
213 return 0;
214
215
216
217
218
219 rc = lmv_intent_remote(exp, lmm, lmmsize, it, &op_data->op_fid1, flags,
220 reqp, cb_blocking, extra_lock_flags);
221 if (rc != 0) {
222 LASSERT(rc < 0);
223
224
225
226
227
228
229 CDEBUG(D_INODE, "Can't handle remote %s: dir " DFID "(" DFID "):%*s: %d\n",
230 LL_IT2STR(it), PFID(&op_data->op_fid2),
231 PFID(&op_data->op_fid1), op_data->op_namelen,
232 op_data->op_name, rc);
233 return rc;
234 }
235
236 return rc;
237}
238
239
240
241
242int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data,
243 void *lmm, int lmmsize, struct lookup_intent *it,
244 int flags, struct ptlrpc_request **reqp,
245 ldlm_blocking_callback cb_blocking,
246 __u64 extra_lock_flags)
247{
248 struct obd_device *obd = exp->exp_obd;
249 struct lmv_obd *lmv = &obd->u.lmv;
250 struct lmv_tgt_desc *tgt = NULL;
251 struct mdt_body *body;
252 int rc = 0;
253
254 tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1);
255 if (IS_ERR(tgt))
256 return PTR_ERR(tgt);
257
258 if (!fid_is_sane(&op_data->op_fid2))
259 fid_zero(&op_data->op_fid2);
260
261 CDEBUG(D_INODE, "LOOKUP_INTENT with fid1="DFID", fid2="DFID
262 ", name='%s' -> mds #%d\n", PFID(&op_data->op_fid1),
263 PFID(&op_data->op_fid2),
264 op_data->op_name ? op_data->op_name : "<NULL>",
265 tgt->ltd_idx);
266
267 op_data->op_bias &= ~MDS_CROSS_REF;
268
269 rc = md_intent_lock(tgt->ltd_exp, op_data, lmm, lmmsize, it,
270 flags, reqp, cb_blocking, extra_lock_flags);
271
272 if (rc < 0 || *reqp == NULL)
273 return rc;
274
275
276
277
278
279 body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY);
280 if (body == NULL)
281 return -EPROTO;
282
283 if (likely(!(body->valid & OBD_MD_MDS)))
284 return 0;
285
286 rc = lmv_intent_remote(exp, lmm, lmmsize, it, NULL, flags, reqp,
287 cb_blocking, extra_lock_flags);
288
289 return rc;
290}
291
292int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data,
293 void *lmm, int lmmsize, struct lookup_intent *it,
294 int flags, struct ptlrpc_request **reqp,
295 ldlm_blocking_callback cb_blocking,
296 __u64 extra_lock_flags)
297{
298 struct obd_device *obd = exp->exp_obd;
299 int rc;
300
301 LASSERT(it != NULL);
302 LASSERT(fid_is_sane(&op_data->op_fid1));
303
304 CDEBUG(D_INODE, "INTENT LOCK '%s' for '%*s' on "DFID"\n",
305 LL_IT2STR(it), op_data->op_namelen, op_data->op_name,
306 PFID(&op_data->op_fid1));
307
308 rc = lmv_check_connect(obd);
309 if (rc)
310 return rc;
311
312 if (it->it_op & (IT_LOOKUP | IT_GETATTR | IT_LAYOUT))
313 rc = lmv_intent_lookup(exp, op_data, lmm, lmmsize, it,
314 flags, reqp, cb_blocking,
315 extra_lock_flags);
316 else if (it->it_op & IT_OPEN)
317 rc = lmv_intent_open(exp, op_data, lmm, lmmsize, it,
318 flags, reqp, cb_blocking,
319 extra_lock_flags);
320 else
321 LBUG();
322 return rc;
323}
324