@@ -233,8 +233,13 @@ int ll_setup_filename(struct inode *dir, const struct qstr *iname,
}
rc = fscrypt_setup_filename(dir, &dname, lookup, fname);
if (rc == -ENOENT && lookup &&
- !fscrypt_has_encryption_key(dir) &&
- unlikely(filename_is_volatile(iname->name, iname->len, NULL))) {
+ ((is_root_inode(dir) && iname->len == strlen(dot_fscrypt_name) &&
+ strncmp(iname->name, dot_fscrypt_name, iname->len) == 0) ||
+ (!fscrypt_has_encryption_key(dir) &&
+ unlikely(filename_is_volatile(iname->name, iname->len, NULL))))) {
+ /* In case of subdir mount of an encrypted directory, we allow
+ * lookup of /.fscrypt directory.
+ */
/* For purpose of migration or mirroring without enc key, we
* allow lookup of volatile file without enc context.
*/
@@ -3157,7 +3157,16 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
return ERR_PTR(-ENOMEM);
ll_i2gids(op_data->op_suppgids, i1, i2);
- op_data->op_fid1 = *ll_inode2fid(i1);
+ /* If the client is using a subdir mount and looks at what it sees as
+ * /.fscrypt, interpret it as the .fscrypt dir at the root of the fs.
+ */
+ if (unlikely(i1->i_sb && i1->i_sb->s_root && is_root_inode(i1) &&
+ !fid_is_root(ll_inode2fid(i1)) &&
+ name && namelen == strlen(dot_fscrypt_name) &&
+ strncmp(name, dot_fscrypt_name, namelen) == 0))
+ lu_root_fid(&op_data->op_fid1);
+ else
+ op_data->op_fid1 = *ll_inode2fid(i1);
if (S_ISDIR(i1->i_mode)) {
down_read_non_owner(&ll_i2info(i1)->lli_lsm_sem);
@@ -2068,6 +2068,15 @@ static int ll_rename(struct inode *src, struct dentry *src_dchild,
if (IS_ERR(op_data))
return PTR_ERR(op_data);
+ /* If the client is using a subdir mount and does a rename to what it
+ * sees as /.fscrypt, interpret it as the .fscrypt dir at fs root.
+ */
+ if (unlikely(is_root_inode(tgt) && !fid_is_root(ll_inode2fid(tgt)) &&
+ tgt_dchild->d_name.len == strlen(dot_fscrypt_name) &&
+ strncmp(tgt_dchild->d_name.name, dot_fscrypt_name,
+ tgt_dchild->d_name.len) == 0))
+ lu_root_fid(&op_data->op_fid2);
+
if (src_dchild->d_inode)
op_data->op_fid3 = *ll_inode2fid(src_dchild->d_inode);
if (tgt_dchild->d_inode)
@@ -1856,6 +1856,7 @@ enum ioc_data_version_flags {
#endif
#define dot_lustre_name ".lustre"
+#define dot_fscrypt_name ".fscrypt"
/********* HSM **********/