Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset e4e546b in mainline


Ignore:
Timestamp:
2017-03-22T19:26:21Z (3 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
master
Children:
c68edd2
Parents:
c990ee6
Message:

Fix L_CREATE and L_UNLINK across mountpoints

Server-side mountpoints broke linking of the first name and unlinking of
the last name of a file across mountpoints. In order to do the expected
thing, both operations need to be split into a mere lookup phase to
locate the parent of the added/removed name, and a link/unlink phase
that adds/removes the name to/from the parent node.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/vfs/vfs_lookup.c

    rc990ee6 re4e546b  
    238238}
    239239
    240 /** Perform a path lookup.
    241  *
    242  * @param base    The file from which to perform the lookup.
    243  * @param path    Path to be resolved; it must be a NULL-terminated
    244  *                string.
    245  * @param lflag   Flags to be used during lookup.
    246  * @param result  Empty structure where the lookup result will be stored.
    247  *                Can be NULL.
    248  *
    249  * @return EOK on success or an error code from errno.h.
    250  *
    251  */
    252 int vfs_lookup_internal(vfs_node_t *base, char *path, int lflag,
    253     vfs_lookup_res_t *result)
    254 {
    255         assert(base != NULL);
    256         assert(path != NULL);
    257        
    258         size_t len;
     240static int _vfs_lookup_internal(vfs_node_t *base, char *path, int lflag,
     241    vfs_lookup_res_t *result, size_t len)
     242{
     243        size_t first;
    259244        int rc;
    260         char *npath = canonify(path, &len);
    261         if (!npath) {
    262                 rc = EINVAL;
    263                 return rc;
    264         }
    265         path = npath;
    266        
    267         assert(path[0] == '/');
    268        
    269         size_t first;
    270        
     245
    271246        plb_entry_t entry;
    272247        rc = plb_insert_entry(&entry, path, &first, len);
     
    347322}
    348323
     324/** Perform a path lookup.
     325 *
     326 * @param base    The file from which to perform the lookup.
     327 * @param path    Path to be resolved; it must be a NULL-terminated
     328 *                string.
     329 * @param lflag   Flags to be used during lookup.
     330 * @param result  Empty structure where the lookup result will be stored.
     331 *                Can be NULL.
     332 *
     333 * @return EOK on success or an error code from errno.h.
     334 *
     335 */
     336int vfs_lookup_internal(vfs_node_t *base, char *path, int lflag,
     337    vfs_lookup_res_t *result)
     338{
     339        assert(base != NULL);
     340        assert(path != NULL);
     341       
     342        size_t len;
     343        int rc;
     344        char *npath = canonify(path, &len);
     345        if (!npath) {
     346                rc = EINVAL;
     347                return rc;
     348        }
     349        path = npath;
     350       
     351        assert(path[0] == '/');
     352
     353
     354        if (lflag & (L_CREATE | L_UNLINK)) {
     355
     356                /*
     357                 * Creation and destruction of names must be done in two
     358                 * separate steps: lookup of the parent node and the name
     359                 * link/unlink operation itself.  Otherwise the parent
     360                 * filesystem would not be able to tell when a mountpoint is
     361                 * crossed. It would attempt to perform the link/unlink in
     362                 * itself instead of letting the mounted filesystem do it,
     363                 * resulting in wrong behavior. This is the wages of server-side
     364                 * mountpoints.
     365                 */
     366
     367                char *slash = str_rchr(path, L'/');
     368                vfs_node_t *parent = base;
     369               
     370                if (slash != path) {
     371                        int tflag = lflag;
     372                        vfs_lookup_res_t tres;
     373
     374                        tflag &= ~(L_CREATE | L_EXCLUSIVE | L_UNLINK | L_FILE);
     375                        tflag |= L_DIRECTORY;
     376                        rc = _vfs_lookup_internal(base, path, tflag, &tres,
     377                            slash - path);
     378                        if (rc != EOK)
     379                                return rc;
     380                        parent = vfs_node_get(&tres);
     381                        if (!parent)
     382                                return ENOMEM;
     383                } else
     384                        vfs_node_addref(parent);
     385
     386                rc = _vfs_lookup_internal(parent, slash, lflag, result,
     387                    len - (slash - path));
     388
     389                vfs_node_put(parent);
     390
     391        } else {
     392                rc = _vfs_lookup_internal(base, path, lflag, result, len);
     393        }
     394       
     395        return rc;
     396}
     397
    349398/**
    350399 * @}
Note: See TracChangeset for help on using the changeset viewer.