mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 02:36:02 +00:00
xfs: remove the xfile_pread/pwrite APIs
All current and pending xfile users use the xfile_obj_load and xfile_obj_store API, so make those the actual implementation. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
This commit is contained in:
parent
0473635d46
commit
e47e2e0ba9
@ -1915,19 +1915,13 @@ four of those five higher level data structures.
|
||||
The fifth use case is discussed in the :ref:`realtime summary <rtsummary>` case
|
||||
study.
|
||||
|
||||
The most general storage interface supported by the xfile enables the reading
|
||||
and writing of arbitrary quantities of data at arbitrary offsets in the xfile.
|
||||
This capability is provided by ``xfile_pread`` and ``xfile_pwrite`` functions,
|
||||
which behave similarly to their userspace counterparts.
|
||||
XFS is very record-based, which suggests that the ability to load and store
|
||||
complete records is important.
|
||||
To support these cases, a pair of ``xfile_obj_load`` and ``xfile_obj_store``
|
||||
functions are provided to read and persist objects into an xfile.
|
||||
They are internally the same as pread and pwrite, except that they treat any
|
||||
error as an out of memory error.
|
||||
For online repair, squashing error conditions in this manner is an acceptable
|
||||
behavior because the only reaction is to abort the operation back to userspace.
|
||||
All five xfile usecases can be serviced by these four functions.
|
||||
To support these cases, a pair of ``xfile_load`` and ``xfile_store``
|
||||
functions are provided to read and persist objects into an xfile that treat any
|
||||
error as an out of memory error. For online repair, squashing error conditions
|
||||
in this manner is an acceptable behavior because the only reaction is to abort
|
||||
the operation back to userspace.
|
||||
|
||||
However, no discussion of file access idioms is complete without answering the
|
||||
question, "But what about mmap?"
|
||||
@ -1939,10 +1933,9 @@ tmpfs can only push a pagecache folio to the swap cache if the folio is neither
|
||||
pinned nor locked, which means the xfile must not pin too many folios.
|
||||
|
||||
Short term direct access to xfile contents is done by locking the pagecache
|
||||
folio and mapping it into kernel address space.
|
||||
Programmatic access (e.g. pread and pwrite) uses this mechanism.
|
||||
Folio locks are not supposed to be held for long periods of time, so long
|
||||
term direct access to xfile contents is done by bumping the folio refcount,
|
||||
folio and mapping it into kernel address space. Object load and store uses this
|
||||
mechanism. Folio locks are not supposed to be held for long periods of time, so
|
||||
long term direct access to xfile contents is done by bumping the folio refcount,
|
||||
mapping it into kernel address space, and dropping the folio lock.
|
||||
These long term users *must* be responsive to memory reclaim by hooking into
|
||||
the shrinker infrastructure to know when to release folios.
|
||||
|
@ -119,7 +119,7 @@ xfsum_load(
|
||||
xfs_rtsumoff_t sumoff,
|
||||
union xfs_suminfo_raw *rawinfo)
|
||||
{
|
||||
return xfile_obj_load(sc->xfile, rawinfo,
|
||||
return xfile_load(sc->xfile, rawinfo,
|
||||
sizeof(union xfs_suminfo_raw),
|
||||
sumoff << XFS_WORDLOG);
|
||||
}
|
||||
@ -130,7 +130,7 @@ xfsum_store(
|
||||
xfs_rtsumoff_t sumoff,
|
||||
const union xfs_suminfo_raw rawinfo)
|
||||
{
|
||||
return xfile_obj_store(sc->xfile, &rawinfo,
|
||||
return xfile_store(sc->xfile, &rawinfo,
|
||||
sizeof(union xfs_suminfo_raw),
|
||||
sumoff << XFS_WORDLOG);
|
||||
}
|
||||
@ -142,7 +142,7 @@ xfsum_copyout(
|
||||
union xfs_suminfo_raw *rawinfo,
|
||||
unsigned int nr_words)
|
||||
{
|
||||
return xfile_obj_load(sc->xfile, rawinfo, nr_words << XFS_WORDLOG,
|
||||
return xfile_load(sc->xfile, rawinfo, nr_words << XFS_WORDLOG,
|
||||
sumoff << XFS_WORDLOG);
|
||||
}
|
||||
|
||||
|
@ -903,8 +903,8 @@ DECLARE_EVENT_CLASS(xfile_class,
|
||||
DEFINE_EVENT(xfile_class, name, \
|
||||
TP_PROTO(struct xfile *xf, loff_t pos, unsigned long long bytecount), \
|
||||
TP_ARGS(xf, pos, bytecount))
|
||||
DEFINE_XFILE_EVENT(xfile_pread);
|
||||
DEFINE_XFILE_EVENT(xfile_pwrite);
|
||||
DEFINE_XFILE_EVENT(xfile_load);
|
||||
DEFINE_XFILE_EVENT(xfile_store);
|
||||
DEFINE_XFILE_EVENT(xfile_seek_data);
|
||||
DEFINE_XFILE_EVENT(xfile_get_page);
|
||||
DEFINE_XFILE_EVENT(xfile_put_page);
|
||||
|
@ -136,7 +136,7 @@ xfarray_load(
|
||||
if (idx >= array->nr)
|
||||
return -ENODATA;
|
||||
|
||||
return xfile_obj_load(array->xfile, ptr, array->obj_size,
|
||||
return xfile_load(array->xfile, ptr, array->obj_size,
|
||||
xfarray_pos(array, idx));
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ xfarray_is_unset(
|
||||
if (array->unset_slots == 0)
|
||||
return false;
|
||||
|
||||
error = xfile_obj_load(array->xfile, temp, array->obj_size, pos);
|
||||
error = xfile_load(array->xfile, temp, array->obj_size, pos);
|
||||
if (!error && xfarray_element_is_null(array, temp))
|
||||
return true;
|
||||
|
||||
@ -184,7 +184,7 @@ xfarray_unset(
|
||||
return 0;
|
||||
|
||||
memset(temp, 0, array->obj_size);
|
||||
error = xfile_obj_store(array->xfile, temp, array->obj_size, pos);
|
||||
error = xfile_store(array->xfile, temp, array->obj_size, pos);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -209,7 +209,7 @@ xfarray_store(
|
||||
|
||||
ASSERT(!xfarray_element_is_null(array, ptr));
|
||||
|
||||
ret = xfile_obj_store(array->xfile, ptr, array->obj_size,
|
||||
ret = xfile_store(array->xfile, ptr, array->obj_size,
|
||||
xfarray_pos(array, idx));
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -245,12 +245,12 @@ xfarray_store_anywhere(
|
||||
for (pos = 0;
|
||||
pos < endpos && array->unset_slots > 0;
|
||||
pos += array->obj_size) {
|
||||
error = xfile_obj_load(array->xfile, temp, array->obj_size,
|
||||
error = xfile_load(array->xfile, temp, array->obj_size,
|
||||
pos);
|
||||
if (error || !xfarray_element_is_null(array, temp))
|
||||
continue;
|
||||
|
||||
error = xfile_obj_store(array->xfile, ptr, array->obj_size,
|
||||
error = xfile_store(array->xfile, ptr, array->obj_size,
|
||||
pos);
|
||||
if (error)
|
||||
return error;
|
||||
@ -552,7 +552,7 @@ xfarray_isort(
|
||||
trace_xfarray_isort(si, lo, hi);
|
||||
|
||||
xfarray_sort_bump_loads(si);
|
||||
error = xfile_obj_load(si->array->xfile, scratch, len, lo_pos);
|
||||
error = xfile_load(si->array->xfile, scratch, len, lo_pos);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -560,7 +560,7 @@ xfarray_isort(
|
||||
sort(scratch, hi - lo + 1, si->array->obj_size, si->cmp_fn, NULL);
|
||||
|
||||
xfarray_sort_bump_stores(si);
|
||||
return xfile_obj_store(si->array->xfile, scratch, len, lo_pos);
|
||||
return xfile_store(si->array->xfile, scratch, len, lo_pos);
|
||||
}
|
||||
|
||||
/* Grab a page for sorting records. */
|
||||
@ -858,7 +858,7 @@ xfarray_sort_load_cached(
|
||||
if (xfarray_sort_terminated(si, &error))
|
||||
return error;
|
||||
|
||||
return xfile_obj_load(si->array->xfile, ptr,
|
||||
return xfile_load(si->array->xfile, ptr,
|
||||
si->array->obj_size, idx_pos);
|
||||
}
|
||||
|
||||
|
@ -101,13 +101,11 @@ xfile_destroy(
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a memory object directly from the xfile's page cache. Unlike regular
|
||||
* pread, we return -E2BIG and -EFBIG for reads that are too large or at too
|
||||
* high an offset, instead of truncating the read. Otherwise, we return
|
||||
* bytes read or an error code, like regular pread.
|
||||
* Load an object. Since we're treating this file as "memory", any error or
|
||||
* short IO is treated as a failure to allocate memory.
|
||||
*/
|
||||
ssize_t
|
||||
xfile_pread(
|
||||
int
|
||||
xfile_load(
|
||||
struct xfile *xf,
|
||||
void *buf,
|
||||
size_t count,
|
||||
@ -116,16 +114,15 @@ xfile_pread(
|
||||
struct inode *inode = file_inode(xf->file);
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
struct page *page = NULL;
|
||||
ssize_t read = 0;
|
||||
unsigned int pflags;
|
||||
int error = 0;
|
||||
|
||||
if (count > MAX_RW_COUNT)
|
||||
return -E2BIG;
|
||||
return -ENOMEM;
|
||||
if (inode->i_sb->s_maxbytes - pos < count)
|
||||
return -EFBIG;
|
||||
return -ENOMEM;
|
||||
|
||||
trace_xfile_pread(xf, pos, count);
|
||||
trace_xfile_load(xf, pos, count);
|
||||
|
||||
pflags = memalloc_nofs_save();
|
||||
while (count > 0) {
|
||||
@ -143,8 +140,10 @@ xfile_pread(
|
||||
__GFP_NOWARN);
|
||||
if (IS_ERR(page)) {
|
||||
error = PTR_ERR(page);
|
||||
if (error != -ENOMEM)
|
||||
if (error != -ENOMEM) {
|
||||
error = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(buf, 0, len);
|
||||
goto advance;
|
||||
@ -168,23 +167,18 @@ xfile_pread(
|
||||
count -= len;
|
||||
pos += len;
|
||||
buf += len;
|
||||
read += len;
|
||||
}
|
||||
memalloc_nofs_restore(pflags);
|
||||
|
||||
if (read > 0)
|
||||
return read;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a memory object directly to the xfile's page cache. Unlike regular
|
||||
* pwrite, we return -E2BIG and -EFBIG for writes that are too large or at too
|
||||
* high an offset, instead of truncating the write. Otherwise, we return
|
||||
* bytes written or an error code, like regular pwrite.
|
||||
* Store an object. Since we're treating this file as "memory", any error or
|
||||
* short IO is treated as a failure to allocate memory.
|
||||
*/
|
||||
ssize_t
|
||||
xfile_pwrite(
|
||||
int
|
||||
xfile_store(
|
||||
struct xfile *xf,
|
||||
const void *buf,
|
||||
size_t count,
|
||||
@ -194,16 +188,15 @@ xfile_pwrite(
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
const struct address_space_operations *aops = mapping->a_ops;
|
||||
struct page *page = NULL;
|
||||
ssize_t written = 0;
|
||||
unsigned int pflags;
|
||||
int error = 0;
|
||||
|
||||
if (count > MAX_RW_COUNT)
|
||||
return -E2BIG;
|
||||
return -ENOMEM;
|
||||
if (inode->i_sb->s_maxbytes - pos < count)
|
||||
return -EFBIG;
|
||||
return -ENOMEM;
|
||||
|
||||
trace_xfile_pwrite(xf, pos, count);
|
||||
trace_xfile_store(xf, pos, count);
|
||||
|
||||
pflags = memalloc_nofs_save();
|
||||
while (count > 0) {
|
||||
@ -222,8 +215,10 @@ xfile_pwrite(
|
||||
*/
|
||||
error = aops->write_begin(NULL, mapping, pos, len, &page,
|
||||
&fsdata);
|
||||
if (error)
|
||||
if (error) {
|
||||
error = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* xfile pages must never be mapped into userspace, so we skip
|
||||
@ -242,13 +237,14 @@ xfile_pwrite(
|
||||
ret = aops->write_end(NULL, mapping, pos, len, len, page,
|
||||
fsdata);
|
||||
if (ret < 0) {
|
||||
error = ret;
|
||||
error = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
written += ret;
|
||||
if (ret != len)
|
||||
if (ret != len) {
|
||||
error = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
count -= ret;
|
||||
pos += ret;
|
||||
@ -256,8 +252,6 @@ xfile_pwrite(
|
||||
}
|
||||
memalloc_nofs_restore(pflags);
|
||||
|
||||
if (written > 0)
|
||||
return written;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -29,38 +29,10 @@ struct xfile {
|
||||
int xfile_create(const char *description, loff_t isize, struct xfile **xfilep);
|
||||
void xfile_destroy(struct xfile *xf);
|
||||
|
||||
ssize_t xfile_pread(struct xfile *xf, void *buf, size_t count, loff_t pos);
|
||||
ssize_t xfile_pwrite(struct xfile *xf, const void *buf, size_t count,
|
||||
int xfile_load(struct xfile *xf, void *buf, size_t count, loff_t pos);
|
||||
int xfile_store(struct xfile *xf, const void *buf, size_t count,
|
||||
loff_t pos);
|
||||
|
||||
/*
|
||||
* Load an object. Since we're treating this file as "memory", any error or
|
||||
* short IO is treated as a failure to allocate memory.
|
||||
*/
|
||||
static inline int
|
||||
xfile_obj_load(struct xfile *xf, void *buf, size_t count, loff_t pos)
|
||||
{
|
||||
ssize_t ret = xfile_pread(xf, buf, count, pos);
|
||||
|
||||
if (ret < 0 || ret != count)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store an object. Since we're treating this file as "memory", any error or
|
||||
* short IO is treated as a failure to allocate memory.
|
||||
*/
|
||||
static inline int
|
||||
xfile_obj_store(struct xfile *xf, const void *buf, size_t count, loff_t pos)
|
||||
{
|
||||
ssize_t ret = xfile_pwrite(xf, buf, count, pos);
|
||||
|
||||
if (ret < 0 || ret != count)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
loff_t xfile_seek_data(struct xfile *xf, loff_t pos);
|
||||
|
||||
int xfile_get_page(struct xfile *xf, loff_t offset, unsigned int len,
|
||||
|
Loading…
Reference in New Issue
Block a user