+int linkea_links_new(struct linkea_data *ldata, struct lu_buf *buf,
+ const struct lu_name *cname, const struct lu_fid *pfid)
+{
+ int rc;
+
+ rc = linkea_data_new(ldata, buf);
+ if (!rc)
+ rc = linkea_add_buf(ldata, cname, pfid);
+
+ return rc;
+}
+EXPORT_SYMBOL(linkea_links_new);
+
+/**
+ * Mark the linkEA as overflow with current timestamp,
+ * and remove the last linkEA entry.
+ *
+ * Return the new linkEA size.
+ */
+int linkea_overflow_shrink(struct linkea_data *ldata)
+{
+ struct link_ea_header *leh;
+ struct lu_name tname;
+ struct lu_fid tfid;
+ int count;
+
+ leh = ldata->ld_leh = ldata->ld_buf->lb_buf;
+ if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) {
+ leh->leh_magic = LINK_EA_MAGIC;
+ leh->leh_reccount = __swab32(leh->leh_reccount);
+ leh->leh_overflow_time = __swab32(leh->leh_overflow_time);
+ leh->leh_padding = __swab32(leh->leh_padding);
+ }
+
+ LASSERT(leh->leh_reccount > 0);
+
+ leh->leh_len = sizeof(struct link_ea_header);
+ leh->leh_reccount--;
+ if (unlikely(leh->leh_reccount == 0))
+ return 0;
+
+ leh->leh_overflow_time = cfs_time_current_sec();
+ if (unlikely(leh->leh_overflow_time == 0))
+ leh->leh_overflow_time++;
+ ldata->ld_reclen = 0;
+ ldata->ld_lee = (struct link_ea_entry *)(leh + 1);
+ for (count = 0; count < leh->leh_reccount; count++) {
+ linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen,
+ &tname, &tfid);
+ leh->leh_len += ldata->ld_reclen;
+ ldata->ld_lee = (struct link_ea_entry *)((char *)ldata->ld_lee +
+ ldata->ld_reclen);
+ }
+
+ linkea_entry_unpack(ldata->ld_lee, &ldata->ld_reclen, &tname, &tfid);
+ CDEBUG(D_INODE, "No enough space to hold the last linkea entry '"
+ DFID": %.*s', shrink it, left %d linkea entries, size %llu\n",
+ PFID(&tfid), tname.ln_namelen, tname.ln_name,
+ leh->leh_reccount, leh->leh_len);
+
+ return leh->leh_len;
+}
+EXPORT_SYMBOL(linkea_overflow_shrink);
+