Skip to content

Commit c33da54

Browse files
sbashirogregkh
authored andcommitted
NFSD: Fix last write offset handling in layoutcommit
[ Upstream commit d68886b ] The data type of loca_last_write_offset is newoffset4 and is switched on a boolean value, no_newoffset, that indicates if a previous write occurred or not. If no_newoffset is FALSE, an offset is not given. This means that client does not try to update the file size. Thus, server should not try to calculate new file size and check if it fits into the segment range. See RFC 8881, section 12.5.4.2. Sometimes the current incorrect logic may cause clients to hang when trying to sync an inode. If layoutcommit fails, the client marks the inode as dirty again. Fixes: 9cf514c ("nfsd: implement pNFS operations") Cc: [email protected] Co-developed-by: Konstantin Evtushenko <[email protected]> Signed-off-by: Konstantin Evtushenko <[email protected]> Signed-off-by: Sergey Bashirov <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent da68bc5 commit c33da54

File tree

2 files changed

+17
-18
lines changed

2 files changed

+17
-18
lines changed

fs/nfsd/blocklayout.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp,
118118
struct iomap *iomaps, int nr_iomaps)
119119
{
120120
struct timespec64 mtime = inode_get_mtime(inode);
121-
loff_t new_size = lcp->lc_last_wr + 1;
122121
struct iattr iattr = { .ia_valid = 0 };
123122
int error;
124123

@@ -128,9 +127,9 @@ nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp,
128127
iattr.ia_valid |= ATTR_ATIME | ATTR_CTIME | ATTR_MTIME;
129128
iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime;
130129

131-
if (new_size > i_size_read(inode)) {
130+
if (lcp->lc_size_chg) {
132131
iattr.ia_valid |= ATTR_SIZE;
133-
iattr.ia_size = new_size;
132+
iattr.ia_size = lcp->lc_newsize;
134133
}
135134

136135
error = inode->i_sb->s_export_op->commit_blocks(inode, iomaps,

fs/nfsd/nfs4proc.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2362,7 +2362,6 @@ nfsd4_layoutcommit(struct svc_rqst *rqstp,
23622362
const struct nfsd4_layout_seg *seg = &lcp->lc_seg;
23632363
struct svc_fh *current_fh = &cstate->current_fh;
23642364
const struct nfsd4_layout_ops *ops;
2365-
loff_t new_size = lcp->lc_last_wr + 1;
23662365
struct inode *inode;
23672366
struct nfs4_layout_stateid *ls;
23682367
__be32 nfserr;
@@ -2378,13 +2377,21 @@ nfsd4_layoutcommit(struct svc_rqst *rqstp,
23782377
goto out;
23792378
inode = d_inode(current_fh->fh_dentry);
23802379

2381-
nfserr = nfserr_inval;
2382-
if (new_size <= seg->offset)
2383-
goto out;
2384-
if (new_size > seg->offset + seg->length)
2385-
goto out;
2386-
if (!lcp->lc_newoffset && new_size > i_size_read(inode))
2387-
goto out;
2380+
lcp->lc_size_chg = false;
2381+
if (lcp->lc_newoffset) {
2382+
loff_t new_size = lcp->lc_last_wr + 1;
2383+
2384+
nfserr = nfserr_inval;
2385+
if (new_size <= seg->offset)
2386+
goto out;
2387+
if (new_size > seg->offset + seg->length)
2388+
goto out;
2389+
2390+
if (new_size > i_size_read(inode)) {
2391+
lcp->lc_size_chg = true;
2392+
lcp->lc_newsize = new_size;
2393+
}
2394+
}
23882395

23892396
nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, &lcp->lc_sid,
23902397
false, lcp->lc_layout_type,
@@ -2400,13 +2407,6 @@ nfsd4_layoutcommit(struct svc_rqst *rqstp,
24002407
/* LAYOUTCOMMIT does not require any serialization */
24012408
mutex_unlock(&ls->ls_mutex);
24022409

2403-
if (new_size > i_size_read(inode)) {
2404-
lcp->lc_size_chg = true;
2405-
lcp->lc_newsize = new_size;
2406-
} else {
2407-
lcp->lc_size_chg = false;
2408-
}
2409-
24102410
nfserr = ops->proc_layoutcommit(inode, rqstp, lcp);
24112411
nfs4_put_stid(&ls->ls_stid);
24122412
out:

0 commit comments

Comments
 (0)