Whamcloud - gitweb
LU-13397 lfs: mirror extend/copy keeps sparseness
[fs/lustre-release.git] / lustre / llite / file.c
index b140514..5791569 100644 (file)
 #include <linux/sched.h>
 #include <linux/user_namespace.h>
 #include <linux/uidgid.h>
+#include <linux/falloc.h>
 
 #include <uapi/linux/lustre/lustre_ioctl.h>
+#include <uapi/linux/llcrypt.h>
 #include <lustre_swab.h>
 
 #include "cl_object.h"
@@ -110,12 +112,12 @@ static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data,
        op_data->op_xvalid |= OP_XVALID_CTIME_SET;
        op_data->op_attr_blocks = inode->i_blocks;
        op_data->op_attr_flags = ll_inode_to_ext_flags(inode->i_flags);
-       if (ll_file_test_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT))
+       if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags))
                op_data->op_attr_flags |= LUSTRE_PROJINHERIT_FL;
        op_data->op_open_handle = och->och_open_handle;
 
        if (och->och_flags & FMODE_WRITE &&
-           ll_file_test_and_clear_flag(ll_i2info(inode), LLIF_DATA_MODIFIED))
+           test_and_clear_bit(LLIF_DATA_MODIFIED, &ll_i2info(inode)->lli_flags))
                /* For HSM: if inode data has been modified, pack it so that
                 * MDT can set data dirty flag in the archive. */
                op_data->op_bias |= MDS_DATA_MODIFIED;
@@ -391,7 +393,7 @@ int ll_file_release(struct inode *inode, struct file *file)
        if (S_ISDIR(inode->i_mode) && lli->lli_opendir_key == fd)
                ll_deauthorize_statahead(inode, fd);
 
-       if (inode->i_sb->s_root == file_dentry(file)) {
+       if (is_root_inode(inode)) {
                file->private_data = NULL;
                ll_file_data_put(fd);
                GOTO(out, rc = 0);
@@ -411,7 +413,7 @@ int ll_file_release(struct inode *inode, struct file *file)
                libcfs_debug_dumplog();
 
 out:
-       if (!rc && inode->i_sb->s_root != file_dentry(file))
+       if (!rc && !is_root_inode(inode))
                ll_stats_ops_tally(sbi, LPROC_LL_RELEASE,
                                   ktime_us_delta(ktime_get(), kstart));
        RETURN(rc);
@@ -421,6 +423,9 @@ static inline int ll_dom_readpage(void *data, struct page *page)
 {
        struct niobuf_local *lnb = data;
        void *kaddr;
+       int rc = 0;
+
+       struct inode *inode = page2inode(page);
 
        kaddr = kmap_atomic(page);
        memcpy(kaddr, lnb->lnb_data, lnb->lnb_len);
@@ -430,14 +435,40 @@ 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)));
+               else {
+                       unsigned int offs = 0;
+
+                       while (offs < PAGE_SIZE) {
+                               /* decrypt only if page is not empty */
+                               if (memcmp(page_address(page) + offs,
+                                          page_address(ZERO_PAGE(0)),
+                                          LUSTRE_ENCRYPTION_UNIT_SIZE) == 0)
+                                       break;
+
+                               rc = llcrypt_decrypt_pagecache_blocks(page,
+                                                   LUSTRE_ENCRYPTION_UNIT_SIZE,
+                                                                     offs);
+                               if (rc)
+                                       break;
+
+                               offs += LUSTRE_ENCRYPTION_UNIT_SIZE;
+                       }
+               }
+       }
        unlock_page(page);
 
-       return 0;
+       return rc;
 }
 
-void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req,
-                       struct lookup_intent *it)
+void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req)
 {
+       struct lu_env *env;
+       struct cl_io *io;
        struct ll_inode_info *lli = ll_i2info(inode);
        struct cl_object *obj = lli->lli_clob;
        struct address_space *mapping = inode->i_mapping;
@@ -447,6 +478,8 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req,
        char *data;
        unsigned long index, start;
        struct niobuf_local lnb;
+       __u16 refcheck;
+       int rc;
 
        ENTRY;
 
@@ -473,13 +506,24 @@ 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);
                RETURN_EXIT;
        }
 
+       env = cl_env_get(&refcheck);
+       if (IS_ERR(env))
+               RETURN_EXIT;
+       io = vvp_env_thread_io(env);
+       io->ci_obj = obj;
+       io->ci_ignore_layout = 1;
+       rc = cl_io_init(env, io, CIT_MISC, obj);
+       if (rc)
+               GOTO(out_io, rc);
+
        CDEBUG(D_INFO, "Get data along with open at %llu len %i, size %llu\n",
               rnb->rnb_offset, rnb->rnb_len, body->mbo_dom_size);
 
@@ -491,6 +535,8 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req,
        LASSERT((lnb.lnb_file_offset & ~PAGE_MASK) == 0);
        lnb.lnb_page_offset = 0;
        do {
+               struct cl_page *page;
+
                lnb.lnb_data = data + (index << PAGE_SHIFT);
                lnb.lnb_len = rnb->rnb_len - (index << PAGE_SHIFT);
                if (lnb.lnb_len > PAGE_SIZE)
@@ -506,9 +552,33 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req,
                              PTR_ERR(vmpage));
                        break;
                }
+               lock_page(vmpage);
+               if (vmpage->mapping == NULL) {
+                       unlock_page(vmpage);
+                       put_page(vmpage);
+                       /* page was truncated */
+                       break;
+               }
+               /* attach VM page to CL page cache */
+               page = cl_page_find(env, obj, vmpage->index, vmpage,
+                                   CPT_CACHEABLE);
+               if (IS_ERR(page)) {
+                       ClearPageUptodate(vmpage);
+                       unlock_page(vmpage);
+                       put_page(vmpage);
+                       break;
+               }
+               cl_page_export(env, page, 1);
+               cl_page_put(env, page);
+               unlock_page(vmpage);
                put_page(vmpage);
                index++;
        } while (rnb->rnb_len > (index << PAGE_SHIFT));
+
+out_io:
+       cl_io_fini(env, io);
+       cl_env_put(env, &refcheck);
+
        EXIT;
 }
 
@@ -590,27 +660,21 @@ retry:
        rc = ll_prep_inode(&de->d_inode, req, NULL, itp);
 
        if (!rc && itp->it_lock_mode) {
-               struct lustre_handle handle = {.cookie = itp->it_lock_handle};
-               struct ldlm_lock *lock;
-               bool has_dom_bit = false;
+               __u64 bits = 0;
 
                /* If we got a lock back and it has a LOOKUP bit set,
                 * make sure the dentry is marked as valid so we can find it.
                 * We don't need to care about actual hashing since other bits
                 * of kernel will deal with that later.
                 */
-               lock = ldlm_handle2lock(&handle);
-               if (lock) {
-                       has_dom_bit = ldlm_has_dom(lock);
-                       if (lock->l_policy_data.l_inodebits.bits &
-                           MDS_INODELOCK_LOOKUP)
-                               d_lustre_revalidate(de);
-
-                       LDLM_LOCK_PUT(lock);
-               }
-               ll_set_lock_data(sbi->ll_md_exp, de->d_inode, itp, NULL);
-               if (has_dom_bit)
-                       ll_dom_finish_open(de->d_inode, req, itp);
+               ll_set_lock_data(sbi->ll_md_exp, de->d_inode, itp, &bits);
+               if (bits & MDS_INODELOCK_LOOKUP)
+                       d_lustre_revalidate(de);
+               /* if DoM bit returned along with LAYOUT bit then there
+                * can be read-on-open data returned.
+                */
+               if (bits & MDS_INODELOCK_DOM && bits & MDS_INODELOCK_LAYOUT)
+                       ll_dom_finish_open(de->d_inode, req);
        }
 
 out:
