xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/FDManager.cpp (revision 5a1d355fdf2747f80f8c46e2539f844a0b813346)
1 // FDManager.cpp
2 
3 #include <new>
4 
5 #include <dirent.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <sys/resource.h>
9 
10 #include <Directory.h>
11 #include <Entry.h>
12 #include <File.h>
13 #include <fs_attr.h>
14 
15 #include "AutoLocker.h"
16 #include "FDManager.h"
17 
18 // FD constants
19 static const int32 kDefaultFDLimit = 512;
20 static const int32 kFDLimitIncrement = 128;
21 
22 
23 // constructor
FDManager()24 FDManager::FDManager()
25 	: fLock("FD manager"),
26 	  fFDLimit(kDefaultFDLimit)
27 {
28 }
29 
30 // destructor
~FDManager()31 FDManager::~FDManager()
32 {
33 }
34 
35 // Init
36 status_t
Init()37 FDManager::Init()
38 {
39 	// ask for a bunch more file descriptors
40 	struct rlimit rl;
41 	rl.rlim_cur = fFDLimit;
42 	rl.rlim_max = RLIM_SAVED_MAX;
43 	if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
44 		return errno;
45 
46 	return B_OK;
47 }
48 
49 // CreateDefault
50 status_t
CreateDefault()51 FDManager::CreateDefault()
52 {
53 	if (sManager)
54 		return B_OK;
55 
56 	FDManager* manager = new(std::nothrow) FDManager;
57 	if (!manager)
58 		return B_NO_MEMORY;
59 
60 	status_t error = manager->Init();
61 	if (error != B_OK) {
62 		delete manager;
63 		return error;
64 	}
65 
66 	sManager = manager;
67 	return B_OK;
68 }
69 
70 // DeleteDefault
71 void
DeleteDefault()72 FDManager::DeleteDefault()
73 {
74 	if (sManager) {
75 		delete sManager;
76 		sManager = NULL;
77 	}
78 }
79 
80 // GetDefault
81 FDManager*
GetDefault()82 FDManager::GetDefault()
83 {
84 	return sManager;
85 }
86 
87 // SetDirectory
88 status_t
SetDirectory(BDirectory * directory,const node_ref * ref)89 FDManager::SetDirectory(BDirectory* directory, const node_ref* ref)
90 {
91 	status_t error = directory->SetTo(ref);
92 
93 	if (error == B_NO_MORE_FDS) {
94 		GetDefault()->_IncreaseLimit();
95 		error = directory->SetTo(ref);
96 	}
97 
98 	return error;
99 }
100 
101 // SetEntry
102 status_t
SetEntry(BEntry * entry,const entry_ref * ref)103 FDManager::SetEntry(BEntry* entry, const entry_ref* ref)
104 {
105 	status_t error = entry->SetTo(ref);
106 
107 	if (error == B_NO_MORE_FDS) {
108 		GetDefault()->_IncreaseLimit();
109 		error = entry->SetTo(ref);
110 	}
111 
112 	return error;
113 }
114 
115 // SetEntry
116 status_t
SetEntry(BEntry * entry,const char * path)117 FDManager::SetEntry(BEntry* entry, const char* path)
118 {
119 	status_t error = entry->SetTo(path);
120 
121 	if (error == B_NO_MORE_FDS) {
122 		GetDefault()->_IncreaseLimit();
123 		error = entry->SetTo(path);
124 	}
125 
126 	return error;
127 }
128 
129 // SetFile
130 status_t
SetFile(BFile * file,const char * path,uint32 openMode)131 FDManager::SetFile(BFile* file, const char* path, uint32 openMode)
132 {
133 	status_t error = file->SetTo(path, openMode);
134 
135 	if (error == B_NO_MORE_FDS) {
136 		GetDefault()->_IncreaseLimit();
137 		error = file->SetTo(path, openMode);
138 	}
139 
140 	return error;
141 }
142 
143 // SetNode
144 status_t
SetNode(BNode * node,const entry_ref * ref)145 FDManager::SetNode(BNode* node, const entry_ref* ref)
146 {
147 	status_t error = node->SetTo(ref);
148 
149 	if (error == B_NO_MORE_FDS) {
150 		GetDefault()->_IncreaseLimit();
151 		error = node->SetTo(ref);
152 	}
153 
154 	return error;
155 }
156 
157 // Open
158 status_t
Open(const char * path,uint32 openMode,mode_t mode,int & fd)159 FDManager::Open(const char* path, uint32 openMode, mode_t mode, int& fd)
160 {
161 	status_t error = B_OK;
162 	fd = open(path, openMode, mode);
163 	if (fd < 0)
164 		error = errno;
165 
166 	if (error == B_NO_MORE_FDS) {
167 		GetDefault()->_IncreaseLimit();
168 
169 		error = B_OK;
170 		fd = open(path, openMode, mode);
171 		if (fd < 0)
172 			error = errno;
173 	}
174 
175 	return error;
176 }
177 
178 // OpenDir
179 status_t
OpenDir(const char * path,DIR * & dir)180 FDManager::OpenDir(const char* path, DIR*& dir)
181 {
182 	status_t error = B_OK;
183 	dir = opendir(path);
184 	if (!dir)
185 		error = errno;
186 
187 	if (error == B_NO_MORE_FDS) {
188 		GetDefault()->_IncreaseLimit();
189 
190 		error = B_OK;
191 		dir = opendir(path);
192 		if (!dir)
193 			error = errno;
194 	}
195 
196 	return error;
197 }
198 
199 // OpenAttrDir
200 status_t
OpenAttrDir(const char * path,DIR * & dir)201 FDManager::OpenAttrDir(const char* path, DIR*& dir)
202 {
203 	status_t error = B_OK;
204 	dir = fs_open_attr_dir(path);
205 	if (!dir)
206 		error = errno;
207 
208 	if (error == B_NO_MORE_FDS) {
209 		GetDefault()->_IncreaseLimit();
210 
211 		error = B_OK;
212 		dir = fs_open_attr_dir(path);
213 		if (!dir)
214 			error = errno;
215 	}
216 
217 	return error;
218 }
219 
220 // _IncreaseLimit
221 status_t
_IncreaseLimit()222 FDManager::_IncreaseLimit()
223 {
224 	AutoLocker<Locker> _(fLock);
225 
226 	int32 newLimit = fFDLimit + kFDLimitIncrement;
227 
228 	struct rlimit rl;
229 	rl.rlim_cur = newLimit;
230 	rl.rlim_max = RLIM_SAVED_MAX;
231 	if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
232 		return errno;
233 
234 	fFDLimit = newLimit;
235 
236 	return B_OK;
237 }
238 
239 
240 // sManager
241 FDManager* FDManager::sManager = NULL;
242