Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFS: Don't zap caches on fallocate()

This patch adds a GETATTR to the end of ALLOCATE and DEALLOCATE
operations so we can set the updated inode size and change attribute
directly. DEALLOCATE will still need to release pagecache pages, so
nfs42_proc_deallocate() now calls truncate_pagecache_range() before
contacting the server.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>

authored by

Anna Schumaker and committed by
Trond Myklebust
9a51940b 8c18d76b

+39 -10
-1
fs/nfs/inode.c
··· 199 199 nfs_zap_caches_locked(inode); 200 200 spin_unlock(&inode->i_lock); 201 201 } 202 - EXPORT_SYMBOL_GPL(nfs_zap_caches); 203 202 204 203 void nfs_zap_mapping(struct inode *inode, struct address_space *mapping) 205 204 {
+19 -4
fs/nfs/nfs42proc.c
··· 36 36 loff_t offset, loff_t len) 37 37 { 38 38 struct inode *inode = file_inode(filep); 39 + struct nfs_server *server = NFS_SERVER(inode); 39 40 struct nfs42_falloc_args args = { 40 41 .falloc_fh = NFS_FH(inode), 41 42 .falloc_offset = offset, 42 43 .falloc_length = len, 44 + .falloc_bitmask = server->cache_consistency_bitmask, 43 45 }; 44 - struct nfs42_falloc_res res; 45 - struct nfs_server *server = NFS_SERVER(inode); 46 + struct nfs42_falloc_res res = { 47 + .falloc_server = server, 48 + }; 46 49 int status; 47 50 48 51 msg->rpc_argp = &args; ··· 55 52 if (status) 56 53 return status; 57 54 58 - return nfs4_call_sync(server->client, server, msg, 59 - &args.seq_args, &res.seq_res, 0); 55 + res.falloc_fattr = nfs_alloc_fattr(); 56 + if (!res.falloc_fattr) 57 + return -ENOMEM; 58 + 59 + status = nfs4_call_sync(server->client, server, msg, 60 + &args.seq_args, &res.seq_res, 0); 61 + if (status == 0) 62 + status = nfs_post_op_update_inode(inode, res.falloc_fattr); 63 + 64 + kfree(res.falloc_fattr); 65 + return status; 60 66 } 61 67 62 68 static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep, ··· 113 101 if (!nfs_server_capable(inode, NFS_CAP_DEALLOCATE)) 114 102 return -EOPNOTSUPP; 115 103 104 + nfs_wb_all(inode); 116 105 err = nfs42_proc_fallocate(&msg, filep, offset, len); 106 + if (err == 0) 107 + truncate_pagecache_range(inode, offset, (offset + len) -1); 117 108 if (err == -EOPNOTSUPP) 118 109 NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE; 119 110 return err;
+16 -4
fs/nfs/nfs42xdr.c
··· 25 25 26 26 #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ 27 27 encode_putfh_maxsz + \ 28 - encode_allocate_maxsz) 28 + encode_allocate_maxsz + \ 29 + encode_getattr_maxsz) 29 30 #define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \ 30 31 decode_putfh_maxsz + \ 31 - decode_allocate_maxsz) 32 + decode_allocate_maxsz + \ 33 + decode_getattr_maxsz) 32 34 #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ 33 35 encode_putfh_maxsz + \ 34 - encode_deallocate_maxsz) 36 + encode_deallocate_maxsz + \ 37 + encode_getattr_maxsz) 35 38 #define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \ 36 39 decode_putfh_maxsz + \ 37 - decode_deallocate_maxsz) 40 + decode_deallocate_maxsz + \ 41 + decode_getattr_maxsz) 38 42 #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ 39 43 encode_putfh_maxsz + \ 40 44 encode_seek_maxsz) ··· 96 92 encode_sequence(xdr, &args->seq_args, &hdr); 97 93 encode_putfh(xdr, args->falloc_fh, &hdr); 98 94 encode_allocate(xdr, args, &hdr); 95 + encode_getfattr(xdr, args->falloc_bitmask, &hdr); 99 96 encode_nops(&hdr); 100 97 } 101 98 ··· 115 110 encode_sequence(xdr, &args->seq_args, &hdr); 116 111 encode_putfh(xdr, args->falloc_fh, &hdr); 117 112 encode_deallocate(xdr, args, &hdr); 113 + encode_getfattr(xdr, args->falloc_bitmask, &hdr); 118 114 encode_nops(&hdr); 119 115 } 120 116 ··· 189 183 if (status) 190 184 goto out; 191 185 status = decode_allocate(xdr, res); 186 + if (status) 187 + goto out; 188 + decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 192 189 out: 193 190 return status; 194 191 } ··· 216 207 if (status) 217 208 goto out; 218 209 status = decode_deallocate(xdr, res); 210 + if (status) 211 + goto out; 212 + decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 219 213 out: 220 214 return status; 221 215 }
-1
fs/nfs/nfs4file.c
··· 165 165 ret = nfs42_proc_allocate(filep, offset, len); 166 166 mutex_unlock(&inode->i_mutex); 167 167 168 - nfs_zap_caches(inode); 169 168 return ret; 170 169 } 171 170 #endif /* CONFIG_NFS_V4_2 */
+4
include/linux/nfs_xdr.h
··· 1273 1273 nfs4_stateid falloc_stateid; 1274 1274 u64 falloc_offset; 1275 1275 u64 falloc_length; 1276 + const u32 *falloc_bitmask; 1276 1277 }; 1277 1278 1278 1279 struct nfs42_falloc_res { 1279 1280 struct nfs4_sequence_res seq_res; 1280 1281 unsigned int status; 1282 + 1283 + struct nfs_fattr *falloc_fattr; 1284 + const struct nfs_server *falloc_server; 1281 1285 }; 1282 1286 1283 1287 struct nfs42_seek_args {