@@ -666,6 +730,8 @@ static int ll_local_open(struct file *file, struct lookup_intent *it,
        file->private_data = fd;
        ll_readahead_init(inode, &fd->fd_ras);
        fd->fd_omode = it->it_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
+       /* turn off the kernel's read-ahead */
+       file->f_ra.ra_pages = 0;
 
        /* ll_cl_context initialize */
        rwlock_init(&fd->fd_lock);
@@ -705,6 +771,12 @@ int ll_file_open(struct inode *inode, struct file *file)
        it = file->private_data; /* XXX: compat macro */
        file->private_data = NULL; /* prevent ll_local_open assertion */
 
+       if (S_ISREG(inode->i_mode)) {
+               rc = llcrypt_file_open(inode, file);
+               if (rc)
+                       GOTO(out_nofiledata, rc);
+       }
+
        fd = ll_file_data_get();
        if (fd == NULL)
                GOTO(out_nofiledata, rc = -ENOMEM);
@@ -713,7 +785,7 @@ int ll_file_open(struct inode *inode, struct file *file)
        if (S_ISDIR(inode->i_mode))
                ll_authorize_statahead(inode, fd);
 
-       if (inode->i_sb->s_root == file_dentry(file)) {
+       if (is_root_inode(inode)) {
                file->private_data = fd;
                RETURN(0);
        }
@@ -860,9 +932,6 @@ restart:
 
        mutex_unlock(&lli->lli_och_mutex);
 
-       /* lockless for direct IO so that it can do IO in parallel */
-       if (file->f_flags & O_DIRECT)
-               fd->fd_flags |= LL_FILE_LOCKLESS_IO;
        fd = NULL;
 
        /* Must do this outside lli_och_mutex lock to prevent deadlock where
@@ -1088,8 +1157,8 @@ ll_lease_open(struct inode *inode, struct file *file, fmode_t fmode,
 
        /* already get lease, handle lease lock */
        ll_set_lock_data(sbi->ll_md_exp, inode, &it, NULL);
-       if (it.it_lock_mode == 0 ||
-           it.it_lock_bits != MDS_INODELOCK_OPEN) {
+       if (!it.it_lock_mode ||
+           !(it.it_lock_bits & MDS_INODELOCK_OPEN)) {
                /* open lock must return for lease */
                CERROR(DFID "lease granted but no open lock, %d/%llu.\n",
                        PFID(ll_inode2fid(inode)), it.it_lock_mode,
@@ -1296,7 +1365,7 @@ int ll_merge_attr(const struct lu_env *env, struct inode *inode)
         * POSIX. Solving this problem needs to send an RPC to MDT for each
         * read, this will hurt performance.
         */
-       if (ll_file_test_and_clear_flag(lli, LLIF_UPDATE_ATIME) ||
+       if (test_and_clear_bit(LLIF_UPDATE_ATIME, &lli->lli_flags) ||
            inode->i_atime.tv_sec < lli->lli_atime)
                inode->i_atime.tv_sec = lli->lli_atime;
 
@@ -1411,8 +1480,8 @@ void ll_io_init(struct cl_io *io, struct file *file, enum cl_io_type iot,
                                           IS_SYNC(inode));
 #ifdef HAVE_GENERIC_WRITE_SYNC_2ARGS
                io->u.ci_wr.wr_sync  |= !!(args &&
-                                          args->via_io_subtype == IO_NORMAL &&
-                                          args->u.normal.via_iocb->ki_flags & IOCB_DSYNC);
+                                          (args->u.normal.via_iocb->ki_flags &
+                                           IOCB_DSYNC));
 #endif
        }
 
@@ -1470,16 +1539,17 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
                   struct file *file, enum cl_io_type iot,
                   loff_t *ppos, size_t count)
 {
-       struct vvp_io           *vio = vvp_env_io(env);
-       struct inode            *inode = file_inode(file);
-       struct ll_inode_info    *lli = ll_i2info(inode);
-       struct ll_file_data     *fd  = file->private_data;
-       struct range_lock       range;
-       struct cl_io            *io;
-       ssize_t                 result = 0;
-       int                     rc = 0;
-       unsigned                retried = 0;
-       unsigned                ignore_lockless = 0;
+       struct vvp_io *vio = vvp_env_io(env);
+       struct inode *inode = file_inode(file);
+       struct ll_inode_info *lli = ll_i2info(inode);
+       struct ll_file_data *fd  = file->private_data;
+       struct range_lock range;
+       struct cl_io *io;
+       ssize_t result = 0;
+       int rc = 0;
+       unsigned int retried = 0, dio_lock = 0;
+       bool is_aio = false;
+       struct cl_dio_aio *ci_aio = NULL;
 
        ENTRY;
 
@@ -1487,10 +1557,20 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
                file_dentry(file)->d_name.name,
                iot == CIT_READ ? "read" : "write", *ppos, count);
 
+       io = vvp_env_thread_io(env);
+       if (file->f_flags & O_DIRECT) {
+               if (!is_sync_kiocb(args->u.normal.via_iocb))
+                       is_aio = true;
+               ci_aio = cl_aio_alloc(args->u.normal.via_iocb);
+               if (!ci_aio)
+                       GOTO(out, rc = -ENOMEM);
+       }
+
 restart:
        io = vvp_env_thread_io(env);
        ll_io_init(io, file, iot, args);
-       io->ci_ignore_lockless = ignore_lockless;
+       io->ci_aio = ci_aio;
+       io->ci_dio_lock = dio_lock;
        io->ci_ndelay_tried = retried;
 
        if (cl_io_rw_init(env, io, iot, *ppos, count) == 0) {
@@ -1502,34 +1582,22 @@ restart:
                        range_lock_init(&range, *ppos, *ppos + count - 1);
 
                vio->vui_fd  = file->private_data;
-               vio->vui_io_subtype = args->via_io_subtype;
-
-               switch (vio->vui_io_subtype) {
-               case IO_NORMAL:
-                       vio->vui_iter = args->u.normal.via_iter;
-                       vio->vui_iocb = args->u.normal.via_iocb;
-                       /* Direct IO reads must also take range lock,
-                        * or multiple reads will try to work on the same pages
-                        * See LU-6227 for details. */
-                       if (((iot == CIT_WRITE) ||
-                           (iot == CIT_READ && (file->f_flags & O_DIRECT))) &&
-                           !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
-                               CDEBUG(D_VFSTRACE, "Range lock "RL_FMT"\n",
-                                      RL_PARA(&range));
-                               rc = range_lock(&lli->lli_write_tree, &range);
-                               if (rc < 0)
-                                       GOTO(out, rc);
+               vio->vui_iter = args->u.normal.via_iter;
+               vio->vui_iocb = args->u.normal.via_iocb;
+               /* Direct IO reads must also take range lock,
+                * or multiple reads will try to work on the same pages
+                * See LU-6227 for details.
+                */
+               if (((iot == CIT_WRITE) ||
+                   (iot == CIT_READ && (file->f_flags & O_DIRECT))) &&
+                   !(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
+                       CDEBUG(D_VFSTRACE, "Range lock "RL_FMT"\n",
+                              RL_PARA(&range));
+                       rc = range_lock(&lli->lli_write_tree, &range);
+                       if (rc < 0)
+                               GOTO(out, rc);
 
-                               range_locked = true;
-                       }
-                       break;
-               case IO_SPLICE:
-                       vio->u.splice.vui_pipe = args->u.splice.via_pipe;
-                       vio->u.splice.vui_flags = args->u.splice.via_flags;
-                       break;
-               default:
-                       CERROR("unknown IO subtype %u\n", vio->vui_io_subtype);
-                       LBUG();
+                       range_locked = true;
                }
 
                ll_cl_add(file, env, io, LCC_RW);
@@ -1546,13 +1614,22 @@ restart:
                rc = io->ci_result;
        }
 
+       /*
+        * In order to move forward AIO, ci_nob was increased,
+        * but that doesn't mean io have been finished, it just
+        * means io have been submited, we will always return
+        * EIOCBQUEUED to the caller, So we could only return
+        * number of bytes in non-AIO case.
+        */
        if (io->ci_nob > 0) {
-               result += io->ci_nob;
-               count  -= io->ci_nob;
-               *ppos = io->u.ci_wr.wr.crw_pos; /* for splice */
+               if (!is_aio) {
+                       result += io->ci_nob;
+                       *ppos = io->u.ci_wr.wr.crw_pos; /* for splice */
+               }
+               count -= io->ci_nob;
 
                /* prepare IO restart */
-               if (count > 0 && args->via_io_subtype == IO_NORMAL)
+               if (count > 0)
                        args->u.normal.via_iter = vio->vui_iter;
        }
 out:
@@ -1572,10 +1649,31 @@ out:
                       *ppos, count, result, rc);
                /* preserve the tried count for FLR */
                retried = io->ci_ndelay_tried;
-               ignore_lockless = io->ci_ignore_lockless;
+               dio_lock = io->ci_dio_lock;
                goto restart;
        }
 
+       if (io->ci_aio) {
+               /*
+                * VFS will call aio_complete() if no -EIOCBQUEUED
+                * is returned for AIO, so we can not call aio_complete()
+                * in our end_io().
+                */
+               if (rc != -EIOCBQUEUED)
+                       io->ci_aio->cda_no_aio_complete = 1;
+               /**
+                * Drop one extra reference so that end_io() could be
+                * called for this IO context, we could call it after
+                * we make sure all AIO requests have been proceed.
+                */
+               cl_sync_io_note(env, &io->ci_aio->cda_sync,
+                               rc == -EIOCBQUEUED ? 0 : rc);
+               if (!is_aio) {
+                       cl_aio_free(io->ci_aio);
+                       io->ci_aio = NULL;
+               }
+       }
+
        if (iot == CIT_READ) {
                if (result > 0)
                        ll_stats_ops_tally(ll_i2sbi(inode),
@@ -1710,7 +1808,7 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
        if (IS_ERR(env))
                return PTR_ERR(env);
 
-       args = ll_env_args(env, IO_NORMAL);
+       args = ll_env_args(env);
        args->u.normal.via_iter = to;
        args->u.normal.via_iocb = iocb;
 
@@ -1785,7 +1883,7 @@ static ssize_t ll_do_tiny_write(struct kiocb *iocb, struct iov_iter *iter)
                ll_heat_add(inode, CIT_WRITE, result);
                ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_WRITE_BYTES,
                                   result);
-               ll_file_set_flag(ll_i2info(inode), LLIF_DATA_MODIFIED);
+               set_bit(LLIF_DATA_MODIFIED, &ll_i2info(inode)->lli_flags);
        }
 
        CDEBUG(D_VFSTRACE, "result: %zu, original count %zu\n", result, count);
@@ -1845,7 +1943,7 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (IS_ERR(env))
                return PTR_ERR(env);
 
-       args = ll_env_args(env, IO_NORMAL);
+       args = ll_env_args(env);
        args->u.normal.via_iter = from;
        args->u.normal.via_iocb = iocb;
 
@@ -1879,7 +1977,8 @@ out:
  * XXX: exact copy from kernel code (__generic_file_aio_write_nolock)
  */
 static int ll_file_get_iov_count(const struct iovec *iov,
-                                unsigned long *nr_segs, size_t *count)
+                                unsigned long *nr_segs, size_t *count,
+                                int access_flags)
 {
        size_t cnt = 0;
        unsigned long seg;
@@ -1894,7 +1993,7 @@ static int ll_file_get_iov_count(const struct iovec *iov,
                cnt += iv->iov_len;
                if (unlikely((ssize_t)(cnt|iv->iov_len) < 0))
                        return -EINVAL;
-               if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
+               if (access_ok(access_flags, iv->iov_base, iv->iov_len))
                        continue;
                if (seg == 0)
                        return -EFAULT;
@@ -1914,7 +2013,7 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
        ssize_t result;
        ENTRY;
 
-       result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
+       result = ll_file_get_iov_count(iov, &nr_segs, &iov_count, VERIFY_READ);
        if (result)
                RETURN(result);
 
@@ -1970,7 +2069,7 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        ssize_t result;
        ENTRY;
 
-       result = ll_file_get_iov_count(iov, &nr_segs, &iov_count);
+       result = ll_file_get_iov_count(iov, &nr_segs, &iov_count, VERIFY_WRITE);
        if (result)
                RETURN(result);
 
@@ -2016,46 +2115,6 @@ static ssize_t ll_file_write(struct file *file, const char __user *buf,
 }
 #endif /* !HAVE_FILE_OPERATIONS_READ_WRITE_ITER */
 
-/*
- * Send file content (through pagecache) somewhere with helper
- */
-static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos,
-                                   struct pipe_inode_info *pipe, size_t count,
-                                   unsigned int flags)
-{
-       struct lu_env *env;
-       struct vvp_io_args *args;
-       ssize_t result;
-       __u16 refcheck;
-       bool cached;
-
-       ENTRY;
-
-       result = pcc_file_splice_read(in_file, ppos, pipe,
-                                     count, flags, &cached);
-       if (cached)
-               RETURN(result);
-
-       ll_ras_enter(in_file, *ppos, count);
-
-       env = cl_env_get(&refcheck);
-       if (IS_ERR(env))
-               RETURN(PTR_ERR(env));
-
-       args = ll_env_args(env, IO_SPLICE);
-       args->u.splice.via_pipe = pipe;
-       args->u.splice.via_flags = flags;
-
-       result = ll_file_io_generic(env, args, in_file, CIT_READ, ppos, count);
-       cl_env_put(env, &refcheck);
-
-       if (result > 0)
-               ll_rw_stats_tally(ll_i2sbi(file_inode(in_file)), current->pid,
-                                 in_file->private_data, *ppos, result,
-                                 READ);
-       RETURN(result);
-}
-
 int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry,
                             __u64 flags, struct lov_user_md *lum, int lum_size)
 {
@@ -2184,7 +2243,7 @@ static int ll_lov_setea(struct inode *inode, struct file *file,
        int                      rc;
        ENTRY;
 
-       if (!cfs_capable(CFS_CAP_SYS_ADMIN))
+       if (!capable(CAP_SYS_ADMIN))
                RETURN(-EPERM);
 
        OBD_ALLOC_LARGE(lump, lum_size);
@@ -2247,6 +2306,13 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file,
                        GOTO(out, rc);
 
                rc = ll_file_getstripe(inode, arg, lum_size);
+               if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode) &&
+                   ll_i2info(inode)->lli_clob) {
+                       struct iattr attr = { 0 };
+
+                       rc = cl_setattr_ost(ll_i2info(inode)->lli_clob, &attr,
+                                           OP_XVALID_FLAGS, LUSTRE_ENCRYPT_FL);
+               }
        }
        cl_lov_delay_create_clear(&file->f_flags);
 
@@ -2315,12 +2381,12 @@ retry:
                        GOTO(out, rc = PTR_ERR(env));
 
                rc = cl_object_layout_get(env, obj, &cl);
-               if (!rc && cl.cl_is_composite)
+               if (rc >= 0 && cl.cl_is_composite)
                        rc = ll_layout_write_intent(inode, LAYOUT_INTENT_WRITE,
                                                    &ext);
 
                cl_env_put(env, &refcheck);
-               if (rc)
+               if (rc < 0)
                        GOTO(out, rc);
        }
 
