Whamcloud - gitweb
LU-13799 llite: Adjust dio refcounting
[fs/lustre-release.git] / lustre / llite / llite_lib.c
index 335f0d8..e20a0c7 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  *
  * lustre/llite/llite_lib.c
  *
@@ -48,7 +47,6 @@
 #include <linux/user_namespace.h>
 #include <linux/delay.h>
 #include <linux/uidgid.h>
-#include <linux/security.h>
 #include <linux/fs_struct.h>
 
 #ifndef HAVE_CPUS_READ_LOCK
@@ -189,6 +187,7 @@ static struct ll_sb_info *ll_init_sbi(void)
        sbi->ll_flags |= LL_SBI_AGL_ENABLED;
        sbi->ll_flags |= LL_SBI_FAST_READ;
        sbi->ll_flags |= LL_SBI_TINY_WRITE;
+       sbi->ll_flags |= LL_SBI_PARALLEL_DIO;
        ll_sbi_set_encrypt(sbi, true);
 
        /* root squash */
@@ -200,6 +199,11 @@ static struct ll_sb_info *ll_init_sbi(void)
        /* Per-filesystem file heat */
        sbi->ll_heat_decay_weight = SBI_DEFAULT_HEAT_DECAY_WEIGHT;
        sbi->ll_heat_period_second = SBI_DEFAULT_HEAT_PERIOD_SECOND;
+
+       /* Per-fs open heat level before requesting open lock */
+       sbi->ll_oc_thrsh_count = SBI_DEFAULT_OPENCACHE_THRESHOLD_COUNT;
+       sbi->ll_oc_max_ms = SBI_DEFAULT_OPENCACHE_THRESHOLD_MAX_MS;
+       sbi->ll_oc_thrsh_ms = SBI_DEFAULT_OPENCACHE_THRESHOLD_MS;
        RETURN(sbi);
 out_destroy_ra:
        if (sbi->ll_foreign_symlink_prefix)
@@ -332,7 +336,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
                                   OBD_CONNECT2_PCC |
                                   OBD_CONNECT2_CRUSH | OBD_CONNECT2_LSEEK |
                                   OBD_CONNECT2_GETATTR_PFID |
-                                  OBD_CONNECT2_DOM_LVB;
+                                  OBD_CONNECT2_DOM_LVB |
+                                  OBD_CONNECT2_REP_MBITS |
+                                  OBD_CONNECT2_ATOMIC_OPEN_LOCK;
 
 #ifdef HAVE_LRU_RESIZE_SUPPORT
         if (sbi->ll_flags & LL_SBI_LRU_RESIZE)
@@ -361,13 +367,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
         */
        sb->s_flags |= SB_NOSEC;
 #endif
-
-       if (sbi->ll_flags & LL_SBI_FLOCK)
-               sbi->ll_fop = &ll_file_operations_flock;
-       else if (sbi->ll_flags & LL_SBI_LOCALFLOCK)
-               sbi->ll_fop = &ll_file_operations;
-       else
-               sbi->ll_fop = &ll_file_operations_noflock;
+       sbi->ll_fop = ll_select_file_operations(sbi);
 
        /* always ping even if server suppress_pings */
        if (sbi->ll_flags & LL_SBI_ALWAYS_PING)
@@ -530,7 +530,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
                                  OBD_CONNECT_BULK_MBITS | OBD_CONNECT_SHORTIO |
                                  OBD_CONNECT_FLAGS2 | OBD_CONNECT_GRANT_SHRINK;
        data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD |
-                                  OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK;
+                                  OBD_CONNECT2_INC_XID | OBD_CONNECT2_LSEEK |
+                                  OBD_CONNECT2_REP_MBITS;
 
        if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_GRANT_PARAM))
                data->ocd_connect_flags |= OBD_CONNECT_GRANT_PARAM;
@@ -664,8 +665,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
                GOTO(out_lock_cn_cb, err);
        }
 
