Whamcloud - gitweb
7f235f44a3ddf891869b198d5bf56a2bd49e696a
[fs/lustre-release.git] / lustre / obdclass / md_local_object.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, Intel Corporation.
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/obdclass/md_local_object.c
37  *
38  * Lustre Local Object create APIs
39  * 'create on first mount' facility. Files registed under llo module will
40  * be created on first mount.
41  *
42  * Author: Pravin Shelar  <pravin.shelar@sun.com>
43  */
44
45 #define DEBUG_SUBSYSTEM S_CLASS
46
47 #include <obd_support.h>
48 #include <lustre_disk.h>
49 #include <lustre_fid.h>
50 #include <lu_object.h>
51 #include <libcfs/list.h>
52 #include <md_object.h>
53
54
55 /** List head to hold list of objects to be created. */
56 static cfs_list_t llo_lobj_list;
57
58 /** Lock to protect list manipulations */
59 static struct mutex     llo_lock;
60
61 /**
62  * Structure used to maintain state of path parsing.
63  * \see llo_find_entry, llo_store_resolve
64  */
65 struct llo_find_hint {
66         struct lu_fid        *lfh_cfid;
67         struct md_device     *lfh_md;
68         struct md_object     *lfh_pobj;
69 };
70
71 /**
72  * Thread Local storage for this module.
73  */
74 struct llo_thread_info {
75         /** buffer to resolve path */
76         char                    lti_buf[DT_MAX_PATH];
77         /** used for path resolve */
78         struct lu_fid           lti_fid;
79         /** used to pass child object fid */
80         struct lu_fid           lti_cfid;
81         struct llo_find_hint    lti_lfh;
82         struct md_op_spec       lti_spc;
83         struct md_attr          lti_ma;
84         struct lu_name          lti_lname;
85 };
86
87 LU_KEY_INIT(llod_global, struct llo_thread_info);
88 LU_KEY_FINI(llod_global, struct llo_thread_info);
89
90 static struct lu_context_key llod_key = {
91         .lct_tags = LCT_MD_THREAD,
92         .lct_init = llod_global_key_init,
93         .lct_fini = llod_global_key_fini
94 };
95
96 static inline struct llo_thread_info * llo_env_info(const struct lu_env *env)
97 {
98         return lu_context_key_get(&env->le_ctx,  &llod_key);
99 }
100
101 /**
102  * Search md object for given fid.
103  */
104 static struct md_object *llo_locate(const struct lu_env *env,
105                                     struct md_device *md,
106                                     const struct lu_fid *fid)
107 {
108         struct lu_object *obj;
109         struct md_object *mdo;
110
111         obj = lu_object_find(env, &md->md_lu_dev, fid, NULL);
112         if (!IS_ERR(obj)) {
113                 obj = lu_object_locate(obj->lo_header, md->md_lu_dev.ld_type);
114                 LASSERT(obj != NULL);
115                 mdo = (struct md_object *) obj;
116         } else
117                 mdo = (struct md_object *)obj;
118         return mdo;
119 }
120
121 /**
122  * Lookup FID for object named \a name in directory \a pobj.
123  */
124 static int llo_lookup(const struct lu_env  *env,
125                       struct md_object *pobj,
126                       const char *name,
127                       struct lu_fid *fid)
128 {
129         struct llo_thread_info *info = llo_env_info(env);
130         struct lu_name          *lname = &info->lti_lname;
131         struct md_op_spec       *spec = &info->lti_spc;
132
133         spec->sp_feat = NULL;
134         spec->sp_cr_flags = 0;
135         spec->sp_cr_lookup = 0;
136         spec->sp_cr_mode = 0;
137
138         lname->ln_name = name;
139         lname->ln_namelen = strlen(name);
140
141         return mdo_lookup(env, pobj, lname, fid, spec);
142 }
143
144 /**
145  * Function to look up path component, this is passed to parsing
146  * function. \see llo_store_resolve
147  *
148  * \retval      rc returns error code for lookup or locate operation
149  *
150  * pointer to object is returned in data (lfh->lfh_pobj)
151  */
152 static int llo_find_entry(const struct lu_env  *env,
153                           const char *name, void *data)
154 {
155         struct llo_find_hint    *lfh = data;
156         struct md_device        *md = lfh->lfh_md;
157         struct lu_fid           *fid = lfh->lfh_cfid;
158         struct md_object        *obj = lfh->lfh_pobj;
159         int                     result;
160
161         /* lookup fid for object */
162         result = llo_lookup(env, obj, name, fid);
163         lu_object_put(env, &obj->mo_lu);
164
165         if (result == 0) {
166                 /* get md object for fid that we got in lookup */
167                 obj = llo_locate(env, md, fid);
168                 if (IS_ERR(obj))
169                         result = PTR_ERR(obj);
170         }
171
172         lfh->lfh_pobj = obj;
173         return result;
174 }
175
176 static struct md_object *llo_reg_open(const struct lu_env *env,
177                                       struct md_device *md,
178                                       struct md_object *p,
179                                       const char *name,
180                                       struct lu_fid *fid)
181 {
182         struct md_object *o;
183         int result;
184
185         result = llo_lookup(env, p, name, fid);
186         if (result == 0)
187                 o = llo_locate(env, md, fid);
188         else
189                 o = ERR_PTR(result);
190
191         return o;
192 }
193
194 /**
195  * Resolve given \a path, on success function returns
196  * md object for last directory and \a fid points to
197  * its fid.
198  */
199 struct md_object *llo_store_resolve(const struct lu_env *env,
200                                     struct md_device *md,
201                                     struct dt_device *dt,
202                                     const char *path,
203                                     struct lu_fid *fid)
204 {
205         struct llo_thread_info *info = llo_env_info(env);
206         struct llo_find_hint *lfh = &info->lti_lfh;
207         char *local = info->lti_buf;
208         struct md_object        *obj;
209         int result;
210
211         strncpy(local, path, DT_MAX_PATH);
212         local[DT_MAX_PATH - 1] = '\0';
213
214         lfh->lfh_md = md;
215         lfh->lfh_cfid = fid;
216         /* start path resolution from backend fs root. */
217         result = dt->dd_ops->dt_root_get(env, dt, fid);
218         if (result == 0) {
219                 /* get md object for root */
220                 obj = llo_locate(env, md, fid);
221                 if (!IS_ERR(obj)) {
222                         /* start path parser from root md */
223                         lfh->lfh_pobj = obj;
224                         result = dt_path_parser(env, local, llo_find_entry, lfh);
225                         if (result != 0)
226                                 obj = ERR_PTR(result);
227                         else
228                                 obj = lfh->lfh_pobj;
229                 }
230         } else {
231                 obj = ERR_PTR(result);
232         }
233         return obj;
234 }
235 EXPORT_SYMBOL(llo_store_resolve);
236
237 /**
238  * Returns md object for \a objname in given \a dirname.
239  */
240 struct md_object *llo_store_open(const struct lu_env *env,
241                                  struct md_device *md,
242                                  struct dt_device *dt,
243                                  const char *dirname,
244                                  const char *objname,
245                                  struct lu_fid *fid)
246 {
247         struct md_object *obj;
248         struct md_object *dir;
249
250         /* search md object for parent dir */
251         dir = llo_store_resolve(env, md, dt, dirname, fid);
252         if (!IS_ERR(dir)) {
253                 obj = llo_reg_open(env, md, dir, objname, fid);
254                 lu_object_put(env, &dir->mo_lu);
255         } else
256                 obj = dir;
257
258         return obj;
259 }
260 EXPORT_SYMBOL(llo_store_open);
261
262 static struct md_object *llo_create_obj(const struct lu_env *env,
263                                         struct md_device *md,
264                                         struct md_object *dir,
265                                         const char *objname,
266                                         const struct lu_fid *fid,
267                                         const struct dt_index_features *feat)
268 {
269         struct llo_thread_info *info = llo_env_info(env);
270         struct md_object        *mdo;
271         struct md_attr          *ma = &info->lti_ma;
272         struct md_op_spec       *spec = &info->lti_spc;
273         struct lu_name          *lname = &info->lti_lname;
274         struct lu_attr          *la = &ma->ma_attr;
275         int rc;
276
277         mdo = llo_locate(env, md, fid);
278         if (IS_ERR(mdo))
279                 return mdo;
280
281         lname->ln_name = objname;
282         lname->ln_namelen = strlen(objname);
283
284         spec->sp_feat = feat;
285         spec->sp_cr_flags = 0;
286         spec->sp_cr_lookup = 1;
287         spec->sp_cr_mode = 0;
288
289         if (feat == &dt_directory_features)
290                 la->la_mode = S_IFDIR | S_IXUGO;
291         else
292                 la->la_mode = S_IFREG;
293
294         la->la_mode |= S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
295         la->la_uid = la->la_gid = 0;
296         la->la_valid = LA_MODE | LA_UID | LA_GID;
297
298         ma->ma_valid = 0;
299         ma->ma_need = 0;
300
301         rc = mdo_create(env, dir, lname, mdo, spec, ma);
302
303         if (rc) {
304                 lu_object_put(env, &mdo->mo_lu);
305                 mdo = ERR_PTR(rc);
306         }
307
308         return mdo;
309 }
310
311 /**
312  * Create md object, object could be diretcory or
313  * special index defined by \a feat in \a directory.
314  *
315  *       \param  md       device
316  *       \param  dirname  parent directory
317  *       \param  objname  file name
318  *       \param  fid      object fid
319  *       \param  feat     index features required for directory create
320  */
321
322 struct md_object *llo_store_create_index(const struct lu_env *env,
323                                          struct md_device *md,
324                                          struct dt_device *dt,
325                                          const char *dirname,
326                                          const char *objname,
327                                          const struct lu_fid *fid,
328                                          const struct dt_index_features *feat)
329 {
330         struct llo_thread_info *info = llo_env_info(env);
331         struct md_object *obj;
332         struct md_object *dir;
333         struct lu_fid *ignore = &info->lti_fid;
334
335         dir = llo_store_resolve(env, md, dt, dirname, ignore);
336         if (!IS_ERR(dir)) {
337                 obj = llo_create_obj(env, md, dir, objname, fid, feat);
338                 lu_object_put(env, &dir->mo_lu);
339         } else {
340                 obj = dir;
341         }
342         return obj;
343 }
344
345 EXPORT_SYMBOL(llo_store_create_index);
346
347 /**
348  * Create md object for regular file in \a directory.
349  *
350  *       \param  md       device
351  *       \param  dirname  parent directory
352  *       \param  objname  file name
353  *       \param  fid      object fid.
354  */
355
356 struct md_object *llo_store_create(const struct lu_env *env,
357                                    struct md_device *md,
358                                    struct dt_device *dt,
359                                    const char *dirname,
360                                    const char *objname,
361                                    const struct lu_fid *fid)
362 {
363         return llo_store_create_index(env, md, dt, dirname,
364                                       objname, fid, NULL);
365 }
366
367 EXPORT_SYMBOL(llo_store_create);
368
369 /**
370  * Register object for 'create on first mount' facility.
371  * objects are created in order of registration.
372  */
373
374 void llo_local_obj_register(struct lu_local_obj_desc *llod)
375 {
376         mutex_lock(&llo_lock);
377         cfs_list_add_tail(&llod->llod_linkage, &llo_lobj_list);
378         mutex_unlock(&llo_lock);
379 }
380
381 EXPORT_SYMBOL(llo_local_obj_register);
382
383 void llo_local_obj_unregister(struct lu_local_obj_desc *llod)
384 {
385         mutex_lock(&llo_lock);
386         cfs_list_del(&llod->llod_linkage);
387         mutex_unlock(&llo_lock);
388 }
389
390 EXPORT_SYMBOL(llo_local_obj_unregister);
391
392 /**
393  * Created registed objects.
394  */
395
396 int llo_local_objects_setup(const struct lu_env *env,
397                              struct md_device * md,
398                              struct dt_device *dt)
399 {
400         struct llo_thread_info *info = llo_env_info(env);
401         struct lu_fid *fid;
402         struct lu_local_obj_desc *scan;
403         struct md_object *mdo;
404         const char *dir;
405         int rc = 0;
406
407         fid = &info->lti_cfid;
408         mutex_lock(&llo_lock);
409
410         cfs_list_for_each_entry(scan, &llo_lobj_list, llod_linkage) {
411                 lu_local_obj_fid(fid, scan->llod_oid);
412                 dir = "";
413                 if (scan->llod_dir)
414                         dir = scan->llod_dir;
415
416                 if (scan->llod_is_index)
417                         mdo = llo_store_create_index(env, md, dt ,
418                                                      dir, scan->llod_name,
419                                                      fid,
420                                                      scan->llod_feat);
421                 else
422                         mdo = llo_store_create(env, md, dt,
423                                                dir, scan->llod_name,
424                                                fid);
425                 if (IS_ERR(mdo) && PTR_ERR(mdo) != -EEXIST) {
426                         rc = PTR_ERR(mdo);
427                         CERROR("creating obj [%s] fid = "DFID" rc = %d\n",
428                                scan->llod_name, PFID(fid), rc);
429                         goto out;
430                 }
431
432                 if (!IS_ERR(mdo))
433                         lu_object_put(env, &mdo->mo_lu);
434         }
435
436 out:
437         mutex_unlock(&llo_lock);
438         return rc;
439 }
440
441 EXPORT_SYMBOL(llo_local_objects_setup);
442
443 int llo_global_init(void)
444 {
445         int result;
446
447         CFS_INIT_LIST_HEAD(&llo_lobj_list);
448         mutex_init(&llo_lock);
449
450         LU_CONTEXT_KEY_INIT(&llod_key);
451         result = lu_context_key_register(&llod_key);
452         return result;
453 }
454
455 void llo_global_fini(void)
456 {
457         lu_context_key_degister(&llod_key);
458         LASSERT(cfs_list_empty(&llo_lobj_list));
459 }