@@ -2396,26 +2462,26 @@ out:
  */
 int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it)
 {
-        struct inode *inode = dentry->d_inode;
-        struct obd_client_handle *och;
-        int rc;
-        ENTRY;
+       struct inode *inode = dentry->d_inode;
+       struct obd_client_handle *och;
+       int rc;
+       ENTRY;
 
-        LASSERT(inode);
+       LASSERT(inode);
 
-        /* Root ? Do nothing. */
-        if (dentry->d_inode->i_sb->s_root == dentry)
-                RETURN(0);
+       /* Root ? Do nothing. */
+       if (is_root_inode(inode))
+               RETURN(0);
 
-        /* No open handle to close? Move away */
-        if (!it_disposition(it, DISP_OPEN_OPEN))
-                RETURN(0);
+       /* No open handle to close? Move away */
+       if (!it_disposition(it, DISP_OPEN_OPEN))
+               RETURN(0);
 
-        LASSERT(it_open_error(DISP_OPEN_OPEN, it) == 0);
+       LASSERT(it_open_error(DISP_OPEN_OPEN, it) == 0);
 
-        OBD_ALLOC(och, sizeof(*och));
-        if (!och)
-                GOTO(out, rc = -ENOMEM);
+       OBD_ALLOC(och, sizeof(*och));
+       if (!och)
+               GOTO(out, rc = -ENOMEM);
 
        rc = ll_och_fill(ll_i2sbi(inode)->ll_md_exp, it, och);
        if (rc)
@@ -2499,7 +2565,7 @@ int ll_fid2path(struct inode *inode, void __user *arg)
 
        ENTRY;
 
-       if (!cfs_capable(CFS_CAP_DAC_READ_SEARCH) &&
+       if (!capable(CAP_DAC_READ_SEARCH) &&
            !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH))
                RETURN(-EPERM);
 
@@ -2787,7 +2853,7 @@ int ll_hsm_state_set(struct inode *inode, struct hsm_state_set *hss)
        /* Non-root users are forbidden to set or clear flags which are
         * NOT defined in HSM_USER_MASK. */
        if (((hss->hss_setmask | hss->hss_clearmask) & ~HSM_USER_MASK) &&
-           !cfs_capable(CFS_CAP_SYS_ADMIN))
+           !capable(CAP_SYS_ADMIN))
                RETURN(-EPERM);
 
        if (!exp_connect_archive_id_array(exp)) {
@@ -2958,9 +3024,9 @@ int ll_file_lock_ahead(struct file *file, struct llapi_lu_ladvise *ladvise)
 
        ENTRY;
 
-       CDEBUG(D_VFSTRACE, "Lock request: file=%.*s, inode=%p, mode=%s "
-              "start=%llu, end=%llu\n", dentry->d_name.len,
-              dentry->d_name.name, dentry->d_inode,
+       CDEBUG(D_VFSTRACE,
+              "Lock request: file=%pd, inode=%p, mode=%s start=%llu, end=%llu\n",
+              dentry, dentry->d_inode,
               user_lockname[ladvise->lla_lockahead_mode], (__u64) start,
               (__u64) end);
 
@@ -3163,7 +3229,7 @@ int ll_ioctl_fsgetxattr(struct inode *inode, unsigned int cmd,
                RETURN(-EFAULT);
 
        fsxattr.fsx_xflags = ll_inode_flags_to_xflags(inode->i_flags);
-       if (ll_file_test_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT))
+       if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags))
                fsxattr.fsx_xflags |= FS_XFLAG_PROJINHERIT;
        fsxattr.fsx_projid = ll_i2info(inode)->lli_projid;
        if (copy_to_user((struct fsxattr __user *)arg,
@@ -3186,7 +3252,7 @@ int ll_ioctl_check_project(struct inode *inode, struct fsxattr *fa)
        if (ll_i2info(inode)->lli_projid != fa->fsx_projid)
                return -EINVAL;
 
-       if (ll_file_test_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT)) {
+       if (test_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags)) {
                if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT))
                        return -EINVAL;
        } else {
@@ -3200,14 +3266,12 @@ int ll_ioctl_check_project(struct inode *inode, struct fsxattr *fa)
 int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
                        unsigned long arg)
 {
-
        struct md_op_data *op_data;
        struct ptlrpc_request *req = NULL;
-       int rc = 0;
        struct fsxattr fsxattr;
        struct cl_object *obj;
-       struct iattr *attr;
-       int flags;
+       unsigned int inode_flags;
+       int rc = 0;
 
        if (copy_from_user(&fsxattr,
                           (const struct fsxattr __user *)arg,
@@ -3223,34 +3287,31 @@ int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));
 
-       flags = ll_xflags_to_inode_flags(fsxattr.fsx_xflags);
-       op_data->op_attr_flags = ll_inode_to_ext_flags(flags);
+       inode_flags = ll_xflags_to_inode_flags(fsxattr.fsx_xflags);
+       op_data->op_attr_flags = ll_inode_to_ext_flags(inode_flags);
        if (fsxattr.fsx_xflags & FS_XFLAG_PROJINHERIT)
                op_data->op_attr_flags |= LUSTRE_PROJINHERIT_FL;
        op_data->op_projid = fsxattr.fsx_projid;
        op_data->op_xvalid |= OP_XVALID_PROJID | OP_XVALID_FLAGS;
-       rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL,
-                       0, &req);
+       rc = md_setattr(ll_i2sbi(inode)->ll_md_exp, op_data, NULL, 0, &req);
        ptlrpc_req_finished(req);
        if (rc)
                GOTO(out_fsxattr, rc);
        ll_update_inode_flags(inode, op_data->op_attr_flags);
