From: Jinshan Xiong Date: Fri, 14 Jul 2017 23:22:46 +0000 (-0700) Subject: LU-9771 clio: no glimpse for data immutable file X-Git-Tag: 2.10.56~9^2^2~27 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=ce61bcac8661e08ffa2a6ec4b9782f11cd3388c6;p=fs%2Flustre-release.git LU-9771 clio: no glimpse for data immutable file When merging a layout to an existing file as a mirror, client will report the size and blocks to the MDT, which will be set to the MDT object. In that case, if the MDT discovers a mirrored file in READ_ONLY state, it will report the size and blocks. Clients should take this advantage and skip glimpse. Test-Parameters: testlist=sanity-flr Signed-off-by: Jinshan Xiong Change-Id: I60831689116e6c5dd0311dea62b91dd0ae3cfd56 Reviewed-on: https://review.whamcloud.com/29084 Tested-by: Jenkins Reviewed-by: Fan Yong Reviewed-by: Bobi Jam Tested-by: Maloo --- diff --git a/lustre/include/uapi/linux/lustre/lustre_idl.h b/lustre/include/uapi/linux/lustre/lustre_idl.h index eaf53bd..3e8f706 100644 --- a/lustre/include/uapi/linux/lustre/lustre_idl.h +++ b/lustre/include/uapi/linux/lustre/lustre_idl.h @@ -1093,6 +1093,7 @@ struct lov_mds_md_v1 { /* LOV EA mds/wire data (little-endian) */ #define XATTR_TRUSTED_PREFIX "trusted." #define XATTR_SECURITY_PREFIX "security." +#define XATTR_NAME_SOM "trusted.som" #define XATTR_NAME_LOV "trusted.lov" #define XATTR_NAME_LMA "trusted.lma" #define XATTR_NAME_LMV "trusted.lmv" diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index cf3c908..314cb97 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -274,6 +274,17 @@ struct lustre_ost_attrs { */ #define LMA_OLD_SIZE (sizeof(struct lustre_mdt_attrs) + 5 * sizeof(__u64)) +enum { + LSOM_FL_VALID = 1 << 0, +}; + +struct lustre_som_attrs { + __u16 lsa_valid; + __u16 lsa_reserved[3]; + __u64 lsa_size; + __u64 lsa_blocks; +}; + /** * OST object IDentifier. */ diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 701b647..7f43784d 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -145,6 +145,9 @@ static int ll_close_inode_openhandle(struct inode *inode, ll_prepare_close(inode, op_data, och); switch (bias) { case MDS_CLOSE_LAYOUT_MERGE: + /* merge blocks from the victim inode */ + op_data->op_attr_blocks += ((struct inode *)data)->i_blocks; + op_data->op_attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS; case MDS_CLOSE_LAYOUT_SWAP: LASSERT(data != NULL); op_data->op_bias |= bias; diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index 8cdfbf4..b100973 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -263,6 +263,13 @@ static int lov_io_slice_init(struct lov_io *lio, } case CIT_GLIMPSE: + lio->lis_pos = 0; + lio->lis_endpos = OBD_OBJECT_EOF; + + if ((obj->lo_lsm->lsm_flags & LCM_FL_FLR_MASK) == LCM_FL_RDONLY) + RETURN(1); /* SoM is accurate, no need glimpse */ + break; + case CIT_MISC: lio->lis_pos = 0; lio->lis_endpos = OBD_OBJECT_EOF; @@ -1127,21 +1134,23 @@ int lov_io_init_composite(const struct lu_env *env, struct cl_object *obj, { struct lov_io *lio = lov_env_io(env); struct lov_object *lov = cl2lov(obj); - + int result; ENTRY; + INIT_LIST_HEAD(&lio->lis_active); - io->ci_result = lov_io_slice_init(lio, lov, io); - if (io->ci_result != 0) - RETURN(io->ci_result); - - if (io->ci_result == 0) { - io->ci_result = lov_io_subio_init(env, lio, io); - if (io->ci_result == 0) { - cl_io_slice_add(io, &lio->lis_cl, obj, &lov_io_ops); - atomic_inc(&lov->lo_active_ios); - } + result = lov_io_slice_init(lio, lov, io); + if (result) + GOTO(out, result); + + result = lov_io_subio_init(env, lio, io); + if (!result) { + cl_io_slice_add(io, &lio->lis_cl, obj, &lov_io_ops); + atomic_inc(&lov->lo_active_ios); } - RETURN(io->ci_result); + EXIT; +out: + io->ci_result = result < 0 ? result : 0; + return result; } int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj, diff --git a/lustre/mdt/Makefile.in b/lustre/mdt/Makefile.in index 0165cfe..ec054d7 100644 --- a/lustre/mdt/Makefile.in +++ b/lustre/mdt/Makefile.in @@ -1,6 +1,6 @@ MODULES := mdt mdt-objs := mdt_handler.o mdt_lib.o mdt_reint.o mdt_xattr.o mdt_recovery.o -mdt-objs += mdt_open.o mdt_identity.o mdt_lproc.o mdt_fs.o +mdt-objs += mdt_open.o mdt_identity.o mdt_lproc.o mdt_fs.o mdt_som.o mdt-objs += mdt_lvb.o mdt_hsm.o mdt_mds.o mdt_io.o mdt-objs += mdt_hsm_cdt_actions.o mdt-objs += mdt_hsm_cdt_requests.o diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 5ef06db..53fd951c 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -732,6 +732,8 @@ void mdt_pack_attr2body(struct mdt_thread_info *info, struct mdt_body *b, else b->mbo_blocks = 1; b->mbo_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS; + } else if (info->mti_som_valid) { /* som is valid */ + b->mbo_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS; } } @@ -992,6 +994,9 @@ int mdt_attr_get_complex(struct mdt_thread_info *info, rc = mo_attr_get(env, next, ma); if (rc) GOTO(out, rc); + + if (S_ISREG(mode)) + (void) mdt_get_som(info, o, &ma->ma_attr); ma->ma_valid |= MA_INODE; } @@ -3282,6 +3287,7 @@ void mdt_thread_info_init(struct ptlrpc_request *req, info->mti_opdata = 0; info->mti_big_lmm_used = 0; info->mti_big_acl_used = 0; + info->mti_som_valid = 0; info->mti_spec.no_create = 0; info->mti_spec.sp_rm_entry = 0; diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index ecd0a85..2054274 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -398,7 +398,8 @@ struct mdt_thread_info { mti_cross_ref:1, /* big_lmm buffer was used and must be used in reply */ mti_big_lmm_used:1, - mti_big_acl_used:1; + mti_big_acl_used:1, + mti_som_valid:1; /* opdata for mdt_reint_open(), has the same as * ldlm_reply:lock_policy_res1. mdt_update_last_rcvd() stores this @@ -468,6 +469,8 @@ struct mdt_thread_info { char mti_xattr_buf[128]; struct ldlm_enqueue_info mti_einfo; struct tg_reply_data *mti_reply_data; + + struct lustre_som_attrs mti_som; }; extern struct lu_context_key mdt_thread_key; @@ -1111,6 +1114,12 @@ static inline enum ldlm_mode mdt_mdl_mode2dlm_mode(mdl_mode_t mode) return mdt_dlm_lock_modes[mode]; } +/* mdt_som.c */ +int mdt_set_som(struct mdt_thread_info *info, struct mdt_object *obj, + struct lu_attr *attr); +int mdt_get_som(struct mdt_thread_info *info, struct mdt_object *obj, + struct lu_attr *attr); + /* mdt_lvb.c */ extern struct ldlm_valblock_ops mdt_lvbo; int mdt_dom_lvb_is_valid(struct ldlm_resource *res); diff --git a/lustre/mdt/mdt_open.c b/lustre/mdt/mdt_open.c index 197b852..36bbad4 100644 --- a/lustre/mdt/mdt_open.c +++ b/lustre/mdt/mdt_open.c @@ -2015,6 +2015,16 @@ int mdt_close_handle_layouts(struct mdt_thread_info *info, buf->lb_buf = mdt_object_child(o == o1 ? o2 : o1); rc = mo_xattr_set(info->mti_env, mdt_object_child(o), buf, XATTR_LUSTRE_LOV, LU_XATTR_MERGE); + if (rc == 0 && ma->ma_attr.la_valid & (LA_SIZE | LA_BLOCKS)) { + int rc2; + + rc2 = mdt_set_som(info, o, &ma->ma_attr); + if (rc2 < 0) + CERROR(DFID": Setting i_blocks error: %d, " + "i_blocks will be reported wrongly and " + "can only be fixed in next resync\n", + PFID(mdt_object_fid(o)), rc2); + } } if (rc < 0) GOTO(out_unlock2, rc); diff --git a/lustre/mdt/mdt_som.c b/lustre/mdt/mdt_som.c new file mode 100644 index 0000000..f4c3306 --- /dev/null +++ b/lustre/mdt/mdt_som.c @@ -0,0 +1,96 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. A copy is + * included in the COPYING file that accompanied this code. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * GPL HEADER END + */ +/* + * Copyright (c) 2017, Intel Corporation. + */ +/* + * lustre/mdt/mdt_som.c + * + * Size on MDS revival + * + * Author: Jinshan Xiong + */ + +#define DEBUG_SUBSYSTEM S_MDS + +#include "mdt_internal.h" + +int mdt_get_som(struct mdt_thread_info *info, struct mdt_object *obj, + struct lu_attr *attr) +{ + struct lu_buf *buf = &info->mti_buf; + struct lustre_som_attrs *som; + int rc; + + som = buf->lb_buf = info->mti_xattr_buf; + buf->lb_len = sizeof(info->mti_xattr_buf); + rc = mo_xattr_get(info->mti_env, mdt_object_child(obj), buf, + XATTR_NAME_SOM); + if (rc >= (int)sizeof(*som) && (som->lsa_valid & LSOM_FL_VALID)) { + attr->la_valid |= LA_SIZE | LA_BLOCKS; + attr->la_size = som->lsa_size; + attr->la_blocks = som->lsa_blocks; + + /* Size on MDS is valid and could be returned to client */ + info->mti_som_valid = 1; + + CDEBUG(D_INODE, DFID": Reading som attrs: " + "valid: %x, size: %lld, blocks: %lld, rc: %d.\n", + PFID(mdt_object_fid(obj)), som->lsa_valid, + som->lsa_size, som->lsa_blocks, rc); + } + + return (rc > 0 || rc == -ENODATA) ? 0 : rc; +} + +int mdt_set_som(struct mdt_thread_info *info, struct mdt_object *obj, + struct lu_attr *attr) +{ + struct md_object *next = mdt_object_child(obj); + struct lu_buf *buf = &info->mti_buf; + struct lustre_som_attrs *som; + int rc; + ENTRY; + + buf->lb_buf = info->mti_xattr_buf; + buf->lb_len = sizeof(info->mti_xattr_buf); + rc = mo_xattr_get(info->mti_env, next, buf, XATTR_NAME_SOM); + if (rc < 0 && rc != -ENODATA) + RETURN(rc); + + som = buf->lb_buf; + + CDEBUG(D_INODE, + DFID": Set som attrs: " "size: %lld, blocks: %lld, rc: %d\n", + PFID(mdt_object_fid(obj)), som->lsa_size, som->lsa_blocks, rc); + + if (rc == -ENODATA) + memset(som, 0, sizeof(*som)); + if (attr->la_valid & (LA_SIZE | LA_BLOCKS)) { + som->lsa_valid |= LSOM_FL_VALID; + som->lsa_size = attr->la_size; + som->lsa_blocks = attr->la_blocks; + } + buf->lb_len = sizeof(*som); + rc = mo_xattr_set(info->mti_env, next, buf, XATTR_NAME_SOM, 0); + RETURN(rc); +} diff --git a/lustre/tests/sanity-flr.sh b/lustre/tests/sanity-flr.sh index 94767b9..101a5ff 100644 --- a/lustre/tests/sanity-flr.sh +++ b/lustre/tests/sanity-flr.sh @@ -152,6 +152,62 @@ test_3() { } run_test 3 "create components from files located on different MDTs" +test_21() { + local tf=$DIR/$tfile + local tf2=$DIR/$tfile-2 + + [[ $OSTCOUNT -lt 2 ]] && skip "need >= 2 OSTs" && return + + $LFS setstripe -E EOF -o 0 $tf + $LFS setstripe -E EOF -o 1 $tf2 + + local dd_count=$((RANDOM % 20 + 1)) + dd if=/dev/zero of=$tf bs=1M count=$dd_count + dd if=/dev/zero of=$tf2 bs=1M count=1 seek=$((dd_count - 1)) + cancel_lru_locks osc + + local blocks=$(du -kc $tf $tf2 | awk '/total/{print $1}') + + # add component + $LFS setstripe --component-add --mirror=$tf2 $tf + + # cancel layout lock + cancel_lru_locks mdc + + local new_blocks=$(du -k $tf | awk '{print $1}') + [ $new_blocks -eq $blocks ] || + error "i_blocks error expected: $blocks, actual: $new_blocks" +} +run_test 21 "glimpse should report accurate i_blocks" + +test_22() { + local tf=$DIR/$tfile + + $LFS setstripe -E EOF -o 0 $tf + dd if=/dev/zero of=$tf bs=1M count=$((RANDOM % 20 + 1)) + + # add component, two mirrors located on the same OST ;-) + $LFS setstripe --component-add --mirror -o 0 $tf + + size_blocks=$(stat --format="%b %s" $tf) + + cancel_lru_locks mdc + cancel_lru_locks osc + + local new_size_blocks=$(stat --format="%b %s" $tf) + + # make sure there is no lock cached + local lock_count=$($LCTL get_param -n \ + ldlm.namespaces.${FSNAME}-OST0000-osc-ffff*.lock_count) + [ $lock_count -eq 0 ] || error "glimpse requests were sent" + + [ "$new_size_blocks" = "$size_blocks" ] || + echo "size expected: $size_blocks, actual: $new_size_blocks" + + rm -f $tmpfile +} +run_test 22 "no glimpse to OSTs for READ_ONLY files" + complete $SECONDS check_and_cleanup_lustre exit_status