Whamcloud - gitweb
- assign ma_lmm and ma_cookie before the calling cross-ref mo_ref_del()
[fs/lustre-release.git] / lustre / mdt / mdt_lib.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/mdt/mdt_lib.c
5  *  Lustre Metadata Target (mdt) request unpacking helper.
6  *
7  *  Copyright (c) 2006 Cluster File Systems, Inc.
8  *   Author: Peter Braam <braam@clusterfs.com>
9  *   Author: Andreas Dilger <adilger@clusterfs.com>
10  *   Author: Phil Schwan <phil@clusterfs.com>
11  *   Author: Mike Shaver <shaver@clusterfs.com>
12  *   Author: Nikita Danilov <nikita@clusterfs.com>
13  *   Author: Huang Hua <huanghua@clusterfs.com>
14  *
15  *
16  *   This file is part of the Lustre file system, http://www.lustre.org
17  *   Lustre is a trademark of Cluster File Systems, Inc.
18  *
19  *   You may have signed or agreed to another license before downloading
20  *   this software.  If so, you are bound by the terms and conditions
21  *   of that agreement, and the following does not apply to you.  See the
22  *   LICENSE file included with this distribution for more information.
23  *
24  *   If you did not agree to a different license, then this copy of Lustre
25  *   is open source software; you can redistribute it and/or modify it
26  *   under the terms of version 2 of the GNU General Public License as
27  *   published by the Free Software Foundation.
28  *
29  *   In either case, Lustre is distributed in the hope that it will be
30  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
31  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32  *   license text for more details.
33  */
34
35
36 #ifndef EXPORT_SYMTAB
37 # define EXPORT_SYMTAB
38 #endif
39 #define DEBUG_SUBSYSTEM S_MDS
40
41 #include "mdt_internal.h"
42
43
44 /* copied from lov/lov_ea.c, just for debugging, will be removed later */
45 void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
46 {
47         const struct lov_ost_data_v1 *lod;
48         int i;
49         __s16 stripe_count =
50                 le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);
51
52         CDEBUG(level, "objid "LPX64", magic 0x%08X, pattern %#X\n",
53                le64_to_cpu(lmm->lmm_object_id), le32_to_cpu(lmm->lmm_magic),
54                le32_to_cpu(lmm->lmm_pattern));
55         CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
56                le32_to_cpu(lmm->lmm_stripe_size),
57                le32_to_cpu(lmm->lmm_stripe_count));
58         LASSERT(stripe_count < (__s16)LOV_MAX_STRIPE_COUNT);
59         for (i = 0, lod = lmm->lmm_objects; i < stripe_count; i++, lod++) {
60                 CDEBUG(level, "stripe %u idx %u subobj "LPX64"/"LPX64"\n",
61                        i, le32_to_cpu(lod->l_ost_idx),
62                        le64_to_cpu(lod->l_object_gr),
63                        le64_to_cpu(lod->l_object_id));
64         }
65 }
66
67 void mdt_shrink_reply(struct mdt_thread_info *info, int offset)
68 {
69         struct ptlrpc_request *req = mdt_info_req(info);
70         struct mdt_body *body;
71         int acl_size = 0;
72         int md_size = 0;
73
74         body = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
75         LASSERT(body != NULL);
76
77         md_size = body->eadatasize;
78         acl_size = body->aclsize;
79
80         CDEBUG(D_INFO, "Shrink to md_size %d cookie_size %d \n",
81                        md_size, acl_size);
82
83         lustre_shrink_reply(req, offset, md_size, 1);
84         lustre_shrink_reply(req, md_size ? offset + 1: offset, acl_size, 0);
85 }
86
87
88 /* if object is dying, pack the lov/llog data,
89  * parameter info->mti_attr should be valid at this point! */
90 int mdt_handle_last_unlink(struct mdt_thread_info *info, struct mdt_object *mo,
91                            const struct md_attr *ma)
92 {
93         struct mdt_body       *repbody;
94         const struct lu_attr *la = &ma->ma_attr;
95         ENTRY;
96
97         repbody = req_capsule_server_get(&info->mti_pill, &RMF_MDT_BODY);
98         LASSERT(repbody != NULL);
99
100         if (ma->ma_valid & MA_INODE)
101                 mdt_pack_attr2body(repbody, la, mdt_object_fid(mo));
102
103         if (ma->ma_valid & MA_LOV) {
104                 __u32 mode;
105
106                 mode = lu_object_attr(&mo->mot_obj.mo_lu);
107                 LASSERT(ma->ma_lmm_size);
108                 mdt_dump_lmm(D_INFO, ma->ma_lmm);
109                 repbody->eadatasize = ma->ma_lmm_size;
110                 if (S_ISREG(mode))
111                         repbody->valid |= OBD_MD_FLEASIZE;
112                 else if (S_ISDIR(mode))
113                         repbody->valid |= OBD_MD_FLDIREA;
114                 else
115                         LBUG();
116         }
117
118         if (ma->ma_cookie_size && (ma->ma_valid & MA_COOKIE)) {
119                 repbody->aclsize = ma->ma_cookie_size;
120                 repbody->valid |= OBD_MD_FLCOOKIE;
121         }
122
123         RETURN(0);
124 }
125
126 static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
127                                   struct md_attr *ma)
128 {
129         __u64 out;
130
131         out = 0;
132         if (in & ATTR_MODE)
133                 out |= LA_MODE;
134         if (in & ATTR_UID)
135                 out |= LA_UID;
136         if (in & ATTR_GID)
137                 out |= LA_GID;
138         if (in & ATTR_SIZE)
139                 out |= LA_SIZE;
140         if (in & ATTR_BLOCKS)
141                 out |= LA_BLOCKS;
142
143         if (in & ATTR_FROM_OPEN)
144                 rr->rr_flags |= MRF_SETATTR_LOCKED;
145
146         if (in & ATTR_ATIME_SET)
147                 out |= LA_ATIME;
148
149         if (in & ATTR_CTIME_SET)
150                 out |= LA_CTIME;
151
152         if (in & ATTR_MTIME_SET)
153                 out |= LA_MTIME;
154
155         if (in & ATTR_ATTR_FLAG)
156                 out |= LA_FLAGS;
157
158         /*XXX need ATTR_RAW?*/
159         in &= ~(ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_BLOCKS|
160                 ATTR_ATIME|ATTR_MTIME|ATTR_CTIME|ATTR_FROM_OPEN|
161                 ATTR_ATIME_SET|ATTR_CTIME_SET|ATTR_MTIME_SET|
162                 ATTR_ATTR_FLAG|ATTR_RAW);
163         if (in != 0)
164                 CERROR("Unknown attr bits: %#llx\n", in);
165         return out;
166 }
167 /* unpacking */
168
169 static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
170 {
171         struct md_attr          *ma = &info->mti_attr;
172         struct lu_attr          *la = &ma->ma_attr;
173         struct req_capsule      *pill = &info->mti_pill;
174         struct mdt_reint_record *rr = &info->mti_rr;
175         struct mdt_rec_setattr  *rec;
176         ENTRY;
177          
178         rec = req_capsule_client_get(pill, &RMF_REC_SETATTR);
179         if (rec == NULL)
180                 RETURN(-EFAULT);
181
182         rr->rr_fid1 = &rec->sa_fid;
183         la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
184         la->la_mode  = rec->sa_mode;
185         la->la_flags = rec->sa_attr_flags;
186         la->la_uid   = rec->sa_uid;
187         la->la_gid   = rec->sa_gid;
188         la->la_size  = rec->sa_size;
189         la->la_blocks = rec->sa_blocks;
190         la->la_ctime = rec->sa_ctime;
191         la->la_atime = rec->sa_atime;
192         la->la_mtime = rec->sa_mtime;
193         ma->ma_valid = MA_INODE;
194         RETURN(0);
195 }
196
197 static int mdt_epoch_unpack(struct mdt_thread_info *info)
198 {
199         struct req_capsule *pill = &info->mti_pill;
200         ENTRY;
201
202         if (req_capsule_get_size(pill, &RMF_MDT_EPOCH, RCL_CLIENT)) 
203                 info->mti_epoch = req_capsule_client_get(pill, &RMF_MDT_EPOCH);
204         else 
205                 /* it is set to NULL already. 
206                 info->mti_epoch = NULL;
207                 */
208                 ;
209         RETURN(info->mti_epoch == NULL ? -EFAULT : 0);
210 }
211
212 static int mdt_setattr_unpack(struct mdt_thread_info *info)
213 {
214         struct md_attr          *ma = &info->mti_attr;
215         struct req_capsule      *pill = &info->mti_pill;
216         int rc;
217         ENTRY;
218
219         rc = mdt_setattr_unpack_rec(info);
220         if (rc)
221                 RETURN(rc);
222
223         /* Epoch may be absent */
224         mdt_epoch_unpack(info);
225
226         if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
227                 ma->ma_lmm = req_capsule_client_get(pill, &RMF_EADATA);
228                 ma->ma_lmm_size = req_capsule_get_size(pill, &RMF_EADATA,
229                                                        RCL_CLIENT);
230                 ma->ma_valid |= MA_LOV;
231         }
232         if (req_capsule_field_present(pill, &RMF_LOGCOOKIES, RCL_CLIENT)) {
233                 ma->ma_cookie = req_capsule_client_get(pill,
234                                                        &RMF_LOGCOOKIES);
235                 ma->ma_cookie_size = req_capsule_get_size(pill,
236                                                           &RMF_LOGCOOKIES,
237                                                           RCL_CLIENT);
238                 ma->ma_valid |= MA_COOKIE;
239         }
240
241         RETURN(0);
242 }
243
244 int mdt_close_unpack(struct mdt_thread_info *info)
245 {
246         int rc;
247         ENTRY;
248
249         rc = mdt_epoch_unpack(info);
250         if (rc)
251                 RETURN(rc);
252         
253         RETURN(mdt_setattr_unpack_rec(info));
254 }
255
256 static int mdt_create_unpack(struct mdt_thread_info *info)
257 {
258         struct mdt_rec_create   *rec;
259         struct lu_attr          *attr = &info->mti_attr.ma_attr;
260         struct mdt_reint_record *rr = &info->mti_rr;
261         struct req_capsule      *pill = &info->mti_pill;
262         int                     result = 0;
263         ENTRY;
264
265         rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
266         if (rec != NULL) {
267                 rr->rr_fid1 = &rec->cr_fid1;
268                 rr->rr_fid2 = &rec->cr_fid2;
269                 attr->la_mode = rec->cr_mode;
270                 attr->la_rdev  = rec->cr_rdev;
271                 attr->la_uid   = rec->cr_fsuid;
272                 attr->la_gid   = rec->cr_fsgid;
273                 attr->la_ctime = rec->cr_time;
274                 attr->la_mtime = rec->cr_time;
275                 attr->la_atime = rec->cr_time;
276                 attr->la_valid = LA_MODE | LA_RDEV | LA_UID | LA_GID |
277                                  LA_CTIME | LA_MTIME | LA_ATIME;
278                 info->mti_spec.sp_cr_flags = rec->cr_flags;
279                 
280                 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
281                 if (S_ISDIR(attr->la_mode)) {
282                         struct md_create_spec *sp = &info->mti_spec;
283                         /* pass parent fid for cross-ref cases */
284                         sp->u.sp_pfid = rr->rr_fid1;
285                         if (info->mti_spec.sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
286                                 /* create salve object req, need 
287                                  * unpack split ea here 
288                                  */
289                                req_capsule_extend(pill, 
290                                                   &RQF_MDS_REINT_CREATE_SLAVE);
291                                LASSERT(req_capsule_field_present(pill, 
292                                                       &RMF_EADATA, RCL_CLIENT));
293                                sp->u.sp_ea.eadata = req_capsule_client_get(pill,
294                                                             &RMF_EADATA);
295                                sp->u.sp_ea.eadatalen =req_capsule_get_size(pill,
296                                                        &RMF_EADATA, RCL_CLIENT);
297                                sp->u.sp_ea.fid = rr->rr_fid1;
298                         }
299                 } else if (S_ISLNK(attr->la_mode)) {
300                         const char *tgt = NULL;
301                         req_capsule_extend(pill, &RQF_MDS_REINT_CREATE_SYM);
302                         if (req_capsule_field_present(pill, &RMF_SYMTGT, 
303                                                       RCL_CLIENT)) {
304                                 tgt = req_capsule_client_get(pill,
305                                                              &RMF_SYMTGT);
306                                 info->mti_spec.u.sp_symname = tgt;
307                         }
308                         if (tgt == NULL)
309                                 result = -EFAULT;
310                 } 
311         } else
312                 result = -EFAULT;
313         RETURN(result);
314 }
315
316 static int mdt_link_unpack(struct mdt_thread_info *info)
317 {
318         struct mdt_rec_link     *rec;
319         struct lu_attr          *attr = &info->mti_attr.ma_attr;
320         struct mdt_reint_record *rr = &info->mti_rr;
321         struct req_capsule      *pill = &info->mti_pill;
322         int                      result = 0;
323         ENTRY;
324
325         rec = req_capsule_client_get(pill, &RMF_REC_LINK);
326         if (rec != NULL) {
327                 attr->la_uid = rec->lk_fsuid;
328                 attr->la_gid = rec->lk_fsgid;
329                 rr->rr_fid1 = &rec->lk_fid1;
330                 rr->rr_fid2 = &rec->lk_fid2;
331                 attr->la_ctime = rec->lk_time;
332                 attr->la_mtime = rec->lk_time;
333                 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
334                 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
335                 if (rr->rr_name == NULL)
336                         result = -EFAULT;
337         } else
338                 result = -EFAULT;
339         RETURN(result);
340 }
341
342 static int mdt_unlink_unpack(struct mdt_thread_info *info)
343 {
344         struct mdt_rec_unlink   *rec;
345         struct lu_attr          *attr = &info->mti_attr.ma_attr;
346         struct mdt_reint_record *rr = &info->mti_rr;
347         struct req_capsule      *pill = &info->mti_pill;
348         int                      result = 0;
349         ENTRY;
350
351         rec = req_capsule_client_get(pill, &RMF_REC_UNLINK);
352         if (rec != NULL) {
353                 attr->la_uid = rec->ul_fsuid;
354                 attr->la_gid = rec->ul_fsgid;
355                 rr->rr_fid1 = &rec->ul_fid1;
356                 rr->rr_fid2 = &rec->ul_fid2;
357                 attr->la_ctime = rec->ul_time;
358                 attr->la_mtime = rec->ul_time;
359                 attr->la_mode  = rec->ul_mode;
360
361                 attr->la_valid = LA_UID   | LA_GID  | LA_CTIME | 
362                                  LA_MTIME | LA_MODE;
363                 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
364                 if (rr->rr_name == NULL)
365                         result = -EFAULT;
366         } else
367                 result = -EFAULT;
368         RETURN(result);
369 }
370
371 static int mdt_rename_unpack(struct mdt_thread_info *info)
372 {
373         struct mdt_rec_rename   *rec;
374         struct lu_attr          *attr = &info->mti_attr.ma_attr;
375         struct mdt_reint_record *rr = &info->mti_rr;
376         struct req_capsule      *pill = &info->mti_pill;
377         int                      result = 0;
378         ENTRY;
379
380         rec = req_capsule_client_get(pill, &RMF_REC_RENAME);
381         if (rec != NULL) {
382                 attr->la_uid = rec->rn_fsuid;
383                 attr->la_gid = rec->rn_fsgid;
384                 rr->rr_fid1 = &rec->rn_fid1;
385                 rr->rr_fid2 = &rec->rn_fid2;
386                 attr->la_ctime = rec->rn_time;
387                 attr->la_mtime = rec->rn_time;
388                 attr->la_valid = LA_UID | LA_GID | LA_CTIME | LA_MTIME;
389                 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
390                 rr->rr_tgt = req_capsule_client_get(pill, &RMF_SYMTGT);
391                 if (rr->rr_name == NULL || rr->rr_tgt == NULL)
392                         result = -EFAULT;
393         } else
394                 result = -EFAULT;
395         RETURN(result);
396 }
397
398 static int mdt_open_unpack(struct mdt_thread_info *info)
399 {
400         struct mdt_rec_create   *rec;
401         struct lu_attr          *attr = &info->mti_attr.ma_attr;
402         struct req_capsule      *pill = &info->mti_pill;
403         struct mdt_reint_record *rr   = &info->mti_rr;
404         int                     result;
405         ENTRY;
406
407         rec = req_capsule_client_get(pill, &RMF_REC_CREATE);
408         if (rec != NULL) {
409                 rr->rr_fid1   = &rec->cr_fid1;
410                 rr->rr_fid2   = &rec->cr_fid2;
411                 attr->la_mode = rec->cr_mode;
412                 attr->la_rdev  = rec->cr_rdev;
413                 attr->la_uid   = rec->cr_fsuid;
414                 attr->la_gid   = rec->cr_fsgid;
415                 attr->la_ctime = rec->cr_time;
416                 attr->la_mtime = rec->cr_time;
417                 attr->la_atime = rec->cr_time;
418                 attr->la_valid = LA_MODE  | LA_RDEV  | LA_UID   | LA_GID |
419                                  LA_CTIME | LA_MTIME | LA_ATIME;
420                 info->mti_spec.sp_cr_flags = rec->cr_flags;
421                 rr->rr_name = req_capsule_client_get(pill, &RMF_NAME);
422                 if (rr->rr_name == NULL)
423                         result = -EFAULT;
424                 else
425                         result = 0;
426         } else
427                 result = -EFAULT;
428
429         if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
430                 struct md_create_spec *sp = &info->mti_spec;
431                 struct ptlrpc_request *req = mdt_info_req(info);
432                 sp->u.sp_ea.eadata = req_capsule_client_get(pill,
433                                                             &RMF_EADATA);
434                 sp->u.sp_ea.eadatalen = req_capsule_get_size(pill,
435                                                              &RMF_EADATA,
436                                                              RCL_CLIENT);
437                 if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
438                         sp->u.sp_ea.no_lov_create = 1;
439         }
440
441         RETURN(result);
442 }
443
444 typedef int (*reint_unpacker)(struct mdt_thread_info *info);
445
446 static reint_unpacker mdt_reint_unpackers[REINT_MAX] = {
447         [REINT_SETATTR]  = mdt_setattr_unpack,
448         [REINT_CREATE]   = mdt_create_unpack,
449         [REINT_LINK]     = mdt_link_unpack,
450         [REINT_UNLINK]   = mdt_unlink_unpack,
451         [REINT_RENAME]   = mdt_rename_unpack,
452         [REINT_OPEN]     = mdt_open_unpack
453 };
454
455 int mdt_reint_unpack(struct mdt_thread_info *info, __u32 op)
456 {
457         int rc;
458
459         ENTRY;
460
461         if (op < REINT_MAX && mdt_reint_unpackers[op] != NULL) {
462                 info->mti_rr.rr_opcode = op;
463                 rc = mdt_reint_unpackers[op](info);
464         } else {
465                 CERROR("Unexpected opcode %d\n", op);
466                 rc = -EFAULT;
467         }
468         RETURN(rc);
469 }