Some operations on encrypted files require to identify all names for
files having the same FID. For instance, for lookup, getattr or unlink
on encrypted files without the encryption key, we need to perform an
operation by FID instead of the actual name.
In order to make operations by FID unambiguous on server side, we
decide to limit the number of possible hard links for encrypted files,
to what the linkEA can contain.
Currently linkEA stores 4KiB of links, that is 14 NAME_MAX links, or
119 16-byte names.
Lustre-change: https://review.whamcloud.com/43387
Lustre-commit:
2ffb8f5726d27e7c2324a3e833491231fdaa3306
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I20a01874899f95b2ff61e05b2aa6851d135633e8
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Lai Siyao <lai.siyao@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/45728
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
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