@@ -305,6 +305,21 @@ static int sparsebundle_read(const char *path, char *buffer, size_t length, off_
305305}
306306
307307#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+
308323static int sparsebundle_read_buf_prepare_file (const char *path)
309324{
310325 sparsebundle_t *sparsebundle = sparsebundle_current ();
@@ -315,7 +330,20 @@ static int sparsebundle_read_buf_prepare_file(const char *path)
315330 fd = iter->second ;
316331 } else {
317332 syslog (LOG_DEBUG, " file %s not opened yet, opening" , path);
318- fd = open (path, O_RDONLY);
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+
319347 sparsebundle->open_files [path] = fd;
320348 }
321349
@@ -361,21 +389,6 @@ static int sparsebundle_read_buf_pad_with_zeroes(size_t length, void *read_data)
361389 return length;
362390}
363391
364- static void sparsebundle_read_buf_close_files ()
365- {
366- sparsebundle_t *sparsebundle = sparsebundle_current ();
367-
368- syslog (LOG_DEBUG, " closing %zu open file descriptor(s)" , sparsebundle->open_files .size ());
369-
370- map<string, int >::iterator iter;
371- for (iter = sparsebundle->open_files .begin (); iter != sparsebundle->open_files .end (); ++iter) {
372- close (iter->second );
373- syslog (LOG_DEBUG, " closed %s" , iter->first .c_str ());
374- }
375-
376- sparsebundle->open_files .clear ();
377- }
378-
379392static int sparsebundle_read_buf (const char *path, struct fuse_bufvec **bufp,
380393 size_t length, off_t offset, struct fuse_file_info *)
381394{
@@ -394,43 +407,6 @@ static int sparsebundle_read_buf(const char *path, struct fuse_bufvec **bufp,
394407 syslog (LOG_DEBUG, " asked to read %zu bytes at offset %ju using zero-copy read" ,
395408 length, uintmax_t (offset));
396409
397- static rlim_t max_open_files = []() {
398- struct rlimit fd_limit;
399- getrlimit (RLIMIT_NOFILE, &fd_limit);
400- auto fd_max = fd_limit.rlim_cur - 1 ;
401- syslog (LOG_DEBUG, " maximum file descriptor number %ju" , uintmax_t (fd_max));
402-
403- // Check how many of the file descriptors are available
404- std::vector<pollfd> file_descriptors (fd_max);
405- for (unsigned i = 0 ; i < file_descriptors.size (); ++i) {
406- file_descriptors[i].fd = i;
407- // We don't really care about these states, but we have
408- // to specify something for poll to give us the POLLNVAL
409- // we do care about.
410- file_descriptors[i].events = POLLRDNORM | POLLWRNORM;
411- }
412- if (poll (file_descriptors.data (), file_descriptors.size (), 0 ) == -1 ) {
413- syslog (LOG_ERR, " failed to resolve available file descriptors: %s" , strerror (errno));
414- return fd_max;
415- }
416-
417- rlim_t available_fds = 0 ;
418- for (auto file_descriptor : file_descriptors) {
419- if (file_descriptor.revents & POLLNVAL)
420- ++available_fds;
421- }
422- syslog (LOG_DEBUG, " %ju available file descriptors (%ju in use)" ,
423- uintmax_t (available_fds), uintmax_t (fd_max - available_fds));
424-
425- return available_fds;
426- }();
427-
428- sparsebundle_t *sparsebundle = sparsebundle_current ();
429- if (sparsebundle->open_files .size () + 1 >= max_open_files) {
430- syslog (LOG_DEBUG, " hit max number of file descriptors" );
431- sparsebundle_read_buf_close_files ();
432- }
433-
434410 ret = sparsebundle_iterate_bands (path, length, offset, &read_ops);
435411 if (ret < 0 )
436412 return ret;
0 commit comments