-       obj = ll_i2info(inode)->lli_clob;
-       if (obj == NULL)
-               GOTO(out_fsxattr, rc);
 
-       /* Avoiding OST RPC if this is only project ioctl */
+       /* Avoid OST RPC if this is only ioctl setting project inherit flag */
        if (fsxattr.fsx_xflags == 0 ||
            fsxattr.fsx_xflags == FS_XFLAG_PROJINHERIT)
                GOTO(out_fsxattr, rc);
 
-       OBD_ALLOC_PTR(attr);
-       if (attr == NULL)
-               GOTO(out_fsxattr, rc = -ENOMEM);
+       obj = ll_i2info(inode)->lli_clob;
+       if (obj) {
+               struct iattr attr = { 0 };
+
+               rc = cl_setattr_ost(obj, &attr, OP_XVALID_FLAGS,
+                                   fsxattr.fsx_xflags);
+       }
 
-       rc = cl_setattr_ost(obj, attr, OP_XVALID_FLAGS,
-                           fsxattr.fsx_xflags);
-       OBD_FREE_PTR(attr);
 out_fsxattr:
        ll_finish_md_op_data(op_data);
        RETURN(rc);
@@ -3897,9 +3958,9 @@ out_ladvise:
                fd->fd_designated_mirror = (__u32)arg;
                RETURN(0);
        }