-       err = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp,
-                              sbi->ll_md_exp, &lmd);
+       err = md_get_lustre_md(sbi->ll_md_exp, &request->rq_pill,
+                              sbi->ll_dt_exp, sbi->ll_md_exp, &lmd);
        if (err) {
                CERROR("failed to understand root inode md: rc = %d\n", err);
                ptlrpc_req_finished(request);
@@ -749,8 +750,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
 
        RETURN(err);
 out_root:
-       if (root)
-               iput(root);
+       iput(root);
 out_lock_cn_cb:
        obd_fid_fini(sbi->ll_dt_exp->exp_obd);
 out_dt:
@@ -1223,6 +1223,8 @@ int ll_fill_super(struct super_block *sb)
        CDEBUG(D_VFSTRACE, "VFS Op: cfg_instance %s-%016lx (sb %p)\n",
               profilenm, cfg_instance, sb);
 
+       OBD_RACE(OBD_FAIL_LLITE_RACE_MOUNT);
+
        OBD_ALLOC_PTR(cfg);
        if (cfg == NULL)
                GOTO(out_free_cfg, err = -ENOMEM);
@@ -1429,8 +1431,6 @@ out_no_sbi:
 
        cl_env_cache_purge(~0);
 
-       module_put(THIS_MODULE);
-
        EXIT;
 } /* client_put_super */
 
@@ -1480,12 +1480,15 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb,
                                      const struct lu_fid *fid,
                                      struct lustre_md *md)
 {
-       struct ll_sb_info       *sbi = ll_s2sbi(sb);
-       struct mdt_body         *body = md->body;
-       struct inode            *inode;
-       ino_t                   ino;
+       struct ll_sb_info *sbi = ll_s2sbi(sb);
+       struct ll_inode_info *lli;
+       struct mdt_body *body = md->body;
+       struct inode *inode;
+       ino_t ino;
+
        ENTRY;
 
+       LASSERT(md->lmv);
        ino = cl_fid_build_ino(fid, sbi->ll_flags & LL_SBI_32BIT_API);
        inode = iget_locked(sb, ino);
        if (inode == NULL) {
@@ -1494,10 +1497,8 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb,
                RETURN(ERR_PTR(-ENOENT));
        }
 
+       lli = ll_i2info(inode);
        if (inode->i_state & I_NEW) {
-               struct ll_inode_info *lli = ll_i2info(inode);
-               struct lmv_stripe_md *lsm = md->lmv;
-
                inode->i_mode = (inode->i_mode & ~S_IFMT) |
                                (body->mbo_mode & S_IFMT);
                LASSERTF(S_ISDIR(inode->i_mode), "Not slave inode "DFID"\n",
@@ -1518,12 +1519,17 @@ static struct inode *ll_iget_anon_dir(struct super_block *sb,
                lli->lli_fid = *fid;
                ll_lli_init(lli);
 
-               LASSERT(lsm != NULL);
                /* master object FID */
                lli->lli_pfid = body->mbo_fid1;
                CDEBUG(D_INODE, "lli %p slave "DFID" master "DFID"\n",
                       lli, PFID(fid), PFID(&lli->lli_pfid));
                unlock_new_inode(inode);
+       } else {
+               /* in directory restripe/auto-split, a directory will be
+                * transformed to a stripe if it's plain, set its pfid here,
+                * otherwise ll_lock_cancel_bits() can't find the master inode.
+                */
+               lli->lli_pfid = body->mbo_fid1;
        }
 
        RETURN(inode);
@@ -1592,30 +1598,27 @@ static void ll_update_default_lsm_md(struct inode *inode, struct lustre_md *md)
                        }
                        up_write(&lli->lli_lsm_sem);
                }
-       } else if (lli->lli_default_lsm_md) {
-               /* update default lsm if it changes */
+               return;
+       }
+
+       if (lli->lli_default_lsm_md) {
+               /* do nonthing if default lsm isn't changed */
                down_read(&lli->lli_lsm_sem);
                if (lli->lli_default_lsm_md &&
-                   !lsm_md_eq(lli->lli_default_lsm_md, md->default_lmv)) {
-                       up_read(&lli->lli_lsm_sem);
-                       down_write(&lli->lli_lsm_sem);
-                       if (lli->lli_default_lsm_md)
-                               lmv_free_memmd(lli->lli_default_lsm_md);
-                       lli->lli_default_lsm_md = md->default_lmv;
-                       lsm_md_dump(D_INODE, md->default_lmv);
-                       md->default_lmv = NULL;
-                       up_write(&lli->lli_lsm_sem);
-               } else {
+                   lsm_md_eq(lli->lli_default_lsm_md, md->default_lmv)) {
                        up_read(&lli->lli_lsm_sem);
+                       return;
                }
-       } else {
-               /* init default lsm */
-               down_write(&lli->lli_lsm_sem);
-               lli->lli_default_lsm_md = md->default_lmv;
-               lsm_md_dump(D_INODE, md->default_lmv);
-               md->default_lmv = NULL;
-               up_write(&lli->lli_lsm_sem);
+               up_read(&lli->lli_lsm_sem);
        }
