]>
Commit | Line | Data |
---|---|---|
d7e09d03 PT |
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) 2011, 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 | * Implementation of cl_object for OSC layer. | |
37 | * | |
38 | * Author: Nikita Danilov <nikita.danilov@sun.com> | |
39 | */ | |
40 | ||
41 | #define DEBUG_SUBSYSTEM S_OSC | |
42 | ||
43 | #include "osc_cl_internal.h" | |
44 | ||
45 | /** \addtogroup osc | |
46 | * @{ | |
47 | */ | |
48 | ||
49 | /***************************************************************************** | |
50 | * | |
51 | * Type conversions. | |
52 | * | |
53 | */ | |
54 | ||
55 | static struct lu_object *osc2lu(struct osc_object *osc) | |
56 | { | |
57 | return &osc->oo_cl.co_lu; | |
58 | } | |
59 | ||
60 | static struct osc_object *lu2osc(const struct lu_object *obj) | |
61 | { | |
62 | LINVRNT(osc_is_object(obj)); | |
63 | return container_of0(obj, struct osc_object, oo_cl.co_lu); | |
64 | } | |
65 | ||
66 | /***************************************************************************** | |
67 | * | |
68 | * Object operations. | |
69 | * | |
70 | */ | |
71 | ||
72 | static int osc_object_init(const struct lu_env *env, struct lu_object *obj, | |
73 | const struct lu_object_conf *conf) | |
74 | { | |
29ac6840 | 75 | struct osc_object *osc = lu2osc(obj); |
d7e09d03 PT |
76 | const struct cl_object_conf *cconf = lu2cl_conf(conf); |
77 | int i; | |
78 | ||
79 | osc->oo_oinfo = cconf->u.coc_oinfo; | |
80 | spin_lock_init(&osc->oo_seatbelt); | |
81 | for (i = 0; i < CRT_NR; ++i) | |
82 | INIT_LIST_HEAD(&osc->oo_inflight[i]); | |
83 | ||
84 | INIT_LIST_HEAD(&osc->oo_ready_item); | |
85 | INIT_LIST_HEAD(&osc->oo_hp_ready_item); | |
86 | INIT_LIST_HEAD(&osc->oo_write_item); | |
87 | INIT_LIST_HEAD(&osc->oo_read_item); | |
88 | ||
89 | osc->oo_root.rb_node = NULL; | |
90 | INIT_LIST_HEAD(&osc->oo_hp_exts); | |
91 | INIT_LIST_HEAD(&osc->oo_urgent_exts); | |
92 | INIT_LIST_HEAD(&osc->oo_rpc_exts); | |
93 | INIT_LIST_HEAD(&osc->oo_reading_exts); | |
94 | atomic_set(&osc->oo_nr_reads, 0); | |
95 | atomic_set(&osc->oo_nr_writes, 0); | |
96 | spin_lock_init(&osc->oo_lock); | |
97 | ||
98 | cl_object_page_init(lu2cl(obj), sizeof(struct osc_page)); | |
99 | ||
100 | return 0; | |
101 | } | |
102 | ||
103 | static void osc_object_free(const struct lu_env *env, struct lu_object *obj) | |
104 | { | |
105 | struct osc_object *osc = lu2osc(obj); | |
106 | int i; | |
107 | ||
108 | for (i = 0; i < CRT_NR; ++i) | |
109 | LASSERT(list_empty(&osc->oo_inflight[i])); | |
110 | ||
111 | LASSERT(list_empty(&osc->oo_ready_item)); | |
112 | LASSERT(list_empty(&osc->oo_hp_ready_item)); | |
113 | LASSERT(list_empty(&osc->oo_write_item)); | |
114 | LASSERT(list_empty(&osc->oo_read_item)); | |
115 | ||
116 | LASSERT(osc->oo_root.rb_node == NULL); | |
117 | LASSERT(list_empty(&osc->oo_hp_exts)); | |
118 | LASSERT(list_empty(&osc->oo_urgent_exts)); | |
119 | LASSERT(list_empty(&osc->oo_rpc_exts)); | |
120 | LASSERT(list_empty(&osc->oo_reading_exts)); | |
121 | LASSERT(atomic_read(&osc->oo_nr_reads) == 0); | |
122 | LASSERT(atomic_read(&osc->oo_nr_writes) == 0); | |
123 | ||
124 | lu_object_fini(obj); | |
125 | OBD_SLAB_FREE_PTR(osc, osc_object_kmem); | |
126 | } | |
127 | ||
128 | int osc_lvb_print(const struct lu_env *env, void *cookie, | |
129 | lu_printer_t p, const struct ost_lvb *lvb) | |
130 | { | |
b0f5aad5 | 131 | return (*p)(env, cookie, "size: %llu mtime: %llu atime: %llu ctime: %llu blocks: %llu", |
d7e09d03 PT |
132 | lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime, |
133 | lvb->lvb_ctime, lvb->lvb_blocks); | |
134 | } | |
135 | ||
136 | static int osc_object_print(const struct lu_env *env, void *cookie, | |
137 | lu_printer_t p, const struct lu_object *obj) | |
138 | { | |
29ac6840 CH |
139 | struct osc_object *osc = lu2osc(obj); |
140 | struct lov_oinfo *oinfo = osc->oo_oinfo; | |
141 | struct osc_async_rc *ar = &oinfo->loi_ar; | |
d7e09d03 | 142 | |
2d00bd17 | 143 | (*p)(env, cookie, "id: " DOSTID " idx: %d gen: %d kms_valid: %u kms %llu rc: %d force_sync: %d min_xid: %llu ", |
d7e09d03 PT |
144 | POSTID(&oinfo->loi_oi), oinfo->loi_ost_idx, |
145 | oinfo->loi_ost_gen, oinfo->loi_kms_valid, oinfo->loi_kms, | |
146 | ar->ar_rc, ar->ar_force_sync, ar->ar_min_xid); | |
147 | osc_lvb_print(env, cookie, p, &oinfo->loi_lvb); | |
148 | return 0; | |
149 | } | |
150 | ||
151 | ||
152 | static int osc_attr_get(const struct lu_env *env, struct cl_object *obj, | |
153 | struct cl_attr *attr) | |
154 | { | |
155 | struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; | |
156 | ||
157 | cl_lvb2attr(attr, &oinfo->loi_lvb); | |
158 | attr->cat_kms = oinfo->loi_kms_valid ? oinfo->loi_kms : 0; | |
159 | return 0; | |
160 | } | |
161 | ||
162 | int osc_attr_set(const struct lu_env *env, struct cl_object *obj, | |
163 | const struct cl_attr *attr, unsigned valid) | |
164 | { | |
165 | struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; | |
29ac6840 | 166 | struct ost_lvb *lvb = &oinfo->loi_lvb; |
d7e09d03 PT |
167 | |
168 | if (valid & CAT_SIZE) | |
169 | lvb->lvb_size = attr->cat_size; | |
170 | if (valid & CAT_MTIME) | |
171 | lvb->lvb_mtime = attr->cat_mtime; | |
172 | if (valid & CAT_ATIME) | |
173 | lvb->lvb_atime = attr->cat_atime; | |
174 | if (valid & CAT_CTIME) | |
175 | lvb->lvb_ctime = attr->cat_ctime; | |
176 | if (valid & CAT_BLOCKS) | |
177 | lvb->lvb_blocks = attr->cat_blocks; | |
178 | if (valid & CAT_KMS) { | |
b0f5aad5 | 179 | CDEBUG(D_CACHE, "set kms from %llu to %llu\n", |
d7e09d03 PT |
180 | oinfo->loi_kms, (__u64)attr->cat_kms); |
181 | loi_kms_set(oinfo, attr->cat_kms); | |
182 | } | |
183 | return 0; | |
184 | } | |
185 | ||
186 | static int osc_object_glimpse(const struct lu_env *env, | |
187 | const struct cl_object *obj, struct ost_lvb *lvb) | |
188 | { | |
189 | struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; | |
190 | ||
29ac6840 | 191 | lvb->lvb_size = oinfo->loi_kms; |
d7e09d03 | 192 | lvb->lvb_blocks = oinfo->loi_lvb.lvb_blocks; |
0a3bdb00 | 193 | return 0; |
d7e09d03 PT |
194 | } |
195 | ||
196 | ||
197 | void osc_object_set_contended(struct osc_object *obj) | |
198 | { | |
199 | obj->oo_contention_time = cfs_time_current(); | |
200 | /* mb(); */ | |
201 | obj->oo_contended = 1; | |
202 | } | |
203 | ||
204 | void osc_object_clear_contended(struct osc_object *obj) | |
205 | { | |
206 | obj->oo_contended = 0; | |
207 | } | |
208 | ||
209 | int osc_object_is_contended(struct osc_object *obj) | |
210 | { | |
29ac6840 | 211 | struct osc_device *dev = lu2osc_dev(obj->oo_cl.co_lu.lo_dev); |
d7e09d03 | 212 | int osc_contention_time = dev->od_contention_time; |
29ac6840 | 213 | unsigned long cur_time = cfs_time_current(); |
a649ad1d | 214 | unsigned long retry_time; |
d7e09d03 PT |
215 | |
216 | if (OBD_FAIL_CHECK(OBD_FAIL_OSC_OBJECT_CONTENTION)) | |
217 | return 1; | |
218 | ||
219 | if (!obj->oo_contended) | |
220 | return 0; | |
221 | ||
222 | /* | |
223 | * I like copy-paste. the code is copied from | |
224 | * ll_file_is_contended. | |
225 | */ | |
226 | retry_time = cfs_time_add(obj->oo_contention_time, | |
227 | cfs_time_seconds(osc_contention_time)); | |
228 | if (cfs_time_after(cur_time, retry_time)) { | |
229 | osc_object_clear_contended(obj); | |
230 | return 0; | |
231 | } | |
232 | return 1; | |
233 | } | |
234 | ||
235 | static const struct cl_object_operations osc_ops = { | |
236 | .coo_page_init = osc_page_init, | |
237 | .coo_lock_init = osc_lock_init, | |
238 | .coo_io_init = osc_io_init, | |
239 | .coo_attr_get = osc_attr_get, | |
240 | .coo_attr_set = osc_attr_set, | |
241 | .coo_glimpse = osc_object_glimpse | |
242 | }; | |
243 | ||
244 | static const struct lu_object_operations osc_lu_obj_ops = { | |
245 | .loo_object_init = osc_object_init, | |
246 | .loo_object_delete = NULL, | |
247 | .loo_object_release = NULL, | |
248 | .loo_object_free = osc_object_free, | |
249 | .loo_object_print = osc_object_print, | |
250 | .loo_object_invariant = NULL | |
251 | }; | |
252 | ||
253 | struct lu_object *osc_object_alloc(const struct lu_env *env, | |
254 | const struct lu_object_header *unused, | |
255 | struct lu_device *dev) | |
256 | { | |
257 | struct osc_object *osc; | |
29ac6840 | 258 | struct lu_object *obj; |
d7e09d03 | 259 | |
0be19afa | 260 | OBD_SLAB_ALLOC_PTR_GFP(osc, osc_object_kmem, GFP_NOFS); |
d7e09d03 PT |
261 | if (osc != NULL) { |
262 | obj = osc2lu(osc); | |
263 | lu_object_init(obj, NULL, dev); | |
264 | osc->oo_cl.co_ops = &osc_ops; | |
265 | obj->lo_ops = &osc_lu_obj_ops; | |
266 | } else | |
267 | obj = NULL; | |
268 | return obj; | |
269 | } | |
270 | ||
271 | /** @} osc */ |