X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Flclient%2Fglimpse.c;h=3bf726173b98f54910aaa66c1f3d581700f53414;hb=593b6ab6d21976d37004621b86f37715df697e9e;hp=268f5d7d36e247dc8e3a0920de6a376a04854333;hpb=15ac26cb2fc0b9b4c6c4507d8cdab683b9b40b7e;p=fs%2Flustre-release.git diff --git a/lustre/lclient/glimpse.c b/lustre/lclient/glimpse.c index 268f5d7..3bf7261 100644 --- a/lustre/lclient/glimpse.c +++ b/lustre/lclient/glimpse.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -28,6 +26,8 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2011, 2013, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -77,8 +77,32 @@ static const struct cl_lock_descr whole_file = { .cld_mode = CLM_READ }; +/* + * Check whether file has possible unwriten pages. + * + * \retval 1 file is mmap-ed or has dirty pages + * 0 otherwise + */ +blkcnt_t dirty_cnt(struct inode *inode) +{ + blkcnt_t cnt = 0; +#ifdef __KERNEL__ + struct ccc_object *vob = cl_inode2ccc(inode); + void *results[1]; + + if (inode->i_mapping != NULL) + cnt += radix_tree_gang_lookup_tag(&inode->i_mapping->page_tree, + results, 0, 1, + PAGECACHE_TAG_DIRTY); + if (cnt == 0 && atomic_read(&vob->cob_mmap_cnt) > 0) + cnt = 1; + +#endif + return (cnt > 0) ? 1 : 0; +} + int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, - struct inode *inode, struct cl_object *clob) + struct inode *inode, struct cl_object *clob, int agl) { struct cl_lock_descr *descr = &ccc_env_info(env)->cti_descr; struct cl_inode_info *lli = cl_i2info(inode); @@ -91,7 +115,7 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, result = 0; if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) { CDEBUG(D_DLMTRACE, "Glimpsing inode "DFID"\n", PFID(fid)); - if (lli->lli_smd) { + if (lli->lli_has_smd) { /* NOTE: this looks like DLM lock request, but it may * not be one. Due to CEF_ASYNC flag (translated * to LDLM_FL_HAS_INTENT by osc), this is @@ -109,33 +133,51 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, descr->cld_obj = clob; descr->cld_mode = CLM_PHANTOM; descr->cld_enq_flags = CEF_ASYNC | CEF_MUST; + if (agl) + descr->cld_enq_flags |= CEF_AGL; cio->cui_glimpse = 1; - /* - * CEF_ASYNC is used because glimpse sub-locks cannot - * deadlock (because they never conflict with other - * locks) and, hence, can be enqueued out-of-order. - * - * CEF_MUST protects glimpse lock from conversion into - * a lockless mode. - */ - lock = cl_lock_request(env, io, descr, "glimpse", - cfs_current()); - cio->cui_glimpse = 0; - if (!IS_ERR(lock)) { - result = cl_wait(env, lock); - if (result == 0) { - cl_merge_lvb(inode); - cl_unuse(env, lock); - } - cl_lock_release(env, lock, - "glimpse", cfs_current()); - } else - result = PTR_ERR(lock); - } else - CDEBUG(D_DLMTRACE, "No objects for inode\n"); - } + /* + * CEF_ASYNC is used because glimpse sub-locks cannot + * deadlock (because they never conflict with other + * locks) and, hence, can be enqueued out-of-order. + * + * CEF_MUST protects glimpse lock from conversion into + * a lockless mode. + */ + lock = cl_lock_request(env, io, descr, "glimpse", + current); + cio->cui_glimpse = 0; + + if (lock == NULL) + RETURN(0); + + if (IS_ERR(lock)) + RETURN(PTR_ERR(lock)); - RETURN(result); + LASSERT(agl == 0); + result = cl_wait(env, lock); + if (result == 0) { + cl_merge_lvb(env, inode); + if (cl_isize_read(inode) > 0 && + inode->i_blocks == 0) { + /* + * LU-417: Add dirty pages block count + * lest i_blocks reports 0, some "cp" or + * "tar" may think it's a completely + * sparse file and skip it. + */ + inode->i_blocks = dirty_cnt(inode); + } + cl_unuse(env, lock); + } + cl_lock_release(env, lock, "glimpse", current); + } else { + CDEBUG(D_DLMTRACE, "No objects for inode\n"); + cl_merge_lvb(env, inode); + } + } + + RETURN(result); } static int cl_io_get(struct inode *inode, struct lu_env **envout, @@ -162,7 +204,7 @@ static int cl_io_get(struct inode *inode, struct lu_env **envout, return result; } -int cl_glimpse_size(struct inode *inode) +int cl_glimpse_size0(struct inode *inode, int agl) { /* * We don't need ast_flags argument to cl_glimpse_size(), because @@ -174,8 +216,8 @@ int cl_glimpse_size(struct inode *inode) * cl_glimpse_size(), which doesn't make sense: glimpse locks are not * blocking anyway. */ - struct lu_env *env; - struct cl_io *io; + struct lu_env *env = NULL; + struct cl_io *io = NULL; int result; int refcheck; @@ -183,6 +225,8 @@ int cl_glimpse_size(struct inode *inode) result = cl_io_get(inode, &env, &io, &refcheck); if (result > 0) { + again: + io->ci_verify_layout = 1; result = cl_io_init(env, io, CIT_MISC, io->ci_obj); if (result > 0) /* @@ -191,17 +235,22 @@ int cl_glimpse_size(struct inode *inode) */ result = io->ci_result; else if (result == 0) - result = cl_glimpse_lock(env, io, inode, io->ci_obj); + result = cl_glimpse_lock(env, io, inode, io->ci_obj, + agl); + + OBD_FAIL_TIMEOUT(OBD_FAIL_GLIMPSE_DELAY, 2); cl_io_fini(env, io); - cl_env_put(env, &refcheck); - } - RETURN(result); + if (unlikely(io->ci_need_restart)) + goto again; + cl_env_put(env, &refcheck); + } + RETURN(result); } int cl_local_size(struct inode *inode) { - struct lu_env *env; - struct cl_io *io; + struct lu_env *env = NULL; + struct cl_io *io = NULL; struct ccc_thread_info *cti; struct cl_object *clob; struct cl_lock_descr *descr; @@ -211,7 +260,7 @@ int cl_local_size(struct inode *inode) ENTRY; - if (!cl_i2info(inode)->lli_smd) + if (!cl_i2info(inode)->lli_has_smd) RETURN(0); result = cl_io_get(inode, &env, &io, &refcheck); @@ -222,23 +271,23 @@ int cl_local_size(struct inode *inode) result = cl_io_init(env, io, CIT_MISC, clob); if (result > 0) result = io->ci_result; - else if (result == 0) { - cti = ccc_env_info(env); - descr = &cti->cti_descr; - - *descr = whole_file; - descr->cld_obj = clob; - lock = cl_lock_peek(env, io, descr, "localsize", cfs_current()); - if (lock != NULL) { - cl_merge_lvb(inode); - cl_unuse(env, lock); - cl_lock_release(env, lock, "localsize", cfs_current()); - result = 0; - } else - result = -ENODATA; - } - cl_io_fini(env, io); - cl_env_put(env, &refcheck); - RETURN(result); + else if (result == 0) { + cti = ccc_env_info(env); + descr = &cti->cti_descr; + + *descr = whole_file; + descr->cld_obj = clob; + lock = cl_lock_peek(env, io, descr, "localsize", current); + if (lock != NULL) { + cl_merge_lvb(env, inode); + cl_unuse(env, lock); + cl_lock_release(env, lock, "localsize", current); + result = 0; + } else + result = -ENODATA; + } + cl_io_fini(env, io); + cl_env_put(env, &refcheck); + RETURN(result); }