X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fllite%2Fllite_lib.c;h=83e94904cf52ee2aeccb79a728c3c1624e6f19a4;hb=a7ae8da2422954fd1a8f91e857a92f337589f3f6;hp=11d616969dc8ff2b401246f856cd115201365e53;hpb=2d0c621d21be4e67b6075b76017af6e6fcd18c64;p=fs%2Flustre-release.git diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 11d6169..83e9490 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -51,6 +51,10 @@ #include #include +#ifdef HAVE_UAPI_LINUX_MOUNT_H +#include +#endif + #include #include #include @@ -73,32 +77,46 @@ static struct ll_sb_info *ll_init_sbi(void) unsigned long pages; unsigned long lru_page_max; struct sysinfo si; + int rc; int i; + ENTRY; OBD_ALLOC_PTR(sbi); if (sbi == NULL) - RETURN(NULL); + RETURN(ERR_PTR(-ENOMEM)); + + rc = pcc_super_init(&sbi->ll_pcc_super); + if (rc < 0) + GOTO(out_sbi, rc); spin_lock_init(&sbi->ll_lock); mutex_init(&sbi->ll_lco.lco_lock); spin_lock_init(&sbi->ll_pp_extent_lock); spin_lock_init(&sbi->ll_process_lock); sbi->ll_rw_stats_on = 0; + sbi->ll_statfs_max_age = OBD_STATFS_CACHE_SECONDS; si_meminfo(&si); pages = si.totalram - si.totalhigh; lru_page_max = pages / 2; + sbi->ll_ra_info.ra_async_max_active = 0; + sbi->ll_ra_info.ll_readahead_wq = + alloc_workqueue("ll-readahead-wq", WQ_UNBOUND, + sbi->ll_ra_info.ra_async_max_active); + if (!sbi->ll_ra_info.ll_readahead_wq) + GOTO(out_pcc, rc = -ENOMEM); + /* initialize ll_cache data */ sbi->ll_cache = cl_cache_init(lru_page_max); - if (sbi->ll_cache == NULL) { - OBD_FREE(sbi, sizeof(*sbi)); - RETURN(NULL); - } + if (sbi->ll_cache == NULL) + GOTO(out_destroy_ra, rc = -ENOMEM); sbi->ll_ra_info.ra_max_pages_per_file = min(pages / 32, SBI_DEFAULT_READAHEAD_MAX); + sbi->ll_ra_info.ra_async_pages_per_file_threshold = + sbi->ll_ra_info.ra_max_pages_per_file; sbi->ll_ra_info.ra_max_pages = sbi->ll_ra_info.ra_max_pages_per_file; sbi->ll_ra_info.ra_max_read_ahead_whole_pages = -1; @@ -137,12 +155,19 @@ static struct ll_sb_info *ll_init_sbi(void) sbi->ll_squash.rsi_uid = 0; sbi->ll_squash.rsi_gid = 0; INIT_LIST_HEAD(&sbi->ll_squash.rsi_nosquash_nids); - init_rwsem(&sbi->ll_squash.rsi_sem); + spin_lock_init(&sbi->ll_squash.rsi_lock); /* Per-filesystem file heat */ sbi->ll_heat_decay_weight = SBI_DEFAULT_HEAT_DECAY_WEIGHT; sbi->ll_heat_period_second = SBI_DEFAULT_HEAT_PERIOD_SECOND; RETURN(sbi); +out_destroy_ra: + destroy_workqueue(sbi->ll_ra_info.ll_readahead_wq); +out_pcc: + pcc_super_fini(&sbi->ll_pcc_super); +out_sbi: + OBD_FREE_PTR(sbi); + RETURN(ERR_PTR(rc)); } static void ll_free_sbi(struct super_block *sb) @@ -153,10 +178,13 @@ static void ll_free_sbi(struct super_block *sb) if (sbi != NULL) { if (!list_empty(&sbi->ll_squash.rsi_nosquash_nids)) cfs_free_nidlist(&sbi->ll_squash.rsi_nosquash_nids); + if (sbi->ll_ra_info.ll_readahead_wq) + destroy_workqueue(sbi->ll_ra_info.ll_readahead_wq); if (sbi->ll_cache != NULL) { cl_cache_decref(sbi->ll_cache); sbi->ll_cache = NULL; } + pcc_super_fini(&sbi->ll_pcc_super); OBD_FREE(sbi, sizeof(*sbi)); } EXIT; @@ -223,16 +251,20 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, data->ocd_connect_flags2 = OBD_CONNECT2_DIR_MIGRATE | OBD_CONNECT2_SUM_STATFS | + OBD_CONNECT2_OVERSTRIPING | OBD_CONNECT2_FLR | OBD_CONNECT2_LOCK_CONVERT | OBD_CONNECT2_ARCHIVE_ID_ARRAY | - OBD_CONNECT2_LSOM; + OBD_CONNECT2_INC_XID | + OBD_CONNECT2_LSOM | + OBD_CONNECT2_ASYNC_DISCARD | + OBD_CONNECT2_PCC; #ifdef HAVE_LRU_RESIZE_SUPPORT if (sbi->ll_flags & LL_SBI_LRU_RESIZE) data->ocd_connect_flags |= OBD_CONNECT_LRU_RESIZE; #endif -#ifdef CONFIG_FS_POSIX_ACL +#ifdef CONFIG_LUSTRE_FS_POSIX_ACL data->ocd_connect_flags |= OBD_CONNECT_ACL | OBD_CONNECT_UMASK | OBD_CONNECT_LARGE_ACL; #endif @@ -242,29 +274,29 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, if (OBD_FAIL_CHECK(OBD_FAIL_MDC_LIGHTWEIGHT)) /* flag mdc connection as lightweight, only used for test * purpose, use with care */ - data->ocd_connect_flags |= OBD_CONNECT_LIGHTWEIGHT; + data->ocd_connect_flags |= OBD_CONNECT_LIGHTWEIGHT; - data->ocd_ibits_known = MDS_INODELOCK_FULL; - data->ocd_version = LUSTRE_VERSION_CODE; + data->ocd_ibits_known = MDS_INODELOCK_FULL; + data->ocd_version = LUSTRE_VERSION_CODE; - if (sb->s_flags & MS_RDONLY) - data->ocd_connect_flags |= OBD_CONNECT_RDONLY; - if (sbi->ll_flags & LL_SBI_USER_XATTR) - data->ocd_connect_flags |= OBD_CONNECT_XATTR; + if (sb->s_flags & SB_RDONLY) + data->ocd_connect_flags |= OBD_CONNECT_RDONLY; + if (sbi->ll_flags & LL_SBI_USER_XATTR) + data->ocd_connect_flags |= OBD_CONNECT_XATTR; -#ifdef MS_NOSEC +#ifdef SB_NOSEC /* Setting this indicates we correctly support S_NOSEC (See kernel * commit 9e1f1de02c2275d7172e18dc4e7c2065777611bf) */ - sb->s_flags |= MS_NOSEC; + 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; + 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; /* always ping even if server suppress_pings */ if (sbi->ll_flags & LL_SBI_ALWAYS_PING) @@ -280,16 +312,16 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, err = obd_connect(NULL, &sbi->ll_md_exp, sbi->ll_md_obd, &sbi->ll_sb_uuid, data, sbi->ll_cache); - if (err == -EBUSY) { - LCONSOLE_ERROR_MSG(0x14f, "An MDT (md %s) is performing " - "recovery, of which this client is not a " - "part. Please wait for recovery to complete," - " abort, or time out.\n", md); - GOTO(out, err); - } else if (err) { - CERROR("cannot connect to %s: rc = %d\n", md, err); - GOTO(out, err); - } + if (err == -EBUSY) { + LCONSOLE_ERROR_MSG(0x14f, "An MDT (md %s) is performing " + "recovery, of which this client is not a " + "part. Please wait for recovery to complete," + " abort, or time out.\n", md); + GOTO(out, err); + } else if (err) { + CERROR("cannot connect to %s: rc = %d\n", md, err); + GOTO(out, err); + } sbi->ll_md_exp->exp_connect_data = *data; @@ -305,7 +337,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, * can make sure the client can be mounted as long as MDT0 is * avaible */ err = obd_statfs(NULL, sbi->ll_md_exp, osfs, - ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS, + ktime_get_seconds() - sbi->ll_statfs_max_age, OBD_STATFS_FOR_MDT0); if (err) GOTO(out_md_fid, err); @@ -351,28 +383,28 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_namelen = osfs->os_namelen; sbi->ll_mnt.mnt = current->fs->root.mnt; - if ((sbi->ll_flags & LL_SBI_USER_XATTR) && - !(data->ocd_connect_flags & OBD_CONNECT_XATTR)) { - LCONSOLE_INFO("Disabling user_xattr feature because " - "it is not supported on the server\n"); - sbi->ll_flags &= ~LL_SBI_USER_XATTR; - } + if ((sbi->ll_flags & LL_SBI_USER_XATTR) && + !(data->ocd_connect_flags & OBD_CONNECT_XATTR)) { + LCONSOLE_INFO("Disabling user_xattr feature because " + "it is not supported on the server\n"); + sbi->ll_flags &= ~LL_SBI_USER_XATTR; + } - if (data->ocd_connect_flags & OBD_CONNECT_ACL) { -#ifdef MS_POSIXACL - sb->s_flags |= MS_POSIXACL; + if (data->ocd_connect_flags & OBD_CONNECT_ACL) { +#ifdef SB_POSIXACL + sb->s_flags |= SB_POSIXACL; #endif - sbi->ll_flags |= LL_SBI_ACL; - } else { - LCONSOLE_INFO("client wants to enable acl, but mdt not!\n"); -#ifdef MS_POSIXACL - sb->s_flags &= ~MS_POSIXACL; + sbi->ll_flags |= LL_SBI_ACL; + } else { + LCONSOLE_INFO("client wants to enable acl, but mdt not!\n"); +#ifdef SB_POSIXACL + sb->s_flags &= ~SB_POSIXACL; #endif - sbi->ll_flags &= ~LL_SBI_ACL; - } + sbi->ll_flags &= ~LL_SBI_ACL; + } - if (data->ocd_connect_flags & OBD_CONNECT_64BITHASH) - sbi->ll_flags |= LL_SBI_64BIT_HASH; + if (data->ocd_connect_flags & OBD_CONNECT_64BITHASH) + sbi->ll_flags |= LL_SBI_64BIT_HASH; if (data->ocd_connect_flags & OBD_CONNECT_LAYOUTLOCK) sbi->ll_flags |= LL_SBI_LAYOUT_LOCK; @@ -433,7 +465,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, data->ocd_connect_flags |= OBD_CONNECT_LOCKAHEAD_OLD; #endif - data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD; + data->ocd_connect_flags2 = OBD_CONNECT2_LOCKAHEAD | + OBD_CONNECT2_INC_XID; if (!OBD_FAIL_CHECK(OBD_FAIL_OSC_CONNECT_GRANT_PARAM)) data->ocd_connect_flags |= OBD_CONNECT_GRANT_PARAM; @@ -483,10 +516,15 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_dt_exp->exp_connect_data = *data; /* Don't change value if it was specified in the config log */ - if (sbi->ll_ra_info.ra_max_read_ahead_whole_pages == -1) + if (sbi->ll_ra_info.ra_max_read_ahead_whole_pages == -1) { sbi->ll_ra_info.ra_max_read_ahead_whole_pages = max_t(unsigned long, SBI_DEFAULT_READAHEAD_WHOLE_MAX, (data->ocd_brw_size >> PAGE_SHIFT)); + if (sbi->ll_ra_info.ra_max_read_ahead_whole_pages > + sbi->ll_ra_info.ra_max_pages_per_file) + sbi->ll_ra_info.ra_max_read_ahead_whole_pages = + sbi->ll_ra_info.ra_max_pages_per_file; + } err = obd_fid_init(sbi->ll_dt_exp->exp_obd, sbi->ll_dt_exp, LUSTRE_SEQ_METADATA); @@ -518,9 +556,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, CDEBUG(D_SUPER, "rootfid "DFID"\n", PFID(&sbi->ll_root_fid)); sb->s_op = &lustre_super_operations; -#ifdef HAVE_XATTR_HANDLER_FLAGS sb->s_xattr = ll_xattr_handlers; -#endif #if THREAD_SIZE >= 8192 /*b=17630*/ sb->s_export_op = &lustre_export_operations; #endif @@ -564,7 +600,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, ptlrpc_req_finished(request); if (IS_ERR(root)) { -#ifdef CONFIG_FS_POSIX_ACL +#ifdef CONFIG_LUSTRE_FS_POSIX_ACL if (lmd.posix_acl) { posix_acl_release(lmd.posix_acl); lmd.posix_acl = NULL; @@ -572,7 +608,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, #endif err = IS_ERR(root) ? PTR_ERR(root) : -EBADF; root = NULL; - CERROR("lustre_lite: bad iget4 for root\n"); + CERROR("%s: bad ll_iget() for root: rc = %d\n", + sbi->ll_fsname, err); GOTO(out_root, err); } @@ -596,9 +633,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, sbi->ll_fsname, err); GOTO(out_root, err); } -#ifdef HAVE_DCACHE_LOCK - sb->s_root->d_op = &ll_d_ops; -#endif sbi->ll_sdev_orig = sb->s_dev; @@ -763,8 +797,8 @@ void ll_kill_super(struct super_block *sb) struct ll_sb_info *sbi; ENTRY; - /* not init sb ?*/ - if (!(sb->s_flags & MS_ACTIVE)) + /* not init sb ?*/ + if (!(sb->s_flags & SB_ACTIVE)) return; sbi = ll_s2sbi(sb); @@ -773,12 +807,11 @@ void ll_kill_super(struct super_block *sb) * put_super not affected real removing devices */ if (sbi) { sb->s_dev = sbi->ll_sdev_orig; - sbi->ll_umounting = 1; /* wait running statahead threads to quit */ while (atomic_read(&sbi->ll_sa_running) > 0) { set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(MSEC_PER_SEC >> 3)); + schedule_timeout(cfs_time_seconds(1) >> 3); } } @@ -806,38 +839,38 @@ static int ll_options(char *options, struct ll_sb_info *sbi) CDEBUG(D_CONFIG, "Parsing opts %s\n", options); - while (*s1) { - CDEBUG(D_SUPER, "next opt=%s\n", s1); - tmp = ll_set_opt("nolock", s1, LL_SBI_NOLCK); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("flock", s1, LL_SBI_FLOCK); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("localflock", s1, LL_SBI_LOCALFLOCK); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("noflock", s1, LL_SBI_FLOCK|LL_SBI_LOCALFLOCK); - if (tmp) { - *flags &= ~tmp; - goto next; - } - tmp = ll_set_opt("user_xattr", s1, LL_SBI_USER_XATTR); - if (tmp) { - *flags |= tmp; - goto next; - } - tmp = ll_set_opt("nouser_xattr", s1, LL_SBI_USER_XATTR); - if (tmp) { - *flags &= ~tmp; - goto next; - } + while (*s1) { + CDEBUG(D_SUPER, "next opt=%s\n", s1); + tmp = ll_set_opt("nolock", s1, LL_SBI_NOLCK); + if (tmp) { + *flags |= tmp; + goto next; + } + tmp = ll_set_opt("flock", s1, LL_SBI_FLOCK); + if (tmp) { + *flags = (*flags & ~LL_SBI_LOCALFLOCK) | tmp; + goto next; + } + tmp = ll_set_opt("localflock", s1, LL_SBI_LOCALFLOCK); + if (tmp) { + *flags = (*flags & ~LL_SBI_FLOCK) | tmp; + goto next; + } + tmp = ll_set_opt("noflock", s1, LL_SBI_FLOCK|LL_SBI_LOCALFLOCK); + if (tmp) { + *flags &= ~tmp; + goto next; + } + tmp = ll_set_opt("user_xattr", s1, LL_SBI_USER_XATTR); + if (tmp) { + *flags |= tmp; + goto next; + } + tmp = ll_set_opt("nouser_xattr", s1, LL_SBI_USER_XATTR); + if (tmp) { + *flags &= ~tmp; + goto next; + } tmp = ll_set_opt("context", s1, 1); if (tmp) goto next; @@ -952,13 +985,11 @@ void ll_lli_init(struct ll_inode_info *lli) LASSERT(lli->lli_vfs_inode.i_mode != 0); if (S_ISDIR(lli->lli_vfs_inode.i_mode)) { - mutex_init(&lli->lli_readdir_mutex); lli->lli_opendir_key = NULL; lli->lli_sai = NULL; spin_lock_init(&lli->lli_sa_lock); lli->lli_opendir_pid = 0; lli->lli_sa_enabled = 0; - lli->lli_def_stripe_offset = -1; init_rwsem(&lli->lli_lsm_sem); } else { mutex_init(&lli->lli_size_mutex); @@ -973,6 +1004,12 @@ void ll_lli_init(struct ll_inode_info *lli) spin_lock_init(&lli->lli_heat_lock); obd_heat_clear(lli->lli_heat_instances, OBD_HEAT_COUNT); lli->lli_heat_flags = 0; + mutex_init(&lli->lli_pcc_lock); + lli->lli_pcc_state = PCC_STATE_FL_NONE; + lli->lli_pcc_inode = NULL; + mutex_init(&lli->lli_group_mutex); + lli->lli_group_users = 0; + lli->lli_group_gid = 0; } mutex_init(&lli->lli_layout_mutex); memset(lli->lli_jobid, 0, sizeof(lli->lli_jobid)); @@ -1046,17 +1083,16 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) /* client additional sb info */ lsi->lsi_llsbi = sbi = ll_init_sbi(); - if (!sbi) - GOTO(out_free_cfg, err = -ENOMEM); + if (IS_ERR(sbi)) + GOTO(out_free_cfg, err = PTR_ERR(sbi)); err = ll_options(lsi->lsi_lmd->lmd_opts, sbi); if (err) GOTO(out_free_cfg, err); -#ifndef HAVE_DCACHE_LOCK /* kernel >= 2.6.38 store dentry operations in sb->s_d_op. */ sb->s_d_op = &ll_d_ops; -#endif + /* UUID handling */ generate_random_uuid(uuid.b); snprintf(sbi->ll_sb_uuid.uuid, UUID_SIZE, "%pU", uuid.b); @@ -1177,7 +1213,7 @@ void ll_put_super(struct super_block *sb) int next, force = 1, rc = 0; ENTRY; - if (!sbi) + if (IS_ERR(sbi)) GOTO(out_no_sbi, 0); /* Should replace instance_id with something better for ASLR */ @@ -1284,10 +1320,15 @@ void ll_dir_clear_lsm_md(struct inode *inode) LASSERT(S_ISDIR(inode->i_mode)); - if (lli->lli_lsm_md != NULL) { + if (lli->lli_lsm_md) { lmv_free_memmd(lli->lli_lsm_md); lli->lli_lsm_md = NULL; } + + if (lli->lli_default_lsm_md) { + lmv_free_memmd(lli->lli_default_lsm_md); + lli->lli_default_lsm_md = NULL; + } } static struct inode *ll_iget_anon_dir(struct super_block *sb, @@ -1356,12 +1397,19 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) ll_i2sbi(inode)->ll_fsname, PFID(&lli->lli_fid)); lsm_md_dump(D_INODE, lsm); + if (!lmv_dir_striped(lsm)) + goto out; + /* XXX sigh, this lsm_root initialization should be in * LMV layer, but it needs ll_iget right now, so we * put this here right now. */ for (i = 0; i < lsm->lsm_md_stripe_count; i++) { fid = &lsm->lsm_md_oinfo[i].lmo_fid; LASSERT(lsm->lsm_md_oinfo[i].lmo_root == NULL); + + if (!fid_is_sane(fid)) + continue; + /* Unfortunately ll_iget will call ll_update_inode, * where the initialization of slave inode is slightly * different, so it reset lsm_md to NULL to avoid @@ -1379,12 +1427,52 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) return rc; } } - +out: lli->lli_lsm_md = lsm; return 0; } +static void ll_update_default_lsm_md(struct inode *inode, struct lustre_md *md) +{ + struct ll_inode_info *lli = ll_i2info(inode); + + if (!md->default_lmv) { + /* clear default lsm */ + if (lli->lli_default_lsm_md) { + 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 = NULL; + } + up_write(&lli->lli_lsm_sem); + } + } else if (lli->lli_default_lsm_md) { + /* update default lsm if it changes */ + 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 { + up_read(&lli->lli_lsm_sem); + } + } 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); + } +} + static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); @@ -1397,6 +1485,10 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) CDEBUG(D_INODE, "update lsm %p of "DFID"\n", lli->lli_lsm_md, PFID(ll_inode2fid(inode))); + /* update default LMV */ + if (md->default_lmv) + ll_update_default_lsm_md(inode, md); + /* * no striped information from request, lustre_md from req does not * include stripeEA, see ll_md_setattr() @@ -1419,10 +1511,9 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) * * foreign LMV should not change. */ - if (lli->lli_lsm_md && - lli->lli_lsm_md->lsm_md_magic != LMV_MAGIC_FOREIGN && - !lsm_md_eq(lli->lli_lsm_md, lsm)) { - if (lsm->lsm_md_layout_version <= + if (lli->lli_lsm_md && !lsm_md_eq(lli->lli_lsm_md, lsm)) { + if (lmv_dir_striped(lli->lli_lsm_md) && + lsm->lsm_md_layout_version <= lli->lli_lsm_md->lsm_md_layout_version) { CERROR("%s: "DFID" dir layout mismatch:\n", ll_i2sbi(inode)->ll_fsname, @@ -1442,15 +1533,6 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) if (!lli->lli_lsm_md) { struct cl_attr *attr; - if (lsm->lsm_md_magic == LMV_MAGIC_FOREIGN) { - /* set md->lmv to NULL, so the following free lustre_md - * will not free this lsm */ - md->lmv = NULL; - lli->lli_lsm_md = lsm; - up_write(&lli->lli_lsm_sem); - RETURN(0); - } - rc = ll_init_lsm_md(inode, md); up_write(&lli->lli_lsm_sem); if (rc != 0) @@ -1466,6 +1548,9 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) */ down_read(&lli->lli_lsm_sem); + if (!lmv_dir_striped(lli->lli_lsm_md)) + GOTO(unlock, rc); + OBD_ALLOC_PTR(attr); if (attr == NULL) GOTO(unlock, rc = -ENOMEM); @@ -1501,17 +1586,20 @@ void ll_clear_inode(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); + ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", PFID(ll_inode2fid(inode)), inode); - if (S_ISDIR(inode->i_mode)) { - /* these should have been cleared in ll_file_release */ - LASSERT(lli->lli_opendir_key == NULL); - LASSERT(lli->lli_sai == NULL); - LASSERT(lli->lli_opendir_pid == 0); - } + if (S_ISDIR(inode->i_mode)) { + /* these should have been cleared in ll_file_release */ + LASSERT(lli->lli_opendir_key == NULL); + LASSERT(lli->lli_sai == NULL); + LASSERT(lli->lli_opendir_pid == 0); + } else { + pcc_inode_free(inode); + } md_null_inode(sbi->ll_md_exp, ll_inode2fid(inode)); @@ -1534,7 +1622,7 @@ void ll_clear_inode(struct inode *inode) ll_xattr_cache_destroy(inode); -#ifdef CONFIG_FS_POSIX_ACL +#ifdef CONFIG_LUSTRE_FS_POSIX_ACL forget_all_cached_acls(inode); if (lli->lli_posix_acl) { posix_acl_release(lli->lli_posix_acl); @@ -1636,7 +1724,9 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); struct md_op_data *op_data = NULL; + ktime_t kstart = ktime_get(); int rc = 0; + ENTRY; CDEBUG(D_VFSTRACE, "%s: setattr inode "DFID"(%p) from %llu to %llu, " @@ -1735,14 +1825,28 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, if (attr->ia_valid & (ATTR_SIZE | ATTR_ATIME | ATTR_ATIME_SET | ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME) || xvalid & OP_XVALID_CTIME_SET) { - /* For truncate and utimes sending attributes to OSTs, setting - * mtime/atime to the past will be performed under PW [0:EOF] - * extent lock (new_size:EOF for truncate). It may seem - * excessive to send mtime/atime updates to OSTs when not - * setting times to past, but it is necessary due to possible - * time de-synchronization between MDT inode and OST objects - */ - rc = cl_setattr_ost(lli->lli_clob, attr, xvalid, 0); + bool cached = false; + + rc = pcc_inode_setattr(inode, attr, &cached); + if (cached) { + if (rc) { + CERROR("%s: PCC inode "DFID" setattr failed: " + "rc = %d\n", + ll_i2sbi(inode)->ll_fsname, + PFID(&lli->lli_fid), rc); + GOTO(out, rc); + } + } else { + /* For truncate and utimes sending attributes to OSTs, + * setting mtime/atime to the past will be performed + * under PW [0:EOF] extent lock (new_size:EOF for + * truncate). It may seem excessive to send mtime/atime + * updates to OSTs when not setting times to past, but + * it is necessary due to possible time + * de-synchronization between MDT inode and OST objects + */ + rc = cl_setattr_ost(lli->lli_clob, attr, xvalid, 0); + } } /* If the file was restored, it needs to set dirty flag. @@ -1793,8 +1897,10 @@ out: inode_has_no_xattr(inode); } - ll_stats_ops_tally(ll_i2sbi(inode), (attr->ia_valid & ATTR_SIZE) ? - LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1); + if (!rc) + ll_stats_ops_tally(ll_i2sbi(inode), attr->ia_valid & ATTR_SIZE ? + LPROC_LL_TRUNC : LPROC_LL_SETATTR, + ktime_us_delta(ktime_get(), kstart)); return rc; } @@ -1838,7 +1944,10 @@ int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs, int rc; ENTRY; - max_age = ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS; + max_age = ktime_get_seconds() - sbi->ll_statfs_max_age; + + if (sbi->ll_flags & LL_SBI_LAZYSTATFS) + flags |= OBD_STATFS_NODELAY; rc = obd_statfs(NULL, sbi->ll_md_exp, osfs, max_age, flags); if (rc) @@ -1852,9 +1961,6 @@ int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs, if (osfs->os_state & OS_STATE_SUM) GOTO(out, rc); - if (sbi->ll_flags & LL_SBI_LAZYSTATFS) - flags |= OBD_STATFS_NODELAY; - rc = obd_statfs(NULL, sbi->ll_dt_exp, &obd_osfs, max_age, flags); if (rc) /* Possibly a filesystem with no OSTs. Report MDT totals. */ GOTO(out, rc = 0); @@ -1882,15 +1988,16 @@ int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs, out: RETURN(rc); } + int ll_statfs(struct dentry *de, struct kstatfs *sfs) { struct super_block *sb = de->d_sb; struct obd_statfs osfs; __u64 fsid = huge_encode_dev(sb->s_dev); + ktime_t kstart = ktime_get(); int rc; - CDEBUG(D_VFSTRACE, "VFS Op: at %llu jiffies\n", get_jiffies_64()); - ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_STAFS, 1); + CDEBUG(D_VFSTRACE, "VFS Op:sb=%s (%p)\n", sb->s_id, sb); /* Some amount of caching on the client is allowed */ rc = ll_statfs_internal(ll_s2sbi(sb), &osfs, OBD_STATFS_SUM); @@ -1913,11 +2020,15 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs) } } - sfs->f_blocks = osfs.os_blocks; - sfs->f_bfree = osfs.os_bfree; - sfs->f_bavail = osfs.os_bavail; + sfs->f_blocks = osfs.os_blocks; + sfs->f_bfree = osfs.os_bfree; + sfs->f_bavail = osfs.os_bavail; sfs->f_fsid.val[0] = (__u32)fsid; sfs->f_fsid.val[1] = (__u32)(fsid >> 32); + + ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_STATFS, + ktime_us_delta(ktime_get(), kstart)); + return 0; } @@ -1967,7 +2078,7 @@ int ll_update_inode(struct inode *inode, struct lustre_md *md) return rc; } -#ifdef CONFIG_FS_POSIX_ACL +#ifdef CONFIG_LUSTRE_FS_POSIX_ACL if (body->mbo_valid & OBD_MD_FLACL) { spin_lock(&lli->lli_lock); if (lli->lli_posix_acl) @@ -2131,13 +2242,21 @@ 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) + if (S_ISREG(inode->i_mode) && lli->lli_clob != NULL) { /* It is last chance to write out dirty pages, - * otherwise we may lose data while umount */ - cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, CL_FSYNC_LOCAL, 1); - + * otherwise we may lose data while umount. + * + * If i_nlink is 0 then just discard data. This is safe because + * local inode gets i_nlink 0 from server only for the last + * unlink, so that file is not opened somewhere else + */ + 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 @@ -2149,9 +2268,9 @@ void ll_delete_inode(struct inode *inode) */ nrpages = mapping->nrpages; if (nrpages) { - xa_lock_irq(&mapping->i_pages); + xa_lock_irqsave(&mapping->i_pages, flags); nrpages = mapping->nrpages; - xa_unlock_irq(&mapping->i_pages); + xa_unlock_irqrestore(&mapping->i_pages, flags); } /* Workaround end */ LASSERTF(nrpages == 0, "%s: inode="DFID"(%p) nrpages=%lu, " @@ -2159,9 +2278,7 @@ void ll_delete_inode(struct inode *inode) ll_i2sbi(inode)->ll_fsname, PFID(ll_inode2fid(inode)), inode, nrpages); -#ifdef HAVE_SBOPS_EVICT_INODE ll_clear_inode(inode); -#endif clear_inode(inode); EXIT; @@ -2294,16 +2411,16 @@ void ll_umount_begin(struct super_block *sb) } obd->obd_force = 1; - obd = class_exp2obd(sbi->ll_dt_exp); - if (obd == NULL) { + obd = class_exp2obd(sbi->ll_dt_exp); + if (obd == NULL) { CERROR("Invalid LOV connection handle %#llx\n", - sbi->ll_dt_exp->exp_handle.h_cookie); - EXIT; - return; - } - obd->obd_force = 1; + sbi->ll_dt_exp->exp_handle.h_cookie); + EXIT; + return; + } + obd->obd_force = 1; - OBD_ALLOC_PTR(ioc_data); + OBD_ALLOC_PTR(ioc_data); if (ioc_data) { obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_md_exp, sizeof *ioc_data, ioc_data, NULL); @@ -2328,34 +2445,34 @@ void ll_umount_begin(struct super_block *sb) int ll_remount_fs(struct super_block *sb, int *flags, char *data) { - struct ll_sb_info *sbi = ll_s2sbi(sb); - char *profilenm = get_profile_name(sb); - int err; - __u32 read_only; - - if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) { - read_only = *flags & MS_RDONLY; - err = obd_set_info_async(NULL, sbi->ll_md_exp, - sizeof(KEY_READ_ONLY), - KEY_READ_ONLY, sizeof(read_only), - &read_only, NULL); - if (err) { - LCONSOLE_WARN("Failed to remount %s %s (%d)\n", - profilenm, read_only ? - "read-only" : "read-write", err); - return err; - } + struct ll_sb_info *sbi = ll_s2sbi(sb); + char *profilenm = get_profile_name(sb); + int err; + __u32 read_only; + + if ((*flags & MS_RDONLY) != (sb->s_flags & SB_RDONLY)) { + read_only = *flags & MS_RDONLY; + err = obd_set_info_async(NULL, sbi->ll_md_exp, + sizeof(KEY_READ_ONLY), + KEY_READ_ONLY, sizeof(read_only), + &read_only, NULL); + if (err) { + LCONSOLE_WARN("Failed to remount %s %s (%d)\n", + profilenm, read_only ? + "read-only" : "read-write", err); + return err; + } - if (read_only) - sb->s_flags |= MS_RDONLY; - else - sb->s_flags &= ~MS_RDONLY; + if (read_only) + sb->s_flags |= SB_RDONLY; + else + sb->s_flags &= ~SB_RDONLY; - if (sbi->ll_flags & LL_SBI_VERBOSE) - LCONSOLE_WARN("Remounted %s %s\n", profilenm, - read_only ? "read-only" : "read-write"); - } - return 0; + if (sbi->ll_flags & LL_SBI_VERBOSE) + LCONSOLE_WARN("Remounted %s %s\n", profilenm, + read_only ? "read-only" : "read-write"); + } + return 0; } /** @@ -2405,7 +2522,9 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, { struct ll_sb_info *sbi = NULL; struct lustre_md md = { NULL }; + bool default_lmv_deleted = false; int rc; + ENTRY; LASSERT(*inode || sb); @@ -2415,6 +2534,15 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, if (rc != 0) GOTO(out, rc); + /* + * clear default_lmv only if intent_getattr reply doesn't contain it. + * but it needs to be done after iget, check this early because + * ll_update_lsm_md() may change md. + */ + if (it && (it->it_op & (IT_LOOKUP | IT_GETATTR)) && + S_ISDIR(md.body->mbo_mode) && !md.default_lmv) + default_lmv_deleted = true; + if (*inode) { rc = ll_update_inode(*inode, &md); if (rc != 0) @@ -2437,7 +2565,7 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, sbi->ll_flags & LL_SBI_32BIT_API), &md); if (IS_ERR(*inode)) { -#ifdef CONFIG_FS_POSIX_ACL +#ifdef CONFIG_LUSTRE_FS_POSIX_ACL if (md.posix_acl) { posix_acl_release(md.posix_acl); md.posix_acl = NULL; @@ -2478,6 +2606,9 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, LDLM_LOCK_PUT(lock); } + if (default_lmv_deleted) + ll_update_default_lsm_md(*inode, &md); + GOTO(out, rc = 0); out: @@ -2554,7 +2685,8 @@ void ll_unlock_md_op_lsm(struct md_op_data *op_data) struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, struct inode *i1, struct inode *i2, const char *name, size_t namelen, - __u32 mode, __u32 opc, void *data) + __u32 mode, enum md_op_code opc, + void *data) { LASSERT(i1 != NULL); @@ -2578,15 +2710,13 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, ll_i2gids(op_data->op_suppgids, i1, i2); op_data->op_fid1 = *ll_inode2fid(i1); - op_data->op_default_stripe_offset = -1; + op_data->op_code = opc; if (S_ISDIR(i1->i_mode)) { down_read(&ll_i2info(i1)->lli_lsm_sem); op_data->op_mea1_sem = &ll_i2info(i1)->lli_lsm_sem; op_data->op_mea1 = ll_i2info(i1)->lli_lsm_md; - if (opc == LUSTRE_OPC_MKDIR) - op_data->op_default_stripe_offset = - ll_i2info(i1)->lli_def_stripe_offset; + op_data->op_default_mea1 = ll_i2info(i1)->lli_default_lsm_md; } if (i2) { @@ -2640,7 +2770,7 @@ int ll_show_options(struct seq_file *seq, struct dentry *dentry) int ll_show_options(struct seq_file *seq, struct vfsmount *vfs) #endif { - struct ll_sb_info *sbi; + struct ll_sb_info *sbi; #ifdef HAVE_SUPEROPS_USE_DENTRY LASSERT((seq != NULL) && (dentry != NULL)); @@ -2650,20 +2780,25 @@ int ll_show_options(struct seq_file *seq, struct vfsmount *vfs) sbi = ll_s2sbi(vfs->mnt_sb); #endif - if (sbi->ll_flags & LL_SBI_NOLCK) - seq_puts(seq, ",nolock"); - - if (sbi->ll_flags & LL_SBI_FLOCK) - seq_puts(seq, ",flock"); + if (sbi->ll_flags & LL_SBI_NOLCK) + seq_puts(seq, ",nolock"); - if (sbi->ll_flags & LL_SBI_LOCALFLOCK) - seq_puts(seq, ",localflock"); + /* "flock" is the default since 2.13, but it wasn't for many years, + * so it is still useful to print this to show it is enabled. + * Start to print "noflock" so it is now clear when flock is disabled. + */ + if (sbi->ll_flags & LL_SBI_FLOCK) + seq_puts(seq, ",flock"); + else if (sbi->ll_flags & LL_SBI_LOCALFLOCK) + seq_puts(seq, ",localflock"); + else + seq_puts(seq, ",noflock"); - if (sbi->ll_flags & LL_SBI_USER_XATTR) - seq_puts(seq, ",user_xattr"); + if (sbi->ll_flags & LL_SBI_USER_XATTR) + seq_puts(seq, ",user_xattr"); - if (sbi->ll_flags & LL_SBI_LAZYSTATFS) - seq_puts(seq, ",lazystatfs"); + if (sbi->ll_flags & LL_SBI_LAZYSTATFS) + seq_puts(seq, ",lazystatfs"); if (sbi->ll_flags & LL_SBI_USER_FID2PATH) seq_puts(seq, ",user_fid2path"); @@ -2671,7 +2806,7 @@ int ll_show_options(struct seq_file *seq, struct vfsmount *vfs) if (sbi->ll_flags & LL_SBI_ALWAYS_PING) seq_puts(seq, ",always_ping"); - RETURN(0); + RETURN(0); } /** @@ -2728,6 +2863,7 @@ void ll_dirty_page_discard_warn(struct page *page, int ioret) path = ll_d_path(dentry, buf, PAGE_SIZE); } + /* The below message is checked in recovery-small.sh test_24b */ CDEBUG(D_WARNING, "%s: dirty page discard: %s/fid: "DFID"/%s may get corrupted " "(rc %d)\n", ll_i2sbi(inode)->ll_fsname, @@ -2756,12 +2892,12 @@ ssize_t ll_copy_user_md(const struct lov_user_md __user *md, if (lum_size < 0) RETURN(lum_size); - OBD_ALLOC(*kbuf, lum_size); + OBD_ALLOC_LARGE(*kbuf, lum_size); if (*kbuf == NULL) RETURN(-ENOMEM); if (copy_from_user(*kbuf, md, lum_size) != 0) { - OBD_FREE(*kbuf, lum_size); + OBD_FREE_LARGE(*kbuf, lum_size); RETURN(-EFAULT); } @@ -2780,7 +2916,7 @@ void ll_compute_rootsquash_state(struct ll_sb_info *sbi) struct lnet_process_id id; /* Update norootsquash flag */ - down_write(&squash->rsi_sem); + spin_lock(&squash->rsi_lock); if (list_empty(&squash->rsi_nosquash_nids)) sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH; else { @@ -2801,7 +2937,7 @@ void ll_compute_rootsquash_state(struct ll_sb_info *sbi) else sbi->ll_flags &= ~LL_SBI_NOROOTSQUASH; } - up_write(&squash->rsi_sem); + spin_unlock(&squash->rsi_lock); } /** @@ -2893,13 +3029,8 @@ int ll_getparent(struct file *file, struct getparent __user *arg) if (rc < 0) GOTO(ldata_free, rc); -#ifdef HAVE_XATTR_HANDLER_FLAGS rc = ll_xattr_list(inode, XATTR_NAME_LINK, XATTR_TRUSTED_T, buf.lb_buf, buf.lb_len, OBD_MD_FLXATTR); -#else - rc = ll_getxattr(file_dentry(file), XATTR_NAME_LINK, buf.lb_buf, - buf.lb_len); -#endif /* HAVE_XATTR_HANDLER_FLAGS */ if (rc < 0) GOTO(lb_free, rc);