Whamcloud - gitweb
LU-13437 mdt: don't fetch LOOKUP lock for remote object
[fs/lustre-release.git] / lustre / llite / file.c
index 7c683b7..4f5bba4 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"
@@ -422,14 +424,14 @@ static inline int ll_dom_readpage(void *data, struct page *page)
        struct niobuf_local *lnb = data;
        void *kaddr;
 
-       kaddr = ll_kmap_atomic(page, KM_USER0);
+       kaddr = kmap_atomic(page);
        memcpy(kaddr, lnb->lnb_data, lnb->lnb_len);
        if (lnb->lnb_len < PAGE_SIZE)
                memset(kaddr + lnb->lnb_len, 0,
                       PAGE_SIZE - lnb->lnb_len);
        flush_dcache_page(page);
        SetPageUptodate(page);
-       ll_kunmap_atomic(kaddr, KM_USER0);
+       kunmap_atomic(kaddr);
        unlock_page(page);
 
        return 0;
@@ -705,6 +707,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);
@@ -1879,7 +1887,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 +1903,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 +1923,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 +1979,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);
 
@@ -2247,6 +2256,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);
 
@@ -2958,9 +2974,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);
 
@@ -3036,8 +3052,8 @@ static int ll_ladvise_sanity(struct inode *inode,
 
        if (advice > LU_LADVISE_MAX || advice == LU_LADVISE_INVALID) {
                rc = -EINVAL;
-               CDEBUG(D_VFSTRACE, "%s: advice with value '%d' not recognized,"
-                      "last supported advice is %s (value '%d'): rc = %d\n",
+               CDEBUG(D_VFSTRACE,
+                      "%s: advice with value '%d' not recognized, last supported advice is %s (value '%d'): rc = %d\n",
                       sbi->ll_fsname, advice,
                       ladvise_names[LU_LADVISE_MAX-1], LU_LADVISE_MAX-1, rc);
                GOTO(out, rc);
@@ -3239,6 +3255,11 @@ int ll_ioctl_fssetxattr(struct inode *inode, unsigned int cmd,
        if (obj == NULL)
                GOTO(out_fsxattr, rc);
 
+       /* Avoiding OST RPC if this is only project ioctl */
+       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);
@@ -3892,9 +3913,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));
@@ -3975,79 +3996,39 @@ 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
        default:
                RETURN(obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL,
                                     (void __user *)arg));
        }
 }
 
-#ifndef HAVE_FILE_LLSEEK_SIZE
-static inline loff_t
-llseek_execute(struct file *file, loff_t offset, loff_t maxsize)
-{
-       if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
-               return -EINVAL;
-       if (offset > maxsize)
-               return -EINVAL;
-
-       if (offset != file->f_pos) {
-               file->f_pos = offset;
-               file->f_version = 0;
-       }
-       return offset;
-}
-
-static loff_t
-generic_file_llseek_size(struct file *file, loff_t offset, int origin,
-                loff_t maxsize, loff_t eof)
-{
-       struct inode *inode = file_inode(file);
-
-       switch (origin) {
-       case SEEK_END:
-               offset += eof;
-               break;
-       case SEEK_CUR:
-               /*
-                * Here we special-case the lseek(fd, 0, SEEK_CUR)
-                * position-querying operation.  Avoid rewriting the "same"
-                * f_pos value back to the file because a concurrent read(),
-                * write() or lseek() might have altered it
-                */
-               if (offset == 0)
-                       return file->f_pos;
-               /*
-                * f_lock protects against read/modify/write race with other
-                * SEEK_CURs. Note that parallel writes and reads behave
-                * like SEEK_SET.
-                */
-               inode_lock(inode);
-               offset = llseek_execute(file, file->f_pos + offset, maxsize);
-               inode_unlock(inode);
-               return offset;
-       case SEEK_DATA:
-               /*
-                * In the generic case the entire file is data, so as long as
-                * offset isn't at the end of the file then the offset is data.
-                */
-               if (offset >= eof)
-                       return -ENXIO;
-               break;
-       case SEEK_HOLE:
-               /*
-                * There is a virtual hole at the end of the file, so as long as
-                * offset isn't i_size or larger, return i_size.
-                */
-               if (offset >= eof)
-                       return -ENXIO;
-               offset = eof;
-               break;
-       }
-
-       return llseek_execute(file, offset, maxsize);
-}
-#endif
-
 static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
 {
        struct inode *inode = file_inode(file);
@@ -4068,8 +4049,8 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
                eof = i_size_read(inode);
        }
 
