diff options
Diffstat (limited to 'node.c')
-rw-r--r-- | node.c | 433 |
1 files changed, 250 insertions, 183 deletions
@@ -1,5 +1,5 @@ /* Hurd unionfs - Copyright (C) 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. Written by Moritz Schulte <moritz@duesseldorf.ccc.de>. This program is free software; you can redistribute it and/or @@ -52,33 +52,36 @@ node_create (lnode_t *lnode, node_t **node) debug_msg ("node_create for lnode: %s", lnode->name); if (! netnode_new) - err = ENOMEM; - else { - node_new = netfs_make_node (netnode_new); - if (! node_new) - { - err = ENOMEM; - free (netnode_new); - } - else - { - node_new->nn->ulfs = NULL; - err = node_ulfs_init (node_new); - if (err) - node_destroy (node_new); - else - { - lnode->node = node_new; - lnode_ref_add (lnode); - node_new->nn->lnode = lnode; - node_new->nn->flags = 0; - node_new->nn->ncache_next = NULL; - node_new->nn->ncache_prev = NULL; - *node = node_new; - } - } + err = ENOMEM; + return err; } + + node_new = netfs_make_node (netnode_new); + if (! node_new) + { + err = ENOMEM; + free (netnode_new); + return err; + } + + node_new->nn->ulfs = NULL; + + err = node_ulfs_init (node_new); + if (err) + { + node_destroy (node_new); + return err; + } + + lnode->node = node_new; + lnode_ref_add (lnode); + node_new->nn->lnode = lnode; + node_new->nn->flags = 0; + node_new->nn->ncache_next = NULL; + node_new->nn->ncache_prev = NULL; + *node = node_new; + return err; } @@ -105,58 +108,103 @@ node_update (node_t *node) error_t err = 0; char *path; + node_ulfs_t *root_ulfs; + struct stat stat; + file_t port; + int i = 0; + debug_msg ("node_update for lnode: %s", node->nn->lnode->name); - if (! node_is_root (node)) + if (node_is_root (node)) + return err; + + mutex_lock (&netfs_root_node->lock); + + err = lnode_path_construct (node->nn->lnode, &path); + if (err) + { + mutex_unlock (&netfs_root_node->lock); + return err; + } + + root_ulfs = netfs_root_node->nn->ulfs; + + node_ulfs_iterate_unlocked (node) { - mutex_lock (&netfs_root_node->lock); - err = lnode_path_construct (node->nn->lnode, &path); - if (! err) + + if (node_ulfs->flags & FLAG_NODE_ULFS_FIXED) { - node_ulfs_t *root_ulfs; - struct stat stat; - file_t port; - int i = 0; - - root_ulfs = netfs_root_node->nn->ulfs; - node_ulfs_iterate_unlocked (node) - { - if (! (node_ulfs->flags & FLAG_NODE_ULFS_FIXED)) - { - /* We really have to update the port. */ - if (port_valid (node_ulfs->port)) - port_dealloc (node_ulfs->port); - err = file_lookup ((root_ulfs + i)->port, path, - O_READ | O_NOTRANS, O_NOTRANS, - 0, &port, &stat); - if (! err) - { - if (stat.st_ino == underlying_node_stat.st_ino - && stat.st_fsid == underlying_node_stat.st_fsid) - /* It's OUR root node. */ - err = ELOOP; - else - { - port_dealloc (port); - err = file_lookup ((root_ulfs + i)->port, path, - O_READ, 0, 0, &port, &stat); - } - } - - if (err) - { - port = MACH_PORT_NULL; - err = 0; - } - node_ulfs->port = port; - } - i++; - } - free (path); - node->nn->flags |= FLAG_NODE_ULFS_UPTODATE; + i++; + continue; } - mutex_unlock (&netfs_root_node->lock); + + /* We really have to update the port. */ + if (port_valid (node_ulfs->port)) + port_dealloc (node_ulfs->port); + + err = file_lookup ((root_ulfs + i)->port, path, + O_READ | O_NOTRANS, O_NOTRANS, + 0, &port, &stat); + + if (err) + { + node_ulfs->port = MACH_PORT_NULL; + err = 0; + i++; + continue; + } + + if (stat.st_ino == underlying_node_stat.st_ino + && stat.st_fsid == underlying_node_stat.st_fsid) + /* It's OUR root node. */ + err = ELOOP; + else + { + port_dealloc (port); + err = file_lookup ((root_ulfs + i)->port, path, + O_READ, 0, 0, &port, &stat); + } + + if (err) + { + port = MACH_PORT_NULL; + err = 0; + } + node_ulfs->port = port; + + i++; + } + + free (path); + node->nn->flags |= FLAG_NODE_ULFS_UPTODATE; + + mutex_unlock (&netfs_root_node->lock); + + return err; +} + +/* Remove all files named NAME beneath DIR on the underlying filesystems + with FLAGS as openflags. */ +error_t +node_unlink_file (node_t *dir, char *name) +{ + error_t err = 0; + + /* Using reverse iteration still have issues. Infact, we could be + deleting a file in some underlying filesystem, and keeping those + after the first occurring error. + FIXME: Check BEFORE starting deletion. */ + + node_ulfs_iterate_reverse_unlocked (dir) + { + + if (!port_valid (node_ulfs->port)) + continue; + + err = dir_unlink (node_ulfs->port, name); + } + err = 0; return err; } @@ -173,31 +221,38 @@ node_lookup_file (node_t *dir, char *name, int flags, node_ulfs_iterate_unlocked (dir) { - if (err == ENOENT && port_valid (node_ulfs->port)) + + if (err != ENOENT) + break; + + if (!port_valid (node_ulfs->port)) + continue; + + err = file_lookup (node_ulfs->port, name, + flags | O_NOTRANS, O_NOTRANS, + 0, &p, &stat); + if (err) + continue; + + if (stat.st_ino == underlying_node_stat.st_ino + && stat.st_fsid == underlying_node_stat.st_fsid) + /* It's OUR root node. */ + err = ELOOP; + else + /* stat.st_mode & S_ITRANS */ { + port_dealloc (p); err = file_lookup (node_ulfs->port, name, - flags | O_NOTRANS, O_NOTRANS, - 0, &p, &stat); - if (! err) - { - if (stat.st_ino == underlying_node_stat.st_ino - && stat.st_fsid == underlying_node_stat.st_fsid) - /* It's OUR root node. */ - err = ELOOP; - else if (1) //stat.st_mode & S_ITRANS) - { - port_dealloc (p); - err = file_lookup (node_ulfs->port, name, - flags, 0, 0, &p, &stat); - } - } + flags, 0, 0, &p, &stat); } } + if (! err) { *s = stat; *port = p; } + return err; } @@ -206,10 +261,14 @@ node_lookup_file (node_t *dir, char *name, int flags, void node_ulfs_free (node_t *node) { + node_ulfs_iterate_unlocked (node) - if (port_valid (node_ulfs->port) - && node_ulfs->port != underlying_node) - port_dealloc (node_ulfs->port); + { + if (port_valid (node_ulfs->port) + && node_ulfs->port != underlying_node) + port_dealloc (node_ulfs->port); + } + free (node->nn->ulfs); } @@ -223,20 +282,21 @@ node_ulfs_init (node_t *node) ulfs_new = malloc (ulfs_num * sizeof (node_ulfs_t)); if (! ulfs_new) - err = ENOMEM; - else { - if (node->nn->ulfs) - node_ulfs_free (node); + err = ENOMEM; + return err; + } - node->nn->ulfs = ulfs_new; - node->nn->ulfs_num = ulfs_num; + if (node->nn->ulfs) + node_ulfs_free (node); + + node->nn->ulfs = ulfs_new; + node->nn->ulfs_num = ulfs_num; - node_ulfs_iterate_unlocked (node) - { - node_ulfs->flags = 0; - node_ulfs->port = port_null; - } + node_ulfs_iterate_unlocked (node) + { + node_ulfs->flags = 0; + node_ulfs->port = port_null; } return err; @@ -258,8 +318,13 @@ node_entries_get (node_t *node, node_dirent_t **dirents) one. */ error_t node_dirent_add (char *name, ino_t fileno, int type) { - node_dirent_t *node_dirent; error_t e = 0; + node_dirent_t *node_dirent; + node_dirent_t *node_dirent_new; + struct dirent *dirent_new; + int name_len = strlen (name); + int size = DIRENT_LEN (name_len); + for (node_dirent = node_dirent_list; node_dirent && strcmp (node_dirent->dirent->d_name, name); @@ -271,64 +336,59 @@ node_entries_get (node_t *node, node_dirent_t **dirents) node_dirent->dirent->d_fileno = fileno; node_dirent->dirent->d_type = type; + return e; } - else + + /* Create new entry. */ + + node_dirent_new = malloc (sizeof (node_dirent_t)); + if (!node_dirent_new) + { + e = ENOMEM; + return e; + } + + dirent_new = malloc (size); + if (!dirent_new) { - /* Create new entry. */ - - node_dirent_t *node_dirent_new; - - node_dirent_new = malloc (sizeof (node_dirent_t)); - if (node_dirent_new) - { - int name_len = strlen (name); - int size = DIRENT_LEN (name_len); - struct dirent *dirent_new; - - dirent_new = malloc (size); - if (dirent_new) - { - /* Fill dirent. */ - dirent_new->d_fileno = fileno; - dirent_new->d_type = type; - dirent_new->d_reclen = size; - strcpy ((char *) dirent_new + DIRENT_NAME_OFFS, name); - - /* Add dirent to the list. */ - node_dirent_new->dirent = dirent_new; - node_dirent_new->next = node_dirent_list; - node_dirent_list = node_dirent_new; - } - else - { - free (node_dirent_new); - e = ENOMEM; - } - } - else - e = ENOMEM; + free (node_dirent_new); + e = ENOMEM; + return e; } + + /* Fill dirent. */ + dirent_new->d_fileno = fileno; + dirent_new->d_type = type; + dirent_new->d_reclen = size; + strcpy ((char *) dirent_new + DIRENT_NAME_OFFS, name); + + /* Add dirent to the list. */ + node_dirent_new->dirent = dirent_new; + node_dirent_new->next = node_dirent_list; + node_dirent_list = node_dirent_new; + return e; } node_ulfs_iterate_unlocked(node) { - if (port_valid (node_ulfs->port)) - { - err = dir_entries_get (node_ulfs->port, &dirent_data, - &dirent_data_size, &dirent_list); - if (! err) - { - for (dirent = dirent_list; (! err) && *dirent; dirent++) - if (strcmp ((*dirent)->d_name, ".") - && strcmp ((*dirent)->d_name, "..")) - err = node_dirent_add ((*dirent)->d_name, - (*dirent)->d_fileno, - (*dirent)->d_type); - free (dirent_list); - munmap (dirent_data, dirent_data_size); - } - } + if (!port_valid (node_ulfs->port)) + continue; + + err = dir_entries_get (node_ulfs->port, &dirent_data, + &dirent_data_size, &dirent_list); + if (err) + continue; + + for (dirent = dirent_list; (! err) && *dirent; dirent++) + if (strcmp ((*dirent)->d_name, ".") + && strcmp ((*dirent)->d_name, "..")) + err = node_dirent_add ((*dirent)->d_name, + (*dirent)->d_fileno, + (*dirent)->d_type); + + free (dirent_list); + munmap (dirent_data, dirent_data_size); } if (err) @@ -363,17 +423,18 @@ node_create_root (node_t **root_node) error_t err = 0; err = lnode_create (NULL, &lnode); - if (! err) + if (err) + return err; + + err = node_create (lnode, &node); + if (err) { - err = node_create (lnode, &node); - if (err) - lnode_destroy (lnode); - else - mutex_unlock (&lnode->lock); + lnode_destroy (lnode); + return err; } - if (! err) - *root_node = node; + mutex_unlock (&lnode->lock); + *root_node = node; return err; } @@ -383,36 +444,42 @@ error_t node_init_root (node_t *node) { error_t err; + ulfs_t *ulfs; + int i = 0; mutex_lock (&ulfs_lock); err = node_ulfs_init (node); - if (! err) + if (err) + { + mutex_unlock (&ulfs_lock); + return err; + } + + node_ulfs_iterate_unlocked (node) { - ulfs_t *ulfs; - int i = 0; - node_ulfs_iterate_unlocked (node) + if (err) + break; + + err = ulfs_get_num (i, &ulfs); + if (err) + break; + + if (ulfs->path) + node_ulfs->port = file_name_lookup (ulfs->path, + O_READ | O_DIRECTORY, 0); + else + node_ulfs->port = underlying_node; + + if (! port_valid (node_ulfs->port)) { - if (! err) - err = ulfs_get_num (i, &ulfs); - if (! err) - { - if (ulfs->path) - node_ulfs->port = file_name_lookup (ulfs->path, - O_READ | O_DIRECTORY, 0); - else - node_ulfs->port = underlying_node; - - if (! port_valid (node_ulfs->port)) - err = errno; - else - { - node_ulfs->flags |= FLAG_NODE_ULFS_FIXED; - i++; - } - } + err = errno; + break; } + + node_ulfs->flags |= FLAG_NODE_ULFS_FIXED; + i++; } mutex_unlock (&ulfs_lock); |