-       case LL_IOC_FSGETXATTR:
+       case FS_IOC_FSGETXATTR:
                RETURN(ll_ioctl_fsgetxattr(inode, cmd, arg));
-       case LL_IOC_FSSETXATTR:
+       case FS_IOC_FSSETXATTR:
                RETURN(ll_ioctl_fssetxattr(inode, cmd, arg));
        case BLKSSZGET:
                RETURN(put_user(PAGE_SIZE, (int __user *)arg));
@@ -3980,34 +4041,132 @@ out_state:
                OBD_FREE_PTR(state);
                RETURN(rc);
        }
+#ifdef HAVE_LUSTRE_CRYPTO
+       case LL_IOC_SET_ENCRYPTION_POLICY:
+               if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+                       return -EOPNOTSUPP;
+               return llcrypt_ioctl_set_policy(file, (const void __user *)arg);
+       case LL_IOC_GET_ENCRYPTION_POLICY_EX:
+               if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+                       return -EOPNOTSUPP;
+               return llcrypt_ioctl_get_policy_ex(file, (void __user *)arg);
+       case LL_IOC_ADD_ENCRYPTION_KEY:
+               if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+                       return -EOPNOTSUPP;
+               return llcrypt_ioctl_add_key(file, (void __user *)arg);
+       case LL_IOC_REMOVE_ENCRYPTION_KEY:
+               if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+                       return -EOPNOTSUPP;
+               return llcrypt_ioctl_remove_key(file, (void __user *)arg);
+       case LL_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
+               if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+                       return -EOPNOTSUPP;
+               return llcrypt_ioctl_remove_key_all_users(file,
+                                                         (void __user *)arg);
+       case LL_IOC_GET_ENCRYPTION_KEY_STATUS:
+               if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
+                       return -EOPNOTSUPP;
+               return llcrypt_ioctl_get_key_status(file, (void __user *)arg);
+#endif
+
+       case LL_IOC_UNLOCK_FOREIGN: {
+               struct dentry *dentry = file_dentry(file);
+
+               /* if not a foreign symlink do nothing */
+               if (ll_foreign_is_removable(dentry, true)) {
+                       CDEBUG(D_INFO,
+                              "prevent unlink of non-foreign file ("DFID")\n",
+                              PFID(ll_inode2fid(inode)));
+                       RETURN(-EOPNOTSUPP);
+               }
+               RETURN(0);
+       }
+
        default:
                RETURN(obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL,
                                     (void __user *)arg));
        }
 }
 
+loff_t ll_lseek(struct file *file, loff_t offset, int whence)
+{
+       struct inode *inode = file_inode(file);
+       struct lu_env *env;
+       struct cl_io *io;
+       struct cl_lseek_io *lsio;
+       __u16 refcheck;
+       int rc;
+       loff_t retval;
+
+       ENTRY;
+
+       env = cl_env_get(&refcheck);
+       if (IS_ERR(env))
+               RETURN(PTR_ERR(env));
+
+       io = vvp_env_thread_io(env);
+       io->ci_obj = ll_i2info(inode)->lli_clob;
+       ll_io_set_mirror(io, file);
+
+       lsio = &io->u.ci_lseek;
+       lsio->ls_start = offset;
+       lsio->ls_whence = whence;
+       lsio->ls_result = -ENXIO;
+
+       do {
+               rc = cl_io_init(env, io, CIT_LSEEK, io->ci_obj);
+               if (!rc) {
+                       struct vvp_io *vio = vvp_env_io(env);
+
+                       vio->vui_fd = file->private_data;
+                       rc = cl_io_loop(env, io);
+               } else {
+                       rc = io->ci_result;
+               }
+               retval = rc ? : lsio->ls_result;
+               cl_io_fini(env, io);
+       } while (unlikely(io->ci_need_restart));
+
+       cl_env_put(env, &refcheck);
+
+       RETURN(retval);
+}
+
 static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
 {
        struct inode *inode = file_inode(file);
-       loff_t retval, eof = 0;
+       loff_t retval = offset, eof = 0;
        ktime_t kstart = ktime_get();
 
        ENTRY;
-       retval = offset + ((origin == SEEK_END) ? i_size_read(inode) :
-                          (origin == SEEK_CUR) ? file->f_pos : 0);
+
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), to=%llu=%#llx(%d)\n",
               PFID(ll_inode2fid(inode)), inode, retval, retval,
               origin);
 
-       if (origin == SEEK_END || origin == SEEK_HOLE || origin == SEEK_DATA) {
+       if (origin == SEEK_END) {
                retval = ll_glimpse_size(inode);
                if (retval != 0)
                        RETURN(retval);
                eof = i_size_read(inode);
        }
 
-       retval = generic_file_llseek_size(file, offset, origin,
-                                         ll_file_maxbytes(inode), eof);
+       if (origin == SEEK_HOLE || origin == SEEK_DATA) {
+               if (offset < 0)
+                       return -ENXIO;
+
+               /* flush local cache first if any */
+               cl_sync_file_range(inode, offset, OBD_OBJECT_EOF,
+                                  CL_FSYNC_LOCAL, 0);
+
+               retval = ll_lseek(file, offset, origin);
+               if (retval < 0)
+                       return retval;
+               retval = vfs_setpos(file, retval, ll_file_maxbytes(inode));
+       } else {
+               retval = generic_file_llseek_size(file, offset, origin,
+                                                 ll_file_maxbytes(inode), eof);
+       }
        if (retval >= 0)
                ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LLSEEK,
                                   ktime_us_delta(ktime_get(), kstart));
@@ -4402,9 +4561,20 @@ int ll_migrate(struct inode *parent, struct file *file, struct lmv_user_md *lum,
         * by checking the migrate FID against the FID of the
         * filesystem root.
         */
-       if (child_inode == parent->i_sb->s_root->d_inode)
+       if (is_root_inode(child_inode))
                GOTO(out_iput, rc = -EINVAL);
 
+       if (IS_ENCRYPTED(child_inode)) {
+               rc = llcrypt_get_encryption_info(child_inode);
+               if (rc)
+                       GOTO(out_iput, rc);
+               if (!llcrypt_has_encryption_key(child_inode)) {
+                       CDEBUG(D_SEC, "no enc key for "DFID"\n",
+                              PFID(ll_inode2fid(child_inode)));
+                       GOTO(out_iput, rc = -ENOKEY);
+               }
+       }
+
        op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen,
                                     child_inode->i_mode, LUSTRE_OPC_ANY, NULL);
        if (IS_ERR(op_data))
@@ -4541,24 +4711,24 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits, enum ldlm_mode l_req_mode)
 
        flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK;
        for (i = 0; i < MDS_INODELOCK_NUMBITS && *bits != 0; i++) {
-               policy.l_inodebits.bits = *bits & (1 << i);
+               policy.l_inodebits.bits = *bits & BIT(i);
                if (policy.l_inodebits.bits == 0)
                        continue;
 
-                if (md_lock_match(ll_i2mdexp(inode), flags, fid, LDLM_IBITS,
-                                  &policy, mode, &lockh)) {
-                        struct ldlm_lock *lock;
-
-                        lock = ldlm_handle2lock(&lockh);
-                        if (lock) {
-                                *bits &=
-                                      ~(lock->l_policy_data.l_inodebits.bits);
-                                LDLM_LOCK_PUT(lock);
-                        } else {
-                                *bits &= ~policy.l_inodebits.bits;
-                        }
-                }
-        }
+               if (md_lock_match(ll_i2mdexp(inode), flags, fid, LDLM_IBITS,
+                                 &policy, mode, &lockh)) {
+                       struct ldlm_lock *lock;
+
+                       lock = ldlm_handle2lock(&lockh);
+                       if (lock) {
+                               *bits &=
+                                       ~(lock->l_policy_data.l_inodebits.bits);
+                               LDLM_LOCK_PUT(lock);
+                       } else {
+                               *bits &= ~policy.l_inodebits.bits;
+                       }
+               }
+       }
         RETURN(*bits == 0);
 }
 
