forked from mirrors/linux
		
	lightnvm: pblk: add trace events for chunk states
Introduce trace points for tracking chunk states in pblk - this is useful for inspection of the entire state of the drive, and real handy for both fw and pblk debugging. Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com> Signed-off-by: Matias Bjørling <mb@lightnvm.io> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
		
							parent
							
								
									43241cfe47
								
							
						
					
					
						commit
						4c44abf43d
					
				
					 5 changed files with 107 additions and 3 deletions
				
			
		|  | @ -16,7 +16,10 @@ | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #define CREATE_TRACE_POINTS | ||||||
|  | 
 | ||||||
| #include "pblk.h" | #include "pblk.h" | ||||||
|  | #include "pblk-trace.h" | ||||||
| 
 | 
 | ||||||
| static void pblk_line_mark_bb(struct work_struct *work) | static void pblk_line_mark_bb(struct work_struct *work) | ||||||
| { | { | ||||||
|  | @ -93,6 +96,9 @@ static void __pblk_end_io_erase(struct pblk *pblk, struct nvm_rq *rqd) | ||||||
| 		chunk->state = NVM_CHK_ST_FREE; | 		chunk->state = NVM_CHK_ST_FREE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	trace_pblk_chunk_state(pblk_disk_name(pblk), &rqd->ppa_addr, | ||||||
|  | 				chunk->state); | ||||||
|  | 
 | ||||||
| 	atomic_dec(&pblk->inflight_io); | 	atomic_dec(&pblk->inflight_io); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -477,9 +483,30 @@ int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd) | ||||||
| 	return nvm_submit_io(dev, rqd); | 	return nvm_submit_io(dev, rqd); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void pblk_check_chunk_state_update(struct pblk *pblk, struct nvm_rq *rqd) | ||||||
|  | { | ||||||
|  | 	struct ppa_addr *ppa_list = nvm_rq_to_ppa_list(rqd); | ||||||
|  | 
 | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < rqd->nr_ppas; i++) { | ||||||
|  | 		struct ppa_addr *ppa = &ppa_list[i]; | ||||||
|  | 		struct nvm_chk_meta *chunk = pblk_dev_ppa_to_chunk(pblk, *ppa); | ||||||
|  | 		u64 caddr = pblk_dev_ppa_to_chunk_addr(pblk, *ppa); | ||||||
|  | 
 | ||||||
|  | 		if (caddr == 0) | ||||||
|  | 			trace_pblk_chunk_state(pblk_disk_name(pblk), | ||||||
|  | 							ppa, NVM_CHK_ST_OPEN); | ||||||
|  | 		else if (caddr == chunk->cnlb) | ||||||
|  | 			trace_pblk_chunk_state(pblk_disk_name(pblk), | ||||||
|  | 							ppa, NVM_CHK_ST_CLOSED); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd) | int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd) | ||||||
| { | { | ||||||
| 	struct nvm_tgt_dev *dev = pblk->dev; | 	struct nvm_tgt_dev *dev = pblk->dev; | ||||||
|  | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	atomic_inc(&pblk->inflight_io); | 	atomic_inc(&pblk->inflight_io); | ||||||
| 
 | 
 | ||||||
|  | @ -488,7 +515,13 @@ int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd) | ||||||
| 		return NVM_IO_ERR; | 		return NVM_IO_ERR; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	return nvm_submit_io_sync(dev, rqd); | 	ret = nvm_submit_io_sync(dev, rqd); | ||||||
|  | 
 | ||||||
|  | 	if (trace_pblk_chunk_state_enabled() && !ret && | ||||||
|  | 	    rqd->opcode == NVM_OP_PWRITE) | ||||||
|  | 		pblk_check_chunk_state_update(pblk, rqd); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void pblk_bio_map_addr_endio(struct bio *bio) | static void pblk_bio_map_addr_endio(struct bio *bio) | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "pblk.h" | #include "pblk.h" | ||||||
|  | #include "pblk-trace.h" | ||||||
| 
 | 
 | ||||||
| static unsigned int write_buffer_size; | static unsigned int write_buffer_size; | ||||||
| 
 | 
 | ||||||
|  | @ -664,6 +665,9 @@ static int pblk_setup_line_meta_chk(struct pblk *pblk, struct pblk_line *line, | ||||||
| 		chunk->cnlb = chunk_meta->cnlb; | 		chunk->cnlb = chunk_meta->cnlb; | ||||||
| 		chunk->wp = chunk_meta->wp; | 		chunk->wp = chunk_meta->wp; | ||||||
| 
 | 
 | ||||||
|  | 		trace_pblk_chunk_state(pblk_disk_name(pblk), &ppa, | ||||||
|  | 					chunk->state); | ||||||
|  | 
 | ||||||
| 		if (chunk->type & NVM_CHK_TP_SZ_SPEC) { | 		if (chunk->type & NVM_CHK_TP_SZ_SPEC) { | ||||||
| 			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n"); | 			WARN_ONCE(1, "pblk: custom-sized chunks unsupported\n"); | ||||||
| 			continue; | 			continue; | ||||||
|  |  | ||||||
							
								
								
									
										53
									
								
								drivers/lightnvm/pblk-trace.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								drivers/lightnvm/pblk-trace.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
|  | #undef TRACE_SYSTEM | ||||||
|  | #define TRACE_SYSTEM pblk | ||||||
|  | 
 | ||||||
|  | #if !defined(_TRACE_PBLK_H) || defined(TRACE_HEADER_MULTI_READ) | ||||||
|  | #define _TRACE_PBLK_H | ||||||
|  | 
 | ||||||
|  | #include <linux/tracepoint.h> | ||||||
|  | 
 | ||||||
|  | struct ppa_addr; | ||||||
|  | 
 | ||||||
|  | #define show_chunk_flags(state) __print_flags(state, "",	\ | ||||||
|  | 	{ NVM_CHK_ST_FREE,		"FREE",		},	\ | ||||||
|  | 	{ NVM_CHK_ST_CLOSED,		"CLOSED",	},	\ | ||||||
|  | 	{ NVM_CHK_ST_OPEN,		"OPEN",		},	\ | ||||||
|  | 	{ NVM_CHK_ST_OFFLINE,		"OFFLINE",	}) | ||||||
|  | 
 | ||||||
|  | TRACE_EVENT(pblk_chunk_state, | ||||||
|  | 
 | ||||||
|  | 	TP_PROTO(const char *name, struct ppa_addr *ppa, int state), | ||||||
|  | 
 | ||||||
|  | 	TP_ARGS(name, ppa, state), | ||||||
|  | 
 | ||||||
|  | 	TP_STRUCT__entry( | ||||||
|  | 		__string(name, name) | ||||||
|  | 		__field(u64, ppa) | ||||||
|  | 		__field(int, state); | ||||||
|  | 	), | ||||||
|  | 
 | ||||||
|  | 	TP_fast_assign( | ||||||
|  | 		__assign_str(name, name); | ||||||
|  | 		__entry->ppa = ppa->ppa; | ||||||
|  | 		__entry->state = state; | ||||||
|  | 	), | ||||||
|  | 
 | ||||||
|  | 	TP_printk("dev=%s grp=%llu pu=%llu chk=%llu state=%s", __get_str(name), | ||||||
|  | 			(u64)(((struct ppa_addr *)(&__entry->ppa))->m.grp), | ||||||
|  | 			(u64)(((struct ppa_addr *)(&__entry->ppa))->m.pu), | ||||||
|  | 			(u64)(((struct ppa_addr *)(&__entry->ppa))->m.chk), | ||||||
|  | 			show_chunk_flags((int)__entry->state)) | ||||||
|  | 
 | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #endif /* !defined(_TRACE_PBLK_H) || defined(TRACE_HEADER_MULTI_READ) */ | ||||||
|  | 
 | ||||||
|  | /* This part must be outside protection */ | ||||||
|  | 
 | ||||||
|  | #undef TRACE_INCLUDE_PATH | ||||||
|  | #define TRACE_INCLUDE_PATH ../../../drivers/lightnvm | ||||||
|  | #undef TRACE_INCLUDE_FILE | ||||||
|  | #define TRACE_INCLUDE_FILE pblk-trace | ||||||
|  | #include <trace/define_trace.h> | ||||||
|  | @ -16,6 +16,7 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "pblk.h" | #include "pblk.h" | ||||||
|  | #include "pblk-trace.h" | ||||||
| 
 | 
 | ||||||
| static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd, | static unsigned long pblk_end_w_bio(struct pblk *pblk, struct nvm_rq *rqd, | ||||||
| 				    struct pblk_c_ctx *c_ctx) | 				    struct pblk_c_ctx *c_ctx) | ||||||
|  | @ -251,11 +252,13 @@ static void pblk_end_io_write(struct nvm_rq *rqd) | ||||||
| 	if (rqd->error) { | 	if (rqd->error) { | ||||||
| 		pblk_end_w_fail(pblk, rqd); | 		pblk_end_w_fail(pblk, rqd); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} else { | ||||||
|  | 		if (trace_pblk_chunk_state_enabled()) | ||||||
|  | 			pblk_check_chunk_state_update(pblk, rqd); | ||||||
| #ifdef CONFIG_NVM_PBLK_DEBUG | #ifdef CONFIG_NVM_PBLK_DEBUG | ||||||
| 	else |  | ||||||
| 		WARN_ONCE(rqd->bio->bi_status, "pblk: corrupted write error\n"); | 		WARN_ONCE(rqd->bio->bi_status, "pblk: corrupted write error\n"); | ||||||
| #endif | #endif | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	pblk_complete_write(pblk, rqd, c_ctx); | 	pblk_complete_write(pblk, rqd, c_ctx); | ||||||
| 	atomic_dec(&pblk->inflight_io); | 	atomic_dec(&pblk->inflight_io); | ||||||
|  | @ -276,6 +279,9 @@ static void pblk_end_io_write_meta(struct nvm_rq *rqd) | ||||||
| 		pblk_log_write_err(pblk, rqd); | 		pblk_log_write_err(pblk, rqd); | ||||||
| 		pblk_err(pblk, "metadata I/O failed. Line %d\n", line->id); | 		pblk_err(pblk, "metadata I/O failed. Line %d\n", line->id); | ||||||
| 		line->w_err_gc->has_write_err = 1; | 		line->w_err_gc->has_write_err = 1; | ||||||
|  | 	} else { | ||||||
|  | 		if (trace_pblk_chunk_state_enabled()) | ||||||
|  | 			pblk_check_chunk_state_update(pblk, rqd); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sync = atomic_add_return(rqd->nr_ppas, &emeta->sync); | 	sync = atomic_add_return(rqd->nr_ppas, &emeta->sync); | ||||||
|  |  | ||||||
|  | @ -785,6 +785,7 @@ void pblk_log_read_err(struct pblk *pblk, struct nvm_rq *rqd); | ||||||
| int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd); | int pblk_submit_io(struct pblk *pblk, struct nvm_rq *rqd); | ||||||
| int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd); | int pblk_submit_io_sync(struct pblk *pblk, struct nvm_rq *rqd); | ||||||
| int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line); | int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line); | ||||||
|  | void pblk_check_chunk_state_update(struct pblk *pblk, struct nvm_rq *rqd); | ||||||
| struct bio *pblk_bio_map_addr(struct pblk *pblk, void *data, | struct bio *pblk_bio_map_addr(struct pblk *pblk, void *data, | ||||||
| 			      unsigned int nr_secs, unsigned int len, | 			      unsigned int nr_secs, unsigned int len, | ||||||
| 			      int alloc_type, gfp_t gfp_mask); | 			      int alloc_type, gfp_t gfp_mask); | ||||||
|  | @ -1427,4 +1428,11 @@ static inline void pblk_setup_uuid(struct pblk *pblk) | ||||||
| 	uuid_le_gen(&uuid); | 	uuid_le_gen(&uuid); | ||||||
| 	memcpy(pblk->instance_uuid, uuid.b, 16); | 	memcpy(pblk->instance_uuid, uuid.b, 16); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | static inline char *pblk_disk_name(struct pblk *pblk) | ||||||
|  | { | ||||||
|  | 	struct gendisk *disk = pblk->disk; | ||||||
|  | 
 | ||||||
|  | 	return disk->disk_name; | ||||||
|  | } | ||||||
| #endif /* PBLK_H_ */ | #endif /* PBLK_H_ */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Hans Holmberg
						Hans Holmberg