@@ -87,9 +87,7 @@ struct sparsebundle_t {
8787 uint64_t band_size;
8888 uint64_t size;
8989 uint64_t times_opened;
90- #if FUSE_SUPPORTS_ZERO_COPY
9190 map<string, int > open_files;
92- #endif
9391 struct {
9492 bool allow_other = false ;
9593 bool allow_root = false ;
@@ -180,6 +178,59 @@ static int sparsebundle_open(const char *path, struct fuse_file_info *fi)
180178 return 0 ;
181179}
182180
181+ static void sparsebundle_close_files ()
182+ {
183+ sparsebundle_t *sparsebundle = sparsebundle_current ();
184+
185+ if (sparsebundle->open_files .empty ())
186+ return ;
187+
188+ syslog (LOG_DEBUG, " closing %zu open file descriptor(s)" , sparsebundle->open_files .size ());
189+
190+ map<string, int >::iterator iter;
191+ for (iter = sparsebundle->open_files .begin (); iter != sparsebundle->open_files .end (); ++iter) {
192+ close (iter->second );
193+ syslog (LOG_DEBUG, " closed %s" , iter->first .c_str ());
194+ }
195+
196+ sparsebundle->open_files .clear ();
197+ }
198+
199+ static rlim_t sparsebundle_max_files ()
200+ {
201+ struct rlimit fd_limit;
202+ getrlimit (RLIMIT_NOFILE, &fd_limit);
203+ return fd_limit.rlim_cur ;
204+ }
205+
206+ static int sparsebundle_open_file (const char *path)
207+ {
208+ sparsebundle_t *sparsebundle = sparsebundle_current ();
209+
210+ int fd = -1 ;
211+ map<string, int >::const_iterator iter = sparsebundle->open_files .find (path);
212+ if (iter != sparsebundle->open_files .end ()) {
213+ fd = iter->second ;
214+ } else {
215+ syslog (LOG_DEBUG, " file %s not opened yet, opening" , path);
216+ if ((fd = open (path, O_RDONLY)) == -1 ) {
217+ if (errno == EMFILE) {
218+ syslog (LOG_DEBUG, " too many open file descriptors (max %ju)" ,
219+ uintmax_t (sparsebundle_max_files ()));
220+
221+ sparsebundle_close_files ();
222+ return sparsebundle_open_file (path);
223+ }
224+ syslog (LOG_ERR, " failed to open %s: %s" , path, strerror (errno));
225+ return -errno;
226+ }
227+
228+ sparsebundle->open_files [path] = fd;
229+ }
230+
231+ return fd;
232+ }
233+
183234struct sparsebundle_read_operations {
184235 int (*process_band) (const char *, size_t , off_t , void *);
185236 int (*pad_with_zeroes) (size_t , void *);
@@ -255,14 +306,9 @@ static int sparsebundle_read_process_band(const char *band_path, size_t length,
255306 syslog (LOG_DEBUG, " reading %zu bytes at offset %ju into %p" ,
256307 length, uintmax_t (offset), static_cast <void *>(*buffer));
257308
258- syslog (LOG_DEBUG, " opening %s" , band_path);
259- int band_file = open (band_path, O_RDONLY);
309+ int band_file = sparsebundle_open_file (band_path);
260310 if (band_file != -1 ) {
261311 read = pread (band_file, *buffer, length, offset);
262-
263- syslog (LOG_DEBUG, " closing %s" , band_path);
264- close (band_file);
265-
266312 if (read == -1 ) {
267313 syslog (LOG_ERR, " failed to read band: %s" , strerror (errno));
268314 return -errno;
@@ -305,51 +351,6 @@ static int sparsebundle_read(const char *path, char *buffer, size_t length, off_
305351}
306352
307353#if FUSE_SUPPORTS_ZERO_COPY
308- static void sparsebundle_read_buf_close_files ()
309- {
310- sparsebundle_t *sparsebundle = sparsebundle_current ();
311-
312- syslog (LOG_DEBUG, " closing %zu open file descriptor(s)" , sparsebundle->open_files .size ());
313-
314- map<string, int >::iterator iter;
315- for (iter = sparsebundle->open_files .begin (); iter != sparsebundle->open_files .end (); ++iter) {
316- close (iter->second );
317- syslog (LOG_DEBUG, " closed %s" , iter->first .c_str ());
318- }
319-
320- sparsebundle->open_files .clear ();
321- }
322-
323- static int sparsebundle_read_buf_prepare_file (const char *path)
324- {
325- sparsebundle_t *sparsebundle = sparsebundle_current ();
326-
327- int fd = -1 ;
328- map<string, int >::const_iterator iter = sparsebundle->open_files .find (path);
329- if (iter != sparsebundle->open_files .end ()) {
330- fd = iter->second ;
331- } else {
332- syslog (LOG_DEBUG, " file %s not opened yet, opening" , path);
333- if ((fd = open (path, O_RDONLY)) == -1 ) {
334- if (errno == EMFILE) {
335- struct rlimit fd_limit;
336- getrlimit (RLIMIT_NOFILE, &fd_limit);
337- syslog (LOG_DEBUG, " too many open files (%ju)" ,
338- uintmax_t (fd_limit.rlim_cur ));
339-
340- sparsebundle_read_buf_close_files ();
341- return sparsebundle_read_buf_prepare_file (path);
342- }
343- syslog (LOG_ERR, " failed to open band %s: %s" , path, strerror (errno));
344- return -errno;
345- }
346-
347- sparsebundle->open_files [path] = fd;
348- }
349-
350- return fd;
351- }
352-
353354static int sparsebundle_read_buf_process_band (const char *band_path, size_t length, off_t offset, void *read_data)
354355{
355356 size_t read = 0 ;
@@ -359,7 +360,7 @@ static int sparsebundle_read_buf_process_band(const char *band_path, size_t leng
359360 syslog (LOG_DEBUG, " preparing %zu bytes at offset %ju" , length,
360361 uintmax_t (offset));
361362
362- int band_file_fd = sparsebundle_read_buf_prepare_file (band_path);
363+ int band_file_fd = sparsebundle_open_file (band_path);
363364 if (band_file_fd != -1 ) {
364365 struct stat band_stat;
365366 stat (band_path, &band_stat);
@@ -382,7 +383,7 @@ static const char zero_device[] = "/dev/zero";
382383static int sparsebundle_read_buf_pad_with_zeroes (size_t length, void *read_data)
383384{
384385 vector<fuse_buf> *buffers = static_cast <vector<fuse_buf> *>(read_data);
385- int zero_device_fd = sparsebundle_read_buf_prepare_file (zero_device);
386+ int zero_device_fd = sparsebundle_open_file (zero_device);
386387 fuse_buf buffer = { length, fuse_buf_flags (FUSE_BUF_IS_FD), 0 , zero_device_fd, 0 };
387388 buffers->push_back (buffer);
388389
@@ -440,11 +441,7 @@ static int sparsebundle_release(const char *path, struct fuse_file_info *)
440441
441442 if (sparsebundle->times_opened == 0 ) {
442443 syslog (LOG_DEBUG, " no more references, cleaning up" );
443-
444- #if FUSE_SUPPORTS_ZERO_COPY
445- if (!sparsebundle->open_files .empty ())
446- sparsebundle_read_buf_close_files ();
447- #endif
444+ sparsebundle_close_files ();
448445 }
449446
450447 return 0 ;
@@ -605,6 +602,9 @@ int main(int argc, char **argv)
605602 sparsebundle_filesystem_operations.read_buf = sparsebundle_read_buf;
606603#endif
607604
605+ syslog (LOG_DEBUG, " max open file descriptors is %ju" ,
606+ uintmax_t (sparsebundle_max_files ()));
607+
608608 int ret = fuse_main (args.argc , args.argv , &sparsebundle_filesystem_operations, &sparsebundle);
609609 syslog (LOG_DEBUG, " exiting with return code %d" , ret);
610610 return ret;
0 commit comments