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, 2015, 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
);
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 kmem_cache_free(osc_object_kmem
, osc
);
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: %llu mtime: %llu atime: %llu ctime: %llu blocks: %llu",
132 lvb
->lvb_size
, lvb
->lvb_mtime
, lvb
->lvb_atime
,
133 lvb
->lvb_ctime
, lvb
->lvb_blocks
);
136 static int osc_object_print(const struct lu_env
*env
, void *cookie
,
137 lu_printer_t p
, const struct lu_object
*obj
)
139 struct osc_object
*osc
= lu2osc(obj
);
140 struct lov_oinfo
*oinfo
= osc
->oo_oinfo
;
141 struct osc_async_rc
*ar
= &oinfo
->loi_ar
;
143 (*p
)(env
, cookie
, "id: " DOSTID
" idx: %d gen: %d kms_valid: %u kms %llu rc: %d force_sync: %d min_xid: %llu ",
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
);
151 static int osc_attr_get(const struct lu_env
*env
, struct cl_object
*obj
,
152 struct cl_attr
*attr
)
154 struct lov_oinfo
*oinfo
= cl2osc(obj
)->oo_oinfo
;
156 cl_lvb2attr(attr
, &oinfo
->loi_lvb
);
157 attr
->cat_kms
= oinfo
->loi_kms_valid
? oinfo
->loi_kms
: 0;
161 static int osc_attr_set(const struct lu_env
*env
, struct cl_object
*obj
,
162 const struct cl_attr
*attr
, unsigned valid
)
164 struct lov_oinfo
*oinfo
= cl2osc(obj
)->oo_oinfo
;
165 struct ost_lvb
*lvb
= &oinfo
->loi_lvb
;
167 if (valid
& CAT_SIZE
)
168 lvb
->lvb_size
= attr
->cat_size
;
169 if (valid
& CAT_MTIME
)
170 lvb
->lvb_mtime
= attr
->cat_mtime
;
171 if (valid
& CAT_ATIME
)
172 lvb
->lvb_atime
= attr
->cat_atime
;
173 if (valid
& CAT_CTIME
)
174 lvb
->lvb_ctime
= attr
->cat_ctime
;
175 if (valid
& CAT_BLOCKS
)
176 lvb
->lvb_blocks
= attr
->cat_blocks
;
177 if (valid
& CAT_KMS
) {
178 CDEBUG(D_CACHE
, "set kms from %llu to %llu\n",
179 oinfo
->loi_kms
, (__u64
)attr
->cat_kms
);
180 loi_kms_set(oinfo
, attr
->cat_kms
);
185 static int osc_object_glimpse(const struct lu_env
*env
,
186 const struct cl_object
*obj
, struct ost_lvb
*lvb
)
188 struct lov_oinfo
*oinfo
= cl2osc(obj
)->oo_oinfo
;
190 lvb
->lvb_size
= oinfo
->loi_kms
;
191 lvb
->lvb_blocks
= oinfo
->loi_lvb
.lvb_blocks
;
195 void osc_object_set_contended(struct osc_object
*obj
)
197 obj
->oo_contention_time
= cfs_time_current();
199 obj
->oo_contended
= 1;
202 void osc_object_clear_contended(struct osc_object
*obj
)
204 obj
->oo_contended
= 0;
207 int osc_object_is_contended(struct osc_object
*obj
)
209 struct osc_device
*dev
= lu2osc_dev(obj
->oo_cl
.co_lu
.lo_dev
);
210 int osc_contention_time
= dev
->od_contention_time
;
211 unsigned long cur_time
= cfs_time_current();
212 unsigned long retry_time
;
214 if (OBD_FAIL_CHECK(OBD_FAIL_OSC_OBJECT_CONTENTION
))
217 if (!obj
->oo_contended
)
221 * I like copy-paste. the code is copied from
222 * ll_file_is_contended.
224 retry_time
= cfs_time_add(obj
->oo_contention_time
,
225 cfs_time_seconds(osc_contention_time
));
226 if (cfs_time_after(cur_time
, retry_time
)) {
227 osc_object_clear_contended(obj
);
233 static const struct cl_object_operations osc_ops
= {
234 .coo_page_init
= osc_page_init
,
235 .coo_lock_init
= osc_lock_init
,
236 .coo_io_init
= osc_io_init
,
237 .coo_attr_get
= osc_attr_get
,
238 .coo_attr_set
= osc_attr_set
,
239 .coo_glimpse
= osc_object_glimpse
242 static const struct lu_object_operations osc_lu_obj_ops
= {
243 .loo_object_init
= osc_object_init
,
244 .loo_object_delete
= NULL
,
245 .loo_object_release
= NULL
,
246 .loo_object_free
= osc_object_free
,
247 .loo_object_print
= osc_object_print
,
248 .loo_object_invariant
= NULL
251 struct lu_object
*osc_object_alloc(const struct lu_env
*env
,
252 const struct lu_object_header
*unused
,
253 struct lu_device
*dev
)
255 struct osc_object
*osc
;
256 struct lu_object
*obj
;
258 osc
= kmem_cache_zalloc(osc_object_kmem
, GFP_NOFS
);
261 lu_object_init(obj
, NULL
, dev
);
262 osc
->oo_cl
.co_ops
= &osc_ops
;
263 obj
->lo_ops
= &osc_lu_obj_ops
;