From 62ab1aadcccd037a7ced4ed99b4d46d2b4190183 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 27 Jan 2021 05:21:15 +0900 Subject: zonefs: add tracepoints for file operations Add tracepoints for file I/O operations to aid in debugging of I/O errors with zonefs. The added tracepoints are in: - zonefs_zone_mgmt() for tracing zone management operations - zonefs_iomap_begin() for tracing regular file I/O - zonefs_file_dio_append() for tracing zone-append operations Signed-off-by: Johannes Thumshirn Signed-off-by: Damien Le Moal --- fs/zonefs/Makefile | 2 ++ fs/zonefs/super.c | 7 ++++ fs/zonefs/trace.h | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 fs/zonefs/trace.h (limited to 'fs/zonefs') diff --git a/fs/zonefs/Makefile b/fs/zonefs/Makefile index 75a380aa1ae1..33c1a4f1132e 100644 --- a/fs/zonefs/Makefile +++ b/fs/zonefs/Makefile @@ -1,4 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 +ccflags-y += -I$(src) + obj-$(CONFIG_ZONEFS_FS) += zonefs.o zonefs-y := super.o diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c index bec47f2d074b..96f0cb0c29aa 100644 --- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -24,6 +24,9 @@ #include "zonefs.h" +#define CREATE_TRACE_POINTS +#include "trace.h" + static inline int zonefs_zone_mgmt(struct inode *inode, enum req_opf op) { @@ -32,6 +35,7 @@ static inline int zonefs_zone_mgmt(struct inode *inode, lockdep_assert_held(&zi->i_truncate_mutex); + trace_zonefs_zone_mgmt(inode, op); ret = blkdev_zone_mgmt(inode->i_sb->s_bdev, op, zi->i_zsector, zi->i_zone_size >> SECTOR_SHIFT, GFP_NOFS); if (ret) { @@ -100,6 +104,8 @@ static int zonefs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, iomap->bdev = inode->i_sb->s_bdev; iomap->addr = (zi->i_zsector << SECTOR_SHIFT) + iomap->offset; + trace_zonefs_iomap_begin(inode, iomap); + return 0; } @@ -703,6 +709,7 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from) ret = submit_bio_wait(bio); zonefs_file_write_dio_end_io(iocb, size, ret, 0); + trace_zonefs_file_dio_append(inode, size, ret); out_release: bio_release_pages(bio, false); diff --git a/fs/zonefs/trace.h b/fs/zonefs/trace.h new file mode 100644 index 000000000000..f369d7d50303 --- /dev/null +++ b/fs/zonefs/trace.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * zonefs filesystem driver tracepoints. + * + * Copyright (C) 2021 Western Digital Corporation or its affiliates. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM zonefs + +#if !defined(_TRACE_ZONEFS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_ZONEFS_H + +#include +#include +#include + +#include "zonefs.h" + +#define show_dev(dev) MAJOR(dev), MINOR(dev) + +TRACE_EVENT(zonefs_zone_mgmt, + TP_PROTO(struct inode *inode, enum req_opf op), + TP_ARGS(inode, op), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(int, op) + __field(sector_t, sector) + __field(sector_t, nr_sectors) + ), + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->op = op; + __entry->sector = ZONEFS_I(inode)->i_zsector; + __entry->nr_sectors = + ZONEFS_I(inode)->i_zone_size >> SECTOR_SHIFT; + ), + TP_printk("bdev=(%d,%d), ino=%lu op=%s, sector=%llu, nr_sectors=%llu", + show_dev(__entry->dev), (unsigned long)__entry->ino, + blk_op_str(__entry->op), __entry->sector, + __entry->nr_sectors + ) +); + +TRACE_EVENT(zonefs_file_dio_append, + TP_PROTO(struct inode *inode, ssize_t size, ssize_t ret), + TP_ARGS(inode, size, ret), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(sector_t, sector) + __field(ssize_t, size) + __field(loff_t, wpoffset) + __field(ssize_t, ret) + ), + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->sector = ZONEFS_I(inode)->i_zsector; + __entry->size = size; + __entry->wpoffset = ZONEFS_I(inode)->i_wpoffset; + __entry->ret = ret; + ), + TP_printk("bdev=(%d, %d), ino=%lu, sector=%llu, size=%zu, wpoffset=%llu, ret=%zu", + show_dev(__entry->dev), (unsigned long)__entry->ino, + __entry->sector, __entry->size, __entry->wpoffset, + __entry->ret + ) +); + +TRACE_EVENT(zonefs_iomap_begin, + TP_PROTO(struct inode *inode, struct iomap *iomap), + TP_ARGS(inode, iomap), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(u64, addr) + __field(loff_t, offset) + __field(u64, length) + ), + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->addr = iomap->addr; + __entry->offset = iomap->offset; + __entry->length = iomap->length; + ), + TP_printk("bdev=(%d,%d), ino=%lu, addr=%llu, offset=%llu, length=%llu", + show_dev(__entry->dev), (unsigned long)__entry->ino, + __entry->addr, __entry->offset, __entry->length + ) +); + +#endif /* _TRACE_ZONEFS_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +/* This part must be outside protection */ +#include -- cgit v1.2.3 From 059c01039c0185dbee7ed080f1f2bd22cb1e4dab Mon Sep 17 00:00:00 2001 From: Shin'ichiro Kawasaki Date: Wed, 17 Feb 2021 18:58:11 +0900 Subject: zonefs: Fix file size of zones in full condition Per ZBC/ZAC/ZNS specifications, write pointers may not have valid values when zones are in full condition. However, when zonefs mounts a zoned block device, zonefs refers write pointers to set file size even when the zones are in full condition. This results in wrong file size. To fix this, refer maximum file size in place of write pointers for zones in full condition. Signed-off-by: Shin'ichiro Kawasaki Fixes: 8dcc1a9d90c1 ("fs: New zonefs file system") Cc: # 5.6+ Signed-off-by: Damien Le Moal --- fs/zonefs/super.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/zonefs') diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c index 96f0cb0c29aa..2e2a234d387b 100644 --- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -256,6 +256,9 @@ static loff_t zonefs_check_zone_condition(struct inode *inode, } inode->i_mode &= ~0222; return i_size_read(inode); + case BLK_ZONE_COND_FULL: + /* The write pointer of full zones is invalid. */ + return zi->i_max_size; default: if (zi->i_ztype == ZONEFS_ZTYPE_CNV) return zi->i_max_size; -- cgit v1.2.3