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