@@ -4608,6 +4778,7 @@ static int ll_inode_revalidate_fini(struct inode *inode, int rc)
 
 static int ll_inode_revalidate(struct dentry *dentry, enum ldlm_intent_flags op)
 {
+       struct inode *parent;
        struct inode *inode = dentry->d_inode;
        struct obd_export *exp = ll_i2mdexp(inode);
        struct lookup_intent oit = {
@@ -4615,18 +4786,30 @@ static int ll_inode_revalidate(struct dentry *dentry, enum ldlm_intent_flags op)
        };
        struct ptlrpc_request *req = NULL;
        struct md_op_data *op_data;
+       const char *name = NULL;
+       size_t namelen = 0;
        int rc = 0;
        ENTRY;
 
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p),name=%s\n",
               PFID(ll_inode2fid(inode)), inode, dentry->d_name.name);
 
-       /* Call getattr by fid, so do not provide name at all. */
-       op_data = ll_prep_md_op_data(NULL, inode, inode, NULL, 0, 0,
+       if (exp_connect_flags2(exp) & OBD_CONNECT2_GETATTR_PFID) {
+               parent = dentry->d_parent->d_inode;
+               name = dentry->d_name.name;
+               namelen = dentry->d_name.len;
+       } else {
+               parent = inode;
+       }
+
+       op_data = ll_prep_md_op_data(NULL, parent, inode, name, namelen, 0,
                                     LUSTRE_OPC_ANY, NULL);
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));
 
+       /* Call getattr by fid */
+       if (exp_connect_flags2(exp) & OBD_CONNECT2_GETATTR_PFID)
+               op_data->op_flags = MF_GETATTR_BY_FID;
        rc = md_intent_lock(exp, op_data, &oit, &req, &ll_md_blocking_ast, 0);
        ll_finish_md_op_data(op_data);
        if (rc < 0) {
@@ -4644,11 +4827,8 @@ static int ll_inode_revalidate(struct dentry *dentry, enum ldlm_intent_flags op)
         * do_lookup() -> ll_revalidate_it(). We cannot use d_drop
         * here to preserve get_cwd functionality on 2.6.
         * Bug 10503 */
-       if (!dentry->d_inode->i_nlink) {
-               spin_lock(&inode->i_lock);
-               d_lustre_invalidate(dentry, 0);
-               spin_unlock(&inode->i_lock);
-       }
+       if (!dentry->d_inode->i_nlink)
+               d_lustre_invalidate(dentry);
 
        ll_lookup_finish_locks(&oit, dentry);
 out:
@@ -4686,25 +4866,69 @@ static int ll_merge_md_attr(struct inode *inode)
        RETURN(0);
 }
 
-int ll_getattr_dentry(struct dentry *de, struct kstat *stat)
+int ll_getattr_dentry(struct dentry *de, struct kstat *stat, u32 request_mask,
+                     unsigned int flags, bool foreign)
 {
        struct inode *inode = de->d_inode;
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ll_inode_info *lli = ll_i2info(inode);
+       struct inode *dir = de->d_parent->d_inode;
+       bool need_glimpse = true;
        ktime_t kstart = ktime_get();
        int rc;
 
+       /* The OST object(s) determine the file size, blocks and mtime. */
+       if (!(request_mask & STATX_SIZE || request_mask & STATX_BLOCKS ||
+             request_mask & STATX_MTIME))
+               need_glimpse = false;
+
+       if (dentry_may_statahead(dir, de))
+               ll_start_statahead(dir, de, need_glimpse &&
+                                  !(flags & AT_STATX_DONT_SYNC));
+
+       if (flags & AT_STATX_DONT_SYNC)
+               GOTO(fill_attr, rc = 0);
+
        rc = ll_inode_revalidate(de, IT_GETATTR);
        if (rc < 0)
                RETURN(rc);
 
-       if (S_ISREG(inode->i_mode)) {
+       /* foreign file/dir are always of zero length, so don't
+        * need to validate size.
+        */
+       if (S_ISREG(inode->i_mode) && !foreign) {
                bool cached;
 
-               rc = pcc_inode_getattr(inode, &cached);
+               if (!need_glimpse)
+                       GOTO(fill_attr, rc);
+
+               rc = pcc_inode_getattr(inode, request_mask, flags, &cached);
                if (cached && rc < 0)
                        RETURN(rc);
 
+               if (cached)
+                       GOTO(fill_attr, rc);
+
+               /*
+                * If the returned attr is masked with OBD_MD_FLSIZE &
+                * OBD_MD_FLBLOCKS & OBD_MD_FLMTIME, it means that the file size
+                * or blocks obtained from MDT is strictly correct, and the file
+                * is usually not being modified by clients, and the [a|m|c]time
+                * got from MDT is also strictly correct.
+                * Under this circumstance, it does not need to send glimpse
+                * RPCs to OSTs for file attributes such as the size and blocks.
+                */
+               if (lli->lli_attr_valid & OBD_MD_FLSIZE &&
+                   lli->lli_attr_valid & OBD_MD_FLBLOCKS &&
+                   lli->lli_attr_valid & OBD_MD_FLMTIME) {
+                       inode->i_mtime.tv_sec = lli->lli_mtime;
+                       if (lli->lli_attr_valid & OBD_MD_FLATIME)
+                               inode->i_atime.tv_sec = lli->lli_atime;
+                       if (lli->lli_attr_valid & OBD_MD_FLCTIME)
+                               inode->i_ctime.tv_sec = lli->lli_ctime;
+                       GOTO(fill_attr, rc);
+               }
+
                /* In case of restore, the MDT has the right size and has
                 * already send it back without granting the layout lock,
                 * inode is up-to-date so glimpse is useless.
@@ -4712,24 +4936,29 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat)
                 * restore the MDT holds the layout lock so the glimpse will
                 * block up to the end of restore (getattr will block)
                 */
-               if (!cached && !ll_file_test_flag(lli, LLIF_FILE_RESTORING)) {
+               if (!test_bit(LLIF_FILE_RESTORING, &lli->lli_flags)) {
                        rc = ll_glimpse_size(inode);
                        if (rc < 0)
                                RETURN(rc);
                }
        } else {
                /* If object isn't regular a file then don't validate size. */
-               if (ll_dir_striped(inode)) {
+               /* foreign dir is not striped dir */
+               if (ll_dir_striped(inode) && !foreign) {
                        rc = ll_merge_md_attr(inode);
                        if (rc < 0)
                                RETURN(rc);
                }
 
-               inode->i_atime.tv_sec = lli->lli_atime;
-               inode->i_mtime.tv_sec = lli->lli_mtime;
-               inode->i_ctime.tv_sec = lli->lli_ctime;
+               if (lli->lli_attr_valid & OBD_MD_FLATIME)
+                       inode->i_atime.tv_sec = lli->lli_atime;
+               if (lli->lli_attr_valid & OBD_MD_FLMTIME)
+                       inode->i_mtime.tv_sec = lli->lli_mtime;
+               if (lli->lli_attr_valid & OBD_MD_FLCTIME)
+                       inode->i_ctime.tv_sec = lli->lli_ctime;
        }
 
+fill_attr:
        OBD_FAIL_TIMEOUT(OBD_FAIL_GETATTR_DELAY, 30);
 
        if (ll_need_32bit_api(sbi)) {
@@ -4742,7 +4971,12 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat)
                stat->rdev = inode->i_rdev;
        }
 
-       stat->mode = inode->i_mode;
+       /* foreign symlink to be exposed as a real symlink */
+       if (!foreign)
+               stat->mode = inode->i_mode;
+       else
+               stat->mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
+
        stat->uid = inode->i_uid;
        stat->gid = inode->i_gid;
        stat->atime = inode->i_atime;
@@ -4761,6 +4995,26 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat)
        stat->size = i_size_read(inode);
        stat->blocks = inode->i_blocks;
 
+#ifdef HAVE_INODEOPS_ENHANCED_GETATTR
+       if (flags & AT_STATX_DONT_SYNC) {
+               if (stat->size == 0 &&
+                   lli->lli_attr_valid & OBD_MD_FLLAZYSIZE)
+                       stat->size = lli->lli_lazysize;
+               if (stat->blocks == 0 &&
+                   lli->lli_attr_valid & OBD_MD_FLLAZYBLOCKS)
+                       stat->blocks = lli->lli_lazyblocks;
+       }
+
+       if (lli->lli_attr_valid & OBD_MD_FLBTIME) {
+               stat->result_mask |= STATX_BTIME;
+               stat->btime.tv_sec = lli->lli_btime;
+       }
+
+       stat->attributes_mask = STATX_ATTR_IMMUTABLE | STATX_ATTR_APPEND;
+       stat->attributes |= ll_inode_to_ext_flags(inode->i_flags);
+       stat->result_mask &= request_mask;
+#endif
+
        ll_stats_ops_tally(sbi, LPROC_LL_GETATTR,
                           ktime_us_delta(ktime_get(), kstart));
 
@@ -4771,12 +5025,112 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat)
 int ll_getattr(const struct path *path, struct kstat *stat,
               u32 request_mask, unsigned int flags)
 {
-       struct dentry *de = path->dentry;
+       return ll_getattr_dentry(path->dentry, stat, request_mask, flags,
+                                false);
+}
 #else
 int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat)
 {
+       return ll_getattr_dentry(de, stat, STATX_BASIC_STATS,
+                                AT_STATX_SYNC_AS_STAT, false);
+}
 #endif