-       retval = ll_generic_file_llseek_size(file, offset, origin,
-                                            ll_file_maxbytes(inode), eof);
+       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));
@@ -4167,8 +4148,8 @@ int ll_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 
        ENTRY;
 
-       CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), start %lld, end %lld,"
-              "datasync %d\n",
+       CDEBUG(D_VFSTRACE,
+              "VFS Op:inode="DFID"(%p), start %lld, end %lld, datasync %d\n",
               PFID(ll_inode2fid(inode)), inode, start, end, datasync);
 
        /* fsync's caller has already called _fdata{sync,write}, we want
@@ -4603,24 +4584,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);
 }
 
@@ -4684,8 +4665,8 @@ static int ll_inode_revalidate(struct dentry *dentry, enum ldlm_intent_flags op)
               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,
-                                    LUSTRE_OPC_ANY, NULL);
+       op_data = ll_prep_md_op_data(NULL, dentry->d_parent->d_inode, inode,
+                                    NULL, 0, 0, LUSTRE_OPC_ANY, NULL);
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));
 
@@ -4731,7 +4712,7 @@ static int ll_merge_md_attr(struct inode *inode)
                RETURN(0);
 
        down_read(&lli->lli_lsm_sem);
-       rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md,
+       rc = md_merge_attr(ll_i2mdexp(inode), &lli->lli_fid, lli->lli_lsm_md,
                           &attr, ll_md_blocking_ast);
        up_read(&lli->lli_lsm_sem);
        if (rc != 0)
@@ -4748,14 +4729,29 @@ 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)
 {
        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);
@@ -4763,10 +4759,36 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat)
        if (S_ISREG(inode->i_mode)) {
                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.
@@ -4774,7 +4796,7 @@ 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 (!ll_file_test_flag(lli, LLIF_FILE_RESTORING)) {
                        rc = ll_glimpse_size(inode);
                        if (rc < 0)
                                RETURN(rc);
@@ -4787,11 +4809,15 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat)
                                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)) {
@@ -4810,12 +4836,39 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat)
        stat->atime = inode->i_atime;
        stat->mtime = inode->i_mtime;
        stat->ctime = inode->i_ctime;
-       stat->blksize = sbi->ll_stat_blksize ?: 1 << inode->i_blkbits;
+       /* stat->blksize is used to tell about preferred IO size */
+       if (sbi->ll_stat_blksize)
+               stat->blksize = sbi->ll_stat_blksize;
+       else if (S_ISREG(inode->i_mode))
+               stat->blksize = 1 << min(PTLRPC_MAX_BRW_BITS + 1,
+                                        LL_MAX_BLKSIZE_BITS);
+       else
+               stat->blksize = 1 << inode->i_sb->s_blocksize_bits;
 
        stat->nlink = inode->i_nlink;
        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));
 
@@ -4826,12 +4879,92 @@ 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);
+}
 #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);
+}
 #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;
+
+       /*
+        * 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);
+
+       RETURN(rc);
 }
 
 static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
@@ -4956,19 +5089,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 (inode == inode->i_sb->s_root->d_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);
@@ -4995,7 +5131,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);
@@ -5037,7 +5173,8 @@ struct file_operations ll_file_operations = {
        .llseek         = ll_file_seek,
        .splice_read    = ll_file_splice_read,
        .fsync          = ll_fsync,
-       .flush          = ll_flush
+       .flush          = ll_flush,
+       .fallocate      = ll_fallocate,
 };
 
 struct file_operations ll_file_operations_flock = {
@@ -5063,7 +5200,8 @@ struct file_operations ll_file_operations_flock = {
        .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 */
@@ -5090,7 +5228,8 @@ struct file_operations ll_file_operations_noflock = {
        .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 = {
@@ -5104,9 +5243,7 @@ struct inode_operations ll_file_inode_operations = {
 #endif
        .listxattr      = ll_listxattr,
        .fiemap         = ll_fiemap,
-#ifdef HAVE_IOP_GET_ACL
        .get_acl        = ll_get_acl,
-#endif
 #ifdef HAVE_IOP_SET_ACL
        .set_acl        = ll_set_acl,
 #endif