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