?找对方向,事半功倍,为什么找这个客户?
by ?找对方向,事半功倍,为什么找这个客户?先生
销售精英2天强化训练
【时间地点】 2016年 10月15-16日深圳 11月05-06日上海
11月19-20日北京 11月26-27日深圳 12月17-18日上海
Judge(评价)一个人,一个公司是不是优秀,不要看他是不是Harvard(哈佛大学),是不是Stanford(斯坦福大学).不要judge(评价)里面有多少名牌大学毕业生,而要judge(评价)这帮人干活是不是发疯一样干,看他每天下班是不是笑眯眯回家!
——阿里巴巴公司马云
——课程简介
第一章客户需求分析
思考:
1、面对客户找不到话说,怎么办?二次沟通应该聊些什么?
2、为什么我把所有资料都给客户了,他还说要考虑一下?
3、同一件事,客户不同的人告诉我不一样的要求,听谁的?
4、同一件事,客户同一个人告诉我两次的答案不一样,听哪次的?
5、推荐哪一种产品给客户好?最好的?稍好的?还是够用的?
4、为什么我按客户要求去做,他还是没有选择我们?
5、不同的客户,我应该如何应对?
6、忠诚的客户应该如何培养?
第一节、为什么要对客户需求进行分析?
1、客户初次告诉我们的信息往往是有所保留的;
2、客户想要的产品,不一定就是实际所需要的;
3、客户不缺少产品信息,困惑的是自己如何选择;
4、客户购买决定是比较出来的,没有比较,产品就没有价值;
5、销售人员第一思想是战争思想,情报最重要;
6、未来的送货员,联络员,报价员将被淘汰;
第二节、如何做好客户需求分析?
一、基本要求:
1.无事不登三宝殿,有目的地做好拜访计划;
2.引导客户,首先要控制谈话的方向、节奏、内容;
3.从讲产品的“卖点”转变到讲客户的“买点”
4.好的,不一定是最适合的,最合适的才是最好的;
5.不要把猜测当成事实,“谈”的是什么?“判”是由谁判?
6.讨论:客户说价格太贵,代表哪15种不同的意思?
二、需求分析要点:
1.了解客户的4种期望目标;
2.了解客户采购的5个适当;
3.判断谁是关键人的8个依据;
4.哪6大类问题不可以问? 要表达别人听得懂的话;
5.提问注意的“3不谈”,“4不讲”;
6.客户需求分析手册制定的6个步骤;
?找对方向,事半功倍,为什么找这个客户?
?时间没对,努力白费,为什么这个时候找?
?找对人,说对话,为什么找这个人?
?为什么推荐这个产品?给客户需要的,而不是自己想给的;
?为什么给这样的服务? 客户看重不是产品,而是使用价值;
?为什么报这个价? 在客户的预算与同行之间找到平衡;
7.为什么还这个价?关注竞争对手,调整自己的策略;
第二章 如何正确推荐产品
思考:
1、为什么我满足客户所提出的要求,客户却还需要考虑一下?
2、为什么客户不相信我质量与服务的承诺?
3、面对客户提出高端产品的要求,而我只有低端产品,怎么办?
4、如何推荐产品才能让客户感觉到我们跟别人不一样;
第一节 为什么需要我们正确地推荐产品?
1、客户往往对自己深层次的问题并不清楚;
2、客户的提出的要求可能是模糊或抽象,有的仅仅提出方向,不要局限于客户明显的问题,头痛医头,脚痛医脚;
3、客户往往会以我们竞品给他的条件要求我们;
4、满足客户提出的要求,是引导客户在不同公司之间做比较,而不在我公司做出决策;
第二节 如何帮助客户建立“排他性”的采购标准?
案例:客户关心的是你如何保证你的质量和服务水平
1、打仗就是打后勤,推荐产品中常用的34项内容;
2、产品的功能与客户需要解决的问题要相对应;客户喜欢提供解决方案的人,而不仅提供工具的人;
3、如何给竞争对手业务员设置障碍?
第三节 见什么人,说什么话;
不同情况下如何讲?时间、能力、精力、兴趣、文化水平、不同的职位等;
1. 什么情况下偏重于理性说服,打动别人的脑?
2. 什么情况下偏重于情感说服,打动别人的心?
3. 何种情况下只讲优势不讲劣势?
4. 何种情况下即讲优势又讲劣势?
第三章如何有效处理异议
思考
1、遇到小气、固执、粗鲁、啰嗦、刻薄、吹毛求疵、优柔寡断的客户应对?
2、客户直接挂电话,怎么办?
3、第二次见面,客户对我大发脾气,怎么办?
4、有一个行业,销售人员每天都会遇到大量的拒绝,为什么却没有任何人会沮丧?
5、客户就没有压力吗?知已知彼,客户采购时会有哪些压力?
6、为什么客户在上班时与下班后会表现不同的性格特征?
第一节:买卖双方的心情分析
1、如果一方比另一方更主动、更积极追求合作,则后者称为潜在客户
2、卖方知道某价一定不能卖,但买方不知道什么价不能买;
3、当卖方表现自己很想卖,买方会表现自己不想买;
4、买方还的价,并不一定是他认为商品就应该值这个价;
5、付钱之前,买方占优势,之后,卖方占优势;
第二节、理解客户购买时的心态;
1、客户谈判时常用7种试探技巧分析;
2、客户态度非常好,就是不下订单,为什么?
3、为什么有些客户让我们感觉高高在上,花钱是大爷?难道他们素质真的差?
4、客户自身会有哪6个压力?
案例:客户提出合理条件,是否我就应该降价?
案例:如何分清客户异议的真实性?
案例:当谈判出现僵局时怎么办?
案例:为什么我答应客户提出的所有的条件,反而失去了订单?
案例:客户一再地提出不同的条件,怎么处理?
案例:客户要求我降价时,怎么办?请分8个步骤处理
第三节 客户异议处理的5个区分
1、要区分“第一” 还是“唯一”
2、对客户要求的真伪进行鉴别;
3、要区分“情绪”还是“行为”
4、区分“假想”还是“事实”
5、区别问题的轻重,缓急;
第四章 如何建立良好的客情关系?
案例:销售工作需要疯狂、圆滑、奉承、见人说人话,见鬼说鬼话吗?
案例:生意不成仁义在,咱俩交个朋友,这句话应该由谁说?
案例:邀请客户吃饭,你应该怎么说?
案例:当客户表扬了你,你会怎么回答?
案例:我代表公司的形象,是否我应该表现自己很强势?
案例:为了获得客户的信任,我是否应该花重金包装自己?让自己很完美?
案例:是否需要处处表现自己很有礼貌?
案例:如何与企业高层、政府高层打交道?
第一节 做回真实和真诚的自己,表里如一
礼仪的目的是尊重别人,而不是伪装自己,礼仪中常见的错误;
1、演别人,再好的演技也会搞砸,想做别人的时候,你就会离自己很远;
2、不同的人,需求不同,越改越累,越改越气,只会把自己折磨得心浮气躁,不得人心;
3、以朋友的心态与客户交往,过多的商业化语言、行为、过多的礼仪只会让客户感觉到生硬、距离、排斥、公事公办,没有感情;
4、适当的暴露自己的缺点,越完美的人越不可信;
5、守时,守信,守约,及时传递进程与信息,让客户感觉到可控性;
6、销售不是向客户笑,而是要让客户对自己笑;
第二节 感谢伤害我的人,是因为我自己错了;
1、一味顺从、推卸责任、理论交谈、谈论小事、无诚信;
2、当客户说过一段时间、以后、改天、回头、月底时,如何应对?
3、越完美的人越不可信,自我暴露的四个层次;
4、做好防错性的服务,签完合同仅仅是合作的开始;
?指导客户如何使用;
?跟踪产品使用的情况;
?为客户在使用过程中提供指导建议;
?积极解答客户在使用中提出的问题;
第四章团队配合
思考:
1.团队配合的前提是什么?是否任意两个人在一起都会有团队精神?
2.团队配合中为什么会出现扯皮的现象?
3.为什么公司花那么高成本让大家加深感情,但有些人之间还是有隔阂?
4.业绩好的人影响业绩差的人容易还是业绩差的影响业绩好的容易?
5.统一底薪好?还是差别化底薪好?如何让大家都觉得公平?
6.为什么有能力的不听话,听话的却没能力?
7.为什么有些人总是不按我要求的方法去做?
8.面对业绩总是很差的员工,到底是留还是开?
第一节团队配合的重要性
1.优秀的业务员业绩往往是普通的几十甚至上百倍;
2.提高成交的效率,不要杀敌一千,而自损八百;
3.优秀业务员缺时间,业绩普通的业务员缺能力,扬长避短,人尽其才;
4.把人力资源效益利用最大化;
5.打造完美的团队,让成员的缺点相互抵消;
第二节,如何开展团队配合
第一、能力互补
1.关注员工的能力,不要把未来寄托在员工未知的潜能上;
2.不要把员工塑造成同一类型的人,不把专才当全才用;
3.团队以能为本,销售岗位常见的14项技能;
4.售前、售中、售后人员要求与如何搭配?
5.案例:新员工有激情,但能力不足,老员工有能力,但激情不足,怎么办?
第二、利益关联
1.为什么成员会相互冷漠、互不关心、彼此封锁信息和资源?
2.为什么团队成员把团队的事不当回事?
3.如何才能让团队成员真心的为优秀的成员而高兴?
4.开除业绩差的员工,其他成员缺乏安全感怎么办?
5.如何才能让团队自动自发的努力工作?
第三节、不同客户喜欢不同风格的销售人员
1、 销售人员形象与举止,注意自己的形象;
2、 是否具备相似的背景,门当户对;
3、 是否具备相同的认识,道不同不相为盟;
4、 是否“投其所好”,话不投机半句多;
5、 赞美,喜欢对方,我们同样对喜欢我们的人有好感;
先交流感情,增进互信,欲速则不达;
6、 是否对销售人员熟悉,销售最忌讳交浅言深;
初次见面就企图跟别人成为朋友的行为很幼稚;
初次见面就暗示好处的行为很肤浅;
刚见面就强调价格很便宜的行为很愚蠢;
7、 销售人员是否具备亲和力,别人的脸是自己的一面镜子;
成交并不取决于说理,而是取决于心情
8、 销售人员是否值得信赖。
第六章 新客户开发
案例:为什么客户一开始很有兴趣,但迟迟不下单?
案例:前天明明说不买的客户居然今天却买了,客户的话能相信吗?
案例:客户答应买我司的产品,却突然变卦买别人的了,为什么?
案例:为什么我们会买自己没有兴趣的而且并不需要的产品?
一、客户是根据自己所投入的精力、金钱来确定自己的态度;
二、如何才能引导客户作自我说服?
1.不要轻易给客户下结论,谁会买,谁不会买
2.态度上的变化叫说服,行为上的变化叫接受;
3.我们都喜欢为我们自己的行为找理由,却不善于做我们已找到理由的事;
4.客户是发现了自己的需求,“发现”的依据是自己的行为;
5.案例:合同签订后,应该问哪4句话,提升客户忠诚度?
第七章 自我激励
1.做销售工作赚钱最快,且最容易得到老板的重视、同事的尊重;
2.不要把第一次见面看成最后一次,工作要积极但不要着急;
3.不是成功太慢,而是放弃太快,钱是给内行的人赚的;
4.不要报着试试看的心态,企图一夜暴富的投机心态让客户反感;
5.不是有希望才坚持,而是坚持了才有希望;
6.付出才会拥有,而不是拥有才付出;做了才会,而不是会了才做;
7.好工作是做出来的,不是找出来的,不要把自己托付给公司,而要独立成长;
8.尝试不同的工作方法,而不是多年重复使用一种方式,具备试错的精神;
9.工作可以出错,但不可以不做,世界上最危险的莫过于原地不动;
10.不要把未来寄托在自己一无所知的行业上,做好目前的工作;
【培训特点】
1.分组讨论,训练为主,互动式教学;2次现场考试;
2.真实案例分析,大量课后作业题,既有抢答,又有辩论,还有现场演练,热烈的课堂氛围;
3.将销售管理融入培训现场:
3.1 不仅关注个人学习表现,而且重视团队合作;
3.2 不仅关注2天以内的学习,而且营造2天以后的培训学习氛围;
3.3 不仅考核个人得分,而且考核团队得分;不仅考核学员的学习成绩,而且考核学员学习的参与度;
【讲师介绍】 王老师
销售团队管理咨询师、销售培训讲师;
曾任可口可乐(中国)公司业务经理;阿里巴巴(中国)网络技术有限公司业务经理;
清华大学.南京大学EMBA特邀培训讲师;新加坡莱佛士学院特约讲师;
2000年至今一直从事销售与销售人员激励与训练工作,曾任可口可乐的业务经理,全球知名企业阿里巴巴公司的业务经理,曾每月疯狂上门拜访100家以上的客户,半军事化的销售职业生涯,高强度的工作压力,全面系统的受训经历,积累了丰富的客户收集、销售谈判、客户跟进、客户服务、自我激励的经验,在公司曾获“悍将杯”榜眼。
【曾经培训过的部份客户】
华为公司/立邦漆业/太平保险/欧普照明/可口可乐/扬子石化/飞利浦/百度/中国移动/北京东信北邮/中国联通/成都通发集团/携程网络/广州方圆房产/深圳南海酒店/桂林三金药业/三一重工/深圳宝德集团/义乌邮政局/广西水电工程局/重庆煤科院/深圳特发股份/北京曲美家私/九阳电器/珠港机场/巢湖邮政/济南邮政/南京医药总公司/国美电器/雨润集团/中国一拖集团能源分公司/重庆科创学院/
【参加对象】 总经理、销售总监、区域经理、销售经理、业务代表、销售培训专员等。
【学习费用】 2800圆/2天/1人(含资.料.费、午.餐、茶.点、发..票等 )
【手....机】 o755-6662o355 l3544ol33l5颜小姐
【邮....箱】 971700732(a)qq.com 微.信: 971700732
退订请转发邮件至971700732(a)qq.com
5 years, 8 months
Enjoy successful Potential Customer Generation at cheap cost
by Dylan Chan
Greetings!
I believe you have seen my company's previous email.
I’m Dylan Chan, and please allow me to share with you briefly what we do
at M&M Group that enables our clients to enjoy an impactful Email Marketing
campaign.
This is the newest email marketing campaign. It has multiple level email
potential leads generation.
We handpicked your potentials clients, helping you to save and drive your
sales to its peak!
See below to understand more. And it’s PIC Claimable! Check out the
attached brochure.
Just call me at 6817 2878 and I will explain more in details
Dylan Chan | Sales Manager
Dylan.Chan(a)mmg.com.sg | +65 9640 2456 | +6817 2878
www.marketinglah.com | Multi-Level Email Marketing
3 Ang Mo Kio Street 62, #06-14, LINK@AMK, Singapore 569139
Click this link to unsubscribe:
http://marketinglahmail.com/engine/unsubscribe.php?M=1475133&C=2e435053dd...
5 years, 8 months
[ndctl PATCH] test, multi-pmem: validate the creation and detection of multi-pmem configurations
by Dan Williams
Create multiple pmem namespaces in a region and check that the same
namespaces return in the same order after a region disable/enable event.
Also, check that the highest BLK capacity is limited to the
dimm-physical-address space after the highest PMEM allocation.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
ndctl/Makefile.am | 1
ndctl/builtin-test.c | 3 +
test.h | 1
test/Makefile.am | 12 ++
test/multi-pmem.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++
util/size.h | 2
6 files changed, 291 insertions(+)
create mode 100644 test/multi-pmem.c
diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
index 63f387b58de9..29237b76713a 100644
--- a/ndctl/Makefile.am
+++ b/ndctl/Makefile.am
@@ -39,5 +39,6 @@ ndctl_SOURCES += ../test/libndctl.c \
../util/sysfs.c \
../test/dpa-alloc.c \
../test/parent-uuid.c \
+ ../test/multi-pmem.c \
../test/core.c
endif
diff --git a/ndctl/builtin-test.c b/ndctl/builtin-test.c
index d8539a133d10..caa666b68e69 100644
--- a/ndctl/builtin-test.c
+++ b/ndctl/builtin-test.c
@@ -62,5 +62,8 @@ int cmd_test(int argc, const char **argv, struct ndctl_ctx *ctx)
rc = test_parent_uuid(loglevel, test, ctx);
fprintf(stderr, "test-parent-uuid: %s\n", result(rc));
+ rc = test_multi_pmem(loglevel, test, ctx);
+ fprintf(stderr, "test-multi-pmem: %s\n", result(rc));
+
return ndctl_test_result(test, rc);
}
diff --git a/test.h b/test.h
index bf708f38bfbf..6010f76dcf1d 100644
--- a/test.h
+++ b/test.h
@@ -16,6 +16,7 @@ void builtin_xaction_namespace_reset(void);
struct ndctl_ctx;
int test_parent_uuid(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx);
+int test_multi_pmem(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx);
int test_dax_directio(int dax_fd, void *dax_addr, off_t offset);
int test_dpa_alloc(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx);
int test_dsm_fail(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx);
diff --git a/test/Makefile.am b/test/Makefile.am
index 5513f429869f..46a1acf98f0d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -5,6 +5,7 @@ TESTS =\
dsm-fail \
dpa-alloc \
parent-uuid \
+ multi-pmem \
create.sh \
clear.sh \
dax-errors.sh
@@ -14,6 +15,7 @@ check_PROGRAMS =\
dsm-fail \
dpa-alloc \
parent-uuid \
+ multi-pmem \
dax-errors
if ENABLE_DESTRUCTIVE
@@ -78,3 +80,13 @@ device_dax_LDADD = \
$(LIBNDCTL_LIB) \
$(JSON_LIBS) \
../libutil.a
+
+multi_pmem_SOURCES = \
+ multi-pmem.c \
+ core.c \
+ ../ndctl/builtin-xaction-namespace.c \
+ ../ndctl/util/json.c
+multi_pmem_LDADD = \
+ $(LIBNDCTL_LIB) \
+ $(JSON_LIBS) \
+ ../libutil.a
diff --git a/test/multi-pmem.c b/test/multi-pmem.c
new file mode 100644
index 000000000000..a7aedd9b5025
--- /dev/null
+++ b/test/multi-pmem.c
@@ -0,0 +1,272 @@
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <libkmod.h>
+#include <uuid/uuid.h>
+#include <sys/types.h>
+#include <util/size.h>
+#include <linux/falloc.h>
+#include <linux/version.h>
+#include <ndctl/libndctl.h>
+#include <ccan/array_size/array_size.h>
+
+#ifdef HAVE_NDCTL_H
+#include <linux/ndctl.h>
+#else
+#include <ndctl.h>
+#endif
+
+#include <ndctl/builtin.h>
+#include <test.h>
+
+#define NUM_NAMESPACES 4
+#define SZ_NAMESPACE SZ_16M
+
+static int setup_namespace(struct ndctl_region *region)
+{
+ struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
+ const char *argv[] = {
+ "__func__", "-v", "-m", "raw", "-s", "16M", "-r", "",
+ };
+ int argc = ARRAY_SIZE(argv);
+
+ argv[argc - 1] = ndctl_region_get_devname(region);
+ builtin_xaction_namespace_reset();
+ return cmd_create_namespace(argc, argv, ctx);
+}
+
+static void destroy_namespace(struct ndctl_namespace *ndns)
+{
+ struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
+ const char *argv[] = {
+ "__func__", "-v", "-f", "",
+ };
+ int argc = ARRAY_SIZE(argv);
+
+ argv[argc - 1] = ndctl_namespace_get_devname(ndns);
+ builtin_xaction_namespace_reset();
+ cmd_destroy_namespace(argc, argv, ctx);
+}
+
+static int do_multi_pmem(struct ndctl_ctx *ctx, struct ndctl_test *test)
+{
+ int i;
+ char devname[100];
+ struct ndctl_bus *bus;
+ uuid_t uuid[NUM_NAMESPACES];
+ struct ndctl_namespace *ndns;
+ struct ndctl_dimm *dimm_target, *dimm;
+ struct ndctl_region *region, *target = NULL;
+ struct ndctl_namespace *namespaces[NUM_NAMESPACES];
+ unsigned long long blk_avail, blk_avail_orig, expect;
+
+ if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 9, 0))) {
+ ndctl_test_skip(test);
+ return 77;
+ }
+
+ bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0");
+ if (!bus)
+ return -ENXIO;
+
+ /* disable all regions so that set_config_data commands are permitted */
+ ndctl_region_foreach(bus, region)
+ ndctl_region_disable_invalidate(region);
+
+ ndctl_dimm_foreach(bus, dimm) {
+ int rc = ndctl_dimm_zero_labels(dimm);
+
+ if (rc < 0) {
+ fprintf(stderr, "failed to zero %s\n",
+ ndctl_dimm_get_devname(dimm));
+ return rc;
+ }
+ }
+
+ /*
+ * Set regions back to their default state and find our target
+ * region.
+ */
+ ndctl_region_foreach(bus, region) {
+ ndctl_region_enable(region);
+ if (ndctl_region_get_available_size(region)
+ == SZ_NAMESPACE * NUM_NAMESPACES)
+ target = region;
+ }
+
+ if (!target) {
+ fprintf(stderr, "multi-pmem: failed to find target region\n");
+ return -ENXIO;
+ }
+ region = target;
+
+ for (i = 0; i < (int) ARRAY_SIZE(uuid); i++) {
+ if (setup_namespace(region) != 0) {
+ fprintf(stderr, "multi-pmem: failed to setup namespace: %d\n", i);
+ return -ENXIO;
+ }
+ sprintf(devname, "namespace%d.%d",
+ ndctl_region_get_id(region), i);
+ ndctl_namespace_foreach(region, ndns)
+ if (strcmp(ndctl_namespace_get_devname(ndns), devname) == 0
+ && ndctl_namespace_is_enabled(ndns))
+ break;
+ if (!ndns) {
+ fprintf(stderr, "multi-pmem: failed to find namespace: %s\n",
+ devname);
+ return -ENXIO;
+ }
+ ndctl_namespace_get_uuid(ndns, uuid[i]);
+ }
+
+ /* bounce the region and verify everything came back as expected */
+ ndctl_region_disable_invalidate(region);
+ ndctl_region_enable(region);
+
+ for (i = 0; i < (int) ARRAY_SIZE(uuid); i++) {
+ char uuid_str1[40], uuid_str2[40];
+ uuid_t uuid_check;
+
+ ndctl_namespace_foreach(region, ndns)
+ sprintf(devname, "namespace%d.%d",
+ ndctl_region_get_id(region), i);
+ ndctl_namespace_foreach(region, ndns)
+ if (strcmp(ndctl_namespace_get_devname(ndns), devname) == 0
+ && ndctl_namespace_is_enabled(ndns))
+ break;
+ if (!ndns) {
+ fprintf(stderr, "multi-pmem: failed to restore namespace: %s\n",
+ devname);
+ return -ENXIO;
+ }
+
+ ndctl_namespace_get_uuid(ndns, uuid_check);
+ uuid_unparse(uuid_check, uuid_str2);
+ uuid_unparse(uuid[i], uuid_str1);
+ if (uuid_compare(uuid_check, uuid[i]) != 0) {
+ fprintf(stderr, "multi-pmem: expected uuid[%d]: %s, got %s\n",
+ i, uuid_str1, uuid_str2);
+ return -ENXIO;
+ }
+ namespaces[i] = ndns;
+ }
+
+ /*
+ * Check that aliased blk capacity does not increase until the
+ * highest dpa pmem-namespace is deleted.
+ */
+ dimm_target = ndctl_region_get_first_dimm(region);
+ if (!dimm_target) {
+ fprintf(stderr, "multi-pmem: failed to retrieve dimm from %s\n",
+ ndctl_region_get_devname(region));
+ return -ENXIO;
+ }
+
+ dimm = NULL;
+ ndctl_region_foreach(bus, region) {
+ if (ndctl_region_get_type(region) != ND_DEVICE_REGION_BLK)
+ continue;
+ ndctl_dimm_foreach_in_region(region, dimm)
+ if (dimm == dimm_target)
+ break;
+ if (dimm)
+ break;
+ }
+
+ blk_avail_orig = ndctl_region_get_available_size(region);
+ for (i = 1; i < NUM_NAMESPACES - 1; i++) {
+ ndns = namespaces[i];
+ sprintf(devname, "%s", ndctl_namespace_get_devname(ndns));
+ destroy_namespace(ndns);
+ blk_avail = ndctl_region_get_available_size(region);
+ if (blk_avail != blk_avail_orig) {
+ fprintf(stderr, "multi-pmem: destroy %s %llx avail, expect %llx\n",
+ devname, blk_avail, blk_avail_orig);
+ return -ENXIO;
+ }
+ }
+
+ ndns = namespaces[NUM_NAMESPACES - 1];
+ sprintf(devname, "%s", ndctl_namespace_get_devname(ndns));
+ destroy_namespace(ndns);
+ blk_avail = ndctl_region_get_available_size(region);
+ expect = (SZ_NAMESPACE / ndctl_region_get_interleave_ways(target))
+ * (NUM_NAMESPACES - 1) + blk_avail_orig;
+ if (blk_avail != expect) {
+ fprintf(stderr, "multi-pmem: destroy %s %llx avail, expect %llx\n",
+ devname, blk_avail, expect);
+ return -ENXIO;
+ }
+
+ ndctl_bus_foreach(ctx, bus) {
+ if (strncmp(ndctl_bus_get_provider(bus), "nfit_test", 9) != 0)
+ continue;
+ ndctl_region_foreach(bus, region)
+ ndctl_region_disable_invalidate(region);
+ }
+
+ return 0;
+}
+
+int test_multi_pmem(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx)
+{
+ struct kmod_module *mod;
+ struct kmod_ctx *kmod_ctx;
+ int err, result = EXIT_FAILURE;
+
+ if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 2, 0)))
+ return 77;
+
+ ndctl_set_log_priority(ctx, loglevel);
+
+ kmod_ctx = kmod_new(NULL, NULL);
+ if (!kmod_ctx)
+ return result;
+ kmod_set_log_priority(kmod_ctx, loglevel);
+
+ err = kmod_module_new_from_name(kmod_ctx, "nfit_test", &mod);
+ if (err < 0)
+ goto err_module;
+
+ err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST,
+ NULL, NULL, NULL, NULL);
+ if (err < 0) {
+ result = 77;
+ ndctl_test_skip(test);
+ fprintf(stderr, "%s unavailable skipping tests\n",
+ "nfit_test");
+ goto err_module;
+ }
+
+ result = do_multi_pmem(ctx, test);
+ kmod_module_remove_module(mod, 0);
+
+ err_module:
+ kmod_unref(kmod_ctx);
+ return result;
+}
+
+int __attribute__((weak)) main(int argc, char *argv[])
+{
+ struct ndctl_test *test = ndctl_test_new(0);
+ struct ndctl_ctx *ctx;
+ int rc;
+
+ if (!test) {
+ fprintf(stderr, "failed to initialize test\n");
+ return EXIT_FAILURE;
+ }
+
+ rc = ndctl_new(&ctx);
+ if (rc)
+ return ndctl_test_result(test, rc);
+ rc = test_multi_pmem(LOG_DEBUG, test, ctx);
+ ndctl_unref(ctx);
+ return ndctl_test_result(test, rc);
+}
diff --git a/util/size.h b/util/size.h
index 9befecb28b14..50917a5cea34 100644
--- a/util/size.h
+++ b/util/size.h
@@ -5,6 +5,8 @@
#define SZ_1M 0x00100000
#define SZ_2M 0x00200000
#define SZ_4M 0x00400000
+#define SZ_16M 0x01000000
+#define SZ_64M 0x04000000
#define SZ_1G 0x40000000
#define SZ_1T 0x10000000000ULL
5 years, 8 months
[GIT PULL] libnvdimm for 4.9
by Williams, Dan J
Hi Linus, please pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm tags/libnvdimm-for-4.9
...to receive the libnvdimm update for 4.9.
Aside from the recently added pmem sub-division support these have been
in -next for several releases with no reported issues. The sub-
division support was included in next-20161010 with no reported issues.
It passes all unit tests including new tests for all the new
functionality below.
The following changes since commit 595c73071e6641e59b83911fbb4026e767471000:
libnvdimm, region: fix flush hint table thinko (2016-09-24 11:45:38 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm tags/libnvdimm-for-4.9
for you to fetch changes up to e476f94482fc20a23b7b33b3d8e50f1953f71828:
Merge branch 'for-4.9/dax' into libnvdimm-for-next (2016-10-07 16:46:30 -0700)
----------------------------------------------------------------
libnvdimm for 4.9
* PMEM sub-division support: Allow a single PMEM region to be divided
into multiple namespaces. Originally, ~2 years ago, it was thought that
partitions of a /dev/pmemX block device could handle sub-allocations of
persistent memory for different use cases. With the decision to not
support DAX mappings of raw block-devices, and the genesis of
device-dax, the need for having multiple pmem-namespace per region has
grown.
* Device-DAX unified inode: In support of dynamic-resizing of a
device-dax instance the kernel arranges for all mappings of a
device-dax node to share the same inode. This allows unmap / truncate /
invalidation events to affect all instances of the device similar to the
behavior of mmap on block devices.
* Hardware error scrubbing reworks: The original address-range-scrub +
badblocks tracking solution allowed clearing entries at the individual
namespace level, but it failed to clear the internal list of media
errors maintained at the bus level. The result was that the next scrub
or namespace disable/re-enable event would restore the cleared
badblocks, but now that is fixed. The v4.8 kernel introduced an
auto-scrub-on-machine-check behavior to repopulate the badblocks list.
Now, in v4.9, the auto-scrub behavior can be disabled and simply arrange
for the error reported in the machine-check to be added to the list.
* DIMM health-event notification support: ACPI 6.1 defines a
notification event code that can be send to ACPI NVDIMM devices. A
poll(2) capable file descriptor for these events can be obtained from
the nmemX/nfit/flags sysfs-attribute of a libnvdimm memory device.
* Miscellaneous fixes: NVDIMM-N probe error, device-dax build error, and
a change to dedup the flush hint list to not flush the memory controller
more than necessary.
----------------------------------------------------------------
Arnd Bergmann (1):
dax: use correct dev_t value
Dan Williams (31):
libnvdimm: fix SMART Health DSM payload definition
tools/testing/nvdimm: unit test for acpi_nfit_notify()
dax: cleanup needlessly global symbol warnings
dax: reorder dax_fops function definitions
dax: rename fops from dax_dev_ to dax_
dax: embed a struct device in dax_dev
dax: convert to the cdev api
dax: define a unified inode/address_space for device-dax mappings
dax: unmap/truncate on device shutdown
dax: check resource alignment at dax region/device create
acpi, nfit: add dimm device notification support
tools/testing/nvdimm: unit test for acpi_nvdimm_notify()
tools/testing/nvdimm: test get_config_size DSM failures
libnvdimm, namespace: debug invalid interleave-set-cookie values
libnvdimm, region: move region-mapping input-paramters to nd_mapping_desc
libnvdimm, label: convert label tracking to a linked list
libnvdimm, namespace: refactor uuid_show() into a namespace_to_uuid() helper
libnvdimm, namespace: unify blk and pmem label scanning
tools/testing/nvdimm: support for sub-dividing a pmem region
libnvdimm, namespace: allow multiple pmem-namespaces per region at scan time
libnvdimm, namespace: sort namespaces by dpa at init
libnvdimm, region: update nd_region_available_dpa() for multi-pmem support
libnvdimm, namespace: expand pmem device naming scheme for multi-pmem
libnvdimm, namespace: update label implementation for multi-pmem
libnvdimm, namespace: enable allocation of multiple pmem namespaces
libnvdimm, namespace: filter out of range labels in scan_labels()
libnvdimm, namespace: lift single pmem limit in scan_labels()
libnvdimm, namespace: allow creation of multiple pmem-namespaces per region
dax: convert devm_create_dax_dev to PTR_ERR
Merge branch 'for-4.9/libnvdimm' into libnvdimm-for-next
Merge branch 'for-4.9/dax' into libnvdimm-for-next
Dave Jiang (2):
nvdimm: remove duplicate nd_mapping declaration
nvdimm: reduce duplicated wpq flushes
Geert Uytterhoeven (1):
nvdimm: Spelling s/unacknoweldged/unacknowledged/
Ross Zwisler (1):
/dev/dax: fix Kconfig dependency build breakage
Toshi Kani (1):
libnvdimm: Fix nvdimm_probe error on NVDIMM-N
Vishal Verma (4):
acpi, nfit: check for the correct event code in notifications
nfit: don't start a full scrub by default for an MCE
pmem: reduce kmap_atomic sections to the memcpys only
libnvdimm: clear the internal poison_list when clearing badblocks
drivers/acpi/nfit/core.c | 210 +++++++--
drivers/acpi/nfit/mce.c | 24 +-
drivers/acpi/nfit/nfit.h | 17 +
drivers/dax/Kconfig | 5 +
drivers/dax/dax.c | 577 +++++++++++++++----------
drivers/dax/dax.h | 5 +-
drivers/dax/pmem.c | 7 +-
drivers/nvdimm/Kconfig | 2 +-
drivers/nvdimm/bus.c | 2 +
drivers/nvdimm/core.c | 73 +++-
drivers/nvdimm/dimm.c | 11 +
drivers/nvdimm/dimm_devs.c | 226 +++++++---
drivers/nvdimm/label.c | 192 +++++----
drivers/nvdimm/namespace_devs.c | 792 +++++++++++++++++++++++-----------
drivers/nvdimm/nd-core.h | 24 +-
drivers/nvdimm/nd.h | 29 +-
drivers/nvdimm/pmem.c | 28 +-
drivers/nvdimm/region_devs.c | 75 +++-
fs/char_dev.c | 1 +
include/linux/libnvdimm.h | 28 +-
include/linux/nd.h | 8 +-
include/uapi/linux/magic.h | 1 +
include/uapi/linux/ndctl.h | 30 +-
tools/testing/nvdimm/Kbuild | 1 +
tools/testing/nvdimm/test/iomap.c | 151 +++++--
tools/testing/nvdimm/test/nfit.c | 160 ++++++-
tools/testing/nvdimm/test/nfit_test.h | 12 +-
27 files changed, 1940 insertions(+), 751 deletions(-)
5 years, 8 months
[PATCH v2] dev-dax: add support to display badblocks in sysfs for dev-dax
by Dave Jiang
Adding support to show badblocks in the pmem region that's provided
by the poison_list. This should show up in
/sys/class/dax/daxN.N/badblocks as read only. Currently we only support
a single resource and we do not support badblocks for seeds. Additional
support code will be implemented to support.
Signed-off-by: Dave Jiang <dave.jiang(a)intel.com>
---
drivers/dax/dax.c | 25 +++++++++++++++++++++----
drivers/dax/dax.h | 8 +++++++-
drivers/dax/pmem.c | 37 ++++++++++++++++++++++++++++++++++++-
3 files changed, 64 insertions(+), 6 deletions(-)
diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c
index ed4843a9..6580f85 100644
--- a/drivers/dax/dax.c
+++ b/drivers/dax/dax.c
@@ -79,6 +79,7 @@ struct dax_dev {
int id;
int num_resources;
struct resource **res;
+ void *private;
};
#define for_each_dax_region_resource(dax_region, res) \
@@ -336,6 +337,20 @@ static struct dax_dev *to_dax_dev(struct device *dev)
return container_of(dev, struct dax_dev, dev);
}
+void *dax_dev_get_private(struct device *dev)
+{
+ struct dax_dev *dax_dev = to_dax_dev(dev);
+
+ return dax_dev->private;
+}
+EXPORT_SYMBOL_GPL(dax_dev_get_private);
+
+void dax_dev_set_private(struct dax_dev *dax_dev, void *priv)
+{
+ dax_dev->private = priv;
+}
+EXPORT_SYMBOL_GPL(dax_dev_set_private);
+
static ssize_t size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -355,9 +370,10 @@ static struct attribute *dax_device_attributes[] = {
NULL,
};
-static const struct attribute_group dax_device_attribute_group = {
+struct attribute_group dax_device_attribute_group = {
.attrs = dax_device_attributes,
};
+EXPORT_SYMBOL_GPL(dax_device_attribute_group);
static const struct attribute_group *dax_attribute_groups[] = {
&dax_device_attribute_group,
@@ -676,7 +692,8 @@ static void unregister_dax_dev(void *dev)
}
struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region,
- struct resource *res, int count)
+ struct resource *res, int count,
+ const struct attribute_group **groups)
{
struct device *parent = dax_region->dev;
struct dax_dev *dax_dev;
@@ -757,7 +774,7 @@ struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region,
dev->devt = dev_t;
dev->class = dax_class;
dev->parent = parent;
- dev->groups = dax_attribute_groups;
+ dev->groups = groups ? groups : dax_attribute_groups;
dev->release = dax_dev_release;
dev_set_name(dev, "dax%d.%d", dax_region->id, dax_dev->id);
/* update resource names now that the owner device is named */
@@ -777,7 +794,7 @@ struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region,
if (atomic_inc_return(&dax_region->child_count) == 1) {
struct dax_dev *seed;
- seed = devm_create_dax_dev(dax_region, NULL, 0);
+ seed = devm_create_dax_dev(dax_region, NULL, 0, NULL);
if (IS_ERR(seed))
dev_warn(parent, "failed to create region seed\n");
else
diff --git a/drivers/dax/dax.h b/drivers/dax/dax.h
index ddd829a..c23c7ac 100644
--- a/drivers/dax/dax.h
+++ b/drivers/dax/dax.h
@@ -16,10 +16,16 @@ struct device;
struct dax_dev;
struct resource;
struct dax_region;
+extern struct attribute_group dax_device_attribute_group;
+
void dax_region_put(struct dax_region *dax_region);
struct dax_region *alloc_dax_region(struct device *parent,
int region_id, struct resource *res, unsigned int align,
void *addr, unsigned long flags);
struct dax_dev *devm_create_dax_dev(struct dax_region *dax_region,
- struct resource *res, int count);
+ struct resource *res, int count,
+ const struct attribute_group **groups);
+void *dax_dev_get_private(struct device *dev);
+void dax_dev_set_private(struct dax_dev *dax_dev, void *priv);
+
#endif /* __DAX_H__ */
diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c
index 9630d88..56282a9 100644
--- a/drivers/dax/pmem.c
+++ b/drivers/dax/pmem.c
@@ -14,6 +14,7 @@
#include <linux/memremap.h>
#include <linux/module.h>
#include <linux/pfn_t.h>
+#include <linux/badblocks.h>
#include "../nvdimm/pfn.h"
#include "../nvdimm/nd.h"
#include "dax.h"
@@ -22,6 +23,32 @@ struct dax_pmem {
struct device *dev;
struct percpu_ref ref;
struct completion cmp;
+ struct badblocks bb;
+};
+
+static ssize_t dax_pmem_badblocks_show(struct device *dev,
+ struct device_attribute *attr, char *page)
+{
+ struct dax_pmem *dax_pmem =
+ (struct dax_pmem *)dax_dev_get_private(dev);
+
+ return badblocks_show(&dax_pmem->bb, page, 0);
+}
+static DEVICE_ATTR(badblocks, S_IRUGO, dax_pmem_badblocks_show, NULL);
+
+static struct attribute *dax_pmem_badblock_attributes[] = {
+ &dev_attr_badblocks.attr,
+ NULL,
+};
+
+static struct attribute_group dax_pmem_badblock_attribute_group = {
+ .attrs = dax_pmem_badblock_attributes,
+};
+
+static const struct attribute_group *dax_pmem_attribute_groups[] = {
+ &dax_device_attribute_group,
+ &dax_pmem_badblock_attribute_group,
+ NULL,
};
static struct dax_pmem *to_dax_pmem(struct percpu_ref *ref)
@@ -127,7 +154,15 @@ static int dax_pmem_probe(struct device *dev)
return -ENOMEM;
/* TODO: support for subdividing a dax region... */
- dax_dev = devm_create_dax_dev(dax_region, &res, 1);
+ dax_dev = devm_create_dax_dev(dax_region, &res, 1,
+ dax_pmem_attribute_groups);
+ dax_dev_set_private(dax_dev, dax_pmem);
+
+ rc = devm_init_badblocks(dev, &dax_pmem->bb);
+ if (rc)
+ return rc;
+
+ nvdimm_badblocks_populate(nd_region, &dax_pmem->bb, &res);
/* child dax_dev instances now own the lifetime of the dax_region */
dax_region_put(dax_region);
5 years, 8 months
[RFC NDCTL PATCH] ndctl: add support for Xen mode namespace
by Haozhong Zhang
Add support to create the Xen mode namespace which turns the underlying
pfn device into PFN_MODE_XEN.
Signed-off-by: Haozhong Zhang <haozhong.zhang(a)intel.com>
---
ndctl/builtin-xaction-namespace.c | 7 ++++++-
ndctl/lib/libndctl.c | 6 ++++++
ndctl/libndctl.h.in | 2 ++
ndctl/util/json.c | 4 ++++
4 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/ndctl/builtin-xaction-namespace.c b/ndctl/builtin-xaction-namespace.c
index 9b1702d..f60551d 100644
--- a/ndctl/builtin-xaction-namespace.c
+++ b/ndctl/builtin-xaction-namespace.c
@@ -176,6 +176,8 @@ static int set_defaults(enum namespace_action mode)
/* pass */;
else if (strcmp(param.map, "dev") == 0)
/* pass */;
+ else if (strcmp(param.map, "xen") == 0)
+ /* pass */;
else {
error("invalid map location '%s'\n", param.map);
rc = -EINVAL;
@@ -292,7 +294,8 @@ static bool do_setup_pfn(struct ndctl_namespace *ndns,
* array in device memory.
*/
if (!ndns || ndctl_namespace_get_mode(ndns) != NDCTL_NS_MODE_MEMORY
- || p->loc == NDCTL_PFN_LOC_PMEM)
+ || p->loc == NDCTL_PFN_LOC_PMEM
+ || p->loc == NDCTL_PFN_LOC_XEN)
return true;
return false;
@@ -486,6 +489,8 @@ static int validate_namespace_options(struct ndctl_region *region,
if (param.map) {
if (!strcmp(param.map, "mem"))
p->loc = NDCTL_PFN_LOC_RAM;
+ else if (!strcmp(param.map, "xen"))
+ p->loc = NDCTL_PFN_LOC_XEN;
else
p->loc = NDCTL_PFN_LOC_PMEM;
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 14bf217..35882db 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -3015,6 +3015,8 @@ NDCTL_EXPORT enum ndctl_namespace_mode ndctl_namespace_get_mode(
return NDCTL_NS_MODE_RAW;
if (strcmp("safe", buf) == 0)
return NDCTL_NS_MODE_SAFE;
+ if (strcmp("xen", buf) == 0)
+ return NDCTL_NS_MODE_XEN;
return -ENXIO;
}
@@ -3998,6 +4000,8 @@ static int __add_pfn(struct ndctl_pfn *pfn, const char *pfn_base)
pfn->loc = NDCTL_PFN_LOC_RAM;
else if (strcmp(buf, "pmem") == 0)
pfn->loc = NDCTL_PFN_LOC_PMEM;
+ else if (strcmp(buf, "xen") == 0)
+ pfn->loc = NDCTL_PFN_LOC_XEN;
else
goto err_read;
@@ -4190,12 +4194,14 @@ NDCTL_EXPORT int ndctl_pfn_set_location(struct ndctl_pfn *pfn,
[NDCTL_PFN_LOC_NONE] = "none",
[NDCTL_PFN_LOC_RAM] = "ram",
[NDCTL_PFN_LOC_PMEM] = "pmem",
+ [NDCTL_PFN_LOC_XEN] = "xen",
};
switch (loc) {
case NDCTL_PFN_LOC_NONE:
case NDCTL_PFN_LOC_RAM:
case NDCTL_PFN_LOC_PMEM:
+ case NDCTL_PFN_LOC_XEN:
break;
default:
return -EINVAL;
diff --git a/ndctl/libndctl.h.in b/ndctl/libndctl.h.in
index 803368b..7d61e32 100644
--- a/ndctl/libndctl.h.in
+++ b/ndctl/libndctl.h.in
@@ -472,6 +472,7 @@ enum ndctl_namespace_mode {
NDCTL_NS_MODE_SAFE,
NDCTL_NS_MODE_RAW,
NDCTL_NS_MODE_DAX,
+ NDCTL_NS_MODE_XEN,
};
enum ndctl_namespace_mode ndctl_namespace_get_mode(
struct ndctl_namespace *ndns);
@@ -560,6 +561,7 @@ enum ndctl_pfn_loc {
NDCTL_PFN_LOC_NONE,
NDCTL_PFN_LOC_RAM,
NDCTL_PFN_LOC_PMEM,
+ NDCTL_PFN_LOC_XEN,
};
int ndctl_pfn_set_location(struct ndctl_pfn *pfn, enum ndctl_pfn_loc loc);
enum ndctl_pfn_loc ndctl_pfn_get_location(struct ndctl_pfn *pfn);
diff --git a/ndctl/util/json.c b/ndctl/util/json.c
index 82e677c..8083219 100644
--- a/ndctl/util/json.c
+++ b/ndctl/util/json.c
@@ -188,6 +188,10 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns,
size = ndctl_namespace_get_size(ndns);
jobj = json_object_new_string("raw");
break;
+ case NDCTL_NS_MODE_XEN:
+ size = ndctl_namespace_get_size(ndns);
+ jobj = json_object_new_string("xen");
+ break;
default:
jobj = NULL;
}
--
2.10.1
5 years, 8 months
Shipment delivery problem #0000613691
by FedEx International MailService
Dear Customer,
Your parcel has arrived at October 09. Courier was unable to deliver the parcel to you.
Please, download Delivery Label attached to this email.
Sincerely,
Mike Daniels,
FedEx Station Agent.
5 years, 8 months
销售人员管理与销售业绩管理
by 销售人员管理与销售业绩管理先生
学习销售主管2天强化训练营您将会收获;
1;明确销售主管的工作定位,知道如何把握工作重点;
2;帮助销售主管理清思路,正确处理销售中的常见问题;
3;了解如何组建销售团队,如何选人、育人、留人;
4;明白销售过程管理的原理与方法;
5;学会销售团队业绩考核指标设定的方法;
6;了解销售业务人员奖惩的基本原理;
QQ:971700732
5 years, 8 months
[PATCH 00/14] libnvdimm: support sub-divisions of pmem for 4.9
by Dan Williams
With the arrival of the device-dax facility in 4.7 a pmem namespace can
now be configured into a total of four distinct modes: 'raw', 'sector',
'memory', and 'dax'. Where raw, sector, and memory are block device
modes and dax supports the device-dax character device. With that degree
of freedom in the use cases it is overly restrictive to continue the
current limit of only one pmem namespace per-region, or "interleave-set"
in ACPI 6+ terminology.
This series adds support for reading and writing configurations that
describe multiple pmem allocations within a region. The new rules for
allocating / validating the available capacity when blk and pmem regions
alias are (quoting space_valid()):
BLK-space is valid as long as it does not precede a PMEM
allocation in a given region. PMEM-space must be contiguous
and adjacent to an existing existing allocation (if one
exists).
Where "adjacent" allocations grow an existing namespace. Note that
growing a namespace is potentially destructive if free space is consumed
from a location preceding the current allocation. There is no support
for dis-continuity within a given namespace allocation.
Previously, since there was only one namespace per-region, the resulting
pmem device would be named after the region. Now, subsequent namespaces
after the first are named with the region index and a
".<namespace-index>" suffix. For example:
/dev/pmem0.1
---
Dan Williams (14):
libnvdimm, region: move region-mapping input-paramters to nd_mapping_desc
libnvdimm, label: convert label tracking to a linked list
libnvdimm, namespace: refactor uuid_show() into a namespace_to_uuid() helper
libnvdimm, namespace: unify blk and pmem label scanning
tools/testing/nvdimm: support for sub-dividing a pmem region
libnvdimm, namespace: allow multiple pmem-namespaces per region at scan time
libnvdimm, namespace: sort namespaces by dpa at init
libnvdimm, region: update nd_region_available_dpa() for multi-pmem support
libnvdimm, namespace: expand pmem device naming scheme for multi-pmem
libnvdimm, namespace: update label implementation for multi-pmem
libnvdimm, namespace: enable allocation of multiple pmem namespaces
libnvdimm, namespace: filter out of range labels in scan_labels()
libnvdimm, namespace: lift single pmem limit in scan_labels()
libnvdimm, namespace: allow creation of multiple pmem-namespaces per region
drivers/acpi/nfit/core.c | 30 +
drivers/nvdimm/dimm_devs.c | 192 ++++++--
drivers/nvdimm/label.c | 192 +++++---
drivers/nvdimm/namespace_devs.c | 786 +++++++++++++++++++++++----------
drivers/nvdimm/nd-core.h | 23 +
drivers/nvdimm/nd.h | 28 +
drivers/nvdimm/region_devs.c | 58 ++
include/linux/libnvdimm.h | 25 -
include/linux/nd.h | 8
tools/testing/nvdimm/test/iomap.c | 134 ++++--
tools/testing/nvdimm/test/nfit.c | 21 -
tools/testing/nvdimm/test/nfit_test.h | 12 -
12 files changed, 1055 insertions(+), 454 deletions(-)
5 years, 8 months