xref: /haiku/src/add-ons/kernel/file_systems/nfs4/MetadataCache.cpp (revision 5676dce83c37481085ee73b69215cd97af78e08a)
1 /*
2  * Copyright 2012-2016 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 
MetadataCache(Inode * inode)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 
~MetadataCache()29 MetadataCache::~MetadataCache()
30 {
31 	mutex_destroy(&fLock);
32 }
33 
34 
35 status_t
GetStat(struct stat * st)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
SetStat(const struct stat & st)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
GrowFile(size_t newSize)75 MetadataCache::GrowFile(size_t newSize)
76 {
77 	MutexLocker _(fLock);
78 	off_t oldSize = fStatCache.st_size;
79 	fStatCache.st_size = max_c((off_t)newSize, fStatCache.st_size);
80 
81 	if (oldSize != fStatCache.st_size) {
82 		notify_stat_changed(fInode->GetFileSystem()->DevId(), -1, fInode->ID(),
83 			B_STAT_SIZE);
84 	}
85 }
86 
87 
88 status_t
GetAccess(uid_t uid,uint32 * allowed)89 MetadataCache::GetAccess(uid_t uid, uint32* allowed)
90 {
91 	ASSERT(allowed != NULL);
92 
93 	MutexLocker _(fLock);
94 	AVLTreeMap<uid_t, AccessEntry>::Iterator it = fAccessCache.Find(uid);
95 	if (!it.HasCurrent())
96 		return B_ENTRY_NOT_FOUND;
97 
98 	if (!fForceValid)
99 		it.CurrentValuePointer()->fForceValid = false;
100 
101 	if (!it.Current().fForceValid && it.Current().fExpire < time(NULL)) {
102 		it.Remove();
103 		return B_ERROR;
104 	}
105 
106 	*allowed = it.Current().fAllowed;
107 
108 	return B_OK;
109 }
110 
111 
112 void
SetAccess(uid_t uid,uint32 allowed)113 MetadataCache::SetAccess(uid_t uid, uint32 allowed)
114 {
115 	MutexLocker _(fLock);
116 	AVLTreeMap<uid_t, AccessEntry>::Iterator it = fAccessCache.Find(uid);
117 	if (it.HasCurrent())
118 		it.Remove();
119 
120 	AccessEntry entry;
121 	entry.fAllowed = allowed;
122 	entry.fExpire = time(NULL) + kExpirationTime;
123 	entry.fForceValid = fForceValid;
124 
125 	fAccessCache.Insert(uid, entry);
126 }
127 
128 
129 status_t
LockValid()130 MetadataCache::LockValid()
131 {
132 	MutexLocker _(fLock);
133 	if (fForceValid || fExpire > time(NULL)) {
134 		fForceValid = true;
135 		return B_OK;
136 	}
137 
138 	return B_ERROR;
139 }
140 
141 
142 void
UnlockValid()143 MetadataCache::UnlockValid()
144 {
145 	MutexLocker _(fLock);
146 	fExpire = time(NULL) + kExpirationTime;
147 	fForceValid = false;
148 }
149 
150 
151 void
NotifyChanges(const struct stat * oldStat,const struct stat * newStat)152 MetadataCache::NotifyChanges(const struct stat* oldStat,
153 	const struct stat* newStat)
154 {
155 	ASSERT(oldStat != NULL);
156 	ASSERT(newStat != NULL);
157 
158 	uint32 flags = 0;
159 	if (oldStat->st_size != newStat->st_size)
160 		flags |= B_STAT_SIZE;
161 	if (oldStat->st_mode != newStat->st_mode)
162 		flags |= B_STAT_MODE;
163 	if (oldStat->st_uid != newStat->st_uid)
164 		flags |= B_STAT_UID;
165 	if (oldStat->st_gid != newStat->st_gid)
166 		flags |= B_STAT_GID;
167 
168 	if (memcmp(&oldStat->st_atim, &newStat->st_atim,
169 		sizeof(struct timespec)) == 0)
170 		flags |= B_STAT_ACCESS_TIME;
171 
172 	if (memcmp(&oldStat->st_ctim, &newStat->st_ctim,
173 		sizeof(struct timespec)) == 0)
174 		flags |= B_STAT_CHANGE_TIME;
175 
176 	if (memcmp(&oldStat->st_crtim, &newStat->st_crtim,
177 		sizeof(struct timespec)) == 0)
178 		flags |= B_STAT_CREATION_TIME;
179 
180 	if (memcmp(&oldStat->st_mtim, &newStat->st_mtim,
181 		sizeof(struct timespec)) == 0)
182 		flags |= B_STAT_MODIFICATION_TIME;
183 
184 	notify_stat_changed(fInode->GetFileSystem()->DevId(), -1, fInode->ID(),
185 		flags);
186 }
187 
188