+
+       down_write(&lli->lli_lsm_sem);
+       if (lli->lli_default_lsm_md)
+               lmv_free_memmd(lli->lli_default_lsm_md);
+       lli->lli_default_lsm_md = md->default_lmv;
+       lsm_md_dump(D_INODE, md->default_lmv);
+       md->default_lmv = NULL;
+       up_write(&lli->lli_lsm_sem);
 }
 
 static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
@@ -1635,6 +1638,12 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md)
        if (md->default_lmv)
                ll_update_default_lsm_md(inode, md);
 
+       /* after dir migration/restripe, a stripe may be turned into a
+        * directory, in this case, zero out its lli_pfid.
+        */
+       if (unlikely(fid_is_norm(&lli->lli_pfid)))
+               fid_zero(&lli->lli_pfid);
+
        /*
         * no striped information from request, lustre_md from req does not
         * include stripeEA, see ll_md_setattr()
@@ -1817,8 +1826,8 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data)
                RETURN(rc);
        }
 
-        rc = md_get_lustre_md(sbi->ll_md_exp, request, sbi->ll_dt_exp,
-                              sbi->ll_md_exp, &md);
+       rc = md_get_lustre_md(sbi->ll_md_exp, &request->rq_pill, sbi->ll_dt_exp,
+                             sbi->ll_md_exp, &md);
         if (rc) {
                 ptlrpc_req_finished(request);
                 RETURN(rc);
@@ -1961,7 +1970,7 @@ int ll_io_zero_page(struct inode *inode, pgoff_t index, pgoff_t offset,
                anchor = &vvp_env_info(env)->vti_anchor;
                cl_sync_io_init(anchor, 1);
                clpage->cp_sync_io = anchor;
-               cl_2queue_add(queue, clpage);
+               cl_2queue_add(queue, clpage, true);
                rc = cl_io_submit_rw(env, io, CRT_WRITE, queue);
                if (rc)
                        GOTO(queuefini1, rc);
@@ -2051,7 +2060,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr,
        /* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */
        if (attr->ia_valid & TIMES_SET_FLAGS) {
                if ((!uid_eq(current_fsuid(), inode->i_uid)) &&
-                   !cfs_capable(CAP_FOWNER))
+                   !capable(CAP_FOWNER))
                        RETURN(-EPERM);
        }
 
@@ -2093,7 +2102,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr,
                 */
                xvalid |= OP_XVALID_OWNEROVERRIDE;
                op_data->op_bias |= MDS_DATA_MODIFIED;
