Message ID | 20210628000218.387833-3-ruansy.fnst@fujitsu.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fsdax: introduce fs query to support reflink | expand |
On Mon, Jun 28, 2021 at 08:02:11AM +0800, Shiyang Ruan wrote: > +int dax_holder_notify_failure(struct dax_device *dax_dev, loff_t offset, > + size_t size, void *data) > +{ > + int rc = -ENXIO; > + if (!dax_dev) > + return rc; > + > + if (dax_dev->holder_data) { > + rc = dax_dev->holder_ops->notify_failure(dax_dev, offset, > + size, data); > + if (rc == -ENODEV) > + rc = -ENXIO; > + } else > + rc = -EOPNOTSUPP; The style looks a little odd. Why not: if (!dax_dev) return -ENXIO if (!dax_dev->holder_data) return -EOPNOTSUPP; return dax_dev->holder_ops->notify_failure(dax_dev, offset, size, data); and let everyone deal with the same errno codes? Also why do we even need the dax_dev NULL check? > +void dax_set_holder(struct dax_device *dax_dev, void *holder, > + const struct dax_holder_operations *ops) > +{ > + if (!dax_dev) > + return; I don't think we really need that check here. > +void *dax_get_holder(struct dax_device *dax_dev) > +{ > + void *holder_data; > + > + if (!dax_dev) > + return NULL; Same here. > + > + down_read(&dax_dev->holder_rwsem); > + holder_data = dax_dev->holder_data; > + up_read(&dax_dev->holder_rwsem); > + > + return holder_data; That lock won't protect anything. I think we simply must have synchronization to prevent unregistration while the ->notify_failure call is in progress. -- dm-devel mailing list dm-devel@redhat.com https://listman.redhat.com/mailman/listinfo/dm-devel
> -----Original Message----- > Subject: Re: [PATCH v5 2/9] dax: Introduce holder for dax_device > > On Mon, Jun 28, 2021 at 08:02:11AM +0800, Shiyang Ruan wrote: > > +int dax_holder_notify_failure(struct dax_device *dax_dev, loff_t offset, > > + size_t size, void *data) > > +{ > > + int rc = -ENXIO; > > + if (!dax_dev) > > + return rc; > > + > > + if (dax_dev->holder_data) { > > + rc = dax_dev->holder_ops->notify_failure(dax_dev, offset, > > + size, data); > > + if (rc == -ENODEV) > > + rc = -ENXIO; > > + } else > > + rc = -EOPNOTSUPP; > > The style looks a little odd. Why not: > > if (!dax_dev) > return -ENXIO > if (!dax_dev->holder_data) > return -EOPNOTSUPP; > return dax_dev->holder_ops->notify_failure(dax_dev, offset, size, data); > > and let everyone deal with the same errno codes? OK. > > Also why do we even need the dax_dev NULL check? Because this dax_dev is obtain by fs_dax_get_by_bdev() in XFS and dax_get_by_host() in MD. According to their definition, NULL may be returned. So I check the dax_dev here. > > > +void dax_set_holder(struct dax_device *dax_dev, void *holder, > > + const struct dax_holder_operations *ops) { > > + if (!dax_dev) > > + return; > > I don't think we really need that check here. > > > +void *dax_get_holder(struct dax_device *dax_dev) { > > + void *holder_data; > > + > > + if (!dax_dev) > > + return NULL; > > Same here. > > > + > > + down_read(&dax_dev->holder_rwsem); > > + holder_data = dax_dev->holder_data; > > + up_read(&dax_dev->holder_rwsem); > > + > > + return holder_data; > > That lock won't protect anything. I think we simply must have synchronization > to prevent unregistration while the ->notify_failure call is in progress. Yes, I misunderstood the purpose of the lock. I'll fix this. -- Thanks, Ruan. -- dm-devel mailing list dm-devel@redhat.com https://listman.redhat.com/mailman/listinfo/dm-devel
diff --git a/drivers/dax/super.c b/drivers/dax/super.c index 5fa6ae9dbc8b..22f0aa3f2e13 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -222,8 +222,11 @@ struct dax_device { struct cdev cdev; const char *host; void *private; + struct rw_semaphore holder_rwsem; + void *holder_data; unsigned long flags; const struct dax_operations *ops; + const struct dax_holder_operations *holder_ops; }; static ssize_t write_cache_show(struct device *dev, @@ -373,6 +376,24 @@ int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, } EXPORT_SYMBOL_GPL(dax_zero_page_range); +int dax_holder_notify_failure(struct dax_device *dax_dev, loff_t offset, + size_t size, void *data) +{ + int rc = -ENXIO; + if (!dax_dev) + return rc; + + if (dax_dev->holder_data) { + rc = dax_dev->holder_ops->notify_failure(dax_dev, offset, + size, data); + if (rc == -ENODEV) + rc = -ENXIO; + } else + rc = -EOPNOTSUPP; + return rc; +} +EXPORT_SYMBOL_GPL(dax_holder_notify_failure); + #ifdef CONFIG_ARCH_HAS_PMEM_API void arch_wb_cache_pmem(void *addr, size_t size); void dax_flush(struct dax_device *dax_dev, void *addr, size_t size) @@ -603,6 +624,7 @@ struct dax_device *alloc_dax(void *private, const char *__host, dax_add_host(dax_dev, host); dax_dev->ops = ops; dax_dev->private = private; + init_rwsem(&dax_dev->holder_rwsem); if (flags & DAXDEV_F_SYNC) set_dax_synchronous(dax_dev); @@ -624,6 +646,33 @@ void put_dax(struct dax_device *dax_dev) } EXPORT_SYMBOL_GPL(put_dax); +void dax_set_holder(struct dax_device *dax_dev, void *holder, + const struct dax_holder_operations *ops) +{ + if (!dax_dev) + return; + down_write(&dax_dev->holder_rwsem); + dax_dev->holder_data = holder; + dax_dev->holder_ops = ops; + up_write(&dax_dev->holder_rwsem); +} +EXPORT_SYMBOL_GPL(dax_set_holder); + +void *dax_get_holder(struct dax_device *dax_dev) +{ + void *holder_data; + + if (!dax_dev) + return NULL; + + down_read(&dax_dev->holder_rwsem); + holder_data = dax_dev->holder_data; + up_read(&dax_dev->holder_rwsem); + + return holder_data; +} +EXPORT_SYMBOL_GPL(dax_get_holder); + /** * dax_get_by_host() - temporary lookup mechanism for filesystem-dax * @host: alternate name for the device registered by a dax driver diff --git a/include/linux/dax.h b/include/linux/dax.h index b52f084aa643..6f4b5c97ceb0 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h @@ -38,10 +38,17 @@ struct dax_operations { int (*zero_page_range)(struct dax_device *, pgoff_t, size_t); }; +struct dax_holder_operations { + int (*notify_failure)(struct dax_device *, loff_t, size_t, void *); +}; + extern struct attribute_group dax_attribute_group; #if IS_ENABLED(CONFIG_DAX) struct dax_device *dax_get_by_host(const char *host); +void dax_set_holder(struct dax_device *dax_dev, void *holder, + const struct dax_holder_operations *ops); +void *dax_get_holder(struct dax_device *dax_dev); struct dax_device *alloc_dax(void *private, const char *host, const struct dax_operations *ops, unsigned long flags); void put_dax(struct dax_device *dax_dev); @@ -77,6 +84,14 @@ static inline struct dax_device *dax_get_by_host(const char *host) { return NULL; } +static inline void dax_set_holder(struct dax_device *dax_dev, void *holder, + const struct dax_holder_operations *ops) +{ +} +static inline void *dax_get_holder(struct dax_device *dax_dev) +{ + return NULL; +} static inline struct dax_device *alloc_dax(void *private, const char *host, const struct dax_operations *ops, unsigned long flags) { @@ -226,6 +241,8 @@ size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i); int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, size_t nr_pages); +int dax_holder_notify_failure(struct dax_device *dax_dev, loff_t offset, + size_t size, void *data); void dax_flush(struct dax_device *dax_dev, void *addr, size_t size); ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,
To easily track filesystem from a pmem device, we introduce a holder for dax_device structure, and also its operation. This holder is used to remember who is using this dax_device: - When it is the backend of a filesystem, the holder will be the superblock of this filesystem. - When this pmem device is one of the targets in a mapped device, the holder will be this mapped device. In this case, the mapped device has its own dax_device and it will follow the first rule. So that we can finally track to the filesystem we needed. The holder and holder_ops will be set when filesystem is being mounted, or an target device is being activated. Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com> --- drivers/dax/super.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/dax.h | 17 ++++++++++++++++ 2 files changed, 66 insertions(+) -- 2.32.0 -- dm-devel mailing list dm-devel@redhat.com https://listman.redhat.com/mailman/listinfo/dm-devel