X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Fllite_lib.c;h=6e913652b8c81e47ad16af32148247e2ec116465;hp=acdec48fd955b797fe6df1d5a9c81cd554b2a40d;hb=9ac37e061515ed6a3efcc8aca87ce71f6fff2a18;hpb=ff3c1a0c6d43fb210faa5e0705241672e0754ce4 diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index acdec48..6e91365 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -27,7 +27,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2012, Whamcloud, Inc. + * Copyright (c) 2011, 2012, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -94,11 +94,7 @@ static struct ll_sb_info *ll_init_sbi(void) si_meminfo(&si); pages = si.totalram - si.totalhigh; if (pages >> (20 - CFS_PAGE_SHIFT) < 512) { -#ifdef HAVE_BGL_SUPPORT - lru_page_max = pages / 4; -#else lru_page_max = pages / 2; -#endif } else { lru_page_max = (pages / 4) * 3; } @@ -221,7 +217,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_RMT_CLIENT | OBD_CONNECT_VBR | OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH| OBD_CONNECT_EINPROGRESS | - OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE; + OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | + OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; @@ -267,7 +264,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (sbi->ll_flags & LL_SBI_RMT_CLIENT) data->ocd_connect_flags |= OBD_CONNECT_RMT_CLIENT_FORCE; - data->ocd_brw_size = PTLRPC_MAX_BRW_SIZE; + data->ocd_brw_size = MD_MAX_BRW_SIZE; err = obd_connect(NULL, &sbi->ll_md_exp, obd, &sbi->ll_sb_uuid, data, NULL); if (err == -EBUSY) { @@ -281,51 +278,51 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, GOTO(out, err); } - err = obd_fid_init(sbi->ll_md_exp); - if (err) { - CERROR("Can't init metadata layer FID infrastructure, " - "rc %d\n", err); - GOTO(out_md, err); - } + sbi->ll_md_exp->exp_connect_data = *data; + + /* For mount, we only need fs info from MDT0, and also in DNE, it + * can make sure the client can be mounted as long as MDT0 is + * avaible */ + err = obd_statfs(NULL, sbi->ll_md_exp, osfs, + cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), + OBD_STATFS_FOR_MDT0); + if (err) + GOTO(out_md, err); + + /* This needs to be after statfs to ensure connect has finished. + * Note that "data" does NOT contain the valid connect reply. + * If connecting to a 1.8 server there will be no LMV device, so + * we can access the MDC export directly and exp_connect_flags will + * be non-zero, but if accessing an upgraded 2.1 server it will + * have the correct flags filled in. + * XXX: fill in the LMV exp_connect_flags from MDC(s). */ + valid = exp_connect_flags(sbi->ll_md_exp) & CLIENT_CONNECT_MDT_REQD; + if (exp_connect_flags(sbi->ll_md_exp) != 0 && + valid != CLIENT_CONNECT_MDT_REQD) { + char *buf; + + OBD_ALLOC_WAIT(buf, CFS_PAGE_SIZE); + obd_connect_flags2str(buf, CFS_PAGE_SIZE, + valid ^ CLIENT_CONNECT_MDT_REQD, ","); + LCONSOLE_ERROR_MSG(0x170, "Server %s does not support " + "feature(s) needed for correct operation " + "of this client (%s). Please upgrade " + "server or downgrade client.\n", + sbi->ll_md_exp->exp_obd->obd_name, buf); + OBD_FREE(buf, CFS_PAGE_SIZE); + GOTO(out_md, err = -EPROTO); + } - err = obd_statfs(NULL, sbi->ll_md_exp, osfs, - cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), 0); - if (err) - GOTO(out_md_fid, err); - - /* This needs to be after statfs to ensure connect has finished. - * Note that "data" does NOT contain the valid connect reply. - * If connecting to a 1.8 server there will be no LMV device, so - * we can access the MDC export directly and exp_connect_flags will - * be non-zero, but if accessing an upgraded 2.1 server it will - * have the correct flags filled in. - * XXX: fill in the LMV exp_connect_flags from MDC(s). */ - valid = sbi->ll_md_exp->exp_connect_flags & CLIENT_CONNECT_MDT_REQD; - if (sbi->ll_md_exp->exp_connect_flags != 0 && - valid != CLIENT_CONNECT_MDT_REQD) { - char *buf; - - OBD_ALLOC_WAIT(buf, CFS_PAGE_SIZE); - obd_connect_flags2str(buf, CFS_PAGE_SIZE, - valid ^ CLIENT_CONNECT_MDT_REQD, ","); - LCONSOLE_ERROR_MSG(0x170, "Server %s does not support " - "feature(s) needed for correct operation " - "of this client (%s). Please upgrade " - "server or downgrade client.\n", - sbi->ll_md_exp->exp_obd->obd_name, buf); - OBD_FREE(buf, CFS_PAGE_SIZE); - GOTO(out_md, err = -EPROTO); - } - - size = sizeof(*data); - err = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_CONN_DATA), - KEY_CONN_DATA, &size, data, NULL); - if (err) { - CERROR("Get connect data failed: %d \n", err); - GOTO(out_md, err); - } + size = sizeof(*data); + err = obd_get_info(NULL, sbi->ll_md_exp, sizeof(KEY_CONN_DATA), + KEY_CONN_DATA, &size, data, NULL); + if (err) { + CERROR("%s: Get connect data failed: rc = %d\n", + sbi->ll_md_exp->exp_obd->obd_name, err); + GOTO(out_md, err); + } - LASSERT(osfs->os_bsize); + LASSERT(osfs->os_bsize); sb->s_blocksize = osfs->os_bsize; sb->s_blocksize_bits = log2(osfs->os_bsize); sb->s_magic = LL_SUPER_MAGIC; @@ -379,21 +376,21 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (data->ocd_connect_flags & OBD_CONNECT_64BITHASH) sbi->ll_flags |= LL_SBI_64BIT_HASH; - if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) - sbi->ll_md_brw_size = data->ocd_brw_size; - else - sbi->ll_md_brw_size = CFS_PAGE_SIZE; + if (data->ocd_connect_flags & OBD_CONNECT_BRW_SIZE) + sbi->ll_md_brw_size = data->ocd_brw_size; + else + sbi->ll_md_brw_size = CFS_PAGE_SIZE; if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) { LCONSOLE_INFO("Layout lock feature supported.\n"); sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; } - obd = class_name2obd(dt); - if (!obd) { - CERROR("DT %s: not setup or attached\n", dt); - GOTO(out_md_fid, err = -ENODEV); - } + obd = class_name2obd(dt); + if (!obd) { + CERROR("DT %s: not setup or attached\n", dt); + GOTO(out_md, err = -ENODEV); + } data->ocd_connect_flags = OBD_CONNECT_GRANT | OBD_CONNECT_VERSION | OBD_CONNECT_REQPORTAL | OBD_CONNECT_BRW_SIZE | @@ -404,7 +401,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, OBD_CONNECT_FULL20 | OBD_CONNECT_64BITHASH | OBD_CONNECT_MAXBYTES | OBD_CONNECT_EINPROGRESS | - OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE; + OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE | + OBD_CONNECT_LAYOUTLOCK | OBD_CONNECT_PINGLESS; if (sbi->ll_flags & LL_SBI_SOM_PREVIEW) data->ocd_connect_flags |= OBD_CONNECT_SOM; @@ -435,82 +433,83 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, obd->obd_upcall.onu_owner = &sbi->ll_lco; obd->obd_upcall.onu_upcall = cl_ocd_update; - data->ocd_brw_size = PTLRPC_MAX_BRW_SIZE; - - err = obd_connect(NULL, &sbi->ll_dt_exp, obd, &sbi->ll_sb_uuid, data, NULL); - if (err == -EBUSY) { - LCONSOLE_ERROR_MSG(0x150, "An OST (dt %s) is performing " - "recovery, of which this client is not a " - "part. Please wait for recovery to " - "complete, abort, or time out.\n", dt); - GOTO(out_md_fid, err); - } else if (err) { - CERROR("Cannot connect to %s: rc = %d\n", dt, err); - GOTO(out_md_fid, err); - } + data->ocd_brw_size = DT_MAX_BRW_SIZE; + + err = obd_connect(NULL, &sbi->ll_dt_exp, obd, &sbi->ll_sb_uuid, data, + NULL); + if (err == -EBUSY) { + LCONSOLE_ERROR_MSG(0x150, "An OST (dt %s) is performing " + "recovery, of which this client is not a " + "part. Please wait for recovery to " + "complete, abort, or time out.\n", dt); + GOTO(out_md, err); + } else if (err) { + CERROR("%s: Cannot connect to %s: rc = %d\n", + sbi->ll_dt_exp->exp_obd->obd_name, dt, err); + GOTO(out_md, err); + } - err = obd_fid_init(sbi->ll_dt_exp); - if (err) { - CERROR("Can't init data layer FID infrastructure, " - "rc %d\n", err); - GOTO(out_dt, err); - } + sbi->ll_dt_exp->exp_connect_data = *data; mutex_lock(&sbi->ll_lco.lco_lock); - sbi->ll_lco.lco_flags = data->ocd_connect_flags; - sbi->ll_lco.lco_md_exp = sbi->ll_md_exp; - sbi->ll_lco.lco_dt_exp = sbi->ll_dt_exp; + sbi->ll_lco.lco_flags = data->ocd_connect_flags; + sbi->ll_lco.lco_md_exp = sbi->ll_md_exp; + sbi->ll_lco.lco_dt_exp = sbi->ll_dt_exp; mutex_unlock(&sbi->ll_lco.lco_lock); - fid_zero(&sbi->ll_root_fid); - err = md_getstatus(sbi->ll_md_exp, &sbi->ll_root_fid, &oc); - if (err) { - CERROR("cannot mds_connect: rc = %d\n", err); - GOTO(out_lock_cn_cb, err); - } - if (!fid_is_sane(&sbi->ll_root_fid)) { - CERROR("Invalid root fid during mount\n"); - GOTO(out_lock_cn_cb, err = -EINVAL); - } - CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid)); + fid_zero(&sbi->ll_root_fid); + err = md_getstatus(sbi->ll_md_exp, &sbi->ll_root_fid, &oc); + if (err) { + CERROR("cannot mds_connect: rc = %d\n", err); + GOTO(out_dt, err); + } + if (!fid_is_sane(&sbi->ll_root_fid)) { + CERROR("%s: Invalid root fid "DFID" during mount\n", + sbi->ll_md_exp->exp_obd->obd_name, + PFID(&sbi->ll_root_fid)); + GOTO(out_dt, err = -EINVAL); + } + CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid)); - sb->s_op = &lustre_super_operations; + sb->s_op = &lustre_super_operations; #if THREAD_SIZE >= 8192 /*b=17630*/ sb->s_export_op = &lustre_export_operations; #endif - /* make root inode - * XXX: move this to after cbd setup? */ - valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMDSCAPA; - if (sbi->ll_flags & LL_SBI_RMT_CLIENT) - valid |= OBD_MD_FLRMTPERM; - else if (sbi->ll_flags & LL_SBI_ACL) - valid |= OBD_MD_FLACL; - - OBD_ALLOC_PTR(op_data); - if (op_data == NULL) - GOTO(out_lock_cn_cb, err = -ENOMEM); - - op_data->op_fid1 = sbi->ll_root_fid; - op_data->op_mode = 0; - op_data->op_capa1 = oc; - op_data->op_valid = valid; + /* make root inode + * XXX: move this to after cbd setup? */ + valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMDSCAPA; + if (sbi->ll_flags & LL_SBI_RMT_CLIENT) + valid |= OBD_MD_FLRMTPERM; + else if (sbi->ll_flags & LL_SBI_ACL) + valid |= OBD_MD_FLACL; + + OBD_ALLOC_PTR(op_data); + if (op_data == NULL) + GOTO(out_dt, err = -ENOMEM); + + op_data->op_fid1 = sbi->ll_root_fid; + op_data->op_mode = 0; + op_data->op_capa1 = oc; + op_data->op_valid = valid; + + err = md_getattr(sbi->ll_md_exp, op_data, &request); + if (oc) + capa_put(oc); + OBD_FREE_PTR(op_data); + if (err) { + CERROR("%s: md_getattr failed for root: rc = %d\n", + sbi->ll_md_exp->exp_obd->obd_name, err); + GOTO(out_dt, err); + } - err = md_getattr(sbi->ll_md_exp, op_data, &request); - if (oc) - capa_put(oc); - OBD_FREE_PTR(op_data); - if (err) { - CERROR("md_getattr failed for root: rc = %d\n", err); - 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); - if (err) { - CERROR("failed to understand root inode md: rc = %d\n", err); - ptlrpc_req_finished (request); - 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); + if (err) { + CERROR("failed to understand root inode md: rc = %d\n", err); + ptlrpc_req_finished(request); + GOTO(out_dt, err); + } LASSERT(fid_is_sane(&sbi->ll_root_fid)); root = ll_iget(sb, cl_fid_build_ino(&sbi->ll_root_fid, 0), &lmd); @@ -559,7 +558,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (sb->s_root == NULL) { CERROR("%s: can't make root dentry\n", ll_get_fsname(sb, NULL, 0)); - GOTO(out_lock_cn_cb, err = -ENOMEM); + GOTO(out_root, err = -ENOMEM); } #ifdef HAVE_DCACHE_LOCK @@ -590,13 +589,11 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, out_root: if (root) iput(root); -out_lock_cn_cb: - obd_fid_fini(sbi->ll_dt_exp); out_dt: obd_disconnect(sbi->ll_dt_exp); sbi->ll_dt_exp = NULL; -out_md_fid: - obd_fid_fini(sbi->ll_md_exp); + /* Make sure all OScs are gone, since cl_cache is accessing sbi. */ + obd_zombie_barrier(); out_md: obd_disconnect(sbi->ll_md_exp); sbi->ll_md_exp = NULL; @@ -625,17 +622,17 @@ int ll_get_max_mdsize(struct ll_sb_info *sbi, int *lmmsize) void ll_dump_inode(struct inode *inode) { - struct list_head *tmp; - int dentry_count = 0; + struct ll_d_hlist_node *tmp; + int dentry_count = 0; - LASSERT(inode != NULL); + LASSERT(inode != NULL); - list_for_each(tmp, &inode->i_dentry) - dentry_count++; + ll_d_hlist_for_each(tmp, &inode->i_dentry) + dentry_count++; - CERROR("inode %p dump: dev=%s ino=%lu mode=%o count=%u, %d dentries\n", - inode, ll_i2mdexp(inode)->exp_obd->obd_name, inode->i_ino, - inode->i_mode, atomic_read(&inode->i_count), dentry_count); + CERROR("inode %p dump: dev=%s ino=%lu mode=%o count=%u, %d dentries\n", + inode, ll_i2mdexp(inode)->exp_obd->obd_name, inode->i_ino, + inode->i_mode, atomic_read(&inode->i_count), dentry_count); } void lustre_dump_dentry(struct dentry *dentry, int recur) @@ -684,13 +681,14 @@ void client_common_put_super(struct super_block *sb) cfs_list_del(&sbi->ll_conn_chain); - obd_fid_fini(sbi->ll_dt_exp); obd_disconnect(sbi->ll_dt_exp); sbi->ll_dt_exp = NULL; + /* wait till all OSCs are gone, since cl_cache is accessing sbi. + * see LU-2543. */ + obd_zombie_barrier(); lprocfs_unregister_mountpoint(sbi); - obd_fid_fini(sbi->ll_md_exp); obd_disconnect(sbi->ll_md_exp); sbi->ll_md_exp = NULL; @@ -918,6 +916,7 @@ void ll_lli_init(struct ll_inode_info *lli) mutex_init(&lli->lli_och_mutex); spin_lock_init(&lli->lli_agl_lock); lli->lli_has_smd = false; + lli->lli_layout_gen = LL_LAYOUT_GEN_NONE; lli->lli_clob = NULL; LASSERT(lli->lli_vfs_inode.i_mode != 0); @@ -939,6 +938,7 @@ void ll_lli_init(struct ll_inode_info *lli) CFS_INIT_LIST_HEAD(&lli->lli_agl_list); lli->lli_agl_index = 0; lli->lli_async_rc = 0; + lli->lli_volatile = false; } mutex_init(&lli->lli_layout_mutex); } @@ -991,14 +991,14 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) if (err) GOTO(out_free, err); - err = ll_bdi_init(&lsi->lsi_bdi); - if (err) - GOTO(out_free, err); - lsi->lsi_flags |= LSI_BDI_INITIALIZED; - lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY; - err = ll_bdi_register(&lsi->lsi_bdi); - if (err) - GOTO(out_free, err); + err = bdi_init(&lsi->lsi_bdi); + if (err) + GOTO(out_free, err); + lsi->lsi_flags |= LSI_BDI_INITIALIZED; + lsi->lsi_bdi.capabilities = BDI_CAP_MAP_COPY; + err = ll_bdi_register(&lsi->lsi_bdi); + if (err) + GOTO(out_free, err); #ifdef HAVE_SB_BDI sb->s_bdi = &lsi->lsi_bdi; @@ -1107,10 +1107,10 @@ void ll_put_super(struct super_block *sb) if (profilenm) class_del_profile(profilenm); - if (lsi->lsi_flags & LSI_BDI_INITIALIZED) { - ll_bdi_destroy(&lsi->lsi_bdi); - lsi->lsi_flags &= ~LSI_BDI_INITIALIZED; - } + if (lsi->lsi_flags & LSI_BDI_INITIALIZED) { + bdi_destroy(&lsi->lsi_bdi); + lsi->lsi_flags &= ~LSI_BDI_INITIALIZED; + } ll_free_sbi(sb); lsi->lsi_llsbi = NULL; @@ -1460,6 +1460,13 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) LTIME_S(attr->ia_mtime), LTIME_S(attr->ia_ctime), cfs_time_current_sec()); + /* If we are changing file size, file content is modified, flag it. */ + if (attr->ia_valid & ATTR_SIZE) { + spin_lock(&lli->lli_lock); + lli->lli_flags |= LLIF_DATA_MODIFIED; + spin_unlock(&lli->lli_lock); + } + /* We always do an MDS RPC, even if we're only changing the size; * only the MDS knows whether truncate() should fail with -ETXTBUSY */ @@ -1472,9 +1479,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) inode_dio_write_done(inode); mutex_unlock(&inode->i_mutex); down_write(&lli->lli_trunc_sem); - mutex_lock(&inode->i_mutex); - if (ia_valid & ATTR_SIZE) - inode_dio_wait(inode); } /* We need a steady stripe configuration for setattr to avoid @@ -1499,6 +1503,13 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) if (rc) GOTO(out, rc); + /* RPC to MDT is sent, cancel data modification flag */ + if (rc == 0 && (op_data->op_bias & MDS_DATA_MODIFIED)) { + spin_lock(&lli->lli_lock); + lli->lli_flags &= ~LLIF_DATA_MODIFIED; + spin_unlock(&lli->lli_lock); + } + ll_ioepoch_open(lli, op_data->op_ioepoch); if (!S_ISREG(inode->i_mode)) GOTO(out, rc = 0); @@ -1525,13 +1536,17 @@ out: } ll_finish_md_op_data(op_data); } - if (!S_ISDIR(inode->i_mode)) + if (!S_ISDIR(inode->i_mode)) { up_write(&lli->lli_trunc_sem); + mutex_lock(&inode->i_mutex); + if (ia_valid & ATTR_SIZE) + inode_dio_wait(inode); + } - ll_stats_ops_tally(ll_i2sbi(inode), (ia_valid & ATTR_SIZE) ? - LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1); + ll_stats_ops_tally(ll_i2sbi(inode), (ia_valid & ATTR_SIZE) ? + LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1); - return rc; + return rc; } int ll_setattr(struct dentry *de, struct iattr *attr) @@ -1682,21 +1697,13 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) LASSERT ((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0)); if (lsm != NULL) { - LASSERT(S_ISREG(inode->i_mode)); - CDEBUG(D_INODE, "adding lsm %p to inode %lu/%u(%p)\n", - lsm, inode->i_ino, inode->i_generation, inode); - /* cl_file_inode_init must go before lli_has_smd or a race - * is possible where client thinks the file has stripes, - * but lov raid0 is not setup yet and parallel e.g. - * glimpse would try to use uninitialized lov */ - if (cl_file_inode_init(inode, md) == 0) - lli->lli_has_smd = true; + if (!lli->lli_has_smd && + !(sbi->ll_flags & LL_SBI_LAYOUT_LOCK)) + cl_file_inode_init(inode, md); lli->lli_maxbytes = lsm->lsm_maxbytes; if (lli->lli_maxbytes > MAX_LFS_FILESIZE) lli->lli_maxbytes = MAX_LFS_FILESIZE; - if (md->lsm != NULL) - obd_free_memmd(ll_i2dtexp(inode), &md->lsm); } if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { @@ -2115,13 +2122,11 @@ int ll_remount_fs(struct super_block *sb, int *flags, char *data) return 0; } -int ll_prep_inode(struct inode **inode, - struct ptlrpc_request *req, - struct super_block *sb) +int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, + struct super_block *sb, struct lookup_intent *it) { struct ll_sb_info *sbi = NULL; struct lustre_md md; - __u64 ibits; int rc; ENTRY; @@ -2145,8 +2150,6 @@ int ll_prep_inode(struct inode **inode, *inode = ll_iget(sb, cl_fid_build_ino(&md.body->fid1, 0), &md); if (*inode == NULL || IS_ERR(*inode)) { - if (md.lsm) - obd_free_memmd(sbi->ll_dt_exp, &md.lsm); #ifdef CONFIG_FS_POSIX_ACL if (md.posix_acl) { posix_acl_release(md.posix_acl); @@ -2160,16 +2163,37 @@ int ll_prep_inode(struct inode **inode, } } - /* sanity check for LAYOUT lock. */ - ibits = MDS_INODELOCK_LAYOUT; - if (S_ISREG(md.body->mode) && sbi->ll_flags & LL_SBI_LAYOUT_LOCK && - md.lsm != NULL && !ll_have_md_lock(*inode, &ibits, LCK_MINMODE)) { - CERROR("%s: inode "DFID" (%p) layout lock not granted.\n", - ll_get_fsname(sb, NULL, 0), - PFID(ll_inode2fid(*inode)), *inode); + /* Handling piggyback layout lock. + * Layout lock can be piggybacked by getattr and open request. + * The lsm can be applied to inode only if it comes with a layout lock + * otherwise correct layout may be overwritten, for example: + * 1. proc1: mdt returns a lsm but not granting layout + * 2. layout was changed by another client + * 3. proc2: refresh layout and layout lock granted + * 4. proc1: to apply a stale layout */ + if (it != NULL && it->d.lustre.it_lock_mode != 0) { + struct lustre_handle lockh; + struct ldlm_lock *lock; + + lockh.cookie = it->d.lustre.it_lock_handle; + lock = ldlm_handle2lock(&lockh); + LASSERT(lock != NULL); + if (ldlm_has_layout(lock)) { + struct cl_object_conf conf; + + memset(&conf, 0, sizeof(conf)); + conf.coc_opc = OBJECT_CONF_SET; + conf.coc_inode = *inode; + conf.coc_lock = lock; + conf.u.coc_md = &md; + (void)ll_layout_conf(*inode, &conf); + } + LDLM_LOCK_PUT(lock); } out: + if (md.lsm != NULL) + obd_free_memmd(sbi->ll_dt_exp, &md.lsm); md_free_lustre_md(sbi->ll_md_exp, &md); RETURN(rc); } @@ -2278,17 +2302,21 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data, op_data->op_capa2 = NULL; } - op_data->op_name = name; - op_data->op_namelen = namelen; - op_data->op_mode = mode; - op_data->op_mod_time = cfs_time_current_sec(); - op_data->op_fsuid = cfs_curproc_fsuid(); - op_data->op_fsgid = cfs_curproc_fsgid(); - op_data->op_cap = cfs_curproc_cap_pack(); - op_data->op_bias = MDS_CHECK_SPLIT; - op_data->op_opc = opc; - op_data->op_mds = 0; - op_data->op_data = data; + op_data->op_name = name; + op_data->op_namelen = namelen; + op_data->op_mode = mode; + op_data->op_mod_time = cfs_time_current_sec(); + op_data->op_fsuid = cfs_curproc_fsuid(); + op_data->op_fsgid = cfs_curproc_fsgid(); + op_data->op_cap = cfs_curproc_cap_pack(); + op_data->op_bias = 0; + op_data->op_cli_flags = 0; + if ((opc == LUSTRE_OPC_CREATE) && (name != NULL) && + filename_is_volatile(name, namelen, NULL)) + op_data->op_bias |= MDS_CREATE_VOLATILE; + op_data->op_opc = opc; + op_data->op_mds = 0; + op_data->op_data = data; /* If the file is being opened after mknod() (normally due to NFS) * try to use the default stripe data from parent directory for @@ -2304,6 +2332,10 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data, /** We ignore parent's capability temporary. */ } + /* When called by ll_setattr_raw, file is i1. */ + if (LLIF_DATA_MODIFIED & ll_i2info(i1)->lli_flags) + op_data->op_bias |= MDS_DATA_MODIFIED; + return op_data; } @@ -2435,7 +2467,8 @@ void ll_dirty_page_discard_warn(cfs_page_t *page, int ioret) struct dentry *dentry = NULL; struct ccc_object *obj = cl_inode2ccc(page->mapping->host); - buf = (char *)__get_free_page(GFP_KERNEL); + /* this can be called inside spin lock so use GFP_ATOMIC. */ + buf = (char *)__get_free_page(GFP_ATOMIC); if (buf != NULL) { dentry = d_find_alias(page->mapping->host); if (dentry != NULL)