1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/cmm/mdc_object.c
38 * Lustre Cluster Metadata Manager (cmm)
40 * Author: Mike Pershin <tappro@clusterfs.com>
44 # define EXPORT_SYMTAB
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"
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;
59 extern struct lu_context_key mdc_thread_key;
61 struct lu_object *mdc_object_alloc(const struct lu_env *env,
62 const struct lu_object_header *hdr,
65 struct mdc_object *mco;
72 lo = &mco->mco_obj.mo_lu;
73 lu_object_init(lo, NULL, ld);
74 mco->mco_obj.mo_ops = &mdc_mo_ops;
75 mco->mco_obj.mo_dir_ops = &mdc_dir_ops;
76 lo->lo_ops = &mdc_obj_ops;
82 static void mdc_object_free(const struct lu_env *env, struct lu_object *lo)
84 struct mdc_object *mco = lu2mdc_obj(lo);
89 static int mdc_object_init(const struct lu_env *env, struct lu_object *lo,
90 const struct lu_object_conf *_)
93 lo->lo_header->loh_attr |= LOHA_REMOTE;
97 static const struct lu_object_operations mdc_obj_ops = {
98 .loo_object_init = mdc_object_init,
99 .loo_object_free = mdc_object_free,
102 /* md_object_operations */
104 struct mdc_thread_info *mdc_info_get(const struct lu_env *env)
106 struct mdc_thread_info *mci;
108 mci = lu_context_key_get(&env->le_ctx, &mdc_thread_key);
114 struct mdc_thread_info *mdc_info_init(const struct lu_env *env)
116 struct mdc_thread_info *mci = mdc_info_get(env);
117 memset(mci, 0, sizeof(*mci));
121 static void mdc_body2attr(struct mdt_body *body, struct md_attr *ma)
123 struct lu_attr *la = &ma->ma_attr;
125 if (body->valid & OBD_MD_FLCTIME && body->ctime >= la->la_ctime) {
126 la->la_ctime = body->ctime;
127 if (body->valid & OBD_MD_FLMTIME)
128 la->la_mtime = body->mtime;
131 if (body->valid & OBD_MD_FLMODE)
132 la->la_mode = body->mode;
133 if (body->valid & OBD_MD_FLSIZE)
134 la->la_size = body->size;
135 if (body->valid & OBD_MD_FLBLOCKS)
136 la->la_blocks = body->blocks;
137 if (body->valid & OBD_MD_FLUID)
138 la->la_uid = body->uid;
139 if (body->valid & OBD_MD_FLGID)
140 la->la_gid = body->gid;
141 if (body->valid & OBD_MD_FLFLAGS)
142 la->la_flags = body->flags;
143 if (body->valid & OBD_MD_FLNLINK)
144 la->la_nlink = body->nlink;
145 if (body->valid & OBD_MD_FLRDEV)
146 la->la_rdev = body->rdev;
148 la->la_valid = body->valid;
149 ma->ma_valid = MA_INODE;
152 static int mdc_req2attr_update(const struct lu_env *env,
155 struct mdc_thread_info *mci;
156 struct ptlrpc_request *req;
157 struct mdt_body *body;
158 struct lov_mds_md *md;
159 struct llog_cookie *cookie;
163 mci = mdc_info_get(env);
166 body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
168 mdc_body2attr(body, ma);
170 if (body->valid & OBD_MD_FLMDSCAPA) {
171 struct lustre_capa *capa;
173 /* create for cross-ref will fetch mds capa from remote obj */
174 capa = req_capsule_server_get(&req->rq_pill, &RMF_CAPA1);
175 LASSERT(capa != NULL);
176 LASSERT(ma->ma_capa != NULL);
177 *ma->ma_capa = *capa;
180 if ((body->valid & OBD_MD_FLEASIZE) || (body->valid & OBD_MD_FLDIREA)) {
181 if (body->eadatasize == 0) {
182 CERROR("No size defined for easize field\n");
186 md = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD,
191 LASSERT(ma->ma_lmm != NULL);
192 LASSERT(ma->ma_lmm_size >= body->eadatasize);
193 ma->ma_lmm_size = body->eadatasize;
194 memcpy(ma->ma_lmm, md, ma->ma_lmm_size);
195 ma->ma_valid |= MA_LOV;
198 if (body->valid & OBD_MD_FLCOOKIE) {
200 * ACL and cookie share the same body->aclsize, we need
201 * to make sure that they both never come here.
203 LASSERT(!(body->valid & OBD_MD_FLACL));
205 if (body->aclsize == 0) {
206 CERROR("No size defined for cookie field\n");
210 cookie = req_capsule_server_sized_get(&req->rq_pill,
216 LASSERT(ma->ma_cookie != NULL);
217 LASSERT(ma->ma_cookie_size == body->aclsize);
218 memcpy(ma->ma_cookie, cookie, ma->ma_cookie_size);
219 ma->ma_valid |= MA_COOKIE;
222 #ifdef CONFIG_FS_POSIX_ACL
223 if (body->valid & OBD_MD_FLACL) {
224 if (body->aclsize == 0) {
225 CERROR("No size defined for acl field\n");
229 acl = req_capsule_server_sized_get(&req->rq_pill,
235 LASSERT(ma->ma_acl != NULL);
236 LASSERT(ma->ma_acl_size == body->aclsize);
237 memcpy(ma->ma_acl, acl, ma->ma_acl_size);
238 ma->ma_valid |= MA_ACL_DEF;
245 static int mdc_attr_get(const struct lu_env *env, struct md_object *mo,
248 struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
249 struct mdc_thread_info *mci;
253 mci = lu_context_key_get(&env->le_ctx, &mdc_thread_key);
256 memset(&mci->mci_opdata, 0, sizeof(mci->mci_opdata));
258 rc = md_getattr(mc->mc_desc.cl_exp, lu_object_fid(&mo->mo_lu),
259 NULL, OBD_MD_FLMODE | OBD_MD_FLUID | OBD_MD_FLGID |
260 OBD_MD_FLFLAGS | OBD_MD_FLCROSSREF, 0, &mci->mci_req);
262 /* get attr from request */
263 rc = mdc_req2attr_update(env, ma);
266 ptlrpc_req_finished(mci->mci_req);
271 static inline struct timespec *mdc_attr_time(struct timespec *t, __u64 seconds)
279 * XXX: It is only used for set ctime when rename's source on remote MDS.
281 static int mdc_attr_set(const struct lu_env *env, struct md_object *mo,
282 const struct md_attr *ma)
284 struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
285 const struct lu_attr *la = &ma->ma_attr;
286 struct mdc_thread_info *mci;
287 struct md_ucred *uc = md_ucred(env);
291 LASSERT(ma->ma_attr.la_valid & LA_CTIME);
293 mci = lu_context_key_get(&env->le_ctx, &mdc_thread_key);
296 memset(&mci->mci_opdata, 0, sizeof(mci->mci_opdata));
298 mci->mci_opdata.op_fid1 = *lu_object_fid(&mo->mo_lu);
299 mdc_attr_time(&mci->mci_opdata.op_attr.ia_ctime, la->la_ctime);
300 mci->mci_opdata.op_attr.ia_mode = la->la_mode;
301 mci->mci_opdata.op_attr.ia_valid = ATTR_CTIME_SET;
303 ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
304 mci->mci_opdata.op_fsuid = uc->mu_fsuid;
305 mci->mci_opdata.op_fsgid = uc->mu_fsgid;
306 mci->mci_opdata.op_cap = uc->mu_cap;
307 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD)) {
308 mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
309 mci->mci_opdata.op_suppgids[1] = uc->mu_suppgids[1];
311 mci->mci_opdata.op_suppgids[0] =
312 mci->mci_opdata.op_suppgids[1] = -1;
315 mci->mci_opdata.op_fsuid = la->la_uid;
316 mci->mci_opdata.op_fsgid = la->la_gid;
317 mci->mci_opdata.op_cap = cfs_curproc_cap_pack();
318 mci->mci_opdata.op_suppgids[0] =
319 mci->mci_opdata.op_suppgids[1] = -1;
322 rc = md_setattr(mc->mc_desc.cl_exp, &mci->mci_opdata,
323 NULL, 0, NULL, 0, &mci->mci_req, NULL);
325 ptlrpc_req_finished(mci->mci_req);
330 static int mdc_object_create(const struct lu_env *env,
331 struct md_object *mo,
332 const struct md_op_spec *spec,
335 struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
336 struct lu_attr *la = &ma->ma_attr;
337 struct mdc_thread_info *mci;
339 struct md_ucred *uc = md_ucred(env);
346 LASSERT(S_ISDIR(la->la_mode));
347 LASSERT(spec->u.sp_pfid != NULL);
349 mci = mdc_info_init(env);
350 mci->mci_opdata.op_bias = MDS_CROSS_REF;
351 mci->mci_opdata.op_fid2 = *lu_object_fid(&mo->mo_lu);
353 /* Parent fid is needed to create dotdot on the remote node. */
354 mci->mci_opdata.op_fid1 = *(spec->u.sp_pfid);
355 mci->mci_opdata.op_mod_time = la->la_ctime;
357 ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
359 if (la->la_mode & S_ISGID)
364 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD))
365 mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
367 mci->mci_opdata.op_suppgids[0] = -1;
372 mci->mci_opdata.op_suppgids[0] = -1;
375 /* get data from spec */
376 if (spec->sp_cr_flags & MDS_CREATE_SLAVE_OBJ) {
377 symname = spec->u.sp_ea.eadata;
378 symlen = spec->u.sp_ea.eadatalen;
379 mci->mci_opdata.op_fid1 = *(spec->u.sp_ea.fid);
380 mci->mci_opdata.op_flags |= MDS_CREATE_SLAVE_OBJ;
381 #ifdef CONFIG_FS_POSIX_ACL
382 } else if (spec->sp_cr_flags & MDS_CREATE_RMT_ACL) {
383 symname = spec->u.sp_ea.eadata;
384 symlen = spec->u.sp_ea.eadatalen;
385 mci->mci_opdata.op_fid1 = *(spec->u.sp_ea.fid);
386 mci->mci_opdata.op_flags |= MDS_CREATE_RMT_ACL;
389 symname = spec->u.sp_symname;
390 symlen = symname ? strlen(symname) + 1 : 0;
393 rc = md_create(mc->mc_desc.cl_exp, &mci->mci_opdata,
394 symname, symlen, la->la_mode, uid, gid,
395 cap, la->la_rdev, &mci->mci_req);
398 /* get attr from request */
399 rc = mdc_req2attr_update(env, ma);
402 ptlrpc_req_finished(mci->mci_req);
407 static int mdc_ref_add(const struct lu_env *env, struct md_object *mo,
408 const struct md_attr *ma)
410 struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
411 const struct lu_attr *la = &ma->ma_attr;
412 struct mdc_thread_info *mci;
413 struct md_ucred *uc = md_ucred(env);
417 mci = lu_context_key_get(&env->le_ctx, &mdc_thread_key);
420 memset(&mci->mci_opdata, 0, sizeof(mci->mci_opdata));
421 mci->mci_opdata.op_bias = MDS_CROSS_REF;
422 mci->mci_opdata.op_fid1 = *lu_object_fid(&mo->mo_lu);
423 mci->mci_opdata.op_mod_time = la->la_ctime;
425 ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
426 mci->mci_opdata.op_fsuid = uc->mu_fsuid;
427 mci->mci_opdata.op_fsgid = uc->mu_fsgid;
428 mci->mci_opdata.op_cap = uc->mu_cap;
429 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD)) {
430 mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
431 mci->mci_opdata.op_suppgids[1] = uc->mu_suppgids[1];
433 mci->mci_opdata.op_suppgids[0] =
434 mci->mci_opdata.op_suppgids[1] = -1;
437 mci->mci_opdata.op_fsuid = la->la_uid;
438 mci->mci_opdata.op_fsgid = la->la_gid;
439 mci->mci_opdata.op_cap = cfs_curproc_cap_pack();
440 mci->mci_opdata.op_suppgids[0] =
441 mci->mci_opdata.op_suppgids[1] = -1;
445 rc = md_link(mc->mc_desc.cl_exp, &mci->mci_opdata, &mci->mci_req);
447 ptlrpc_req_finished(mci->mci_req);
452 static int mdc_ref_del(const struct lu_env *env, struct md_object *mo,
455 struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
456 struct lu_attr *la = &ma->ma_attr;
457 struct mdc_thread_info *mci;
458 struct md_ucred *uc = md_ucred(env);
462 mci = mdc_info_init(env);
463 mci->mci_opdata.op_bias = MDS_CROSS_REF;
464 if (ma->ma_attr_flags & MDS_VTX_BYPASS)
465 mci->mci_opdata.op_bias |= MDS_VTX_BYPASS;
467 mci->mci_opdata.op_bias &= ~MDS_VTX_BYPASS;
468 mci->mci_opdata.op_fid1 = *lu_object_fid(&mo->mo_lu);
469 mci->mci_opdata.op_mode = la->la_mode;
470 mci->mci_opdata.op_mod_time = la->la_ctime;
472 ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
473 mci->mci_opdata.op_fsuid = uc->mu_fsuid;
474 mci->mci_opdata.op_fsgid = uc->mu_fsgid;
475 mci->mci_opdata.op_cap = uc->mu_cap;
476 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD))
477 mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
479 mci->mci_opdata.op_suppgids[0] = -1;
481 mci->mci_opdata.op_fsuid = la->la_uid;
482 mci->mci_opdata.op_fsgid = la->la_gid;
483 mci->mci_opdata.op_cap = cfs_curproc_cap_pack();
484 mci->mci_opdata.op_suppgids[0] = -1;
487 rc = md_unlink(mc->mc_desc.cl_exp, &mci->mci_opdata, &mci->mci_req);
489 /* get attr from request */
490 rc = mdc_req2attr_update(env, ma);
493 ptlrpc_req_finished(mci->mci_req);
498 #ifdef HAVE_SPLIT_SUPPORT
499 int mdc_send_page(struct cmm_device *cm, const struct lu_env *env,
500 struct md_object *mo, struct page *page, __u32 offset)
502 struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
506 rc = mdc_sendpage(mc->mc_desc.cl_exp, lu_object_fid(&mo->mo_lu),
508 CDEBUG(rc ? D_ERROR : D_INFO, "send page %p offset %d fid "DFID
509 " rc %d \n", page, offset, PFID(lu_object_fid(&mo->mo_lu)), rc);
514 static const struct md_object_operations mdc_mo_ops = {
515 .moo_attr_get = mdc_attr_get,
516 .moo_attr_set = mdc_attr_set,
517 .moo_object_create = mdc_object_create,
518 .moo_ref_add = mdc_ref_add,
519 .moo_ref_del = mdc_ref_del,
522 /* md_dir_operations */
523 static int mdc_rename_tgt(const struct lu_env *env, struct md_object *mo_p,
524 struct md_object *mo_t, const struct lu_fid *lf,
525 const struct lu_name *lname, struct md_attr *ma)
527 struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo_p));
528 struct lu_attr *la = &ma->ma_attr;
529 struct mdc_thread_info *mci;
530 struct md_ucred *uc = md_ucred(env);
534 mci = mdc_info_init(env);
535 mci->mci_opdata.op_bias = MDS_CROSS_REF;
536 if (ma->ma_attr_flags & MDS_VTX_BYPASS)
537 mci->mci_opdata.op_bias |= MDS_VTX_BYPASS;
539 mci->mci_opdata.op_bias &= ~MDS_VTX_BYPASS;
540 mci->mci_opdata.op_fid1 = *lu_object_fid(&mo_p->mo_lu);
541 mci->mci_opdata.op_fid2 = *lf;
542 mci->mci_opdata.op_mode = la->la_mode;
543 mci->mci_opdata.op_mod_time = la->la_ctime;
545 ((uc->mu_valid == UCRED_OLD) || (uc->mu_valid == UCRED_NEW))) {
546 mci->mci_opdata.op_fsuid = uc->mu_fsuid;
547 mci->mci_opdata.op_fsgid = uc->mu_fsgid;
548 mci->mci_opdata.op_cap = uc->mu_cap;
549 if (uc->mu_ginfo || (uc->mu_valid == UCRED_OLD)) {
550 mci->mci_opdata.op_suppgids[0] = uc->mu_suppgids[0];
551 mci->mci_opdata.op_suppgids[1] = uc->mu_suppgids[1];
553 mci->mci_opdata.op_suppgids[0] =
554 mci->mci_opdata.op_suppgids[1] = -1;
557 mci->mci_opdata.op_fsuid = la->la_uid;
558 mci->mci_opdata.op_fsgid = la->la_gid;
559 mci->mci_opdata.op_cap = cfs_curproc_cap_pack();
560 mci->mci_opdata.op_suppgids[0] =
561 mci->mci_opdata.op_suppgids[1] = -1;
564 rc = md_rename(mc->mc_desc.cl_exp, &mci->mci_opdata, NULL, 0,
565 lname->ln_name, lname->ln_namelen, &mci->mci_req);
567 /* get attr from request */
568 mdc_req2attr_update(env, ma);
571 ptlrpc_req_finished(mci->mci_req);
576 * Return resulting fid in sfid
577 * 0: fids are not relatives
578 * fid: fid at which search stopped
580 static int mdc_is_subdir(const struct lu_env *env, struct md_object *mo,
581 const struct lu_fid *fid, struct lu_fid *sfid)
583 struct mdc_device *mc = md2mdc_dev(md_obj2dev(mo));
584 struct mdc_thread_info *mci;
585 struct mdt_body *body;
589 mci = mdc_info_init(env);
591 rc = md_is_subdir(mc->mc_desc.cl_exp, lu_object_fid(&mo->mo_lu),
593 if (rc == 0 || rc == -EREMOTE) {
594 body = req_capsule_server_get(&mci->mci_req->rq_pill,
596 LASSERT(body->valid & OBD_MD_FLID);
598 CDEBUG(D_INFO, "Remote mdo_is_subdir(), new src "DFID"\n",
602 ptlrpc_req_finished(mci->mci_req);
606 static const struct md_dir_operations mdc_dir_ops = {
607 .mdo_is_subdir = mdc_is_subdir,
608 .mdo_rename_tgt = mdc_rename_tgt