Whamcloud - gitweb
LU-14521 flr: delete mirror without volatile file
[fs/lustre-release.git] / lustre / mdt / mdt_som.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 (c) 2017, Intel Corporation.
24  */
25 /*
26  * lustre/mdt/mdt_som.c
27  *
28  * Size on MDS revival
29  *
30  * Author: Jinshan Xiong <jinshan.xiong@intel.com>
31  * Author: Yingjin Qian <qian@ddn.com>
32  */
33
34 #define DEBUG_SUBSYSTEM S_MDS
35
36 #include "mdt_internal.h"
37
38 /*
39  * Swab and extract SOM attributes from on-disk xattr.
40  *
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.
44  */
45 int lustre_buf2som(void *buf, int rc, struct md_som *ms)
46 {
47         struct lustre_som_attrs *attrs = (struct lustre_som_attrs *)buf;
48         ENTRY;
49
50         if (rc == 0 || rc == -ENODATA)
51                 /* no LSOM attributes */
52                 RETURN(-ENODATA);
53
54         if (rc < 0)
55                 /* error hit while fetching xattr */
56                 RETURN(rc);
57
58         /* unpack LSOM attributes */
59         lustre_som_swab(attrs);
60
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;
65
66         RETURN(0);
67 }
68
69 int mdt_get_som(struct mdt_thread_info *info, struct mdt_object *obj,
70                 struct md_attr *ma)
71 {
72         struct lu_buf *buf = &info->mti_buf;
73         struct lu_attr *attr = &ma->ma_attr;
74         int rc;
75
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,
81                           XATTR_NAME_SOM);
82         rc = lustre_buf2som(info->mti_xattr_buf, rc, &ma->ma_som);
83         if (rc == 0) {
84                 struct md_som *som = &ma->ma_som;
85
86                 ma->ma_valid |= MA_SOM;
87
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);
92
93                 if (som->ms_valid & SOM_FL_STRICT) {
94                         attr->la_valid |= LA_SIZE | LA_BLOCKS;
95
96                         /*
97                          * Size on MDS is valid and could be returned
98                          * to client.
99                          */
100                         attr->la_size = som->ms_size;
101                         attr->la_blocks = som->ms_blocks;
102                         info->mti_som_valid = 1;
103                 }
104         } else if (rc == -ENODATA) {
105                 rc = 0;
106         }
107
108         return rc;
109 }
110
111 /**
112  * Update SOM on-disk attributes.
113  */
114 int mdt_set_som(struct mdt_thread_info *info, struct mdt_object *obj,
115                 enum lustre_som_flags flag, __u64 size, __u64 blocks)
116 {
117         struct md_object *next = mdt_object_child(obj);
118         struct lu_buf *buf = &info->mti_buf;
119         struct lustre_som_attrs *som;
120         int rc;
121
122         ENTRY;
123
124         CDEBUG(D_INODE,
125                DFID": Set SOM attrs S/B/F: %lld/%lld/%x.\n",
126                PFID(mdt_object_fid(obj)), size, blocks, flag);
127
128         som = (struct lustre_som_attrs *)info->mti_xattr_buf;
129         BUILD_BUG_ON(sizeof(info->mti_xattr_buf) < sizeof(*som));
130
131         som->lsa_valid = flag;
132         som->lsa_size = size;
133         som->lsa_blocks = blocks;
134         memset(&som->lsa_reserved, 0, sizeof(som->lsa_reserved));
135         lustre_som_swab(som);
136
137         /* update SOM attributes */
138         buf->lb_buf = som;
139         buf->lb_len = sizeof(*som);
140         rc = mo_xattr_set(info->mti_env, next, buf, XATTR_NAME_SOM, 0);
141
142         RETURN(rc);
143 }
144
145 /**
146  * SOM state transition from STRICT to STALE,
147  */
148 int mdt_lsom_downgrade(struct mdt_thread_info *info, struct mdt_object *o)
149 {
150         struct md_attr *tmp_ma;
151         int rc;
152
153         ENTRY;
154
155         mutex_lock(&o->mot_som_mutex);
156         tmp_ma = &info->mti_u.som.attr;
157         tmp_ma->ma_need = MA_SOM;
158         tmp_ma->ma_valid = 0;
159
160         rc = mdt_get_som(info, o, tmp_ma);
161         if (rc < 0)
162                 GOTO(out_lock, rc);
163
164         if (tmp_ma->ma_valid & MA_SOM) {
165                 struct md_som *som = &tmp_ma->ma_som;
166
167                 info->mti_som_valid = 0;
168                 /* The size and blocks info should be still correct. */
169                 if (som->ms_valid & SOM_FL_STRICT)
170                         rc = mdt_set_som(info, o, SOM_FL_STALE,
171                                          som->ms_size, som->ms_blocks);
172         }
173 out_lock:
174         mutex_unlock(&o->mot_som_mutex);
175         RETURN(rc);
176 }
177
178 int mdt_lsom_update(struct mdt_thread_info *info,
179                     struct mdt_object *o, bool truncate)
180 {
181         struct md_attr *ma, *tmp_ma;
182         struct lu_attr *la;
183         int rc = 0;
184
185         ENTRY;
186
187         ma = &info->mti_attr;
188         la = &ma->ma_attr;
189
190         mutex_lock(&o->mot_som_mutex);
191         tmp_ma = &info->mti_u.som.attr;
192         tmp_ma->ma_need = MA_INODE | MA_SOM;
193         tmp_ma->ma_valid = 0;
194
195         rc = mdt_attr_get_complex(info, o, tmp_ma);
196         if (rc)
197                 GOTO(out_lock, rc);
198
199         /**
200          * If mti_big_lmm_used is set, it indicates that mti_big_lmm
201          * should contain valid LOV EA data, and can be used directly.
202          */
203         if (!info->mti_big_lmm_used) {
204                 rc = mdt_big_xattr_get(info, o, XATTR_NAME_LOV);
205                 if (rc < 0 && rc != -ENODATA)
206                         GOTO(out_lock, rc);
207
208                 /* No LOV EA */
209                 if (rc == -ENODATA)
210                         GOTO(out_lock, rc = 0);
211
212                 rc = 0;
213         }
214
215         /**
216          * Check if a Lazy Size-on-MDS update is needed. Skip the
217          * file with no LOV EA, unlink files or DoM-only file.
218          * MDS only updates LSOM of the file if the size or block
219          * size is being increased or the file is being truncated.
220          */
221         if (!mdt_lmm_dom_only(info->mti_big_lmm) &&
222             !(tmp_ma->ma_valid & MA_INODE && tmp_ma->ma_attr.la_nlink == 0)) {
223                 __u64 size;
224                 __u64 blocks;
225                 bool changed = false;
226                 struct md_som *som = &tmp_ma->ma_som;
227
228                 if (truncate) {
229                         size = la->la_size;
230                         if (size == 0) {
231                                 blocks = 0;
232                         } else if (!(tmp_ma->ma_valid & MA_SOM) ||
233                                     size < som->ms_size) {
234                                 /* We cannot rely to blocks after
235                                  * truncate especially for spare file,
236                                  * and the truncate operation is usually
237                                  * followed with a close, so just set blocks
238                                  * to 1 here, and the following close will
239                                  * update it accordingly.
240                                  */
241                                 blocks = 1;
242                         } else {
243                                 blocks = som->ms_blocks;
244                         }
245                 } else {
246                         if (!(tmp_ma->ma_valid & MA_SOM)) {
247                                 /* Only set initial SOM Xattr data when both
248                                  * size and blocks are valid.
249                                  */
250                                 if (la->la_valid & (LA_SIZE | LA_LSIZE) &&
251                                     la->la_valid & (LA_BLOCKS | LA_LBLOCKS)) {
252                                         changed = true;
253                                         size = la->la_size;
254                                         blocks = la->la_blocks;
255                                 }
256                         } else {
257                                 /* Double check whether it is already set
258                                  * to SOM_FL_STRICT in mdt_mfd_close.
259                                  * If file is in SOM_FL_STALE state, and
260                                  * the close indicates there is no data
261                                  * modified, skip to transimit to LAZY
262                                  * state.
263                                  */
264                                 if (som->ms_valid & SOM_FL_STRICT ||
265                                     (som->ms_valid & SOM_FL_STALE &&
266                                      !(ma->ma_attr_flags & MDS_DATA_MODIFIED)))
267                                         GOTO(out_lock, rc);
268
269                                 size = som->ms_size;
270                                 blocks = som->ms_blocks;
271                                 if (la->la_valid & (LA_SIZE | LA_LSIZE) &&
272                                     la->la_size > som->ms_size) {
273                                         changed = true;
274                                         size = la->la_size;
275                                 }
276                                 if (la->la_valid & (LA_BLOCKS | LA_LBLOCKS) &&
277                                     la->la_blocks > som->ms_blocks) {
278                                         changed = true;
279                                         blocks = la->la_blocks;
280                                 }
281                         }
282                 }
283                 if (truncate || changed)
284                         rc = mdt_set_som(info, o, SOM_FL_LAZY, size, blocks);
285         }
286
287 out_lock:
288         mutex_unlock(&o->mot_som_mutex);
289         RETURN(rc);
290 }