- ENTRY;
-
- einfo.ei_type = LDLM_EXTENT;
- einfo.ei_mode = LCK_PR;
- einfo.ei_cb_bl = osc_extent_blocking_cb;
- einfo.ei_cb_cp = ldlm_completion_ast;
- einfo.ei_cb_gl = ll_glimpse_callback;
- einfo.ei_cbdata = NULL;
-
- oinfo.oi_policy.l_extent.end = OBD_OBJECT_EOF;
- oinfo.oi_lockh = &lockh;
- oinfo.oi_md = lsm;
- oinfo.oi_flags = LDLM_FL_HAS_INTENT;
-
- rc = obd_enqueue_rqset(sbi->ll_dt_exp, &oinfo, &einfo);
- if (rc == -ENOENT)
- RETURN(rc);
- if (rc != 0) {
- CERROR("obd_enqueue returned rc %d, "
- "returning -EIO\n", rc);
- RETURN(rc > 0 ? -EIO : rc);
- }
-
- lov_stripe_lock(lsm);
- memset(&lvb, 0, sizeof(lvb));
- obd_merge_lvb(sbi->ll_dt_exp, lsm, &lvb, 0);
- st->st_size = lvb.lvb_size;
- st->st_blocks = lvb.lvb_blocks;
- st->st_mtime = lvb.lvb_mtime;
- st->st_atime = lvb.lvb_atime;
- st->st_ctime = lvb.lvb_ctime;
- lov_stripe_unlock(lsm);
-
- RETURN(rc);
-}
-
-/* NB: obd_merge_lvb will prefer locally cached writes if they extend the
- * file (because it prefers KMS over RSS when larger) */
-int ll_glimpse_size(struct inode *inode, int ast_flags)
-{
- struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct lustre_handle lockh = { 0 };
- struct ldlm_enqueue_info einfo = { 0 };
- struct obd_info oinfo = { { { 0 } } };
- int rc;
- ENTRY;
-
- if (lli->lli_flags & LLIF_MDS_SIZE_LOCK)
- RETURN(0);
-
- CDEBUG(D_DLMTRACE, "Glimpsing inode %lu\n", inode->i_ino);
-
- if (!lli->lli_smd) {
- CDEBUG(D_DLMTRACE, "No objects for inode %lu\n", inode->i_ino);
- RETURN(0);
- }
-
- /* NOTE: this looks like DLM lock request, but it may not be one. Due
- * to LDLM_FL_HAS_INTENT flag, this is glimpse request, that
- * won't revoke any conflicting DLM locks held. Instead,
- * ll_glimpse_callback() will be called on each client
- * holding a DLM lock against this file, and resulting size
- * will be returned for each stripe. DLM lock on [0, EOF] is
- * acquired only if there were no conflicting locks. */
- einfo.ei_type = LDLM_EXTENT;
- einfo.ei_mode = LCK_PR;
- einfo.ei_cb_bl = osc_extent_blocking_cb;
- einfo.ei_cb_cp = ldlm_completion_ast;
- einfo.ei_cb_gl = ll_glimpse_callback;
- einfo.ei_cbdata = inode;
-
- oinfo.oi_policy.l_extent.end = OBD_OBJECT_EOF;
- oinfo.oi_lockh = &lockh;
- oinfo.oi_md = lli->lli_smd;
- oinfo.oi_flags = ast_flags | LDLM_FL_HAS_INTENT;
-
- rc = obd_enqueue_rqset(sbi->ll_dt_exp, &oinfo, &einfo);
- if (rc == -ENOENT)
- RETURN(rc);
- if (rc != 0) {
- CERROR("obd_enqueue returned rc %d, returning -EIO\n", rc);
- RETURN(rc > 0 ? -EIO : rc);
- }
-
- rc = ll_merge_lvb(inode);
-
- CDEBUG(D_DLMTRACE, "glimpse: size: %llu, blocks: %llu\n",
- i_size_read(inode), (unsigned long long)inode->i_blocks);
-
- RETURN(rc);
-}
-
-int ll_extent_lock(struct ll_file_data *fd, struct inode *inode,
- struct lov_stripe_md *lsm, int mode,
- ldlm_policy_data_t *policy, struct lustre_handle *lockh,
- int ast_flags)
-{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ost_lvb lvb;
- struct ldlm_enqueue_info einfo = { 0 };
- struct obd_info oinfo = { { { 0 } } };
- int rc;
- ENTRY;
-
- LASSERT(!lustre_handle_is_used(lockh));
- LASSERT(lsm != NULL);
-
- /* don't drop the mmapped file to LRU */
- if (mapping_mapped(inode->i_mapping))
- ast_flags |= LDLM_FL_NO_LRU;
-
- /* XXX phil: can we do this? won't it screw the file size up? */
- if ((fd && (fd->fd_flags & LL_FILE_IGNORE_LOCK)) ||
- (sbi->ll_flags & LL_SBI_NOLCK))
- RETURN(0);
-
- CDEBUG(D_DLMTRACE, "Locking inode %lu, start "LPU64" end "LPU64"\n",
- inode->i_ino, policy->l_extent.start, policy->l_extent.end);
-
- einfo.ei_type = LDLM_EXTENT;
- einfo.ei_mode = mode;
- einfo.ei_cb_bl = osc_extent_blocking_cb;
- einfo.ei_cb_cp = ldlm_completion_ast;
- einfo.ei_cb_gl = ll_glimpse_callback;
- einfo.ei_cbdata = inode;
-
- oinfo.oi_policy = *policy;
- oinfo.oi_lockh = lockh;
- oinfo.oi_md = lsm;
- oinfo.oi_flags = ast_flags;
-
- rc = obd_enqueue(sbi->ll_dt_exp, &oinfo, &einfo, NULL);
- *policy = oinfo.oi_policy;
- if (rc > 0)
- rc = -EIO;
-
- ll_inode_size_lock(inode, 1);
- inode_init_lvb(inode, &lvb);
- obd_merge_lvb(sbi->ll_dt_exp, lsm, &lvb, 1);
-
- if (policy->l_extent.start == 0 &&
- policy->l_extent.end == OBD_OBJECT_EOF) {
- /* vmtruncate()->ll_truncate() first sets the i_size and then
- * the kms under both a DLM lock and the
- * ll_inode_size_lock(). If we don't get the
- * ll_inode_size_lock() here we can match the DLM lock and
- * reset i_size from the kms before the truncating path has
- * updated the kms. generic_file_write can then trust the
- * stale i_size when doing appending writes and effectively
- * cancel the result of the truncate. Getting the
- * ll_inode_size_lock() after the enqueue maintains the DLM
- * -> ll_inode_size_lock() acquiring order. */
- i_size_write(inode, lvb.lvb_size);
- CDEBUG(D_INODE, "inode=%lu, updating i_size %llu\n",
- inode->i_ino, i_size_read(inode));
- }
-