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, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 021110-1307, USA
24 * Copyright (c) 2013, 2014, Intel Corporation.
25 * Use is subject to license terms.
27 * Author: Di Wang <di.wang@intel.com>
30 #include <lustre/lustre_idl.h>
32 #include <lustre_linkea.h>
34 int linkea_data_new(struct linkea_data *ldata, struct lu_buf *buf)
36 ldata->ld_buf = lu_buf_check_and_alloc(buf, PAGE_CACHE_SIZE);
37 if (ldata->ld_buf->lb_buf == NULL)
39 ldata->ld_leh = ldata->ld_buf->lb_buf;
40 ldata->ld_leh->leh_magic = LINK_EA_MAGIC;
41 ldata->ld_leh->leh_len = sizeof(struct link_ea_header);
42 ldata->ld_leh->leh_reccount = 0;
45 EXPORT_SYMBOL(linkea_data_new);
47 int linkea_init(struct linkea_data *ldata)
49 struct link_ea_header *leh;
51 LASSERT(ldata->ld_buf != NULL);
52 leh = ldata->ld_buf->lb_buf;
53 if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) {
54 leh->leh_magic = LINK_EA_MAGIC;
55 leh->leh_reccount = __swab32(leh->leh_reccount);
56 leh->leh_len = __swab64(leh->leh_len);
57 /* entries are swabbed by linkea_entry_unpack */
59 if (leh->leh_magic != LINK_EA_MAGIC)
61 if (leh->leh_reccount == 0)
67 EXPORT_SYMBOL(linkea_init);
70 * Pack a link_ea_entry.
71 * All elements are stored as chars to avoid alignment issues.
72 * Numbers are always big-endian
73 * \retval record length
75 int linkea_entry_pack(struct link_ea_entry *lee, const struct lu_name *lname,
76 const struct lu_fid *pfid)
82 if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_MUL_REF))
84 if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_CRASH))
86 fid_cpu_to_be(&tmpfid, &tmpfid);
87 memcpy(&lee->lee_parent_fid, &tmpfid, sizeof(tmpfid));
88 memcpy(lee->lee_name, lname->ln_name, lname->ln_namelen);
89 reclen = sizeof(struct link_ea_entry) + lname->ln_namelen;
91 lee->lee_reclen[0] = (reclen >> 8) & 0xff;
92 lee->lee_reclen[1] = reclen & 0xff;
95 EXPORT_SYMBOL(linkea_entry_pack);
97 void linkea_entry_unpack(const struct link_ea_entry *lee, int *reclen,
98 struct lu_name *lname, struct lu_fid *pfid)
100 *reclen = (lee->lee_reclen[0] << 8) | lee->lee_reclen[1];
101 memcpy(pfid, &lee->lee_parent_fid, sizeof(*pfid));
102 fid_be_to_cpu(pfid, pfid);
104 lname->ln_name = lee->lee_name;
105 lname->ln_namelen = *reclen - sizeof(struct link_ea_entry);
108 EXPORT_SYMBOL(linkea_entry_unpack);
111 * Add a record to the end of link ea buf
113 int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname,
114 const struct lu_fid *pfid)
116 LASSERT(ldata->ld_leh != NULL);
118 if (lname == NULL || pfid == NULL)
121 ldata->ld_reclen = lname->ln_namelen + sizeof(struct link_ea_entry);
122 if (ldata->ld_leh->leh_len + ldata->ld_reclen >
123 ldata->ld_buf->lb_len) {
124 if (lu_buf_check_and_grow(ldata->ld_buf,
125 ldata->ld_leh->leh_len +
126 ldata->ld_reclen) < 0)
130 ldata->ld_leh = ldata->ld_buf->lb_buf;
131 ldata->ld_lee = ldata->ld_buf->lb_buf + ldata->ld_leh->leh_len;
132 ldata->ld_reclen = linkea_entry_pack(ldata->ld_lee, lname, pfid);
133 ldata->ld_leh->leh_len += ldata->ld_reclen;
134 ldata->ld_leh->leh_reccount++;
135 CDEBUG(D_INODE, "New link_ea name '"DFID":%.*s' is added\n",
136 PFID(pfid), lname->ln_namelen, lname->ln_name);
139 EXPORT_SYMBOL(linkea_add_buf);
141 /** Del the current record from the link ea buf */
142 void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname)
144 LASSERT(ldata->ld_leh != NULL && ldata->ld_lee != NULL);
146 ldata->ld_leh->leh_reccount--;
147 ldata->ld_leh->leh_len -= ldata->ld_reclen;
148 memmove(ldata->ld_lee, (char *)ldata->ld_lee + ldata->ld_reclen,
149 (char *)ldata->ld_leh + ldata->ld_leh->leh_len -
150 (char *)ldata->ld_lee);
151 CDEBUG(D_INODE, "Old link_ea name '%.*s' is removed\n",
152 lname->ln_namelen, lname->ln_name);
154 if ((char *)ldata->ld_lee >= ((char *)ldata->ld_leh +
155 ldata->ld_leh->leh_len))
156 ldata->ld_lee = NULL;
158 EXPORT_SYMBOL(linkea_del_buf);
161 * Check if such a link exists in linkEA.
163 * \param ldata link data the search to be done on
164 * \param lname name in the parent's directory entry pointing to this object
165 * \param pfid parent fid the link to be found for
168 * \retval -ENOENT link does not exist
169 * \retval -ve on error
171 int linkea_links_find(struct linkea_data *ldata, const struct lu_name *lname,
172 const struct lu_fid *pfid)
174 struct lu_name tmpname;
175 struct lu_fid tmpfid;
178 LASSERT(ldata->ld_leh != NULL);
181 ldata->ld_lee = (struct link_ea_entry *)(ldata->ld_leh + 1);
183 for (count = 0; count < ldata->ld_leh->leh_reccount; count++) {
184 linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen,
186 if (tmpname.ln_namelen == lname->ln_namelen &&
187 lu_fid_eq(&tmpfid, pfid) &&
188 (strncmp(tmpname.ln_name, lname->ln_name,
189 tmpname.ln_namelen) == 0))
191 ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee +
195 if (count == ldata->ld_leh->leh_reccount) {
196 CDEBUG(D_INODE, "Old link_ea name '%.*s' not found\n",
197 lname->ln_namelen, lname->ln_name);
198 ldata->ld_lee = NULL;
199 ldata->ld_reclen = 0;
204 EXPORT_SYMBOL(linkea_links_find);