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,
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.
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
23 * Copyright (c) 2017, Intel Corporation.
26 * lustre/mdt/mdt_som.c
30 * Author: Jinshan Xiong <jinshan.xiong@intel.com>
31 * Author: Yingjin Qian <qian@ddn.com>
34 #define DEBUG_SUBSYSTEM S_MDS
36 #include "mdt_internal.h"
39 * Swab and extract SOM attributes from on-disk xattr.
41 * \param buf - is a buffer containing the on-disk LSOM extended attribute.
42 * \param rc - is the SOM xattr stored in \a buf
43 * \param ms - is the md_som structure where to extract SOM attributes.
45 static int lustre_buf2som(void *buf, int rc, struct md_som *ms)
47 struct lustre_som_attrs *attrs = (struct lustre_som_attrs *)buf;
50 if (rc == 0 || rc == -ENODATA)
51 /* no LSOM attributes */
55 /* error hit while fetching xattr */
58 /* unpack LSOM attributes */
59 lustre_som_swab(attrs);
61 /* fill in-memory md_som structure */
62 ms->ms_valid = attrs->lsa_valid;
63 ms->ms_size = attrs->lsa_size;
64 ms->ms_blocks = attrs->lsa_blocks;
69 int mdt_get_som(struct mdt_thread_info *info, struct mdt_object *obj,
72 struct lu_buf *buf = &info->mti_buf;
73 struct lu_attr *attr = &ma->ma_attr;
76 buf->lb_buf = info->mti_xattr_buf;
77 buf->lb_len = sizeof(info->mti_xattr_buf);
78 BUILD_BUG_ON(sizeof(struct lustre_som_attrs) >
79 sizeof(info->mti_xattr_buf));
80 rc = mo_xattr_get(info->mti_env, mdt_object_child(obj), buf,
82 rc = lustre_buf2som(info->mti_xattr_buf, rc, &ma->ma_som);
84 struct md_som *som = &ma->ma_som;
86 ma->ma_valid |= MA_SOM;
88 CDEBUG(D_INODE, DFID": Reading som attrs: "
89 "valid: %x, size: %lld, blocks: %lld\n",
90 PFID(mdt_object_fid(obj)), som->ms_valid,
91 som->ms_size, som->ms_blocks);
93 if (som->ms_valid & SOM_FL_STRICT) {
94 attr->la_valid |= LA_SIZE | LA_BLOCKS;
97 * Size on MDS is valid and could be returned
100 attr->la_size = som->ms_size;
101 attr->la_blocks = som->ms_blocks;
102 info->mti_som_strict = 1;
103 } else if (!obj->mot_lsom_inited &&
104 (som->ms_valid & SOM_FL_LAZY) &&
105 !mutex_is_locked(&obj->mot_som_mutex)) {
106 mutex_lock(&obj->mot_som_mutex);
107 obj->mot_lsom_size = som->ms_size;
108 obj->mot_lsom_blocks = som->ms_blocks;
109 obj->mot_lsom_inited = true;
110 mutex_unlock(&obj->mot_som_mutex);
112 } else if (rc == -ENODATA) {
120 * Update SOM on-disk attributes.
122 int mdt_set_som(struct mdt_thread_info *info, struct mdt_object *obj,
123 enum lustre_som_flags flag, __u64 size, __u64 blocks)
125 struct md_object *next = mdt_object_child(obj);
126 struct lu_buf *buf = &info->mti_buf;
127 struct lustre_som_attrs *som;
133 DFID": Set SOM attrs S/B/F: %lld/%lld/%x.\n",
134 PFID(mdt_object_fid(obj)), size, blocks, flag);
136 som = (struct lustre_som_attrs *)info->mti_xattr_buf;
137 BUILD_BUG_ON(sizeof(info->mti_xattr_buf) < sizeof(*som));
139 som->lsa_valid = flag;
140 som->lsa_size = size;
141 som->lsa_blocks = blocks;
142 memset(&som->lsa_reserved, 0, sizeof(som->lsa_reserved));
143 lustre_som_swab(som);
145 /* update SOM attributes */
147 buf->lb_len = sizeof(*som);
148 rc = mo_xattr_set(info->mti_env, next, buf, XATTR_NAME_SOM, 0);
149 if (!rc && flag == SOM_FL_LAZY) {
150 obj->mot_lsom_size = size;
151 obj->mot_lsom_blocks = blocks;
152 obj->mot_lsom_inited = true;
158 * SOM state transition from STRICT to STALE,
160 int mdt_lsom_downgrade(struct mdt_thread_info *info, struct mdt_object *o)
162 struct md_attr *tmp_ma;
167 mutex_lock(&o->mot_som_mutex);
168 tmp_ma = &info->mti_u.som.attr;
169 tmp_ma->ma_need = MA_SOM;
170 tmp_ma->ma_valid = 0;
172 rc = mdt_get_som(info, o, tmp_ma);
176 if (tmp_ma->ma_valid & MA_SOM) {
177 struct md_som *som = &tmp_ma->ma_som;
179 info->mti_som_strict = 0;
180 /* The size and blocks info should be still correct. */
181 if (som->ms_valid & SOM_FL_STRICT)
182 rc = mdt_set_som(info, o, SOM_FL_STALE,
183 som->ms_size, som->ms_blocks);
186 mutex_unlock(&o->mot_som_mutex);
190 int mdt_lsom_update(struct mdt_thread_info *info,
191 struct mdt_object *o, bool truncate)
193 struct md_attr *ma, *tmp_ma;
199 ma = &info->mti_attr;
203 "valid %llx, lsom init %d lsom size %llu size %llu lsom blocks %llu blocks %llu truncate %d\n",
204 la->la_valid, o->mot_lsom_inited, o->mot_lsom_size, la->la_size,
205 o->mot_lsom_blocks, la->la_blocks, truncate);
206 if (!(la->la_valid & (LA_SIZE | LA_LSIZE) &&
207 o->mot_lsom_size < la->la_size) &&
208 !(la->la_valid & (LA_BLOCKS | LA_LBLOCKS) &&
209 o->mot_lsom_blocks < la->la_blocks) && !truncate &&
213 tmp_ma = &info->mti_u.som.attr;
214 tmp_ma->ma_need = MA_INODE | MA_SOM;
215 tmp_ma->ma_valid = 0;
217 rc = mdt_attr_get_complex(info, o, tmp_ma);
222 * If mti_big_lmm_used is set, it indicates that mti_big_lmm
223 * should contain valid LOV EA data, and can be used directly.
225 if (!info->mti_big_lmm_used) {
226 rc = mdt_big_xattr_get(info, o, XATTR_NAME_LOV);
227 if (rc < 0 && rc != -ENODATA)
238 * Check if a Lazy Size-on-MDS update is needed. Skip the
239 * file with no LOV EA, unlink files or DoM-only file.
240 * MDS only updates LSOM of the file if the size or block
241 * size is being increased or the file is being truncated.
243 if (!mdt_lmm_dom_only(info->mti_big_lmm) &&
244 !(tmp_ma->ma_valid & MA_INODE && tmp_ma->ma_attr.la_nlink == 0)) {
247 bool changed = false;
248 struct md_som *som = &tmp_ma->ma_som;
254 } else if (!(tmp_ma->ma_valid & MA_SOM) ||
255 size < som->ms_size) {
256 /* We cannot rely to blocks after
257 * truncate especially for spare file,
258 * and the truncate operation is usually
259 * followed with a close, so just set blocks
260 * to 1 here, and the following close will
261 * update it accordingly.
265 blocks = som->ms_blocks;
268 if (!(tmp_ma->ma_valid & MA_SOM)) {
269 /* Only set initial SOM Xattr data when both
270 * size and blocks are valid.
272 if (la->la_valid & (LA_SIZE | LA_LSIZE) &&
273 la->la_valid & (LA_BLOCKS | LA_LBLOCKS)) {
276 blocks = la->la_blocks;
279 /* Double check whether it is already set
280 * to SOM_FL_STRICT in mdt_mfd_close.
281 * If file is in SOM_FL_STALE state, and
282 * the close indicates there is no data
283 * modified, skip to transimit to LAZY
286 if (som->ms_valid & SOM_FL_STRICT ||
287 (som->ms_valid & SOM_FL_STALE &&
288 !(ma->ma_attr_flags & MDS_DATA_MODIFIED)))
292 blocks = som->ms_blocks;
293 if (la->la_valid & (LA_SIZE | LA_LSIZE) &&
294 la->la_size > som->ms_size) {
298 if (la->la_valid & (LA_BLOCKS | LA_LBLOCKS) &&
299 la->la_blocks > som->ms_blocks) {
301 blocks = la->la_blocks;
305 if (truncate || changed) {
306 mutex_lock(&o->mot_som_mutex);
307 if (size <= o->mot_lsom_size &&
308 blocks <= o->mot_lsom_blocks && !truncate &&
309 o->mot_lsom_inited) {
310 mutex_unlock(&o->mot_som_mutex);
313 if (!truncate && size < o->mot_lsom_size)
314 size = o->mot_lsom_size;
315 if (!truncate && blocks < o->mot_lsom_blocks)
316 blocks = o->mot_lsom_blocks;
317 rc = mdt_set_som(info, o, SOM_FL_LAZY, size, blocks);
318 mutex_unlock(&o->mot_som_mutex);