Whamcloud - gitweb
LU-8851 nodemap: add uid/gid only flags to control mapping
[fs/lustre-release.git] / lustre / obdclass / linkea.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, 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, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 021110-1307, USA
20  *
21  * GPL HEADER END
22  */
23 /*
24  * Copyright (c) 2013, 2016, Intel Corporation.
25  * Use is subject to license terms.
26  *
27  * Author: Di Wang <di.wang@intel.com>
28  */
29
30 #include <lustre/lustre_idl.h>
31 #include <obd.h>
32 #include <lustre_linkea.h>
33
34 int linkea_data_new(struct linkea_data *ldata, struct lu_buf *buf)
35 {
36         ldata->ld_buf = lu_buf_check_and_alloc(buf, PAGE_SIZE);
37         if (ldata->ld_buf->lb_buf == NULL)
38                 return -ENOMEM;
39         ldata->ld_leh = ldata->ld_buf->lb_buf;
40         ldata->ld_leh->leh_magic = LINK_EA_MAGIC;
41         ldata->ld_leh->leh_reccount = 0;
42         ldata->ld_leh->leh_len = sizeof(struct link_ea_header);
43         ldata->ld_leh->leh_overflow_time = 0;
44         ldata->ld_leh->leh_padding = 0;
45         return 0;
46 }
47 EXPORT_SYMBOL(linkea_data_new);
48
49 int linkea_init(struct linkea_data *ldata)
50 {
51         struct link_ea_header *leh;
52
53         LASSERT(ldata->ld_buf != NULL);
54         leh = ldata->ld_buf->lb_buf;
55         if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) {
56                 leh->leh_magic = LINK_EA_MAGIC;
57                 leh->leh_reccount = __swab32(leh->leh_reccount);
58                 leh->leh_len = __swab64(leh->leh_len);
59                 leh->leh_overflow_time = __swab32(leh->leh_overflow_time);
60                 leh->leh_padding = __swab32(leh->leh_padding);
61                 /* individual entries are swabbed by linkea_entry_unpack() */
62         }
63
64         if (leh->leh_magic != LINK_EA_MAGIC)
65                 return -EINVAL;
66
67         if (leh->leh_reccount == 0 && leh->leh_overflow_time == 0)
68                 return -ENODATA;
69
70         ldata->ld_leh = leh;
71         return 0;
72 }
73 EXPORT_SYMBOL(linkea_init);
74
75 int linkea_init_with_rec(struct linkea_data *ldata)
76 {
77         int rc;
78
79         rc = linkea_init(ldata);
80         if (!rc && ldata->ld_leh->leh_reccount == 0)
81                 rc = -ENODATA;
82
83         return rc;
84 }
85 EXPORT_SYMBOL(linkea_init_with_rec);
86
87 /**
88  * Pack a link_ea_entry.
89  * All elements are stored as chars to avoid alignment issues.
90  * Numbers are always big-endian
91  * \retval record length
92  */
93 int linkea_entry_pack(struct link_ea_entry *lee, const struct lu_name *lname,
94                       const struct lu_fid *pfid)
95 {
96         struct lu_fid   tmpfid;
97         int             reclen;
98
99         tmpfid = *pfid;
100         if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_MUL_REF))
101                 tmpfid.f_oid--;
102         if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_CRASH))
103                 tmpfid.f_ver = ~0;
104         fid_cpu_to_be(&tmpfid, &tmpfid);
105         memcpy(&lee->lee_parent_fid, &tmpfid, sizeof(tmpfid));
106         memcpy(lee->lee_name, lname->ln_name, lname->ln_namelen);
107         reclen = sizeof(struct link_ea_entry) + lname->ln_namelen;
108
109         lee->lee_reclen[0] = (reclen >> 8) & 0xff;
110         lee->lee_reclen[1] = reclen & 0xff;
111         return reclen;
112 }
113 EXPORT_SYMBOL(linkea_entry_pack);
114
115 void linkea_entry_unpack(const struct link_ea_entry *lee, int *reclen,
116                          struct lu_name *lname, struct lu_fid *pfid)
117 {
118         LASSERT(lee != NULL);
119
120         *reclen = (lee->lee_reclen[0] << 8) | lee->lee_reclen[1];
121         memcpy(pfid, &lee->lee_parent_fid, sizeof(*pfid));
122         fid_be_to_cpu(pfid, pfid);
123         if (lname != NULL) {
124                 lname->ln_name = lee->lee_name;
125                 lname->ln_namelen = *reclen - sizeof(struct link_ea_entry);
126         }
127 }
128 EXPORT_SYMBOL(linkea_entry_unpack);
129
130 /**
131  * Add a record to the end of link ea buf
132  **/
133 int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname,
134                    const struct lu_fid *pfid)
135 {
136         struct link_ea_header *leh = ldata->ld_leh;
137         int reclen;
138
139         LASSERT(leh != NULL);
140
141         if (lname == NULL || pfid == NULL)
142                 return -EINVAL;
143
144         reclen = lname->ln_namelen + sizeof(struct link_ea_entry);
145         if (unlikely(leh->leh_len + reclen > MAX_LINKEA_SIZE)) {
146                 /* Use 32-bits to save the overflow time, although it will
147                  * shrink the cfs_time_current_sec() returned 64-bits value
148                  * to 32-bits value, it is still quite large and can be used
149                  * for about 140 years. That is enough. */
150                 leh->leh_overflow_time = cfs_time_current_sec();
151                 if (unlikely(leh->leh_overflow_time == 0))
152                         leh->leh_overflow_time++;
153
154                 CDEBUG(D_INODE, "No enough space to hold linkea entry '"
155                        DFID": %.*s' at %u\n", PFID(pfid), lname->ln_namelen,
156                        lname->ln_name, leh->leh_overflow_time);
157                 return 0;
158         }
159
160         if (leh->leh_len + reclen > ldata->ld_buf->lb_len) {
161                 if (lu_buf_check_and_grow(ldata->ld_buf,
162                                           leh->leh_len + reclen) < 0)
163                         return -ENOMEM;
164
165                 leh = ldata->ld_leh = ldata->ld_buf->lb_buf;
166         }
167
168         ldata->ld_lee = ldata->ld_buf->lb_buf + leh->leh_len;
169         ldata->ld_reclen = linkea_entry_pack(ldata->ld_lee, lname, pfid);
170         leh->leh_len += ldata->ld_reclen;
171         leh->leh_reccount++;
172         CDEBUG(D_INODE, "New link_ea name '"DFID":%.*s' is added\n",
173                PFID(pfid), lname->ln_namelen, lname->ln_name);
174         return 0;
175 }
176 EXPORT_SYMBOL(linkea_add_buf);
177
178 /** Del the current record from the link ea buf */
179 void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname)
180 {
181         LASSERT(ldata->ld_leh != NULL && ldata->ld_lee != NULL);
182         LASSERT(ldata->ld_leh->leh_reccount > 0);
183
184         ldata->ld_leh->leh_reccount--;
185         ldata->ld_leh->leh_len -= ldata->ld_reclen;
186         memmove(ldata->ld_lee, (char *)ldata->ld_lee + ldata->ld_reclen,
187                 (char *)ldata->ld_leh + ldata->ld_leh->leh_len -
188                 (char *)ldata->ld_lee);
189         CDEBUG(D_INODE, "Old link_ea name '%.*s' is removed\n",
190                lname->ln_namelen, lname->ln_name);
191
192         if ((char *)ldata->ld_lee >= ((char *)ldata->ld_leh +
193                                       ldata->ld_leh->leh_len))
194                 ldata->ld_lee = NULL;
195 }
196 EXPORT_SYMBOL(linkea_del_buf);
197
198 int linkea_links_new(struct linkea_data *ldata, struct lu_buf *buf,
199                      const struct lu_name *cname, const struct lu_fid *pfid)
200 {
201         int rc;
202
203         rc = linkea_data_new(ldata, buf);
204         if (!rc)
205                 rc = linkea_add_buf(ldata, cname, pfid);
206
207         return rc;
208 }
209 EXPORT_SYMBOL(linkea_links_new);
210
211 /**
212  * Mark the linkEA as overflow with current timestamp,
213  * and remove the last linkEA entry.
214  *
215  * Return the new linkEA size.
216  */
217 int linkea_overflow_shrink(struct linkea_data *ldata)
218 {
219         struct link_ea_header *leh;
220         struct lu_name tname;
221         struct lu_fid tfid;
222         int count;
223
224         leh = ldata->ld_leh = ldata->ld_buf->lb_buf;
225         if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) {
226                 leh->leh_magic = LINK_EA_MAGIC;
227                 leh->leh_reccount = __swab32(leh->leh_reccount);
228                 leh->leh_overflow_time = __swab32(leh->leh_overflow_time);
229                 leh->leh_padding = __swab32(leh->leh_padding);
230         }
231
232         LASSERT(leh->leh_reccount > 0);
233
234         leh->leh_len = sizeof(struct link_ea_header);
235         leh->leh_reccount--;
236         if (unlikely(leh->leh_reccount == 0))
237                 return 0;
238
239         leh->leh_overflow_time = cfs_time_current_sec();
240         if (unlikely(leh->leh_overflow_time == 0))
241                 leh->leh_overflow_time++;
242         ldata->ld_reclen = 0;
243         ldata->ld_lee = (struct link_ea_entry *)(leh + 1);
244         for (count = 0; count < leh->leh_reccount; count++) {
245                 linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen,
246                                     &tname, &tfid);
247                 leh->leh_len += ldata->ld_reclen;
248                 ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee +
249                                                          ldata->ld_reclen);
250         }
251
252         linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, &tname, &tfid);
253         CDEBUG(D_INODE, "No enough space to hold the last linkea entry '"
254                DFID": %.*s', shrink it, left %d linkea entries, size %llu\n",
255                PFID(&tfid), tname.ln_namelen, tname.ln_name,
256                leh->leh_reccount, leh->leh_len);
257
258         return leh->leh_len;
259 }
260 EXPORT_SYMBOL(linkea_overflow_shrink);
261
262 /**
263  * Check if such a link exists in linkEA.
264  *
265  * \param ldata link data the search to be done on
266  * \param lname name in the parent's directory entry pointing to this object
267  * \param pfid parent fid the link to be found for
268  *
269  * \retval   0 success
270  * \retval -ENOENT link does not exist
271  * \retval -ve on error
272  */
273 int linkea_links_find(struct linkea_data *ldata, const struct lu_name *lname,
274                       const struct lu_fid  *pfid)
275 {
276         struct lu_name tmpname;
277         struct lu_fid  tmpfid;
278         int count;
279
280         LASSERT(ldata->ld_leh != NULL);
281
282         /* link #0, if leh_reccount == 0 we skip the loop and return -ENOENT */
283         if (likely(ldata->ld_leh->leh_reccount > 0))
284                 ldata->ld_lee = (struct link_ea_entry *)(ldata->ld_leh + 1);
285
286         for (count = 0; count < ldata->ld_leh->leh_reccount; count++) {
287                 linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen,
288                                     &tmpname, &tmpfid);
289                 if (tmpname.ln_namelen == lname->ln_namelen &&
290                     lu_fid_eq(&tmpfid, pfid) &&
291                     (strncmp(tmpname.ln_name, lname->ln_name,
292                              tmpname.ln_namelen) == 0))
293                         break;
294                 ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee +
295                                                          ldata->ld_reclen);
296         }
297
298         if (count == ldata->ld_leh->leh_reccount) {
299                 CDEBUG(D_INODE, "Old link_ea name '%.*s' not found\n",
300                        lname->ln_namelen, lname->ln_name);
301                 ldata->ld_lee = NULL;
302                 ldata->ld_reclen = 0;
303                 return -ENOENT;
304         }
305         return 0;
306 }
307 EXPORT_SYMBOL(linkea_links_find);