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