Whamcloud - gitweb
LU-1303 lod: destroy and setattr to use striping
[fs/lustre-release.git] / lustre / lod / lod_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,
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.
15
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
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright  2009 Sun Microsystems, Inc. All rights reserved
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2012, Intel, Inc.
27  */
28 /*
29  * lustre/lod/lod_object.c
30  *
31  * Author: Alex Zhuravlev <alexey.zhuravlev@intel.com>
32  */
33
34 #ifndef EXPORT_SYMTAB
35 # define EXPORT_SYMTAB
36 #endif
37 #define DEBUG_SUBSYSTEM S_MDS
38
39 #include <obd.h>
40 #include <obd_class.h>
41 #include <lustre_ver.h>
42 #include <obd_support.h>
43 #include <lprocfs_status.h>
44
45 #include <lustre_fid.h>
46 #include <lustre_param.h>
47 #include <lustre_fid.h>
48 #include <obd_lov.h>
49
50 #include "lod_internal.h"
51
52 extern cfs_mem_cache_t *lod_object_kmem;
53 static const struct dt_body_operations lod_body_lnk_ops;
54
55 static int lod_index_lookup(const struct lu_env *env, struct dt_object *dt,
56                             struct dt_rec *rec, const struct dt_key *key,
57                             struct lustre_capa *capa)
58 {
59         struct dt_object *next = dt_object_child(dt);
60         return next->do_index_ops->dio_lookup(env, next, rec, key, capa);
61 }
62
63 static int lod_declare_index_insert(const struct lu_env *env,
64                                     struct dt_object *dt,
65                                     const struct dt_rec *rec,
66                                     const struct dt_key *key,
67                                     struct thandle *handle)
68 {
69         return dt_declare_insert(env, dt_object_child(dt), rec, key, handle);
70 }
71
72 static int lod_index_insert(const struct lu_env *env,
73                             struct dt_object *dt,
74                             const struct dt_rec *rec,
75                             const struct dt_key *key,
76                             struct thandle *th,
77                             struct lustre_capa *capa,
78                             int ign)
79 {
80         return dt_insert(env, dt_object_child(dt), rec, key, th, capa, ign);
81 }
82
83 static int lod_declare_index_delete(const struct lu_env *env,
84                                     struct dt_object *dt,
85                                     const struct dt_key *key,
86                                     struct thandle *th)
87 {
88         return dt_declare_delete(env, dt_object_child(dt), key, th);
89 }
90
91 static int lod_index_delete(const struct lu_env *env,
92                             struct dt_object *dt,
93                             const struct dt_key *key,
94                             struct thandle *th,
95                             struct lustre_capa *capa)
96 {
97         return dt_delete(env, dt_object_child(dt), key, th, capa);
98 }
99
100 static struct dt_it *lod_it_init(const struct lu_env *env,
101                                  struct dt_object *dt, __u32 attr,
102                                  struct lustre_capa *capa)
103 {
104         struct dt_object   *next = dt_object_child(dt);
105
106         return next->do_index_ops->dio_it.init(env, next, attr, capa);
107 }
108
109 static struct dt_index_operations lod_index_ops = {
110         .dio_lookup         = lod_index_lookup,
111         .dio_declare_insert = lod_declare_index_insert,
112         .dio_insert         = lod_index_insert,
113         .dio_declare_delete = lod_declare_index_delete,
114         .dio_delete         = lod_index_delete,
115         .dio_it     = {
116                 .init       = lod_it_init,
117         }
118 };
119
120 static void lod_object_read_lock(const struct lu_env *env,
121                                  struct dt_object *dt, unsigned role)
122 {
123         dt_read_lock(env, dt_object_child(dt), role);
124 }
125
126 static void lod_object_write_lock(const struct lu_env *env,
127                                   struct dt_object *dt, unsigned role)
128 {
129         dt_write_lock(env, dt_object_child(dt), role);
130 }
131
132 static void lod_object_read_unlock(const struct lu_env *env,
133                                    struct dt_object *dt)
134 {
135         dt_read_unlock(env, dt_object_child(dt));
136 }
137
138 static void lod_object_write_unlock(const struct lu_env *env,
139                                     struct dt_object *dt)
140 {
141         dt_write_unlock(env, dt_object_child(dt));
142 }
143
144 static int lod_object_write_locked(const struct lu_env *env,
145                                    struct dt_object *dt)
146 {
147         return dt_write_locked(env, dt_object_child(dt));
148 }
149
150 static int lod_attr_get(const struct lu_env *env,
151                         struct dt_object *dt,
152                         struct lu_attr *attr,
153                         struct lustre_capa *capa)
154 {
155         return dt_attr_get(env, dt_object_child(dt), attr, capa);
156 }
157
158 static int lod_declare_attr_set(const struct lu_env *env,
159                                 struct dt_object *dt,
160                                 const struct lu_attr *attr,
161                                 struct thandle *handle)
162 {
163         struct dt_object  *next = dt_object_child(dt);
164         struct lod_object *lo = lod_dt_obj(dt);
165         int                rc, i;
166         ENTRY;
167
168         /*
169          * declare setattr on the local object
170          */
171         rc = dt_declare_attr_set(env, next, attr, handle);
172         if (rc)
173                 RETURN(rc);
174
175         /*
176          * load striping information, notice we don't do this when object
177          * is being initialized as we don't need this information till
178          * few specific cases like destroy, chown
179          */
180         rc = lod_load_striping(env, lo);
181         if (rc)
182                 RETURN(rc);
183
184         /*
185          * if object is striped declare changes on the stripes
186          */
187         LASSERT(lo->ldo_stripe || lo->ldo_stripenr == 0);
188         for (i = 0; i < lo->ldo_stripenr; i++) {
189                 LASSERT(lo->ldo_stripe[i]);
190                 rc = dt_declare_attr_set(env, lo->ldo_stripe[i], attr, handle);
191                 if (rc) {
192                         CERROR("failed declaration: %d\n", rc);
193                         break;
194                 }
195         }
196
197         RETURN(rc);
198 }
199
200 static int lod_attr_set(const struct lu_env *env,
201                         struct dt_object *dt,
202                         const struct lu_attr *attr,
203                         struct thandle *handle,
204                         struct lustre_capa *capa)
205 {
206         struct dt_object  *next = dt_object_child(dt);
207         struct lod_object *lo = lod_dt_obj(dt);
208         int                rc, i;
209         ENTRY;
210
211         /*
212          * apply changes to the local object
213          */
214         rc = dt_attr_set(env, next, attr, handle, capa);
215         if (rc)
216                 RETURN(rc);
217
218         /*
219          * if object is striped, apply changes to all the stripes
220          */
221         LASSERT(lo->ldo_stripe || lo->ldo_stripenr == 0);
222         for (i = 0; i < lo->ldo_stripenr; i++) {
223                 LASSERT(lo->ldo_stripe[i]);
224                 rc = dt_attr_set(env, lo->ldo_stripe[i], attr, handle, capa);
225                 if (rc) {
226                         CERROR("failed declaration: %d\n", rc);
227                         break;
228                 }
229         }
230
231         RETURN(rc);
232 }
233
234 static int lod_xattr_get(const struct lu_env *env, struct dt_object *dt,
235                          struct lu_buf *buf, const char *name,
236                          struct lustre_capa *capa)
237 {
238         return dt_xattr_get(env, dt_object_child(dt), buf, name, capa);
239 }
240
241 /*
242  * LOV xattr is a storage for striping, and LOD owns this xattr.
243  * but LOD allows others to control striping to some extent
244  * - to reset strping
245  * - to set new defined striping
246  * - to set new semi-defined striping
247  *   - number of stripes is defined
248  *   - number of stripes + osts are defined
249  *   - ??
250  */
251 static int lod_declare_xattr_set(const struct lu_env *env,
252                                  struct dt_object *dt,
253                                  const struct lu_buf *buf,
254                                  const char *name, int fl,
255                                  struct thandle *th)
256 {
257         struct dt_object *next = dt_object_child(dt);
258         int               rc;
259         ENTRY;
260
261         rc = dt_declare_xattr_set(env, next, buf, name, fl, th);
262
263         RETURN(rc);
264 }
265
266 static int lod_xattr_set(const struct lu_env *env,
267                          struct dt_object *dt, const struct lu_buf *buf,
268                          const char *name, int fl, struct thandle *th,
269                          struct lustre_capa *capa)
270 {
271         struct dt_object *next = dt_object_child(dt);
272         int               rc;
273         ENTRY;
274
275         /*
276          * behave transparantly for all other EAs
277          */
278         rc = dt_xattr_set(env, next, buf, name, fl, th, capa);
279
280         RETURN(rc);
281 }
282
283 static int lod_declare_xattr_del(const struct lu_env *env,
284                                  struct dt_object *dt, const char *name,
285                                  struct thandle *th)
286 {
287         return dt_declare_xattr_del(env, dt_object_child(dt), name, th);
288 }
289
290 static int lod_xattr_del(const struct lu_env *env, struct dt_object *dt,
291                          const char *name, struct thandle *th,
292                          struct lustre_capa *capa)
293 {
294         return dt_xattr_del(env, dt_object_child(dt), name, th, capa);
295 }
296
297 static int lod_xattr_list(const struct lu_env *env,
298                           struct dt_object *dt, struct lu_buf *buf,
299                           struct lustre_capa *capa)
300 {
301         return dt_xattr_list(env, dt_object_child(dt), buf, capa);
302 }
303
304 int lod_object_set_pool(struct lod_object *o, char *pool)
305 {
306         int len;
307
308         if (o->ldo_pool) {
309                 len = strlen(o->ldo_pool);
310                 OBD_FREE(o->ldo_pool, len + 1);
311                 o->ldo_pool = NULL;
312         }
313         if (pool) {
314                 len = strlen(pool);
315                 OBD_ALLOC(o->ldo_pool, len + 1);
316                 if (o->ldo_pool == NULL)
317                         return -ENOMEM;
318                 strcpy(o->ldo_pool, pool);
319         }
320         return 0;
321 }
322
323 /**
324  * used to transfer default striping data to the object being created
325  */
326 static void lod_ah_init(const struct lu_env *env,
327                         struct dt_allocation_hint *ah,
328                         struct dt_object *parent,
329                         struct dt_object *child,
330                         cfs_umode_t child_mode)
331 {
332         struct dt_object  *nextc;
333         struct dt_object  *nextp = NULL;
334         struct lod_object *lc;
335         ENTRY;
336
337         LASSERT(child);
338
339         if (likely(parent))
340                 nextp = dt_object_child(parent);
341
342         nextc = dt_object_child(child);
343         lc = lod_dt_obj(child);
344
345         LASSERT(lc->ldo_stripenr == 0);
346         LASSERT(lc->ldo_stripe == NULL);
347
348         /*
349          * local object may want some hints
350          * in case of late striping creation, ->ah_init()
351          * can be called with local object existing
352          */
353         if (!dt_object_exists(nextc))
354                 nextc->do_ops->do_ah_init(env, ah, nextp, nextc, child_mode);
355
356         EXIT;
357 }
358
359 static int lod_declare_object_create(const struct lu_env *env,
360                                      struct dt_object *dt,
361                                      struct lu_attr *attr,
362                                      struct dt_allocation_hint *hint,
363                                      struct dt_object_format *dof,
364                                      struct thandle *th)
365 {
366         struct dt_object   *next = dt_object_child(dt);
367         int                 rc;
368         ENTRY;
369
370         LASSERT(dof);
371         LASSERT(attr);
372         LASSERT(th);
373         LASSERT(!dt_object_exists(next));
374
375         /*
376          * first of all, we declare creation of local object
377          */
378         rc = dt_declare_create(env, next, attr, hint, dof, th);
379         if (rc)
380                 GOTO(out, rc);
381
382         if (dof->dof_type == DFT_SYM)
383                 dt->do_body_ops = &lod_body_lnk_ops;
384
385 out:
386         RETURN(rc);
387 }
388
389 static int lod_object_create(const struct lu_env *env, struct dt_object *dt,
390                              struct lu_attr *attr,
391                              struct dt_allocation_hint *hint,
392                              struct dt_object_format *dof, struct thandle *th)
393 {
394         struct dt_object   *next = dt_object_child(dt);
395         int                 rc;
396         ENTRY;
397
398         /* create local object */
399         rc = dt_create(env, next, attr, hint, dof, th);
400
401         RETURN(rc);
402 }
403
404 static int lod_declare_object_destroy(const struct lu_env *env,
405                                       struct dt_object *dt,
406                                       struct thandle *th)
407 {
408         struct dt_object   *next = dt_object_child(dt);
409         struct lod_object  *lo = lod_dt_obj(dt);
410         int                 rc, i;
411         ENTRY;
412
413         /*
414          * we declare destroy for the local object
415          */
416         rc = dt_declare_destroy(env, next, th);
417         if (rc)
418                 RETURN(rc);
419
420         /*
421          * load striping information, notice we don't do this when object
422          * is being initialized as we don't need this information till
423          * few specific cases like destroy, chown
424          */
425         rc = lod_load_striping(env, lo);
426         if (rc)
427                 RETURN(rc);
428
429         /* declare destroy for all underlying objects */
430         for (i = 0; i < lo->ldo_stripenr; i++) {
431                 LASSERT(lo->ldo_stripe[i]);
432                 rc = dt_declare_destroy(env, lo->ldo_stripe[i], th);
433
434                 if (rc)
435                         break;
436         }
437
438         RETURN(rc);
439 }
440
441 static int lod_object_destroy(const struct lu_env *env,
442                 struct dt_object *dt, struct thandle *th)
443 {
444         struct dt_object  *next = dt_object_child(dt);
445         struct lod_object *lo = lod_dt_obj(dt);
446         int                rc, i;
447         ENTRY;
448
449         /* destroy local object */
450         rc = dt_destroy(env, next, th);
451         if (rc)
452                 RETURN(rc);
453
454         /* destroy all underlying objects */
455         for (i = 0; i < lo->ldo_stripenr; i++) {
456                 LASSERT(lo->ldo_stripe[i]);
457                 rc = dt_destroy(env, lo->ldo_stripe[i], th);
458                 if (rc)
459                         break;
460         }
461
462         RETURN(rc);
463 }
464
465 static int lod_index_try(const struct lu_env *env, struct dt_object *dt,
466                          const struct dt_index_features *feat)
467 {
468         struct dt_object *next = dt_object_child(dt);
469         int               rc;
470         ENTRY;
471
472         LASSERT(next->do_ops);
473         LASSERT(next->do_ops->do_index_try);
474
475         rc = next->do_ops->do_index_try(env, next, feat);
476         if (next->do_index_ops && dt->do_index_ops == NULL) {
477                 dt->do_index_ops = &lod_index_ops;
478                 /* XXX: iterators don't accept device, so bypass LOD */
479                 /* will be fixed with DNE */
480                 if (lod_index_ops.dio_it.fini == NULL) {
481                         lod_index_ops.dio_it = next->do_index_ops->dio_it;
482                         lod_index_ops.dio_it.init = lod_it_init;
483                 }
484         }
485
486         RETURN(rc);
487 }
488
489 static int lod_declare_ref_add(const struct lu_env *env,
490                                struct dt_object *dt, struct thandle *th)
491 {
492         return dt_declare_ref_add(env, dt_object_child(dt), th);
493 }
494
495 static int lod_ref_add(const struct lu_env *env,
496                        struct dt_object *dt, struct thandle *th)
497 {
498         return dt_ref_add(env, dt_object_child(dt), th);
499 }
500
501 static int lod_declare_ref_del(const struct lu_env *env,
502                                struct dt_object *dt, struct thandle *th)
503 {
504         return dt_declare_ref_del(env, dt_object_child(dt), th);
505 }
506
507 static int lod_ref_del(const struct lu_env *env,
508                        struct dt_object *dt, struct thandle *th)
509 {
510         return dt_ref_del(env, dt_object_child(dt), th);
511 }
512
513 static struct obd_capa *lod_capa_get(const struct lu_env *env,
514                                      struct dt_object *dt,
515                                      struct lustre_capa *old, __u64 opc)
516 {
517         return dt_capa_get(env, dt_object_child(dt), old, opc);
518 }
519
520 static int lod_object_sync(const struct lu_env *env, struct dt_object *dt)
521 {
522         return dt_object_sync(env, dt_object_child(dt));
523 }
524
525 struct dt_object_operations lod_obj_ops = {
526         .do_read_lock           = lod_object_read_lock,
527         .do_write_lock          = lod_object_write_lock,
528         .do_read_unlock         = lod_object_read_unlock,
529         .do_write_unlock        = lod_object_write_unlock,
530         .do_write_locked        = lod_object_write_locked,
531         .do_attr_get            = lod_attr_get,
532         .do_declare_attr_set    = lod_declare_attr_set,
533         .do_attr_set            = lod_attr_set,
534         .do_xattr_get           = lod_xattr_get,
535         .do_declare_xattr_set   = lod_declare_xattr_set,
536         .do_xattr_set           = lod_xattr_set,
537         .do_declare_xattr_del   = lod_declare_xattr_del,
538         .do_xattr_del           = lod_xattr_del,
539         .do_xattr_list          = lod_xattr_list,
540         .do_ah_init             = lod_ah_init,
541         .do_declare_create      = lod_declare_object_create,
542         .do_create              = lod_object_create,
543         .do_declare_destroy     = lod_declare_object_destroy,
544         .do_destroy             = lod_object_destroy,
545         .do_index_try           = lod_index_try,
546         .do_declare_ref_add     = lod_declare_ref_add,
547         .do_ref_add             = lod_ref_add,
548         .do_declare_ref_del     = lod_declare_ref_del,
549         .do_ref_del             = lod_ref_del,
550         .do_capa_get            = lod_capa_get,
551         .do_object_sync         = lod_object_sync,
552 };
553
554 static ssize_t lod_read(const struct lu_env *env, struct dt_object *dt,
555                         struct lu_buf *buf, loff_t *pos,
556                         struct lustre_capa *capa)
557 {
558         struct dt_object *next = dt_object_child(dt);
559         return next->do_body_ops->dbo_read(env, next, buf, pos, capa);
560 }
561
562 static ssize_t lod_declare_write(const struct lu_env *env,
563                                  struct dt_object *dt,
564                                  const loff_t size, loff_t pos,
565                                  struct thandle *th)
566 {
567         return dt_declare_record_write(env, dt_object_child(dt),
568                                        size, pos, th);
569 }
570
571 static ssize_t lod_write(const struct lu_env *env, struct dt_object *dt,
572                          const struct lu_buf *buf, loff_t *pos,
573                          struct thandle *th, struct lustre_capa *capa, int iq)
574 {
575         struct dt_object *next = dt_object_child(dt);
576         LASSERT(next);
577         return next->do_body_ops->dbo_write(env, next, buf, pos, th, capa, iq);
578 }
579
580 static const struct dt_body_operations lod_body_lnk_ops = {
581         .dbo_read               = lod_read,
582         .dbo_declare_write      = lod_declare_write,
583         .dbo_write              = lod_write
584 };
585
586 static int lod_object_init(const struct lu_env *env, struct lu_object *o,
587                            const struct lu_object_conf *conf)
588 {
589         struct lod_device *d = lu2lod_dev(o->lo_dev);
590         struct lu_object  *below;
591         struct lu_device  *under;
592         ENTRY;
593
594         /*
595          * create local object
596          */
597         under = &d->lod_child->dd_lu_dev;
598         below = under->ld_ops->ldo_object_alloc(env, o->lo_header, under);
599         if (below == NULL)
600                 RETURN(-ENOMEM);
601
602         lu_object_add(o, below);
603
604         RETURN(0);
605 }
606
607 void lod_object_free_striping(const struct lu_env *env, struct lod_object *lo)
608 {
609         int i;
610
611         if (lo->ldo_stripe) {
612                 LASSERT(lo->ldo_stripes_allocated > 0);
613
614                 for (i = 0; i < lo->ldo_stripenr; i++) {
615                         if (lo->ldo_stripe[i])
616                                 lu_object_put(env, &lo->ldo_stripe[i]->do_lu);
617                 }
618
619                 i = sizeof(struct dt_object *) * lo->ldo_stripes_allocated;
620                 OBD_FREE(lo->ldo_stripe, i);
621                 lo->ldo_stripe = NULL;
622                 lo->ldo_stripes_allocated = 0;
623         }
624         lo->ldo_stripenr = 0;
625 }
626
627 /*
628  * ->start is called once all slices are initialized, including header's
629  * cache for mode (object type). using the type we can initialize ops
630  */
631 static int lod_object_start(const struct lu_env *env, struct lu_object *o)
632 {
633         if (S_ISLNK(o->lo_header->loh_attr & S_IFMT))
634                 lu2lod_obj(o)->ldo_obj.do_body_ops = &lod_body_lnk_ops;
635         return 0;
636 }
637
638 static void lod_object_free(const struct lu_env *env, struct lu_object *o)
639 {
640         struct lod_object *mo = lu2lod_obj(o);
641
642         /*
643          * release all underlying object pinned
644          */
645
646         lod_object_free_striping(env, mo);
647
648         lod_object_set_pool(mo, NULL);
649
650         lu_object_fini(o);
651         OBD_SLAB_FREE_PTR(mo, lod_object_kmem);
652 }
653
654 static void lod_object_release(const struct lu_env *env, struct lu_object *o)
655 {
656         /* XXX: shouldn't we release everything here in case if object
657          * creation failed before? */
658 }
659
660 static int lod_object_print(const struct lu_env *env, void *cookie,
661                             lu_printer_t p, const struct lu_object *l)
662 {
663         struct lod_object *o = lu2lod_obj((struct lu_object *) l);
664
665         return (*p)(env, cookie, LUSTRE_LOD_NAME"-object@%p", o);
666 }
667
668 struct lu_object_operations lod_lu_obj_ops = {
669         .loo_object_init        = lod_object_init,
670         .loo_object_start       = lod_object_start,
671         .loo_object_free        = lod_object_free,
672         .loo_object_release     = lod_object_release,
673         .loo_object_print       = lod_object_print,
674 };