Skip to content

Commit 41963c1

Browse files
bcodding-rhtrondmypd
authored andcommitted
pnfs/blocklayout: update last_write_offset atomically with extents
Block/SCSI layout write completion may add committable extents to the extent tree before updating the layout's last-written byte under the inode lock. If a sync happens before this value is updated, then prepare_layoutcommit may find and encode these extents which would produce a LAYOUTCOMMIT request whose encoded extents are larger than the request's loca_length. Fix this by using a last-written byte value that is updated atomically with the extent tree so that commitable extents always match. Signed-off-by: Benjamin Coddington <bcodding@redhat.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
1 parent b88fa69 commit 41963c1

File tree

3 files changed

+10
-5
lines changed

3 files changed

+10
-5
lines changed

fs/nfs/blocklayout/blocklayout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ static void bl_write_cleanup(struct work_struct *work)
346346
PAGE_SIZE - 1) & (loff_t)PAGE_MASK;
347347

348348
ext_tree_mark_written(bl, start >> SECTOR_SHIFT,
349-
(end - start) >> SECTOR_SHIFT);
349+
(end - start) >> SECTOR_SHIFT, end);
350350
}
351351

352352
pnfs_ld_write_done(hdr);

fs/nfs/blocklayout/blocklayout.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ struct pnfs_block_layout {
141141
struct rb_root bl_ext_ro;
142142
spinlock_t bl_ext_lock; /* Protects list manipulation */
143143
bool bl_scsi_layout;
144+
u64 bl_lwb;
144145
};
145146

146147
static inline struct pnfs_block_layout *
@@ -182,7 +183,7 @@ int ext_tree_insert(struct pnfs_block_layout *bl,
182183
int ext_tree_remove(struct pnfs_block_layout *bl, bool rw, sector_t start,
183184
sector_t end);
184185
int ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start,
185-
sector_t len);
186+
sector_t len, u64 lwb);
186187
bool ext_tree_lookup(struct pnfs_block_layout *bl, sector_t isect,
187188
struct pnfs_block_extent *ret, bool rw);
188189
int ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg);

fs/nfs/blocklayout/extent_tree.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ ext_tree_split(struct rb_root *root, struct pnfs_block_extent *be,
402402

403403
int
404404
ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start,
405-
sector_t len)
405+
sector_t len, u64 lwb)
406406
{
407407
struct rb_root *root = &bl->bl_ext_rw;
408408
sector_t end = start + len;
@@ -471,6 +471,8 @@ ext_tree_mark_written(struct pnfs_block_layout *bl, sector_t start,
471471
}
472472
}
473473
out:
474+
if (bl->bl_lwb < lwb)
475+
bl->bl_lwb = lwb;
474476
spin_unlock(&bl->bl_ext_lock);
475477

476478
__ext_put_deviceids(&tmp);
@@ -518,7 +520,7 @@ static __be32 *encode_scsi_range(struct pnfs_block_extent *be, __be32 *p)
518520
}
519521

520522
static int ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p,
521-
size_t buffer_size, size_t *count)
523+
size_t buffer_size, size_t *count, __u64 *lastbyte)
522524
{
523525
struct pnfs_block_extent *be;
524526
int ret = 0;
@@ -542,6 +544,8 @@ static int ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p,
542544
p = encode_block_extent(be, p);
543545
be->be_tag = EXTENT_COMMITTING;
544546
}
547+
*lastbyte = bl->bl_lwb - 1;
548+
bl->bl_lwb = 0;
545549
spin_unlock(&bl->bl_ext_lock);
546550

547551
return ret;
@@ -564,7 +568,7 @@ ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg)
564568
arg->layoutupdate_pages = &arg->layoutupdate_page;
565569

566570
retry:
567-
ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, &count);
571+
ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, &count, &arg->lastbytewritten);
568572
if (unlikely(ret)) {
569573
ext_tree_free_commitdata(arg, buffer_size);
570574

0 commit comments

Comments
 (0)