int linkea_entry_pack(struct link_ea_entry *lee, const struct lu_name *lname,
const struct lu_fid *pfid);
int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname,
- const struct lu_fid *pfid);
-void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname);
+ const struct lu_fid *pfid, bool err_on_overflow);
+void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname,
+ bool is_encrypted);
int linkea_links_new(struct linkea_data *ldata, struct lu_buf *buf,
const struct lu_name *cname, const struct lu_fid *pfid);
int linkea_overflow_shrink(struct linkea_data *ldata);
ldata->ld_lee = NULL;
} else {
- linkea_del_buf(ldata, lname);
+ linkea_del_buf(ldata, lname, false);
}
}
GOTO(stop, rc);
}
- rc = linkea_add_buf(&ldata, cname, pfid);
+ rc = linkea_add_buf(&ldata, cname, pfid, false);
if (rc == 0)
rc = lfsck_links_write(env, obj, &ldata, handle);
if (rc != 0)
const struct lu_fid *pfid,
int first, int check)
{
+ /* cattr is set in mdd_link */
+ struct lu_attr *cattr = MDD_ENV_VAR(env, cattr);
int rc;
if (ldata->ld_leh == NULL) {
*tfid = *pfid;
tfid->f_ver = ~0;
- linkea_add_buf(ldata, lname, tfid);
+ linkea_add_buf(ldata, lname, tfid, false);
}
if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_MORE2))
- linkea_add_buf(ldata, lname, pfid);
+ linkea_add_buf(ldata, lname, pfid, false);
- return linkea_add_buf(ldata, lname, pfid);
+ /* For encrypted file, we want to limit number of hard links to what
+ * linkEA can contain. So ask to return error in case of overflow.
+ * Currently linkEA stores 4KiB of links, that is 14 NAME_MAX links,
+ * or 119 16-byte names.
+ */
+ return linkea_add_buf(ldata, lname, pfid,
+ cattr->la_valid & LA_FLAGS &&
+ cattr->la_flags & LUSTRE_ENCRYPT_FL);
}
static int __mdd_links_del(const struct lu_env *env,
const struct lu_name *lname,
const struct lu_fid *pfid)
{
+ /* cattr is set in mdd_link */
+ struct lu_attr *cattr = MDD_ENV_VAR(env, cattr);
int rc;
if (ldata->ld_leh == NULL) {
if (rc)
return rc;
- linkea_del_buf(ldata, lname);
+ linkea_del_buf(ldata, lname,
+ cattr->la_valid & LA_FLAGS &&
+ cattr->la_flags & LUSTRE_ENCRYPT_FL);
return 0;
}
* Add a record to the end of link ea buf
**/
int linkea_add_buf(struct linkea_data *ldata, const struct lu_name *lname,
- const struct lu_fid *pfid)
+ const struct lu_fid *pfid, bool err_on_overflow)
{
struct link_ea_header *leh = ldata->ld_leh;
int reclen;
CDEBUG(D_INODE, "No enough space to hold linkea entry '"
DFID": %.*s' at %u\n", PFID(pfid), lname->ln_namelen,
lname->ln_name, leh->leh_overflow_time);
- return 0;
+ return err_on_overflow ? -EOVERFLOW : 0;
}
if (leh->leh_len + reclen > ldata->ld_buf->lb_len) {
ldata->ld_reclen = linkea_entry_pack(ldata->ld_lee, lname, pfid);
leh->leh_len += ldata->ld_reclen;
leh->leh_reccount++;
- CDEBUG(D_INODE, "New link_ea name '"DFID":%.*s' is added\n",
- PFID(pfid), lname->ln_namelen, lname->ln_name);
+ if (err_on_overflow)
+ CDEBUG(D_INODE,
+ "New link_ea name '"DFID":<encrypted (%d)>' is added\n",
+ PFID(pfid), lname->ln_namelen);
+ else
+ CDEBUG(D_INODE, "New link_ea name '"DFID":%.*s' is added\n",
+ PFID(pfid), lname->ln_namelen, lname->ln_name);
return 0;
}
EXPORT_SYMBOL(linkea_add_buf);
/** Del the current record from the link ea buf */
-void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname)
+void linkea_del_buf(struct linkea_data *ldata, const struct lu_name *lname,
+ bool is_encrypted)
{
LASSERT(ldata->ld_leh != NULL && ldata->ld_lee != NULL);
LASSERT(ldata->ld_leh->leh_reccount > 0);
memmove(ldata->ld_lee, (char *)ldata->ld_lee + ldata->ld_reclen,
(char *)ldata->ld_leh + ldata->ld_leh->leh_len -
(char *)ldata->ld_lee);
- CDEBUG(D_INODE, "Old link_ea name '%.*s' is removed\n",
- lname->ln_namelen, lname->ln_name);
+ if (is_encrypted)
+ CDEBUG(D_INODE,
+ "Old link_ea name '<encrypted (%d)>' is removed\n",
+ lname->ln_namelen);
+ else
+ CDEBUG(D_INODE, "Old link_ea name '%.*s' is removed\n",
+ lname->ln_namelen, lname->ln_name);
if ((char *)ldata->ld_lee >= ((char *)ldata->ld_leh +
ldata->ld_leh->leh_len))
rc = linkea_data_new(ldata, buf);
if (!rc)
- rc = linkea_add_buf(ldata, cname, pfid);
+ rc = linkea_add_buf(ldata, cname, pfid, false);
return rc;
}
error "link from encrypted to unencrypted dir should succeed"
rm -f $tmpfile
+ # check we are limited in the number of hard links
+ # we can create for encrypted files, to what can fit into LinkEA
+ for i in $(seq 1 160); do
+ ln $testfile2 ${testfile}_$i || break
+ done
+ [ $i -lt 160 ] || error "hard link $i should fail"
+
mrename $testfile2 $tmpfile &&
error "rename from encrypted to unencrypted dir should fail"
touch $tmpfile