static __be32 nfsd4_block_proc_layoutcommit(struct inode *inode, struct nfsd4_layoutcommit *lcp) { loff_t new_size = lcp->lc_last_wr + 1; struct iattr iattr = { .ia_valid = 0 }; struct iomap *iomaps; int nr_iomaps; int error; nr_iomaps = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout, lcp->lc_up_len, &iomaps, 1 << inode->i_blkbits); if (nr_iomaps < 0) return nfserrno(nr_iomaps); if (lcp->lc_mtime.tv_nsec == UTIME_NOW || timespec_compare(&lcp->lc_mtime, &inode->i_mtime) < 0) lcp->lc_mtime = current_fs_time(inode->i_sb); iattr.ia_valid |= ATTR_ATIME | ATTR_CTIME | ATTR_MTIME; iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime; if (new_size > i_size_read(inode)) { iattr.ia_valid |= ATTR_SIZE; iattr.ia_size = new_size; } error = inode->i_sb->s_export_op->commit_blocks(inode, iomaps, nr_iomaps, &iattr); kfree(iomaps); return nfserrno(error); } const struct nfsd4_layout_ops bl_layout_ops = { /* * Pretend that we send notification to the client. This is a blatant * lie to force recent Linux clients to cache our device IDs. * We rarely ever change the device ID, so the harm of leaking deviceids * for a while isn't too bad. Unfortunately RFC5661 is a complete mess * in this regard, but I filed errata 4119 for this a while ago, and * hopefully the Linux client will eventually start caching deviceids * without this again. */ .notify_types = NOTIFY_DEVICEID4_DELETE | NOTIFY_DEVICEID4_CHANGE, .proc_getdeviceinfo = nfsd4_block_proc_getdeviceinfo, .encode_getdeviceinfo = nfsd4_block_encode_getdeviceinfo, .proc_layoutget = nfsd4_block_proc_layoutget, .encode_layoutget = nfsd4_block_encode_layoutget, .proc_layoutcommit = nfsd4_block_proc_layoutcommit, };
static __be32 nfsd4_block_proc_layoutcommit(struct inode *inode, struct nfsd4_layoutcommit *lcp) { loff_t new_size = lcp->lc_last_wr + 1; struct iattr iattr = { .ia_valid = 0 }; struct iomap *iomaps; int nr_iomaps; int error; nr_iomaps = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout, lcp->lc_up_len, &iomaps, 1 << inode->i_blkbits); if (nr_iomaps < 0) return nfserrno(nr_iomaps); if (lcp->lc_mtime.tv_nsec == UTIME_NOW || timespec_compare(&lcp->lc_mtime, &inode->i_mtime) < 0) lcp->lc_mtime = current_fs_time(inode->i_sb); iattr.ia_valid |= ATTR_ATIME | ATTR_CTIME | ATTR_MTIME; iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime; if (new_size > i_size_read(inode)) { iattr.ia_valid |= ATTR_SIZE; iattr.ia_size = new_size; } error = inode->i_sb->s_export_op->commit_blocks(inode, iomaps, nr_iomaps, &iattr); kfree(iomaps); return nfserrno(error); } const struct nfsd4_layout_ops bl_layout_ops = { .proc_getdeviceinfo = nfsd4_block_proc_getdeviceinfo, .encode_getdeviceinfo = nfsd4_block_encode_getdeviceinfo, .proc_layoutget = nfsd4_block_proc_layoutget, .encode_layoutget = nfsd4_block_encode_layoutget, .proc_layoutcommit = nfsd4_block_proc_layoutcommit, };