Whamcloud - gitweb
d373f0b515d05091c199826003ec844591ce7229
[fs/lustre-release.git] / lustre / cmm / mdc_object.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) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/cmm/mdc_object.c
37  *
38  * Lustre Cluster Metadata Manager (cmm)
39  *
40  * Author: Mike Pershin <tappro@clusterfs.com>
41  */
42
43 #ifndef EXPORT_SYMTAB
44 # define EXPORT_SYMTAB
45 #endif
46
47 #define DEBUG_SUBSYSTEM S_MDS
48 #include <obd_support.h>
49 #include <lustre_lib.h>
50 #include <obd_class.h>
51 #include <lustre_mdc.h>
52 #include "cmm_internal.h"
53 #include "mdc_internal.h"
54
55 static const struct md_object_operations mdc_mo_ops;
56 static const struct md_dir_operations mdc_dir_ops;
57 static const struct lu_object_operations mdc_obj_ops;
58
59 extern struct lu_context_key mdc_thread_key;
60 /**
61  * \addtogroup cmm_mdc
62  * @{
63  */
64 /**
65  * Allocate new mdc object.
66  */
67 struct lu_object *mdc_object_alloc(const struct lu_env *env,
68                                    const struct lu_object_header *hdr,
69                                    struct lu_device *ld)
70 {
71         struct mdc_object *mco;
72         ENTRY;
73
74         OBD_ALLOC_PTR(mco);
75         if (mco != NULL) {
76                 struct lu_object *lo;
77
78                 lo = &mco->mco_obj.mo_lu;
79                 lu_object_init(lo, NULL, ld);
80                 mco->mco_obj.mo_ops = &mdc_mo_ops;
81                 mco->mco_obj.mo_dir_ops = &mdc_dir_ops;
82                 lo->lo_ops = &mdc_obj_ops;
83                 RETURN(lo);
84         } else
85                 RETURN(NULL);
86 }
87
88 /** Free current mdc object */
89 static void mdc_object_free(const struct lu_env *env, struct lu_object *lo)
90 {
91         struct mdc_object *mco = lu2mdc_obj(lo);
92         lu_object_fini(lo);
93         OBD_FREE_PTR(mco);
94 }
95
96 /**
97  * Initialize mdc object. All of them have loh_attr::LOHA_REMOTE set.
98  */
99 static int mdc_object_init(const struct lu_env *env, struct lu_object *lo,
100                            const struct lu_object_conf *unused)
101 {
102         ENTRY;
103         lo->lo_header->loh_attr |= LOHA_REMOTE;
104         RETURN(0);
105 }
106
107 /**
108  * Instance of lu_object_operations for mdc.
109  */
110 static const struct lu_object_operations mdc_obj_ops = {
111         .loo_object_init    = mdc_object_init,
112         .loo_object_free    = mdc_object_free,
113 };
114
115 /**
116  * \name The set of md_object_operations.
117  * @{
118  */
119 /**
120  * Get mdc_thread_info from lu_context
121  */
122 static
123 struct mdc_thread_info *mdc_info_get(const struct lu_env *env)
124 {
125         struct mdc_thread_info *mci;
126
127         mci = lu_context_key_get(&env->le_ctx, &mdc_thread_key);
128         LASSERT(mci);
129         return mci;
130 }
131
132 /**
133  * Initialize mdc_thread_info.
134  */
135 static
136 struct mdc_thread_info *mdc_info_init(const struct lu_env *env)
137 {
138         struct mdc_thread_info *mci = mdc_info_get(env);
139         memset(mci, 0, sizeof(*mci));
140         return mci;
141 }
142
143 /**
144  * Convert attributes from mdt_body to the md_attr.
145  */
146 static void mdc_body2attr(struct mdt_body *body, struct md_attr *ma)
147 {
148         struct lu_attr *la = &ma->ma_attr;
149         /* update time */
150         if (body->valid & OBD_MD_FLCTIME && body->ctime >= la->la_ctime) {
151                 la->la_ctime = body->ctime;
152                 if (body->valid & OBD_MD_FLMTIME)
153                         la->la_mtime = body->mtime;
154         }
155
156         if (body->valid & OBD_MD_FLMODE)
157                 la->la_mode = body->mode;
158         if (body->valid & OBD_MD_FLSIZE)
159                 la->la_size = body->size;
160         if (body->valid & OBD_MD_FLBLOCKS)
161                 la->la_blocks = body->blocks;
162         if (body->valid & OBD_MD_FLUID)
163                 la->la_uid = body->uid;
164         if (body->valid & OBD_MD_FLGID)
165                 la->la_gid = body->gid;
166         if (body->valid & OBD_MD_FLFLAGS)
167                 la->la_flags = body->flags;
168         if (body->valid & OBD_MD_FLNLINK)
169                 la->la_nlink = body->nlink;
170         if (body->valid & OBD_MD_FLRDEV)
171                 la->la_rdev = body->rdev;
172
173         la->la_valid = body->valid;
174         ma->ma_valid = MA_INODE;
175 }
176
177 /**
178  * Fill the md_attr \a ma with attributes from request.
179  */
180 static int mdc_req2attr_update(const struct lu_env *env,
181                                struct md_attr *ma)
182 {
183         struct mdc_thread_info *mci;
184         struct ptlrpc_request *req;
185         struct mdt_body *body;
186         struct lov_mds_md *md;
187         struct llog_cookie *cookie;
188         void *acl;
189
190         ENTRY;
191         mci = mdc_info_get(env);
192         req = mci->mci_req;
193         LASSERT(req);
194         body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
195         LASSERT(body);
196         mdc_body2attr(body, ma);
197
198         if (body->valid & OBD_MD_FLMDSCAPA) {
199                 struct lustre_capa *capa;
200
201                 /* create for cross-ref will fetch mds capa from remote obj */
202                 capa = req_capsule_server_get(&req->rq_pill, &RMF_CAPA1);
203                 LASSERT(capa != NULL);
204                 LASSERT(ma->ma_capa != NULL);
205                 *ma->ma_capa = *capa;
206         }
207
208         if ((body->valid & OBD_MD_FLEASIZE) || (body->valid & OBD_MD_FLDIREA)) {
209                 if (body->eadatasize == 0) {
210                         CERROR("No size defined for easize field\n");
211                         RETURN(-EPROTO);
212                 }
213
214                 md = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD,
215                                                   body->eadatasize);
216                 if (md == NULL)
217                         RETURN(-EPROTO);
218
219                 LASSERT(ma->ma_lmm != NULL);
220                 LASSERT(ma->ma_lmm_size >= body->eadatasize);
221                 ma->ma_lmm_size = body->eadatasize;
222                 memcpy(ma->ma_lmm, md, ma->ma_lmm_size);
223                 ma->ma_valid |= MA_LOV;
224         }
225
226         if (body->valid & OBD_MD_FLCOOKIE) {
227                 /*
228                  * ACL and cookie share the same body->aclsize, we need
229                  * to make sure that they both never come here.
230                  */
231                 LASSERT(!(body->valid & OBD_MD_FLACL));
232
233                 if (body->aclsize == 0) {
234                         CERROR("No size defined for cookie field\n");
235                         RETURN(-EPROTO);
236                 }
237
238                 cookie = req_capsule_server_sized_get(&req->rq_pill,
239                                                       &RMF_LOGCOOKIES,
240                                                       body->aclsize);
241                 if (cookie == NULL)
242                         RETURN(-EPROTO);
243
244                 LASSERT(ma->ma_cookie != NULL);
245                 LASSERT(ma->ma_cookie_size == body->aclsize);
246                 memcpy(ma->ma_cookie, cookie, ma->ma_cookie_size);
247                 ma->ma_valid |= MA_COOKIE;
248         }
249
250 #ifdef CONFIG_FS_POSIX_ACL
251         if (body->valid & OBD_MD_FLACL) {
252                 if (body->aclsize == 0) {
253                         CERROR("No size defined for acl field\n");
254                         RETURN(-EPROTO);
255                 }
256
257                 acl = req_capsule_server_sized_get(&req->rq_pill,
258                                                    &RMF_ACL,
259                                                    body->aclsize);
260                 if (acl == NULL)
261                         RETURN(-EPROTO);
262
263                 LASSERT(ma->ma_acl != NULL);
264                 LASSERT(ma->ma_acl_size == body->aclsize);
265                 memcpy(ma->ma_acl, acl, ma->ma_acl_size);
266                 ma->ma_valid |= MA_ACL_DEF;
267         }
268 #endif
269
270         RETURN(0);
271 }
272
273 /**
274  * The md_object_operations::moo_attr_get() in mdc.
275  */
276 static int mdc_attr_get(const struct lu_env *env, struct md_object *mo,
277                         struct md_attr *ma)
278 {
279         struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
280         struct mdc_thread_info *mci;
281         int rc;
282         ENTRY;
283
284         mci = lu_context_key_get(&env->le_ctx, &mdc_thread_key);
285         LASSERT(mci);
286
287         memset(&mci->mci_opdata, 0, sizeof(mci->mci_opdata));
288
289         memcpy(&mci->mci_opdata.op_fid1, lu_object_fid(&mo->mo_lu),
290                sizeof (struct lu_fid));
291         mci->mci_opdata.op_valid = OBD_MD_FLMODE | OBD_MD_FLUID |
292                                    OBD_MD_FLGID | OBD_MD_FLFLAGS |
293                                    OBD_MD_FLCROSSREF;
294
295         rc = md_getattr(mc->mc_desc.cl_exp, &mci->mci_opdata, &mci->mci_req);
296         if (rc == 0) {
297                 /* get attr from request */
298                 rc = mdc_req2attr_update(env, ma);
299         }
300
301         ptlrpc_req_finished(mci->mci_req);
302
303         RETURN(rc);
304 }
305
306 /**
307  * Helper to init timspec \a t.
308  */
309 static inline struct timespec *mdc_attr_time(struct timespec *t, __u64 seconds)
310 {
311         t->tv_sec = seconds;
312         t->tv_nsec = 0;
313         return t;
314 }
315
316 /**
317  * The md_object_operations::moo_attr_set() in mdc.
318  *
319  * \note It is only used for set ctime when rename's source on remote MDS.
320  */
321 static int mdc_attr_set(const struct lu_env *env, struct md_object *mo,
322                         const struct md_attr *ma)
323 {
324         struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
325         const struct lu_attr *la = &ma->ma_attr;
326         struct mdc_thread_info *mci;
327         struct md_ucred *uc = md_ucred(env);
328         int rc;
329         ENTRY;
330
331         LASSERT(ma->ma_attr.la_valid & LA_CTIME);
332
333         mci = lu_context_key_get(&env->le_ctx, &mdc_thread_key);
334         LASSERT(mci);
335
336         memset(&mci->mci_opdata, 0, sizeof(mci->mci_opdata));
337
338         mci->mci_opdata.op_fid1 = *lu_object_fid(&mo->mo_lu);
339         mdc_attr_time(&mci->mci_opdata.op_attr.ia_ctime, la->la_ctime);
340         mci->mci_opdata.op_attr.ia_mode = la->la_mode;
341         mci->mci_opdata.op_attr.ia_valid = ATTR_CTIME_SET;
342         if (uc &&
343             ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
344                 mci->mci_opdata.op_fsuid = uc->mu_fsuid;
345                 mci->mci_opdata.op_fsgid = uc->mu_fsgid;
346                 mci->mci_opdata.op_cap = uc->mu_cap;
347                 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD)) {
348                         mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
349                         mci->mci_opdata.op_suppgids[1] = uc->mu_suppgids[1];
350                 } else {
351                         mci->mci_opdata.op_suppgids[0] =
352                                 mci->mci_opdata.op_suppgids[1] = -1;
353                 }
354         } else {
355                 mci->mci_opdata.op_fsuid = la->la_uid;
356                 mci->mci_opdata.op_fsgid = la->la_gid;
357                 mci->mci_opdata.op_cap = cfs_curproc_cap_pack();
358                 mci->mci_opdata.op_suppgids[0] =
359                                 mci->mci_opdata.op_suppgids[1] = -1;
360         }
361
362         rc = md_setattr(mc->mc_desc.cl_exp, &mci->mci_opdata,
363                         NULL, 0, NULL, 0, &mci->mci_req, NULL);
364
365         ptlrpc_req_finished(mci->mci_req);
366
367         RETURN(rc);
368 }
369
370 /**
371  * The md_object_operations::moo_object_create() in mdc.
372  */
373 static int mdc_object_create(const struct lu_env *env,
374                              struct md_object *mo,
375                              const struct md_op_spec *spec,
376                              struct md_attr *ma)
377 {
378         struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
379         struct lu_attr *la = &ma->ma_attr;
380         struct mdc_thread_info *mci;
381         const void *symname;
382         struct md_ucred *uc = md_ucred(env);
383         int rc, symlen;
384         uid_t uid;
385         gid_t gid;
386         cfs_cap_t cap;
387         ENTRY;
388
389         LASSERT(S_ISDIR(la->la_mode));
390         LASSERT(spec->u.sp_pfid != NULL);
391
392         mci = mdc_info_init(env);
393         mci->mci_opdata.op_bias = MDS_CROSS_REF;
394         mci->mci_opdata.op_fid2 = *lu_object_fid(&mo->mo_lu);
395
396         /* Parent fid is needed to create dotdot on the remote node. */
397         mci->mci_opdata.op_fid1 = *(spec->u.sp_pfid);
398         mci->mci_opdata.op_mod_time = la->la_ctime;
399         if (uc &&
400             ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
401                 uid = uc->mu_fsuid;
402                 if (la->la_mode & S_ISGID)
403                         gid = la->la_gid;
404                 else
405                         gid = uc->mu_fsgid;
406                 cap = uc->mu_cap;
407                 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD))
408                         mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
409                 else
410                         mci->mci_opdata.op_suppgids[0] = -1;
411         } else {
412                 uid = la->la_uid;
413                 gid = la->la_gid;
414                 cap = 0;
415                 mci->mci_opdata.op_suppgids[0] = -1;
416         }
417
418         /* get data from spec */
419         if (spec->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
420                 symname = spec->u.sp_ea.eadata;
421                 symlen = spec->u.sp_ea.eadatalen;
422                 mci->mci_opdata.op_fid1 = *(spec->u.sp_ea.fid);
423                 mci->mci_opdata.op_flags |= MDS_CREATE_SLAVE_OBJ;
424 #ifdef CONFIG_FS_POSIX_ACL
425         } else if (spec->sp_cr_flags & MDS_CREATE_RMT_ACL) {
426                 symname = spec->u.sp_ea.eadata;
427                 symlen = spec->u.sp_ea.eadatalen;
428                 mci->mci_opdata.op_fid1 = *(spec->u.sp_ea.fid);
429                 mci->mci_opdata.op_flags |= MDS_CREATE_RMT_ACL;
430 #endif
431         } else {
432                 symname = spec->u.sp_symname;
433                 symlen = symname ? strlen(symname) + 1 : 0;
434         }
435
436         rc = md_create(mc->mc_desc.cl_exp, &mci->mci_opdata,
437                        symname, symlen, la->la_mode, uid, gid,
438                        cap, la->la_rdev, &mci->mci_req);
439
440         if (rc == 0) {
441                 /* get attr from request */
442                 rc = mdc_req2attr_update(env, ma);
443         }
444
445         ptlrpc_req_finished(mci->mci_req);
446
447         RETURN(rc);
448 }
449
450 /**
451  * The md_object_operations::moo_ref_add() in mdc.
452  */
453 static int mdc_ref_add(const struct lu_env *env, struct md_object *mo,
454                        const struct md_attr *ma)
455 {
456         struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
457         const struct lu_attr *la = &ma->ma_attr;
458         struct mdc_thread_info *mci;
459         struct md_ucred *uc = md_ucred(env);
460         int rc;
461         ENTRY;
462
463         mci = lu_context_key_get(&env->le_ctx, &mdc_thread_key);
464         LASSERT(mci);
465
466         memset(&mci->mci_opdata, 0, sizeof(mci->mci_opdata));
467         mci->mci_opdata.op_bias = MDS_CROSS_REF;
468         mci->mci_opdata.op_fid1 = *lu_object_fid(&mo->mo_lu);
469         mci->mci_opdata.op_mod_time = la->la_ctime;
470         if (uc &&
471             ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
472                 mci->mci_opdata.op_fsuid = uc->mu_fsuid;
473                 mci->mci_opdata.op_fsgid = uc->mu_fsgid;
474                 mci->mci_opdata.op_cap = uc->mu_cap;
475                 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD)) {
476                         mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
477                         mci->mci_opdata.op_suppgids[1] = uc->mu_suppgids[1];
478                 } else {
479                         mci->mci_opdata.op_suppgids[0] =
480                                 mci->mci_opdata.op_suppgids[1] = -1;
481                 }
482         } else {
483                 mci->mci_opdata.op_fsuid = la->la_uid;
484                 mci->mci_opdata.op_fsgid = la->la_gid;
485                 mci->mci_opdata.op_cap = cfs_curproc_cap_pack();
486                 mci->mci_opdata.op_suppgids[0] =
487                                 mci->mci_opdata.op_suppgids[1] = -1;
488         }
489
490
491         rc = md_link(mc->mc_desc.cl_exp, &mci->mci_opdata, &mci->mci_req);
492
493         ptlrpc_req_finished(mci->mci_req);
494
495         RETURN(rc);
496 }
497
498 /**
499  * The md_object_operations::moo_ref_del() in mdc.
500  */
501 static int mdc_ref_del(const struct lu_env *env, struct md_object *mo,
502                        struct md_attr *ma)
503 {
504         struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
505         struct lu_attr *la = &ma->ma_attr;
506         struct mdc_thread_info *mci;
507         struct md_ucred *uc = md_ucred(env);
508         int rc;
509         ENTRY;
510
511         mci = mdc_info_init(env);
512         mci->mci_opdata.op_bias = MDS_CROSS_REF;
513         if (ma->ma_attr_flags & MDS_VTX_BYPASS)
514                 mci->mci_opdata.op_bias |= MDS_VTX_BYPASS;
515         else
516                 mci->mci_opdata.op_bias &= ~MDS_VTX_BYPASS;
517         mci->mci_opdata.op_fid1 = *lu_object_fid(&mo->mo_lu);
518         mci->mci_opdata.op_mode = la->la_mode;
519         mci->mci_opdata.op_mod_time = la->la_ctime;
520         if (uc &&
521             ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
522                 mci->mci_opdata.op_fsuid = uc->mu_fsuid;
523                 mci->mci_opdata.op_fsgid = uc->mu_fsgid;
524                 mci->mci_opdata.op_cap = uc->mu_cap;
525                 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD))
526                         mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
527                 else
528                         mci->mci_opdata.op_suppgids[0] = -1;
529         } else {
530                 mci->mci_opdata.op_fsuid = la->la_uid;
531                 mci->mci_opdata.op_fsgid = la->la_gid;
532                 mci->mci_opdata.op_cap = cfs_curproc_cap_pack();
533                 mci->mci_opdata.op_suppgids[0] = -1;
534         }
535
536         rc = md_unlink(mc->mc_desc.cl_exp, &mci->mci_opdata, &mci->mci_req);
537         if (rc == 0) {
538                 /* get attr from request */
539                 rc = mdc_req2attr_update(env, ma);
540         }
541
542         ptlrpc_req_finished(mci->mci_req);
543
544         RETURN(rc);
545 }
546
547 #ifdef HAVE_SPLIT_SUPPORT
548 /** Send page with directory entries to another MDS. */
549 int mdc_send_page(struct cmm_device *cm, const struct lu_env *env,
550                   struct md_object *mo, struct page *page, __u32 offset)
551 {
552         struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
553         int rc;
554         ENTRY;
555
556         rc = mdc_sendpage(mc->mc_desc.cl_exp, lu_object_fid(&mo->mo_lu),
557                           page, offset);
558         CDEBUG(rc ? D_ERROR : D_INFO, "send page %p  offset %d fid "DFID
559                " rc %d \n", page, offset, PFID(lu_object_fid(&mo->mo_lu)), rc);
560         RETURN(rc);
561 }
562 #endif
563
564 /**
565  * Instance of md_object_operations for mdc.
566  */
567 static const struct md_object_operations mdc_mo_ops = {
568         .moo_attr_get       = mdc_attr_get,
569         .moo_attr_set       = mdc_attr_set,
570         .moo_object_create  = mdc_object_create,
571         .moo_ref_add        = mdc_ref_add,
572         .moo_ref_del        = mdc_ref_del,
573 };
574 /** @} */
575
576 /**
577  * \name The set of md_dir_operations.
578  * @{
579  */
580 /**
581  * The md_dir_operations::mdo_rename_tgt in mdc.
582  */
583 static int mdc_rename_tgt(const struct lu_env *env, struct md_object *mo_p,
584                           struct md_object *mo_t, const struct lu_fid *lf,
585                           const struct lu_name *lname, struct md_attr *ma)
586 {
587         struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo_p));
588         struct lu_attr *la = &ma->ma_attr;
589         struct mdc_thread_info *mci;
590         struct md_ucred *uc = md_ucred(env);
591         int rc;
592         ENTRY;
593
594         mci = mdc_info_init(env);
595         mci->mci_opdata.op_bias = MDS_CROSS_REF;
596         if (ma->ma_attr_flags & MDS_VTX_BYPASS)
597                 mci->mci_opdata.op_bias |= MDS_VTX_BYPASS;
598         else
599                 mci->mci_opdata.op_bias &= ~MDS_VTX_BYPASS;
600         mci->mci_opdata.op_fid1 = *lu_object_fid(&mo_p->mo_lu);
601         mci->mci_opdata.op_fid2 = *lf;
602         mci->mci_opdata.op_mode = la->la_mode;
603         mci->mci_opdata.op_mod_time = la->la_ctime;
604         if (uc &&
605             ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
606                 mci->mci_opdata.op_fsuid = uc->mu_fsuid;
607                 mci->mci_opdata.op_fsgid = uc->mu_fsgid;
608                 mci->mci_opdata.op_cap = uc->mu_cap;
609                 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD)) {
610                         mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
611                         mci->mci_opdata.op_suppgids[1] = uc->mu_suppgids[1];
612                 } else {
613                         mci->mci_opdata.op_suppgids[0] =
614                                 mci->mci_opdata.op_suppgids[1] = -1;
615                 }
616         } else {
617                 mci->mci_opdata.op_fsuid = la->la_uid;
618                 mci->mci_opdata.op_fsgid = la->la_gid;
619                 mci->mci_opdata.op_cap = cfs_curproc_cap_pack();
620                 mci->mci_opdata.op_suppgids[0] =
621                                 mci->mci_opdata.op_suppgids[1] = -1;
622         }
623
624         rc = md_rename(mc->mc_desc.cl_exp, &mci->mci_opdata, NULL, 0,
625                        lname->ln_name, lname->ln_namelen, &mci->mci_req);
626         if (rc == 0) {
627                 /* get attr from request */
628                 mdc_req2attr_update(env, ma);
629         }
630
631         ptlrpc_req_finished(mci->mci_req);
632
633         RETURN(rc);
634 }
635 /**
636  * Check the fids are not relatives.
637  * The md_dir_operations::mdo_is_subdir() in mdc.
638  *
639  * Return resulting fid in sfid.
640  * \retval \a sfid = 0 fids are not relatives
641  * \retval \a sfid = FID at which search stopped
642  */
643 static int mdc_is_subdir(const struct lu_env *env, struct md_object *mo,
644                          const struct lu_fid *fid, struct lu_fid *sfid)
645 {
646         struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
647         struct mdc_thread_info *mci;
648         struct mdt_body *body;
649         int rc;
650         ENTRY;
651
652         mci = mdc_info_init(env);
653
654         rc = md_is_subdir(mc->mc_desc.cl_exp, lu_object_fid(&mo->mo_lu),
655                           fid, &mci->mci_req);
656         if (rc == 0 || rc == -EREMOTE) {
657                 body = req_capsule_server_get(&mci->mci_req->rq_pill,
658                                               &RMF_MDT_BODY);
659                 LASSERT(body->valid & OBD_MD_FLID);
660
661                 CDEBUG(D_INFO, "Remote mdo_is_subdir(), new src "DFID"\n",
662                        PFID(&body->fid1));
663                 *sfid = body->fid1;
664         }
665         ptlrpc_req_finished(mci->mci_req);
666         RETURN(rc);
667 }
668
669 /** Instance of md_dir_operations for mdc. */
670 static const struct md_dir_operations mdc_dir_ops = {
671         .mdo_is_subdir   = mdc_is_subdir,
672         .mdo_rename_tgt  = mdc_rename_tgt
673 };
674 /** @} */