-               ll_file_clear_flag(lli, LLIF_DATA_MODIFIED);
+               clear_bit(LLIF_DATA_MODIFIED, &lli->lli_flags);
        }
 
        if (attr->ia_valid & ATTR_FILE) {
@@ -2138,8 +2147,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr,
                         * it is necessary due to possible time
                         * de-synchronization between MDT inode and OST objects
                         */
-                       if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode) &&
-                           attr->ia_valid & ATTR_SIZE) {
+                       if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) {
                                xvalid |= OP_XVALID_FLAGS;
                                flags = LUSTRE_ENCRYPT_FL;
                                /* Call to ll_io_zero_page is not necessary if
@@ -2148,7 +2156,8 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr,
                                 * In case of Direct IO, all we need is to set
                                 * new size.
                                 */
-                               if (attr->ia_size & ~PAGE_MASK &&
+                               if (attr->ia_valid & ATTR_SIZE &&
+                                   attr->ia_size & ~PAGE_MASK &&
                                    !(attr->ia_valid & ATTR_FILE &&
                                      attr->ia_file->f_flags & O_DIRECT)) {
                                        pgoff_t offset =
@@ -2178,7 +2187,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr,
         * LLIF_DATA_MODIFIED is not set(see vvp_io_setattr_fini()).
         * This way we can save an RPC for common open + trunc
         * operation. */
-       if (ll_file_test_and_clear_flag(lli, LLIF_DATA_MODIFIED)) {
+       if (test_and_clear_bit(LLIF_DATA_MODIFIED, &lli->lli_flags)) {
                struct hsm_state_set hss = {
                        .hss_valid = HSS_SETMASK,
                        .hss_setmask = HS_DIRTY,
@@ -2419,15 +2428,15 @@ void ll_inode_size_unlock(struct inode *inode)
        mutex_unlock(&lli->lli_size_mutex);
 }
 
-void ll_update_inode_flags(struct inode *inode, int ext_flags)
+void ll_update_inode_flags(struct inode *inode, unsigned int ext_flags)
 {
        /* do not clear encryption flag */
        ext_flags |= ll_inode_to_ext_flags(inode->i_flags) & LUSTRE_ENCRYPT_FL;
        inode->i_flags = ll_ext_to_inode_flags(ext_flags);
        if (ext_flags & LUSTRE_PROJINHERIT_FL)
-               ll_file_set_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT);
+               set_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags);
        else
-               ll_file_clear_flag(ll_i2info(inode), LLIF_PROJECT_INHERIT);
+               clear_bit(LLIF_PROJECT_INHERIT, &ll_i2info(inode)->lli_flags);
 }
 
 int ll_update_inode(struct inode *inode, struct lustre_md *md)
@@ -2543,14 +2552,42 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md)
                 * glimpsing updated attrs
                 */
                if (body->mbo_t_state & MS_RESTORE)
-                       ll_file_set_flag(lli, LLIF_FILE_RESTORING);
+                       set_bit(LLIF_FILE_RESTORING, &lli->lli_flags);
                else
-                       ll_file_clear_flag(lli, LLIF_FILE_RESTORING);
+                       clear_bit(LLIF_FILE_RESTORING, &lli->lli_flags);
        }
 
        return 0;
 }
 
+void ll_truncate_inode_pages_final(struct inode *inode)
+{
+       struct address_space *mapping = &inode->i_data;
+       unsigned long nrpages;
+       unsigned long flags;
+
+       truncate_inode_pages_final(mapping);
+
+       /* Workaround for LU-118: Note nrpages may not be totally updated when
+        * truncate_inode_pages() returns, as there can be a page in the process
+        * of deletion (inside __delete_from_page_cache()) in the specified
+        * range. Thus mapping->nrpages can be non-zero when this function
+        * returns even after truncation of the whole mapping.  Only do this if
+        * npages isn't already zero.
+        */
+       nrpages = mapping->nrpages;
+       if (nrpages) {
+               ll_xa_lock_irqsave(&mapping->i_pages, flags);
+               nrpages = mapping->nrpages;
+               ll_xa_unlock_irqrestore(&mapping->i_pages, flags);
+       } /* Workaround end */
+
+       LASSERTF(nrpages == 0, "%s: inode="DFID"(%p) nrpages=%lu, "
+                "see https://jira.whamcloud.com/browse/LU-118\n",
+                ll_i2sbi(inode)->ll_fsname,
+                PFID(ll_inode2fid(inode)), inode, nrpages);
+}
+
 int ll_read_inode2(struct inode *inode, void *opaque)
 {
         struct lustre_md *md = opaque;
@@ -2608,10 +2645,6 @@ int ll_read_inode2(struct inode *inode, void *opaque)
 void ll_delete_inode(struct inode *inode)
 {
        struct ll_inode_info *lli = ll_i2info(inode);
-       struct address_space *mapping = &inode->i_data;
-       unsigned long nrpages;
-       unsigned long flags;
-
        ENTRY;
 
        if (S_ISREG(inode->i_mode) && lli->lli_clob != NULL) {
@@ -2625,27 +2658,8 @@ void ll_delete_inode(struct inode *inode)
                cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, inode->i_nlink ?
                                   CL_FSYNC_LOCAL : CL_FSYNC_DISCARD, 1);
        }
-       truncate_inode_pages_final(mapping);
-
-       /* Workaround for LU-118: Note nrpages may not be totally updated when
-        * truncate_inode_pages() returns, as there can be a page in the process
-        * of deletion (inside __delete_from_page_cache()) in the specified
-        * range. Thus mapping->nrpages can be non-zero when this function
-        * returns even after truncation of the whole mapping.  Only do this if
-        * npages isn't already zero.
-        */
-       nrpages = mapping->nrpages;
-       if (nrpages) {
-               ll_xa_lock_irqsave(&mapping->i_pages, flags);
-               nrpages = mapping->nrpages;
-               ll_xa_unlock_irqrestore(&mapping->i_pages, flags);
-       } /* Workaround end */
-
-       LASSERTF(nrpages == 0, "%s: inode="DFID"(%p) nrpages=%lu, "
-                "see https://jira.whamcloud.com/browse/LU-118\n",
-                ll_i2sbi(inode)->ll_fsname,
-                PFID(ll_inode2fid(inode)), inode, nrpages);
 
+       ll_truncate_inode_pages_final(inode);
        ll_clear_inode(inode);
        clear_inode(inode);
 
@@ -2702,7 +2716,8 @@ int ll_iocontrol(struct inode *inode, struct file *file,
                if (flags & LUSTRE_PROJINHERIT_FL)
                        fa.fsx_xflags = FS_XFLAG_PROJINHERIT;
 
-               rc = ll_ioctl_check_project(inode, &fa);
+               rc = ll_ioctl_check_project(inode, fa.fsx_xflags,
+                                           fa.fsx_projid);
                if (rc)
                        RETURN(rc);
 
@@ -2859,7 +2874,7 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data)
  * \param[in] sb       super block for this file-system
  * \param[in] open_req pointer to the original open request
  */
-void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req)
+void ll_open_cleanup(struct super_block *sb, struct req_capsule *pill)
 {
        struct mdt_body                 *body;
        struct md_op_data               *op_data;
@@ -2867,7 +2882,7 @@ void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req)
        struct obd_export               *exp       = ll_s2sbi(sb)->ll_md_exp;
        ENTRY;
 