-       return ll_getattr_dentry(de, stat);
+
+int cl_falloc(struct inode *inode, int mode, loff_t offset, loff_t len)
+{
+       struct lu_env *env;
+       struct cl_io *io;
+       __u16 refcheck;
+       int rc; loff_t sa_falloc_end;
+       loff_t size = i_size_read(inode);
+
+       ENTRY;
+
+       env = cl_env_get(&refcheck);
+       if (IS_ERR(env))
+               RETURN(PTR_ERR(env));
+
+       io = vvp_env_thread_io(env);
+       io->ci_obj = ll_i2info(inode)->lli_clob;
+       io->ci_verify_layout = 1;
+       io->u.ci_setattr.sa_parent_fid = lu_object_fid(&io->ci_obj->co_lu);
+       io->u.ci_setattr.sa_falloc_mode = mode;
+       io->u.ci_setattr.sa_falloc_offset = offset;
+       io->u.ci_setattr.sa_falloc_len = len;
+       io->u.ci_setattr.sa_falloc_end = io->u.ci_setattr.sa_falloc_offset +
+               io->u.ci_setattr.sa_falloc_len;
+       io->u.ci_setattr.sa_subtype = CL_SETATTR_FALLOCATE;
+       sa_falloc_end = io->u.ci_setattr.sa_falloc_end;
+       if (sa_falloc_end > size) {
+               /* Check new size against VFS/VM file size limit and rlimit */
+               rc = inode_newsize_ok(inode, sa_falloc_end);
+               if (rc)
+                       goto out;
+               if (sa_falloc_end > ll_file_maxbytes(inode)) {
+                       CDEBUG(D_INODE, "file size too large %llu > %llu\n",
+                              (unsigned long long)(sa_falloc_end),
+                              ll_file_maxbytes(inode));
+                       rc = -EFBIG;
+                       goto out;
+               }
+               io->u.ci_setattr.sa_attr.lvb_size = sa_falloc_end;
+               if (!(mode & FALLOC_FL_KEEP_SIZE))
+                       io->u.ci_setattr.sa_avalid |= ATTR_SIZE;
+       } else {
+               io->u.ci_setattr.sa_attr.lvb_size = size;
+       }
+
+again:
+       if (cl_io_init(env, io, CIT_SETATTR, io->ci_obj) == 0)
+               rc = cl_io_loop(env, io);
+       else
+               rc = io->ci_result;
+
+       cl_io_fini(env, io);
+       if (unlikely(io->ci_need_restart))
+               goto again;
+
+out:
+       cl_env_put(env, &refcheck);
+       RETURN(rc);
+}
+
+long ll_fallocate(struct file *filp, int mode, loff_t offset, loff_t len)
+{
+       struct inode *inode = filp->f_path.dentry->d_inode;
+       int rc;
+
+       /*
+        * Encrypted inodes can't handle collapse range or zero range or insert
+        * range since we would need to re-encrypt blocks with a different IV or
+        * XTS tweak (which are based on the logical block number).
+        * Similar to what ext4 does.
+        */
+       if (IS_ENCRYPTED(inode) &&
+           (mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE |
+                    FALLOC_FL_ZERO_RANGE)))
+               RETURN(-EOPNOTSUPP);
+
+       /*
+        * Only mode == 0 (which is standard prealloc) is supported now.
+        * Punch is not supported yet.
+        */
+       if (mode & ~FALLOC_FL_KEEP_SIZE)
+               RETURN(-EOPNOTSUPP);
+
+       ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_FALLOCATE, 1);
+
+       rc = cl_falloc(inode, mode, offset, len);
+       /*
+        * ENOTSUPP (524) is an NFSv3 specific error code erroneously
+        * used by Lustre in several places. Retuning it here would
+        * confuse applications that explicity test for EOPNOTSUPP
+        * (95) and fall back to ftruncate().
+        */
+       if (rc == -ENOTSUPP)
+               rc = -EOPNOTSUPP;
+
+       RETURN(rc);
 }
 
 static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
@@ -4805,6 +5159,15 @@ static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 
        rc = ll_do_fiemap(inode, fiemap, num_bytes);
 
+       if (IS_ENCRYPTED(inode)) {
+               int i;
+
+               for (i = 0; i < fiemap->fm_mapped_extents; i++)
+                       fiemap->fm_extents[i].fe_flags |=
+                               FIEMAP_EXTENT_DATA_ENCRYPTED |
+                               FIEMAP_EXTENT_ENCODED;
+       }
+
        fieinfo->fi_flags = fiemap->fm_flags;
        fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents;
        if (extent_count > 0 &&
@@ -4817,80 +5180,6 @@ out:
        return rc;
 }
 
