4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * Implementation of cl_object for OSC layer.
38 * Author: Nikita Danilov <nikita.danilov@sun.com>
41 #define DEBUG_SUBSYSTEM S_OSC
43 #include "osc_cl_internal.h"
49 /*****************************************************************************
55 static struct lu_object
*osc2lu(struct osc_object
*osc
)
57 return &osc
->oo_cl
.co_lu
;
60 static struct osc_object
*lu2osc(const struct lu_object
*obj
)
62 LINVRNT(osc_is_object(obj
));
63 return container_of0(obj
, struct osc_object
, oo_cl
.co_lu
);
66 /*****************************************************************************
72 static int osc_object_init(const struct lu_env
*env
, struct lu_object
*obj
,
73 const struct lu_object_conf
*conf
)
75 struct osc_object
*osc
= lu2osc(obj
);
76 const struct cl_object_conf
*cconf
= lu2cl_conf(conf
);
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
]);
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
);
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
);
98 cl_object_page_init(lu2cl(obj
), sizeof(struct osc_page
));
103 static void osc_object_free(const struct lu_env
*env
, struct lu_object
*obj
)
105 struct osc_object
*osc
= lu2osc(obj
);
108 for (i
= 0; i
< CRT_NR
; ++i
)
109 LASSERT(list_empty(&osc
->oo_inflight
[i
]));
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
));
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);
125 OBD_SLAB_FREE_PTR(osc
, osc_object_kmem
);
128 int osc_lvb_print(const struct lu_env
*env
, void *cookie
,
129 lu_printer_t p
, const struct ost_lvb
*lvb
)
131 return (*p
)(env
, cookie
, "size: "LPU64
" mtime: "LPU64
" atime: "LPU64
" "
132 "ctime: "LPU64
" blocks: "LPU64
,
133 lvb
->lvb_size
, lvb
->lvb_mtime
, lvb
->lvb_atime
,
134 lvb
->lvb_ctime
, lvb
->lvb_blocks
);
137 static int osc_object_print(const struct lu_env
*env
, void *cookie
,
138 lu_printer_t p
, const struct lu_object
*obj
)
140 struct osc_object
*osc
= lu2osc(obj
);
141 struct lov_oinfo
*oinfo
= osc
->oo_oinfo
;
142 struct osc_async_rc
*ar
= &oinfo
->loi_ar
;
144 (*p
)(env
, cookie
, "id: "DOSTID
" "
145 "idx: %d gen: %d kms_valid: %u kms "LPU64
" "
146 "rc: %d force_sync: %d min_xid: "LPU64
" ",
147 POSTID(&oinfo
->loi_oi
), oinfo
->loi_ost_idx
,
148 oinfo
->loi_ost_gen
, oinfo
->loi_kms_valid
, oinfo
->loi_kms
,
149 ar
->ar_rc
, ar
->ar_force_sync
, ar
->ar_min_xid
);
150 osc_lvb_print(env
, cookie
, p
, &oinfo
->loi_lvb
);
155 static int osc_attr_get(const struct lu_env
*env
, struct cl_object
*obj
,
156 struct cl_attr
*attr
)
158 struct lov_oinfo
*oinfo
= cl2osc(obj
)->oo_oinfo
;
160 cl_lvb2attr(attr
, &oinfo
->loi_lvb
);
161 attr
->cat_kms
= oinfo
->loi_kms_valid
? oinfo
->loi_kms
: 0;
165 int osc_attr_set(const struct lu_env
*env
, struct cl_object
*obj
,
166 const struct cl_attr
*attr
, unsigned valid
)
168 struct lov_oinfo
*oinfo
= cl2osc(obj
)->oo_oinfo
;
169 struct ost_lvb
*lvb
= &oinfo
->loi_lvb
;
171 if (valid
& CAT_SIZE
)
172 lvb
->lvb_size
= attr
->cat_size
;
173 if (valid
& CAT_MTIME
)
174 lvb
->lvb_mtime
= attr
->cat_mtime
;
175 if (valid
& CAT_ATIME
)
176 lvb
->lvb_atime
= attr
->cat_atime
;
177 if (valid
& CAT_CTIME
)
178 lvb
->lvb_ctime
= attr
->cat_ctime
;
179 if (valid
& CAT_BLOCKS
)
180 lvb
->lvb_blocks
= attr
->cat_blocks
;
181 if (valid
& CAT_KMS
) {
182 CDEBUG(D_CACHE
, "set kms from "LPU64
"to "LPU64
"\n",
183 oinfo
->loi_kms
, (__u64
)attr
->cat_kms
);
184 loi_kms_set(oinfo
, attr
->cat_kms
);
189 static int osc_object_glimpse(const struct lu_env
*env
,
190 const struct cl_object
*obj
, struct ost_lvb
*lvb
)
192 struct lov_oinfo
*oinfo
= cl2osc(obj
)->oo_oinfo
;
194 lvb
->lvb_size
= oinfo
->loi_kms
;
195 lvb
->lvb_blocks
= oinfo
->loi_lvb
.lvb_blocks
;
200 void osc_object_set_contended(struct osc_object
*obj
)
202 obj
->oo_contention_time
= cfs_time_current();
204 obj
->oo_contended
= 1;
207 void osc_object_clear_contended(struct osc_object
*obj
)
209 obj
->oo_contended
= 0;
212 int osc_object_is_contended(struct osc_object
*obj
)
214 struct osc_device
*dev
= lu2osc_dev(obj
->oo_cl
.co_lu
.lo_dev
);
215 int osc_contention_time
= dev
->od_contention_time
;
216 cfs_time_t cur_time
= cfs_time_current();
217 cfs_time_t retry_time
;
219 if (OBD_FAIL_CHECK(OBD_FAIL_OSC_OBJECT_CONTENTION
))
222 if (!obj
->oo_contended
)
226 * I like copy-paste. the code is copied from
227 * ll_file_is_contended.
229 retry_time
= cfs_time_add(obj
->oo_contention_time
,
230 cfs_time_seconds(osc_contention_time
));
231 if (cfs_time_after(cur_time
, retry_time
)) {
232 osc_object_clear_contended(obj
);
238 static const struct cl_object_operations osc_ops
= {
239 .coo_page_init
= osc_page_init
,
240 .coo_lock_init
= osc_lock_init
,
241 .coo_io_init
= osc_io_init
,
242 .coo_attr_get
= osc_attr_get
,
243 .coo_attr_set
= osc_attr_set
,
244 .coo_glimpse
= osc_object_glimpse
247 static const struct lu_object_operations osc_lu_obj_ops
= {
248 .loo_object_init
= osc_object_init
,
249 .loo_object_delete
= NULL
,
250 .loo_object_release
= NULL
,
251 .loo_object_free
= osc_object_free
,
252 .loo_object_print
= osc_object_print
,
253 .loo_object_invariant
= NULL
256 struct lu_object
*osc_object_alloc(const struct lu_env
*env
,
257 const struct lu_object_header
*unused
,
258 struct lu_device
*dev
)
260 struct osc_object
*osc
;
261 struct lu_object
*obj
;
263 OBD_SLAB_ALLOC_PTR_GFP(osc
, osc_object_kmem
, __GFP_IO
);
266 lu_object_init(obj
, NULL
, dev
);
267 osc
->oo_cl
.co_ops
= &osc_ops
;
268 obj
->lo_ops
= &osc_lu_obj_ops
;