4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License version 2 for more details. A copy is
14 * included in the COPYING file that accompanied this code.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Copyright (c) 2012, Intel Corporation.
24 * Use is subject to license terms.
25 * Copyright (c) 2011, 2012 Commissariat a l'energie atomique et aux energies
29 * lustre/mdt/mdt_hsm.c
31 * Lustre Metadata Target (mdt) request handler
33 * Author: Aurelien Degremont <aurelien.degremont@cea.fr>
34 * Author: JC Lafoucriere <jacques-charles.lafoucriere@cea.fr>
38 # define EXPORT_SYMTAB
40 #define DEBUG_SUBSYSTEM S_MDS
42 #include "mdt_internal.h"
45 * fake functions, will be replace by real one with HSM Coordinator patch
48 int mdt_hsm_copytool_send(struct obd_export *exp)
53 static int mdt_hsm_coordinator_update(struct mdt_thread_info *info,
54 struct hsm_progress_kernel *pgs)
59 static int mdt_hsm_agent_register_mask(struct mdt_thread_info *info,
60 struct obd_uuid *uuid,
66 static int mdt_hsm_agent_unregister(struct mdt_thread_info *info,
67 struct obd_uuid *uuid)
72 static int mdt_hsm_coordinator_get_actions(struct mdt_thread_info *mti,
73 struct hsm_action_list *hal)
79 * Update on-disk HSM attributes.
81 int mdt_hsm_attr_set(struct mdt_thread_info *info, struct mdt_object *obj,
84 struct md_object *next = mdt_object_child(obj);
85 struct lu_buf *buf = &info->mti_buf;
86 struct hsm_attrs *attrs;
90 attrs = (struct hsm_attrs *)info->mti_xattr_buf;
91 CLASSERT(sizeof(info->mti_xattr_buf) >= sizeof(*attrs));
93 /* pack HSM attributes */
94 lustre_hsm2buf(info->mti_xattr_buf, mh);
96 /* update SOM attributes */
98 buf->lb_len = sizeof(*attrs);
99 rc = mo_xattr_set(info->mti_env, next, buf, XATTR_NAME_HSM, 0);
105 * Extract information coming from a copytool and asks coordinator to update
106 * a request status depending on the update content.
108 * Copytools could use this to report failure in their process.
110 * This is HSM_PROGRESS RPC handler.
112 int mdt_hsm_progress(struct mdt_thread_info *info)
114 struct hsm_progress_kernel *hpk;
118 hpk = req_capsule_client_get(info->mti_pill, &RMF_MDS_HSM_PROGRESS);
121 CDEBUG(D_HSM, "Progress on "DFID": len="LPU64" err=%d\n",
122 PFID(&hpk->hpk_fid), hpk->hpk_extent.length, hpk->hpk_errval);
125 CDEBUG(D_HSM, "Copytool progress on "DFID" failed (%d); %s.\n",
126 PFID(&hpk->hpk_fid), hpk->hpk_errval,
127 hpk->hpk_flags & HP_FLAG_RETRY ? "will retry" : "fatal");
129 if (hpk->hpk_flags & HP_FLAG_COMPLETED)
130 CDEBUG(D_HSM, "Finished "DFID" (%d) cancel cookie="LPX64"\n",
131 PFID(&hpk->hpk_fid), hpk->hpk_errval, hpk->hpk_cookie);
133 rc = mdt_hsm_coordinator_update(info, hpk);
138 int mdt_hsm_ct_register(struct mdt_thread_info *info)
140 struct ptlrpc_request *req = mdt_info_req(info);
145 archives = req_capsule_client_get(info->mti_pill, &RMF_MDS_HSM_ARCHIVE);
148 /* XXX: directly include this function here? */
149 rc = mdt_hsm_agent_register_mask(info, &req->rq_export->exp_client_uuid,
155 int mdt_hsm_ct_unregister(struct mdt_thread_info *info)
157 struct ptlrpc_request *req = mdt_info_req(info);
161 /* XXX: directly include this function here? */
162 rc = mdt_hsm_agent_unregister(info, &req->rq_export->exp_client_uuid);
169 * Retrieve the current HSM flags, archive id and undergoing HSM requests for
170 * the fid provided in RPC body.
172 * Current requests are read from coordinator states.
174 * This is MDS_HSM_STATE_GET RPC handler.
176 int mdt_hsm_state_get(struct mdt_thread_info *info)
178 struct mdt_object *obj = info->mti_object;
179 struct md_attr *ma = &info->mti_attr;
180 struct hsm_user_state *hus;
181 struct mdt_lock_handle *lh;
185 lh = &info->mti_lh[MDT_LH_CHILD];
186 mdt_lock_reg_init(lh, LCK_PR);
187 rc = mdt_object_lock(info, obj, lh, MDS_INODELOCK_LOOKUP,
192 /* Only valid if client is remote */
193 rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
195 GOTO(out_unlock, rc = err_serious(rc));
198 ma->ma_need = MA_HSM;
199 rc = mdt_attr_get_complex(info, obj, ma);
203 if (req_capsule_get_size(info->mti_pill, &RMF_CAPA1, RCL_CLIENT))
204 mdt_set_capainfo(info, 0, &info->mti_body->fid1,
205 req_capsule_client_get(info->mti_pill, &RMF_CAPA1));
207 hus = req_capsule_server_get(info->mti_pill, &RMF_HSM_USER_STATE);
210 /* Current HSM flags */
211 hus->hus_states = ma->ma_hsm.mh_flags;
212 hus->hus_archive_id = ma->ma_hsm.mh_arch_id;
216 mdt_exit_ucred(info);
218 mdt_object_unlock(info, obj, lh, 1);
223 * Change HSM state and archive number of a file.
225 * Archive number is changed iif the value is not 0.
226 * The new flagset that will be computed should result in a coherent state.
227 * This function checks that are flags are compatible.
229 * This is MDS_HSM_STATE_SET RPC handler.
231 int mdt_hsm_state_set(struct mdt_thread_info *info)
233 struct mdt_object *obj = info->mti_object;
234 struct md_attr *ma = &info->mti_attr;
235 struct hsm_state_set *hss;
236 struct mdt_lock_handle *lh;
241 lh = &info->mti_lh[MDT_LH_CHILD];
242 mdt_lock_reg_init(lh, LCK_PW);
243 rc = mdt_object_lock(info, obj, lh, MDS_INODELOCK_LOOKUP,
248 /* Only valid if client is remote */
249 rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
251 GOTO(out_obj, rc = err_serious(rc));
253 /* Read current HSM info */
255 ma->ma_need = MA_HSM;
256 rc = mdt_attr_get_complex(info, obj, ma);
260 hss = req_capsule_client_get(info->mti_pill, &RMF_HSM_STATE_SET);
263 if (req_capsule_get_size(info->mti_pill, &RMF_CAPA1, RCL_CLIENT))
264 mdt_set_capainfo(info, 0, &info->mti_body->fid1,
265 req_capsule_client_get(info->mti_pill, &RMF_CAPA1));
267 /* Change HSM flags depending on provided masks */
268 if (hss->hss_valid & HSS_SETMASK)
269 ma->ma_hsm.mh_flags |= hss->hss_setmask;
270 if (hss->hss_valid & HSS_CLEARMASK)
271 ma->ma_hsm.mh_flags &= ~hss->hss_clearmask;
273 /* Change archive_id if provided. */
274 if (hss->hss_valid & HSS_ARCHIVE_ID) {
275 if (!(ma->ma_hsm.mh_flags & HS_EXISTS)) {
276 CDEBUG(D_HSM, "Could not set an archive number for "
277 DFID "if HSM EXISTS flag is not set.\n",
278 PFID(&info->mti_body->fid1));
281 ma->ma_hsm.mh_arch_id = hss->hss_archive_id;
284 /* Check for inconsistant HSM flagset.
285 * DIRTY without EXISTS: no dirty if no archive was created.
286 * DIRTY and RELEASED: a dirty file could not be released.
287 * RELEASED without ARCHIVED: do not release a non-archived file.
288 * LOST without ARCHIVED: cannot lost a non-archived file.
290 flags = ma->ma_hsm.mh_flags;
291 if (((flags & HS_DIRTY) && !(flags & HS_EXISTS)) ||
292 ((flags & HS_RELEASED) && (flags & HS_DIRTY)) ||
293 ((flags & HS_RELEASED) && !(flags & HS_ARCHIVED)) ||
294 ((flags & HS_LOST) && !(flags & HS_ARCHIVED))) {
295 CDEBUG(D_HSM, "Incompatible flag change on "DFID
297 PFID(&info->mti_body->fid1), flags);
298 GOTO(out_ucred, rc = -EINVAL);
301 /* Save the modified flags */
302 rc = mdt_hsm_attr_set(info, obj, &ma->ma_hsm);
309 mdt_exit_ucred(info);
311 mdt_object_unlock(info, obj, lh, 1);
316 * Retrieve undergoing HSM requests for the fid provided in RPC body.
317 * Current requests are read from coordinator states.
319 * This is MDS_HSM_ACTION RPC handler.
321 int mdt_hsm_action(struct mdt_thread_info *info)
323 struct hsm_current_action *hca;
324 struct hsm_action_list *hal = NULL;
325 struct hsm_action_item *hai;
329 /* Only valid if client is remote */
330 rc = mdt_init_ucred(info, (struct mdt_body *)info->mti_body);
332 RETURN(rc = err_serious(rc));
334 if (req_capsule_get_size(info->mti_pill, &RMF_CAPA1, RCL_CLIENT))
335 mdt_set_capainfo(info, 0, &info->mti_body->fid1,
336 req_capsule_client_get(info->mti_pill,
339 hca = req_capsule_server_get(info->mti_pill,
340 &RMF_MDS_HSM_CURRENT_ACTION);
343 /* Coordinator information */
344 len = sizeof(*hal) + MTI_NAME_MAXLEN /* fsname */ +
345 cfs_size_round(sizeof(*hai));
349 GOTO(out_ucred, -ENOMEM);
351 hal->hal_version = HAL_VERSION;
352 hal->hal_archive_num = 0;
354 obd_uuid2fsname(hal->hal_fsname, mdt2obd_dev(info->mti_mdt)->obd_name,
358 hai->hai_action = HSMA_NONE;
361 hai->hai_fid = info->mti_body->fid1;
362 hai->hai_len = sizeof(*hai);
364 rc = mdt_hsm_coordinator_get_actions(info, hal);
368 /* cookie is used to give back request status */
369 if (hai->hai_cookie == 0)
370 hca->hca_state = HPS_WAITING;
372 hca->hca_state = HPS_RUNNING;
374 switch (hai->hai_action) {
376 hca->hca_action = HUA_NONE;
379 hca->hca_action = HUA_ARCHIVE;
382 hca->hca_action = HUA_RESTORE;
385 hca->hca_action = HUA_REMOVE;
388 hca->hca_action = HUA_CANCEL;
391 hca->hca_action = HUA_NONE;
392 CERROR("%s: Unknown hsm action: %d on "DFID"\n",
393 mdt2obd_dev(info->mti_mdt)->obd_name,
394 hai->hai_action, PFID(&hai->hai_fid));
398 hca->hca_location = hai->hai_extent;
404 mdt_exit_ucred(info);