xref: /haiku/src/add-ons/kernel/file_systems/nfs4/MetadataCache.cpp (revision 372a66634410cf0450e426716c14ad42d40c0da4)
1 /*
2  * Copyright 2012 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Paweł Dziepak, pdziepak@quarnos.org
7  */
8 
9 
10 #include "MetadataCache.h"
11 
12 #include <NodeMonitor.h>
13 
14 #include "Inode.h"
15 
16 
17 MetadataCache::MetadataCache(Inode* inode)
18 	:
19 	fExpire(0),
20 	fForceValid(false),
21 	fInode(inode),
22 	fInited(false)
23 {
24 	ASSERT(inode != NULL);
25 	mutex_init(&fLock, NULL);
26 }
27 
28 
29 MetadataCache::~MetadataCache()
30 {
31 	mutex_destroy(&fLock);
32 }
33 
34 
35 status_t
36 MetadataCache::GetStat(struct stat* st)
37 {
38 	ASSERT(st != NULL);
39 
40 	MutexLocker _(fLock);
41 	if (fForceValid || fExpire > time(NULL)) {
42 		// Do not touch other members of struct stat
43 		st->st_size = fStatCache.st_size;
44 		st->st_mode = fStatCache.st_mode;
45 		st->st_nlink = fStatCache.st_nlink;
46 		st->st_uid = fStatCache.st_uid;
47 		st->st_gid = fStatCache.st_gid;
48 		st->st_atim = fStatCache.st_atim;
49 		st->st_ctim = fStatCache.st_ctim;
50 		st->st_crtim = fStatCache.st_crtim;
51 		st->st_mtim = fStatCache.st_mtim;
52 		st->st_blksize = fStatCache.st_blksize;
53 		st->st_blocks = fStatCache.st_blocks;
54 		return B_OK;
55 	}
56 
57 	return B_ERROR;
58 }
59 
60 
61 void
62 MetadataCache::SetStat(const struct stat& st)
63 {
64 	MutexLocker _(fLock);
65 	if (fInited)
66 		NotifyChanges(&fStatCache, &st);
67 
68 	fStatCache = st;
69 	fExpire = time(NULL) + kExpirationTime;
70 	fInited = true;
71 }
72 
73 
74 void
75 MetadataCache::GrowFile(size_t newSize)
76 {
77 	MutexLocker _(fLock);
78 	fStatCache.st_size = max_c((off_t)newSize, fStatCache.st_size);
79 }
80 
81 
82 status_t
83 MetadataCache::GetAccess(uid_t uid, uint32* allowed)
84 {
85 	ASSERT(allowed != NULL);
86 
87 	MutexLocker _(fLock);
88 	AVLTreeMap<uid_t, AccessEntry>::Iterator it = fAccessCache.Find(uid);
89 	if (!it.HasCurrent())
90 		return B_ENTRY_NOT_FOUND;
91 
92 	if (!fForceValid)
93 		it.CurrentValuePointer()->fForceValid = false;
94 
95 	if (!it.Current().fForceValid && it.Current().fExpire < time(NULL)) {
96 		it.Remove();
97 		return B_ERROR;
98 	}
99 
100 	*allowed = it.Current().fAllowed;
101 
102 	return B_OK;
103 }
104 
105 
106 void
107 MetadataCache::SetAccess(uid_t uid, uint32 allowed)
108 {
109 	MutexLocker _(fLock);
110 	AVLTreeMap<uid_t, AccessEntry>::Iterator it = fAccessCache.Find(uid);
111 	if (it.HasCurrent())
112 		it.Remove();
113 
114 	AccessEntry entry;
115 	entry.fAllowed = allowed;
116 	entry.fExpire = time(NULL) + kExpirationTime;
117 	entry.fForceValid = fForceValid;
118 
119 	fAccessCache.Insert(uid, entry);
120 }
121 
122 
123 status_t
124 MetadataCache::LockValid()
125 {
126 	MutexLocker _(fLock);
127 	if (fForceValid || fExpire > time(NULL)) {
128 		fForceValid = true;
129 		return B_OK;
130 	}
131 
132 	return B_ERROR;
133 }
134 
135 
136 void
137 MetadataCache::UnlockValid()
138 {
139 	MutexLocker _(fLock);
140 	fExpire = time(NULL) + kExpirationTime;
141 	fForceValid = false;
142 }
143 
144 
145 void
146 MetadataCache::NotifyChanges(const struct stat* oldStat,
147 	const struct stat* newStat)
148 {
149 	ASSERT(oldStat != NULL);
150 	ASSERT(newStat != NULL);
151 
152 	uint32 flags = 0;
153 	if (oldStat->st_size != newStat->st_size)
154 		flags |= B_STAT_SIZE;
155 	if (oldStat->st_mode != newStat->st_mode)
156 		flags |= B_STAT_MODE;
157 	if (oldStat->st_uid != newStat->st_uid)
158 		flags |= B_STAT_UID;
159 	if (oldStat->st_gid != newStat->st_gid)
160 		flags |= B_STAT_GID;
161 
162 	if (memcmp(&oldStat->st_atim, &newStat->st_atim,
163 		sizeof(struct timespec) == 0))
164 		flags |= B_STAT_ACCESS_TIME;
165 
166 	if (memcmp(&oldStat->st_ctim, &newStat->st_ctim,
167 		sizeof(struct timespec) == 0))
168 		flags |= B_STAT_CHANGE_TIME;
169 
170 	if (memcmp(&oldStat->st_crtim, &newStat->st_crtim,
171 		sizeof(struct timespec) == 0))
172 		flags |= B_STAT_CREATION_TIME;
173 
174 	if (memcmp(&oldStat->st_mtim, &newStat->st_mtim,
175 		sizeof(struct timespec) == 0))
176 		flags |= B_STAT_MODIFICATION_TIME;
177 
178 	notify_stat_changed(fInode->GetFileSystem()->DevId(), fInode->ID(), flags);
179 }
180 
181