-struct posix_acl *ll_get_acl(struct inode *inode, int type)
-{
-       struct ll_inode_info *lli = ll_i2info(inode);
-       struct posix_acl *acl = NULL;
-       ENTRY;
-
-       spin_lock(&lli->lli_lock);
-       /* VFS' acl_permission_check->check_acl will release the refcount */
-       acl = posix_acl_dup(lli->lli_posix_acl);
-       spin_unlock(&lli->lli_lock);
-
-       RETURN(acl);
-}
-
-#ifdef HAVE_IOP_SET_ACL
-#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
-int ll_set_acl(struct inode *inode, struct posix_acl *acl, int type)
-{
-       struct ll_sb_info *sbi = ll_i2sbi(inode);
-       struct ptlrpc_request *req = NULL;
-       const char *name = NULL;
-       char *value = NULL;
-       size_t value_size = 0;
-       int rc = 0;
-       ENTRY;
-
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               name = XATTR_NAME_POSIX_ACL_ACCESS;
-               if (acl)
-                       rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
-               break;
-
-       case ACL_TYPE_DEFAULT:
-               name = XATTR_NAME_POSIX_ACL_DEFAULT;
-               if (!S_ISDIR(inode->i_mode))
-                       rc = acl ? -EACCES : 0;
-               break;
-
-       default:
-               rc = -EINVAL;
-               break;
-       }
-       if (rc)
-               return rc;
-
-       if (acl) {
-               value_size = posix_acl_xattr_size(acl->a_count);
-               value = kmalloc(value_size, GFP_NOFS);
-               if (value == NULL)
-                       GOTO(out, rc = -ENOMEM);
-
-               rc = posix_acl_to_xattr(&init_user_ns, acl, value, value_size);
-               if (rc < 0)
-                       GOTO(out_value, rc);
-       }
-
-       rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode),
-                        value ? OBD_MD_FLXATTR : OBD_MD_FLXATTRRM,
-                        name, value, value_size, 0, 0, &req);
-
-       ptlrpc_req_finished(req);
-out_value:
-       kfree(value);
-out:
-       if (rc)
-               forget_cached_acl(inode, type);
-       else
-               set_cached_acl(inode, type, acl);
-       RETURN(rc);
-}
-#endif /* CONFIG_LUSTRE_FS_POSIX_ACL */
-#endif /* HAVE_IOP_SET_ACL */
-
 int ll_inode_permission(struct inode *inode, int mask)
 {
        int rc = 0;
@@ -4901,19 +5190,22 @@ int ll_inode_permission(struct inode *inode, int mask)
        cfs_cap_t cap;
        bool squash_id = false;
        ktime_t kstart = ktime_get();
+
        ENTRY;
 
        if (mask & MAY_NOT_BLOCK)
                return -ECHILD;
 
-       /* as root inode are NOT getting validated in lookup operation,
-        * need to do it before permission check. */
+       /*
+        * as root inode are NOT getting validated in lookup operation,
+        * need to do it before permission check.
+        */
 
-        if (inode == inode->i_sb->s_root->d_inode) {
+       if (is_root_inode(inode)) {
                rc = ll_inode_revalidate(inode->i_sb->s_root, IT_LOOKUP);
-                if (rc)
-                        RETURN(rc);
-        }
+               if (rc)
+                       RETURN(rc);
+       }
 
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), inode mode %x mask %o\n",
               PFID(ll_inode2fid(inode)), inode, inode->i_mode, mask);
@@ -4940,7 +5232,7 @@ int ll_inode_permission(struct inode *inode, int mask)
                cred->fsuid = make_kuid(&init_user_ns, squash->rsi_uid);
                cred->fsgid = make_kgid(&init_user_ns, squash->rsi_gid);
                for (cap = 0; cap < sizeof(cfs_cap_t) * 8; cap++) {
-                       if ((1 << cap) & CFS_CAP_FS_MASK)
+                       if (BIT(cap) & CFS_CAP_FS_MASK)
                                cap_lower(cred->cap_effective, cap);
                }
                old_cred = override_creds(cred);
@@ -4961,7 +5253,7 @@ int ll_inode_permission(struct inode *inode, int mask)
 }
 
 /* -o localflock - only provides locally consistent flock locks */
-struct file_operations ll_file_operations = {
+static const struct file_operations ll_file_operations = {
 #ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
 # ifdef HAVE_SYNC_READ_WRITE
        .read           = new_sync_read,
@@ -4980,12 +5272,17 @@ struct file_operations ll_file_operations = {
        .release        = ll_file_release,
        .mmap           = ll_file_mmap,
        .llseek         = ll_file_seek,
-       .splice_read    = ll_file_splice_read,
+#ifndef HAVE_DEFAULT_FILE_SPLICE_READ_EXPORT
+       .splice_read    = generic_file_splice_read,
+#else
+       .splice_read    = pcc_file_splice_read,
+#endif
        .fsync          = ll_fsync,
-       .flush          = ll_flush
+       .flush          = ll_flush,
+       .fallocate      = ll_fallocate,
 };
 
-struct file_operations ll_file_operations_flock = {
+static const struct file_operations ll_file_operations_flock = {
 #ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
 # ifdef HAVE_SYNC_READ_WRITE
        .read           = new_sync_read,
@@ -5004,15 +5301,20 @@ struct file_operations ll_file_operations_flock = {
        .release        = ll_file_release,
        .mmap           = ll_file_mmap,
        .llseek         = ll_file_seek,
-       .splice_read    = ll_file_splice_read,
+#ifndef HAVE_DEFAULT_FILE_SPLICE_READ_EXPORT
+       .splice_read    = generic_file_splice_read,
+#else
+       .splice_read    = pcc_file_splice_read,
+#endif
        .fsync          = ll_fsync,
        .flush          = ll_flush,
        .flock          = ll_file_flock,
-       .lock           = ll_file_flock
+       .lock           = ll_file_flock,
+       .fallocate      = ll_fallocate,
 };
 
 /* These are for -o noflock - to return ENOSYS on flock calls */
-struct file_operations ll_file_operations_noflock = {
+static const struct file_operations ll_file_operations_noflock = {
 #ifdef HAVE_FILE_OPERATIONS_READ_WRITE_ITER
 # ifdef HAVE_SYNC_READ_WRITE
        .read           = new_sync_read,
@@ -5031,14 +5333,19 @@ struct file_operations ll_file_operations_noflock = {
        .release        = ll_file_release,
        .mmap           = ll_file_mmap,
        .llseek         = ll_file_seek,
-       .splice_read    = ll_file_splice_read,
+#ifndef HAVE_DEFAULT_FILE_SPLICE_READ_EXPORT
+       .splice_read    = generic_file_splice_read,
+#else
+       .splice_read    = pcc_file_splice_read,
+#endif
        .fsync          = ll_fsync,
        .flush          = ll_flush,
        .flock          = ll_file_noflock,
-       .lock           = ll_file_noflock
+       .lock           = ll_file_noflock,
+       .fallocate      = ll_fallocate,
 };
 
-struct inode_operations ll_file_inode_operations = {
+const struct inode_operations ll_file_inode_operations = {
        .setattr        = ll_setattr,
        .getattr        = ll_getattr,
        .permission     = ll_inode_permission,
@@ -5055,6 +5362,18 @@ struct inode_operations ll_file_inode_operations = {
 #endif
 };
 
+const struct file_operations *ll_select_file_operations(struct ll_sb_info *sbi)
+{
+       const struct file_operations *fops = &ll_file_operations_noflock;
+
+       if (sbi->ll_flags & LL_SBI_FLOCK)
+               fops = &ll_file_operations_flock;
+       else if (sbi->ll_flags & LL_SBI_LOCALFLOCK)
+               fops = &ll_file_operations;
+
+       return fops;
+}
+
 int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf)
 {
        struct ll_inode_info *lli = ll_i2info(inode);
@@ -5104,7 +5423,7 @@ int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf)
 out:
        cl_env_put(env, &refcheck);
 
-       RETURN(rc);
+       RETURN(rc < 0 ? rc : 0);
 }
 
 /* Fetch layout from MDT with getxattr request, if it's not ready yet */