@@ -31,17 +31,13 @@
static int ll_get_context(struct inode *inode, void *ctx, size_t len)
{
- struct dentry *dentry;
+ struct dentry *dentry = d_find_any_alias(inode);
int rc;
- if (hlist_empty(&inode->i_dentry))
- return -ENODATA;
-
- hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias)
- break;
-
rc = __vfs_getxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
ctx, len);
+ if (dentry)
+ dput(dentry);
/* used as encryption unit size */
if (S_ISREG(inode->i_mode))
@@ -429,8 +429,10 @@ int ll_file_release(struct inode *inode, struct file *file)
static inline int ll_dom_readpage(void *data, struct page *page)
{
+ struct inode *inode = page2inode(page);
struct niobuf_local *lnb = data;
void *kaddr;
+ int rc = 0;
kaddr = kmap_atomic(page);
memcpy(kaddr, lnb->lnb_data, lnb->lnb_len);
@@ -440,9 +442,22 @@ static inline int ll_dom_readpage(void *data, struct page *page)
flush_dcache_page(page);
SetPageUptodate(page);
kunmap_atomic(kaddr);
+
+ if (inode && IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) {
+ if (!llcrypt_has_encryption_key(inode))
+ CDEBUG(D_SEC, "no enc key for " DFID "\n",
+ PFID(ll_inode2fid(inode)));
+ /* decrypt only if page is not empty */
+ else if (memcmp(page_address(page),
+ page_address(ZERO_PAGE(0)),
+ PAGE_SIZE) != 0)
+ rc = llcrypt_decrypt_pagecache_blocks(page,
+ PAGE_SIZE,
+ 0);
+ }
unlock_page(page);
- return 0;
+ return rc;
}
void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req,
@@ -481,7 +496,8 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req,
* buffer, in both cases total size should be equal to the file size.
*/
body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
- if (rnb->rnb_offset + rnb->rnb_len != body->mbo_dom_size) {
+ if (rnb->rnb_offset + rnb->rnb_len != body->mbo_dom_size &&
+ !(inode && IS_ENCRYPTED(inode))) {
CERROR("%s: server returns off/len %llu/%u but size %llu\n",
ll_i2sbi(inode)->ll_fsname, rnb->rnb_offset,
rnb->rnb_len, body->mbo_dom_size);
@@ -629,6 +629,36 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
if (rc)
return rc;
+ /* If encryption context was returned by MDT, put it in
+ * inode now to save an extra getxattr and avoid deadlock.
+ */
+ if (body->mbo_valid & OBD_MD_ENCCTX) {
+ encctx = req_capsule_server_get(pill, &RMF_FILE_ENCCTX);
+ encctxlen = req_capsule_get_size(pill,
+ &RMF_FILE_ENCCTX,
+ RCL_SERVER);
+
+ if (encctxlen) {
+ CDEBUG(D_SEC,
+ "server returned encryption ctx for " DFID "\n",
+ PFID(ll_inode2fid(inode)));
+ rc = ll_xattr_cache_insert(inode,
+ LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+ encctx, encctxlen);
+ if (rc) {
+ CWARN("%s: cannot set enc ctx for " DFID ": rc = %d\n",
+ ll_i2sbi(inode)->ll_fsname,
+ PFID(ll_inode2fid(inode)), rc);
+ } else if (encrypt) {
+ rc = llcrypt_get_encryption_info(inode);
+ if (rc)
+ CDEBUG(D_SEC,
+ "cannot get enc info for " DFID ": rc = %d\n",
+ PFID(ll_inode2fid(inode)), rc);
+ }
+ }
+ }
+
if (it->it_op & IT_OPEN)
ll_dom_finish_open(inode, request, it);
@@ -674,28 +704,6 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
rc);
}
- /* If encryption context was returned by MDT, put it in
- * inode now to save an extra getxattr and avoid deadlock.
- */
- if (body->mbo_valid & OBD_MD_ENCCTX) {
- encctx = req_capsule_server_get(pill, &RMF_FILE_ENCCTX);
- encctxlen = req_capsule_get_size(pill,
- &RMF_FILE_ENCCTX,
- RCL_SERVER);
-
- if (encctxlen) {
- CDEBUG(D_SEC,
- "server returned encryption ctx for " DFID "\n",
- PFID(ll_inode2fid(inode)));
- rc = ll_xattr_cache_insert(inode,
- LL_XATTR_NAME_ENCRYPTION_CONTEXT,
- encctx, encctxlen);
- if (rc)
- CWARN("%s: cannot set enc ctx for " DFID ": rc = %d\n",
- ll_i2sbi(inode)->ll_fsname,
- PFID(ll_inode2fid(inode)), rc);
- }
- }
}
alias = ll_splice_alias(inode, *de);