-       body = req_capsule_server_get(&open_req->rq_pill, &RMF_MDT_BODY);
+       body = req_capsule_server_get(pill, &RMF_MDT_BODY);
        OBD_ALLOC_PTR(op_data);
        if (op_data == NULL) {
                CWARN("%s: cannot allocate op_data to release open handle for "
@@ -2886,7 +2901,7 @@ void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req)
        EXIT;
 }
 
-int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
+int ll_prep_inode(struct inode **inode, struct req_capsule *pill,
                  struct super_block *sb, struct lookup_intent *it)
 {
        struct ll_sb_info *sbi = NULL;
@@ -2898,7 +2913,7 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
 
        LASSERT(*inode || sb);
        sbi = sb ? ll_s2sbi(sb) : ll_i2sbi(*inode);
-       rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp,
+       rc = md_get_lustre_md(sbi->ll_md_exp, pill, sbi->ll_dt_exp,
                              sbi->ll_md_exp, &md);
        if (rc != 0)
                GOTO(out, rc);
@@ -2988,7 +3003,7 @@ out:
 
        if (rc != 0 && it != NULL && it->it_op & IT_OPEN) {
                ll_intent_drop_lock(it);
-               ll_open_cleanup(sb != NULL ? sb : (*inode)->i_sb, req);
+               ll_open_cleanup(sb != NULL ? sb : (*inode)->i_sb, pill);
        }
 
        return rc;
@@ -3137,8 +3152,8 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data,
 void ll_finish_md_op_data(struct md_op_data *op_data)
 {
        ll_unlock_md_op_lsm(op_data);
-       security_release_secctx(op_data->op_file_secctx,
-                               op_data->op_file_secctx_size);
+       ll_security_release_secctx(op_data->op_file_secctx,
+                                  op_data->op_file_secctx_size);
        llcrypt_free_ctx(op_data->op_file_encctx, op_data->op_file_encctx_size);
        OBD_FREE_PTR(op_data);
 }
@@ -3201,7 +3216,7 @@ int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg)
         struct obd_device *obd;
         ENTRY;
 
-        if (cmd == OBD_IOC_GETDTNAME)
+       if (cmd == OBD_IOC_GETNAME_OLD || cmd == OBD_IOC_GETDTNAME)
                 obd = class_exp2obd(sbi->ll_dt_exp);
         else if (cmd == OBD_IOC_GETMDNAME)
                 obd = class_exp2obd(sbi->ll_md_exp);
@@ -3391,7 +3406,7 @@ int ll_getparent(struct file *file, struct getparent __user *arg)
 
        ENTRY;
 
-       if (!cfs_capable(CAP_DAC_READ_SEARCH) &&
+       if (!capable(CAP_DAC_READ_SEARCH) &&
            !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH))
                RETURN(-EPERM);