Skip to content

Commit 1ce9d79

Browse files
committed
Merge tag 'ceph-for-5.19-rc7' of https://github.com/ceph/ceph-client
Pull ceph fix from Ilya Dryomov: "A folio locking fixup that Xiubo and David cooperated on, marked for stable. Most of it is in netfs but I picked it up into ceph tree on agreement with David" * tag 'ceph-for-5.19-rc7' of https://github.com/ceph/ceph-client: netfs: do not unlock and put the folio twice
2 parents 8006112 + fac47b4 commit 1ce9d79

File tree

5 files changed

+23
-17
lines changed

5 files changed

+23
-17
lines changed

Documentation/filesystems/netfs_library.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ through which it can issue requests and negotiate::
301301
void (*issue_read)(struct netfs_io_subrequest *subreq);
302302
bool (*is_still_valid)(struct netfs_io_request *rreq);
303303
int (*check_write_begin)(struct file *file, loff_t pos, unsigned len,
304-
struct folio *folio, void **_fsdata);
304+
struct folio **foliop, void **_fsdata);
305305
void (*done)(struct netfs_io_request *rreq);
306306
};
307307

@@ -381,8 +381,10 @@ The operations are as follows:
381381
allocated/grabbed the folio to be modified to allow the filesystem to flush
382382
conflicting state before allowing it to be modified.
383383

384-
It should return 0 if everything is now fine, -EAGAIN if the folio should be
385-
regrabbed and any other error code to abort the operation.
384+
It may unlock and discard the folio it was given and set the caller's folio
385+
pointer to NULL. It should return 0 if everything is now fine (``*foliop``
386+
left set) or the op should be retried (``*foliop`` cleared) and any other
387+
error code to abort the operation.
386388

387389
* ``done``
388390

fs/afs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ static int afs_begin_cache_operation(struct netfs_io_request *rreq)
375375
}
376376

377377
static int afs_check_write_begin(struct file *file, loff_t pos, unsigned len,
378-
struct folio *folio, void **_fsdata)
378+
struct folio **foliop, void **_fsdata)
379379
{
380380
struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
381381

fs/ceph/addr.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
(CONGESTION_ON_THRESH(congestion_kb) >> 2))
6464

6565
static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned int len,
66-
struct folio *folio, void **_fsdata);
66+
struct folio **foliop, void **_fsdata);
6767

6868
static inline struct ceph_snap_context *page_snap_context(struct page *page)
6969
{
@@ -1288,18 +1288,19 @@ ceph_find_incompatible(struct page *page)
12881288
}
12891289

12901290
static int ceph_netfs_check_write_begin(struct file *file, loff_t pos, unsigned int len,
1291-
struct folio *folio, void **_fsdata)
1291+
struct folio **foliop, void **_fsdata)
12921292
{
12931293
struct inode *inode = file_inode(file);
12941294
struct ceph_inode_info *ci = ceph_inode(inode);
12951295
struct ceph_snap_context *snapc;
12961296

1297-
snapc = ceph_find_incompatible(folio_page(folio, 0));
1297+
snapc = ceph_find_incompatible(folio_page(*foliop, 0));
12981298
if (snapc) {
12991299
int r;
13001300

1301-
folio_unlock(folio);
1302-
folio_put(folio);
1301+
folio_unlock(*foliop);
1302+
folio_put(*foliop);
1303+
*foliop = NULL;
13031304
if (IS_ERR(snapc))
13041305
return PTR_ERR(snapc);
13051306

fs/netfs/buffered_read.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,9 @@ static bool netfs_skip_folio_read(struct folio *folio, loff_t pos, size_t len,
319319
* conflicting writes once the folio is grabbed and locked. It is passed a
320320
* pointer to the fsdata cookie that gets returned to the VM to be passed to
321321
* write_end. It is permitted to sleep. It should return 0 if the request
322-
* should go ahead; unlock the folio and return -EAGAIN to cause the folio to
323-
* be regot; or return an error.
322+
* should go ahead or it may return an error. It may also unlock and put the
323+
* folio, provided it sets ``*foliop`` to NULL, in which case a return of 0
324+
* will cause the folio to be re-got and the process to be retried.
324325
*
325326
* The calling netfs must initialise a netfs context contiguous to the vfs
326327
* inode before calling this.
@@ -348,13 +349,13 @@ int netfs_write_begin(struct netfs_inode *ctx,
348349

349350
if (ctx->ops->check_write_begin) {
350351
/* Allow the netfs (eg. ceph) to flush conflicts. */
351-
ret = ctx->ops->check_write_begin(file, pos, len, folio, _fsdata);
352+
ret = ctx->ops->check_write_begin(file, pos, len, &folio, _fsdata);
352353
if (ret < 0) {
353354
trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin);
354-
if (ret == -EAGAIN)
355-
goto retry;
356355
goto error;
357356
}
357+
if (!folio)
358+
goto retry;
358359
}
359360

360361
if (folio_test_uptodate(folio))
@@ -416,8 +417,10 @@ int netfs_write_begin(struct netfs_inode *ctx,
416417
error_put:
417418
netfs_put_request(rreq, false, netfs_rreq_trace_put_failed);
418419
error:
419-
folio_unlock(folio);
420-
folio_put(folio);
420+
if (folio) {
421+
folio_unlock(folio);
422+
folio_put(folio);
423+
}
421424
_leave(" = %d", ret);
422425
return ret;
423426
}

include/linux/netfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ struct netfs_request_ops {
214214
void (*issue_read)(struct netfs_io_subrequest *subreq);
215215
bool (*is_still_valid)(struct netfs_io_request *rreq);
216216
int (*check_write_begin)(struct file *file, loff_t pos, unsigned len,
217-
struct folio *folio, void **_fsdata);
217+
struct folio **foliop, void **_fsdata);
218218
void (*done)(struct netfs_io_request *rreq);
219219
};
220220

0 commit comments

Comments
 (0)