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

nfs: use change attribute for NFS re-exports

When exporting NFS, we may as well use the real change attribute
returned by the original server instead of faking up a change attribute
from the ctime.

Note we can't do that by setting I_VERSION--that would also turn on the
logic in iversion.h which treats the lower bit specially, and that
doesn't make sense for NFS.

So instead we define a new export operation for filesystems like NFS
that want to manage the change attribute themselves.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by

J. Bruce Fields and committed by
Chuck Lever
3cc55f44 02591f9f

+23 -1
+18
fs/nfs/export.c
··· 167 167 return parent; 168 168 } 169 169 170 + static u64 nfs_fetch_iversion(struct inode *inode) 171 + { 172 + struct nfs_server *server = NFS_SERVER(inode); 173 + 174 + /* Is this the right call?: */ 175 + nfs_revalidate_inode(server, inode); 176 + /* 177 + * Also, note we're ignoring any returned error. That seems to be 178 + * the practice for cache consistency information elsewhere in 179 + * the server, but I'm not sure why. 180 + */ 181 + if (server->nfs_client->rpc_ops->version >= 4) 182 + return inode_peek_iversion_raw(inode); 183 + else 184 + return time_to_chattr(&inode->i_ctime); 185 + } 186 + 170 187 const struct export_operations nfs_export_ops = { 171 188 .encode_fh = nfs_encode_fh, 172 189 .fh_to_dentry = nfs_fh_to_dentry, 173 190 .get_parent = nfs_get_parent, 191 + .fetch_iversion = nfs_fetch_iversion, 174 192 .flags = EXPORT_OP_NOWCC|EXPORT_OP_NOSUBTREECHK| 175 193 EXPORT_OP_CLOSE_BEFORE_UNLINK|EXPORT_OP_REMOTE_FS| 176 194 EXPORT_OP_NOATOMIC_ATTR,
+4 -1
fs/nfsd/nfsfh.h
··· 12 12 #include <linux/sunrpc/svc.h> 13 13 #include <uapi/linux/nfsd/nfsfh.h> 14 14 #include <linux/iversion.h> 15 + #include <linux/exportfs.h> 15 16 16 17 static inline __u32 ino_t_to_u32(ino_t ino) 17 18 { ··· 265 264 static inline u64 nfsd4_change_attribute(struct kstat *stat, 266 265 struct inode *inode) 267 266 { 268 - if (IS_I_VERSION(inode)) { 267 + if (inode->i_sb->s_export_op->fetch_iversion) 268 + return inode->i_sb->s_export_op->fetch_iversion(inode); 269 + else if (IS_I_VERSION(inode)) { 269 270 u64 chattr; 270 271 271 272 chattr = stat->ctime.tv_sec;
+1
include/linux/exportfs.h
··· 213 213 bool write, u32 *device_generation); 214 214 int (*commit_blocks)(struct inode *inode, struct iomap *iomaps, 215 215 int nr_iomaps, struct iattr *iattr); 216 + u64 (*fetch_iversion)(struct inode *); 216 217 #define EXPORT_OP_NOWCC (0x1) /* don't collect v3 wcc data */ 217 218 #define EXPORT_OP_NOSUBTREECHK (0x2) /* no subtree checking */ 218 219 #define EXPORT_OP_CLOSE_BEFORE_UNLINK (0x4) /* close files before unlink */