@@ -29,7 +29,10 @@ static void namespace_io_release(struct device *dev)
2929static void namespace_pmem_release (struct device * dev )
3030{
3131 struct nd_namespace_pmem * nspm = to_nd_namespace_pmem (dev );
32+ struct nd_region * nd_region = to_nd_region (dev -> parent );
3233
34+ if (nspm -> id >= 0 )
35+ ida_simple_remove (& nd_region -> ns_ida , nspm -> id );
3336 kfree (nspm -> alt_name );
3437 kfree (nspm -> uuid );
3538 kfree (nspm );
@@ -833,13 +836,45 @@ static int grow_dpa_allocation(struct nd_region *nd_region,
833836 return 0 ;
834837}
835838
836- static void nd_namespace_pmem_set_size (struct nd_region * nd_region ,
839+ static void nd_namespace_pmem_set_resource (struct nd_region * nd_region ,
837840 struct nd_namespace_pmem * nspm , resource_size_t size )
838841{
839842 struct resource * res = & nspm -> nsio .res ;
843+ resource_size_t offset = 0 ;
840844
841- res -> start = nd_region -> ndr_start ;
842- res -> end = nd_region -> ndr_start + size - 1 ;
845+ if (size && !nspm -> uuid ) {
846+ WARN_ON_ONCE (1 );
847+ size = 0 ;
848+ }
849+
850+ if (size && nspm -> uuid ) {
851+ struct nd_mapping * nd_mapping = & nd_region -> mapping [0 ];
852+ struct nvdimm_drvdata * ndd = to_ndd (nd_mapping );
853+ struct nd_label_id label_id ;
854+ struct resource * res ;
855+
856+ if (!ndd ) {
857+ size = 0 ;
858+ goto out ;
859+ }
860+
861+ nd_label_gen_id (& label_id , nspm -> uuid , 0 );
862+
863+ /* calculate a spa offset from the dpa allocation offset */
864+ for_each_dpa_resource (ndd , res )
865+ if (strcmp (res -> name , label_id .id ) == 0 ) {
866+ offset = (res -> start - nd_mapping -> start )
867+ * nd_region -> ndr_mappings ;
868+ goto out ;
869+ }
870+
871+ WARN_ON_ONCE (1 );
872+ size = 0 ;
873+ }
874+
875+ out :
876+ res -> start = nd_region -> ndr_start + offset ;
877+ res -> end = res -> start + size - 1 ;
843878}
844879
845880static bool uuid_not_set (const u8 * uuid , struct device * dev , const char * where )
@@ -930,7 +965,7 @@ static ssize_t __size_store(struct device *dev, unsigned long long val)
930965 if (is_namespace_pmem (dev )) {
931966 struct nd_namespace_pmem * nspm = to_nd_namespace_pmem (dev );
932967
933- nd_namespace_pmem_set_size (nd_region , nspm ,
968+ nd_namespace_pmem_set_resource (nd_region , nspm ,
934969 val * nd_region -> ndr_mappings );
935970 } else if (is_namespace_blk (dev )) {
936971 struct nd_namespace_blk * nsblk = to_nd_namespace_blk (dev );
@@ -1546,6 +1581,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id)
15461581
15471582 for (i = 0 ; i < nd_region -> ndr_mappings ; i ++ ) {
15481583 struct nd_mapping * nd_mapping = & nd_region -> mapping [i ];
1584+ struct nvdimm_drvdata * ndd = to_ndd (nd_mapping );
15491585 struct nd_namespace_label * nd_label = NULL ;
15501586 u64 hw_start , hw_end , pmem_start , pmem_end ;
15511587 struct nd_label_ent * label_ent ;
@@ -1573,10 +1609,14 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id)
15731609 hw_end = hw_start + nd_mapping -> size ;
15741610 pmem_start = __le64_to_cpu (nd_label -> dpa );
15751611 pmem_end = pmem_start + __le64_to_cpu (nd_label -> rawsize );
1576- if (pmem_start == hw_start && pmem_end <= hw_end )
1612+ if (pmem_start >= hw_start && pmem_start < hw_end
1613+ && pmem_end <= hw_end && pmem_end > hw_start )
15771614 /* pass */ ;
1578- else
1615+ else {
1616+ dev_dbg (& nd_region -> dev , "%s invalid label for %pUb\n" ,
1617+ dev_name (ndd -> dev ), nd_label -> uuid );
15791618 return - EINVAL ;
1619+ }
15801620
15811621 /* move recently validated label to the front of the list */
15821622 list_move (& label_ent -> list , & nd_mapping -> labels );
@@ -1618,6 +1658,7 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
16181658 if (!nspm )
16191659 return ERR_PTR (- ENOMEM );
16201660
1661+ nspm -> id = -1 ;
16211662 dev = & nspm -> nsio .common .dev ;
16221663 dev -> type = & namespace_pmem_device_type ;
16231664 dev -> parent = & nd_region -> dev ;
@@ -1629,11 +1670,15 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
16291670 if (!has_uuid_at_pos (nd_region , nd_label -> uuid , cookie , i ))
16301671 break ;
16311672 if (i < nd_region -> ndr_mappings ) {
1673+ struct nvdimm_drvdata * ndd = to_ndd (& nd_region -> mapping [i ]);
1674+
16321675 /*
16331676 * Give up if we don't find an instance of a uuid at each
16341677 * position (from 0 to nd_region->ndr_mappings - 1), or if we
16351678 * find a dimm with two instances of the same uuid.
16361679 */
1680+ dev_err (& nd_region -> dev , "%s missing label for %pUb\n" ,
1681+ dev_name (ndd -> dev ), nd_label -> uuid );
16371682 rc = - EINVAL ;
16381683 goto err ;
16391684 }
@@ -1679,7 +1724,7 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
16791724 goto err ;
16801725 }
16811726
1682- nd_namespace_pmem_set_size (nd_region , nspm , size );
1727+ nd_namespace_pmem_set_resource (nd_region , nspm , size );
16831728
16841729 return dev ;
16851730 err :
@@ -1961,23 +2006,31 @@ static struct device **scan_labels(struct nd_region *nd_region)
19612006 goto err ;
19622007 dev = & nspm -> nsio .common .dev ;
19632008 dev -> type = & namespace_pmem_device_type ;
1964- nd_namespace_pmem_set_size (nd_region , nspm , 0 );
2009+ nd_namespace_pmem_set_resource (nd_region , nspm , 0 );
19652010 }
19662011 dev -> parent = & nd_region -> dev ;
19672012 devs [count ++ ] = dev ;
19682013 } else if (is_nd_pmem (& nd_region -> dev )) {
19692014 /* clean unselected labels */
19702015 for (i = 0 ; i < nd_region -> ndr_mappings ; i ++ ) {
2016+ struct list_head * l , * e ;
2017+ LIST_HEAD (list );
2018+ int j ;
2019+
19712020 nd_mapping = & nd_region -> mapping [i ];
19722021 if (list_empty (& nd_mapping -> labels )) {
19732022 WARN_ON (1 );
19742023 continue ;
19752024 }
1976- label_ent = list_first_entry (& nd_mapping -> labels ,
1977- typeof (* label_ent ), list );
1978- list_del (& label_ent -> list );
2025+
2026+ j = count ;
2027+ list_for_each_safe (l , e , & nd_mapping -> labels ) {
2028+ if (!j -- )
2029+ break ;
2030+ list_move_tail (l , & list );
2031+ }
19792032 nd_mapping_free_labels (nd_mapping );
1980- list_add ( & label_ent -> list , & nd_mapping -> labels );
2033+ list_splice_init ( & list , & nd_mapping -> labels );
19812034 }
19822035 }
19832036
@@ -2117,6 +2170,13 @@ int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
21172170 id = ida_simple_get (& nd_region -> ns_ida , 0 , 0 ,
21182171 GFP_KERNEL );
21192172 nsblk -> id = id ;
2173+ } else if (type == ND_DEVICE_NAMESPACE_PMEM ) {
2174+ struct nd_namespace_pmem * nspm ;
2175+
2176+ nspm = to_nd_namespace_pmem (dev );
2177+ id = ida_simple_get (& nd_region -> ns_ida , 0 , 0 ,
2178+ GFP_KERNEL );
2179+ nspm -> id = id ;
21202180 } else
21212181 id = i ;
21222182
0 commit comments