Skip to content

Commit

Permalink
[FS-1111] Counts dir entries in a dir before writing to it.
Browse files Browse the repository at this point in the history
  • Loading branch information
playmaker-pk committed Feb 13, 2023
1 parent 23fb283 commit 934aa78
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/fusedav.c
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,9 @@ static int dav_mkdir(const char *path, mode_t mode) {
long response_code = 500; // seed it as bad so we can enter the loop
CURLcode res = CURLE_OK;
rwp_t rwp = WRITE;
char *parentpath;
unsigned BLOCKING_THRESHOLD = 5;
unsigned direntcnt;

if (use_readonly_mode()) {
log_print(LOG_WARNING, SECTION_FUSEDAV_FILE, "dav_mkdir: %s aborted; in readonly mode", path);
Expand All @@ -1387,6 +1390,25 @@ static int dav_mkdir(const char *path, mode_t mode) {

log_print(LOG_INFO, SECTION_FUSEDAV_DIR, "CALLBACK: %s(%s, %04o)", funcname, path, mode);

// Highly populated directory check
parentpath = path_parent(path);
if (parentpath == NULL) {
log_print(LOG_NOTICE, SECTION_FUSEDAV_DIR, "Stat entry for the path %s is NULL.", path);
} else {
direntcnt = log_dirent_count(config->cache, parentpath);
if(direntcnt > BLOCKING_THRESHOLD) {
log_print(LOG_NOTICE, SECTION_FUSEDAV_DIR, "dav_mkdir: %s; dirent count (%u) above threshold for %s", path, direntcnt, parentpath);
// TODO: This is currently just logging but not preventing the dav_mkdir operation.
// Once we are confident on the decision to go ahead with blocking the writes,
// uncomment/modify the code below to enforce it. Specific error to client TBD, ENOSPC used tentatively.

// log_print(LOG_WARNING, SECTION_FUSEDAV_DIR, "dav_mkdir: %s aborted; dirent count (%u) above threshold for %s", path, direntcnt, parentpath);
// g_set_error(&gerr, fusedav_quark(), ENOSPC, "aborted; dirent count above threshold");
// return processed_gerror("dav_mkdir: ", path, &gerr);
}
}
free(parentpath);

snprintf(fn, sizeof(fn), "%s/", path);

for (int idx = 0; idx < num_filesystem_server_nodes && (res != CURLE_OK || response_code >= 500); idx++) {
Expand Down Expand Up @@ -2129,6 +2151,9 @@ static int dav_create(const char *path, mode_t mode, struct fuse_file_info *info
struct stat_cache_value value;
GError *gerr = NULL;
int fd;
char *parentpath;
unsigned BLOCKING_THRESHOLD = 5;
unsigned direntcnt;

if (use_readonly_mode()) {
log_print(LOG_WARNING, SECTION_FUSEDAV_FILE, "dav_create: %s aborted; in readonly mode", path);
Expand All @@ -2140,6 +2165,25 @@ static int dav_create(const char *path, mode_t mode, struct fuse_file_info *info

log_print(LOG_INFO, SECTION_FUSEDAV_FILE, "CALLBACK: dav_create(%s, %04o)", path, mode);

// Highly populated directory check
parentpath = path_parent(path);
if (parentpath == NULL) {
log_print(LOG_NOTICE, SECTION_FUSEDAV_FILE, "Stat entry for the path %s is NULL.", path);
} else {
direntcnt = log_dirent_count(config->cache, parentpath);
if(direntcnt > BLOCKING_THRESHOLD) {
log_print(LOG_NOTICE, SECTION_FUSEDAV_FILE, "dav_create: %s; dirent count (%u) above threshold for %s", path, direntcnt, parentpath);
// TODO: This is currently just logging but not preventing the dav_create operation.
// Once we are confident on the decision to go ahead with blocking the writes,
// uncomment/modify the code below to enforce it. Specific error to client TBD, ENOSPC used tentatively.

// log_print(LOG_WARNING, SECTION_FUSEDAV_FILE, "dav_create: %s aborted; dirent count (%u) above threshold for %s", path, direntcnt, parentpath);
// g_set_error(&gerr, fusedav_quark(), ENOSPC, "aborted; dirent count above threshold");
// return processed_gerror("dav_create: ", path, &gerr);
}
}
free(parentpath);

info->flags |= O_CREAT | O_TRUNC;
do_open(path, info, &gerr);

Expand Down
52 changes: 52 additions & 0 deletions src/statcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,58 @@ int stat_cache_enumerate(stat_cache_t *cache, const char *path_prefix, void (*f)
return E_SC_SUCCESS;
}

// log_dirent_count is based on stat_cache_enumerate and ignores cache freshness.
unsigned log_dirent_count(stat_cache_t *cache, const char *path_prefix) {
struct stat_cache_iterator *iter;
struct stat_cache_entry *entry;
unsigned found_entries = 0;

// BUMP(statcache_enumerate);

// log_print(LOG_DEBUG, SECTION_STATCACHE_ITER, "count_dir_entries(%s)", path_prefix);

//stat_cache_list_all(cache, path_prefix);
// if (!force) {
// time_t timestamp;
// time_t current_time;
// // Pass NULL for gerr; not tracking error, just zero return
// timestamp = stat_cache_read_updated_children(cache, path_prefix, NULL);

// if (timestamp == 0) {
// return -STAT_CACHE_NO_DATA;
// }

// // Check for cache values which are too old; but timestamp = 0 needs to trigger below
// current_time = time(NULL);
// if (current_time - timestamp > STAT_CACHE_NEGATIVE_TTL) {
// log_print(LOG_DEBUG, SECTION_STATCACHE_ITER, "cache value too old: %s %u", path_prefix, (unsigned)timestamp);
// return -STAT_CACHE_OLD_DATA;
// }
// }

iter = stat_cache_iter_init(cache, path_prefix);
log_print(LOG_NOTICE, SECTION_STATCACHE_ITER, "iterator initialized with prefix: %s", iter->key_prefix);

while ((entry = stat_cache_iter_current(iter))) {
// log_print(LOG_NOTICE, SECTION_STATCACHE_ITER, "key: %s", entry->key);
// log_print(LOG_NOTICE, SECTION_STATCACHE_ITER, "fn: %s", entry->key + (iter->key_prefix_len - 1));
// Ignore negative (non-existent) entries, those tagged with st_mode == 0
if (entry->value->st.st_mode != 0) {
// f(path_prefix, entry->key + (iter->key_prefix_len - 1), user);
++found_entries;
}
free(entry);
stat_cache_iter_next(iter);
}
stat_cache_iterator_free(iter);
log_print(LOG_NOTICE, SECTION_STATCACHE_ITER, "Done iterating: %u items.", found_entries);

// if (found_entries == 0)
// return -STAT_CACHE_NO_DATA;

return found_entries;
}

void stat_cache_walk(void) {
leveldb_readoptions_t *roptions;
struct leveldb_iterator_t *iter;
Expand Down
1 change: 1 addition & 0 deletions src/statcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ void stat_cache_delete_older(stat_cache_t *cache, const char *key_prefix, unsign
void stat_cache_walk(void);
int stat_cache_enumerate(stat_cache_t *cache, const char *key_prefix, void (*f) (const char *path_prefix,
const char *filename, void *user), void *user, bool force);
unsigned log_dirent_count(stat_cache_t *cache, const char *key_prefix);
bool stat_cache_dir_has_child(stat_cache_t *cache, const char *path);
void stat_cache_prune(stat_cache_t *cache, bool first);

Expand Down

0 comments on commit 934aa78

Please sign in to comment.