1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* vnode and volume validity verification.
4 * Copyright (C) 2023 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/sched.h>
14 * mark the data attached to an inode as obsolete due to a write on the server
15 * - might also want to ditch all the outstanding writes and dirty pages
17 static void afs_zap_data(struct afs_vnode *vnode)
19 _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
21 afs_invalidate_cache(vnode, 0);
23 /* nuke all the non-dirty pages that aren't locked, mapped or being
24 * written back in a regular file and completely discard the pages in a
25 * directory or symlink */
26 if (S_ISREG(vnode->netfs.inode.i_mode))
27 invalidate_remote_inode(&vnode->netfs.inode);
29 invalidate_inode_pages2(vnode->netfs.inode.i_mapping);
33 * Check to see if we have a server currently serving this volume and that it
34 * hasn't been reinitialised or dropped from the list.
36 static bool afs_check_server_good(struct afs_vnode *vnode)
38 struct afs_server_list *slist;
39 struct afs_server *server;
43 if (vnode->cb_fs_s_break == atomic_read(&vnode->volume->cell->fs_s_break))
48 slist = rcu_dereference(vnode->volume->servers);
49 for (i = 0; i < slist->nr_servers; i++) {
50 server = slist->servers[i].server;
51 if (server == vnode->cb_server) {
52 good = (vnode->cb_s_break == server->cb_s_break);
63 * Check the validity of a vnode/inode.
65 bool afs_check_validity(struct afs_vnode *vnode)
67 enum afs_cb_break_reason need_clear = afs_cb_break_no_break;
68 time64_t now = ktime_get_real_seconds();
69 unsigned int cb_break;
73 seq = read_seqbegin(&vnode->cb_lock);
74 cb_break = vnode->cb_break;
76 if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
77 if (vnode->cb_v_break != vnode->volume->cb_v_break)
78 need_clear = afs_cb_break_for_v_break;
79 else if (!afs_check_server_good(vnode))
80 need_clear = afs_cb_break_for_s_reinit;
81 else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
82 need_clear = afs_cb_break_for_zap;
83 else if (vnode->cb_expires_at - 10 <= now)
84 need_clear = afs_cb_break_for_lapsed;
85 } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
88 need_clear = afs_cb_break_no_promise;
91 } while (read_seqretry(&vnode->cb_lock, seq));
93 if (need_clear == afs_cb_break_no_break)
96 write_seqlock(&vnode->cb_lock);
97 if (need_clear == afs_cb_break_no_promise)
98 vnode->cb_v_break = vnode->volume->cb_v_break;
99 else if (cb_break == vnode->cb_break)
100 __afs_break_callback(vnode, need_clear);
102 trace_afs_cb_miss(&vnode->fid, need_clear);
103 write_sequnlock(&vnode->cb_lock);
108 * Returns true if the pagecache is still valid. Does not sleep.
110 bool afs_pagecache_valid(struct afs_vnode *vnode)
112 if (unlikely(test_bit(AFS_VNODE_DELETED, &vnode->flags))) {
113 if (vnode->netfs.inode.i_nlink)
114 clear_nlink(&vnode->netfs.inode);
118 if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags) &&
119 afs_check_validity(vnode))
126 * validate a vnode/inode
127 * - there are several things we need to check
128 * - parent dir data changes (rm, rmdir, rename, mkdir, create, link,
130 * - parent dir metadata changed (security changes)
131 * - dentry data changed (write, truncate)
132 * - dentry metadata changed (security changes)
134 int afs_validate(struct afs_vnode *vnode, struct key *key)
138 _enter("{v={%llx:%llu} fl=%lx},%x",
139 vnode->fid.vid, vnode->fid.vnode, vnode->flags,
142 if (afs_pagecache_valid(vnode))
145 down_write(&vnode->validate_lock);
147 /* if the promise has expired, we need to check the server again to get
148 * a new promise - note that if the (parent) directory's metadata was
149 * changed then the security may be different and we may no longer have
151 if (!test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
152 _debug("not promised");
153 ret = afs_fetch_status(vnode, key, false, NULL);
155 if (ret == -ENOENT) {
156 set_bit(AFS_VNODE_DELETED, &vnode->flags);
161 _debug("new promise [fl=%lx]", vnode->flags);
164 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
165 _debug("file already deleted");
170 /* if the vnode's data version number changed then its contents are
172 if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
174 up_write(&vnode->validate_lock);
180 up_write(&vnode->validate_lock);
181 _leave(" = %d", ret);