The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/gnu/fs/reiserfs/reiserfs_namei.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright 2000 Hans Reiser
    3  * See README for licensing and copyright details
    4  * 
    5  * Ported to FreeBSD by Jean-Sébastien Pédron <jspedron@club-internet.fr>
    6  * 
    7  * $FreeBSD$
    8  */
    9 
   10 #include <gnu/fs/reiserfs/reiserfs_fs.h>
   11 
   12 static int      reiserfs_find_entry(struct reiserfs_node *dp,
   13     const char *name, int namelen,
   14     struct path * path_to_entry, struct reiserfs_dir_entry *de);
   15 
   16 MALLOC_DEFINE(M_REISERFSCOOKIES, "reiserfs_cookies",
   17     "ReiserFS VOP_READDIR cookies");
   18 
   19 /* -------------------------------------------------------------------
   20  * Lookup functions
   21  * -------------------------------------------------------------------*/
   22 
   23 int
   24 reiserfs_lookup(struct vop_cachedlookup_args *ap)
   25 {
   26         int error, retval;
   27         struct vnode *vdp         = ap->a_dvp;
   28         struct vnode **vpp        = ap->a_vpp;
   29         struct componentname *cnp = ap->a_cnp;
   30 
   31         int flags         = cnp->cn_flags;
   32         struct thread *td = cnp->cn_thread;
   33         struct cpu_key *saved_ino;
   34 
   35         struct vnode *vp;
   36         struct vnode *pdp;  /* Saved dp during symlink work */
   37         struct reiserfs_node *dp;
   38         struct reiserfs_dir_entry de;
   39         INITIALIZE_PATH(path_to_entry);
   40 
   41         char c = cnp->cn_nameptr[cnp->cn_namelen];
   42         cnp->cn_nameptr[cnp->cn_namelen] = '\0';
   43         reiserfs_log(LOG_DEBUG, "looking for `%s', %ld (%s)\n",
   44             cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_pnbuf);
   45         cnp->cn_nameptr[cnp->cn_namelen] = c;
   46 
   47         vp = NULL;
   48         dp = VTOI(vdp);
   49 
   50         if (REISERFS_MAX_NAME(dp->i_reiserfs->s_blocksize) < cnp->cn_namelen)
   51                 return (ENAMETOOLONG);
   52 
   53         reiserfs_log(LOG_DEBUG, "searching entry\n");
   54         de.de_gen_number_bit_string = 0;
   55         retval = reiserfs_find_entry(dp, cnp->cn_nameptr, cnp->cn_namelen,
   56             &path_to_entry, &de);
   57         pathrelse(&path_to_entry);
   58 
   59         if (retval == NAME_FOUND) {
   60                 reiserfs_log(LOG_DEBUG, "found\n");
   61         } else {
   62                 reiserfs_log(LOG_DEBUG, "not found\n");
   63         }
   64 
   65         if (retval == NAME_FOUND) {
   66 #if 0
   67                 /* Hide the .reiserfs_priv directory */
   68                 if (reiserfs_xattrs(dp->i_reiserfs) &&
   69                     !old_format_only(dp->i_reiserfs) &&
   70                     REISERFS_SB(dp->i_reiserfs)->priv_root &&
   71                     REISERFS_SB(dp->i_reiserfs)->priv_root->d_inode &&
   72                     de.de_objectid == le32toh(INODE_PKEY(REISERFS_SB(
   73                     dp->i_reiserfs)->priv_root->d_inode)->k_objectid)) {
   74                         return (EACCES);
   75                 }
   76 #endif
   77 
   78                 reiserfs_log(LOG_DEBUG, "reading vnode\n");
   79                 pdp = vdp;
   80                 if (flags & ISDOTDOT) {
   81                         saved_ino = (struct cpu_key *)&(de.de_dir_id);
   82                         VOP_UNLOCK(pdp, 0);
   83                         error = reiserfs_iget(vdp->v_mount,
   84                             saved_ino, &vp, td);
   85                         vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY);
   86                         if (error != 0)
   87                                 return (error);
   88                         *vpp = vp;
   89                 } else if (de.de_objectid == dp->i_number &&
   90                     de.de_dir_id == dp->i_ino) {
   91                         VREF(vdp); /* We want ourself, ie "." */
   92                         *vpp = vdp;
   93                 } else {
   94                         if ((error = reiserfs_iget(vdp->v_mount,
   95                             (struct cpu_key *)&(de.de_dir_id), &vp, td)) != 0)
   96                                 return (error);
   97                         *vpp = vp;
   98                 }
   99 
  100                 /*
  101                  * Propogate the priv_object flag so we know we're in the
  102                  * priv tree
  103                  */
  104                 /*if (is_reiserfs_priv_object(dir))
  105                         REISERFS_I(inode)->i_flags |= i_priv_object;*/
  106         } else {
  107                 if (retval == IO_ERROR) {
  108                         reiserfs_log(LOG_DEBUG, "IO error\n");
  109                         return (EIO);
  110                 }
  111 
  112                 return (ENOENT);
  113         }
  114 
  115         /* Insert name into cache if appropriate. */
  116         if (cnp->cn_flags & MAKEENTRY)
  117                 cache_enter(vdp, *vpp, cnp);
  118 
  119         reiserfs_log(LOG_DEBUG, "done\n");
  120         return (0);
  121 }
  122 
  123 extern struct key MIN_KEY;
  124 
  125 int
  126 reiserfs_readdir(struct vop_readdir_args  /* {
  127                 struct vnode *a_vp;
  128                 struct uio *a_uio;
  129                 struct ucred *a_cred;
  130                 int *a_eofflag;
  131                 int *a_ncookies;
  132                 u_long **a_cookies;
  133         } */*ap)
  134 {
  135         int error = 0;
  136         struct dirent dstdp;
  137         struct uio *uio = ap->a_uio;
  138 
  139         off_t next_pos;
  140         struct buf *bp;
  141         struct item_head *ih;
  142         struct cpu_key pos_key;
  143         const struct key *rkey;
  144         struct reiserfs_node *ip;
  145         struct reiserfs_dir_entry de;
  146         INITIALIZE_PATH(path_to_entry);
  147         int entry_num, item_num, search_res;
  148 
  149         /* The NFS part */
  150         int ncookies = 0;
  151         u_long *cookies = NULL;
  152 
  153         /*
  154          * Form key for search the next directory entry using f_pos field of
  155          * file structure
  156          */
  157         ip = VTOI(ap->a_vp);
  158         make_cpu_key(&pos_key,
  159             ip, uio->uio_offset ? uio->uio_offset : DOT_OFFSET,
  160             TYPE_DIRENTRY, 3);
  161         next_pos = cpu_key_k_offset(&pos_key);
  162 
  163         reiserfs_log(LOG_DEBUG, "listing entries for "
  164             "(objectid=%d, dirid=%d)\n",
  165             pos_key.on_disk_key.k_objectid, pos_key.on_disk_key.k_dir_id);
  166         reiserfs_log(LOG_DEBUG, "uio_offset = %jd, uio_resid = %d\n",
  167             (intmax_t)uio->uio_offset, uio->uio_resid);
  168 
  169         if (ap->a_ncookies && ap->a_cookies) {
  170                 cookies = (u_long *)malloc(
  171                     uio->uio_resid / 16 * sizeof(u_long),
  172                     M_REISERFSCOOKIES, M_WAITOK);
  173         }
  174 
  175         while (1) {
  176                 //research:
  177                 /*
  178                  * Search the directory item, containing entry with
  179                  * specified key
  180                  */
  181                 reiserfs_log(LOG_DEBUG, "search directory to read\n");
  182                 search_res = search_by_entry_key(ip->i_reiserfs, &pos_key,
  183                     &path_to_entry, &de);
  184                 if (search_res == IO_ERROR) {
  185                         error = EIO;
  186                         goto out;
  187                 }
  188 
  189                 entry_num = de.de_entry_num;
  190                 item_num  = de.de_item_num;
  191                 bp = de.de_bp;
  192                 ih = de.de_ih;
  193 
  194                 if (search_res == POSITION_FOUND ||
  195                     entry_num < I_ENTRY_COUNT(ih)) {
  196                         /*
  197                          * Go through all entries in the directory item
  198                          * beginning from the entry, that has been found.
  199                          */
  200                         struct reiserfs_de_head *deh = B_I_DEH(bp, ih) +
  201                             entry_num;
  202 
  203                         if (ap->a_ncookies == NULL) {
  204                                 cookies = NULL;
  205                         } else {
  206                                 //ncookies = 
  207                         }
  208 
  209                         reiserfs_log(LOG_DEBUG,
  210                             "walking through directory entries\n");
  211                         for (; entry_num < I_ENTRY_COUNT(ih);
  212                             entry_num++, deh++) {
  213                                 int d_namlen;
  214                                 char *d_name;
  215                                 off_t d_off;
  216                                 ino_t d_ino;
  217 
  218                                 if (!de_visible(deh)) {
  219                                         /* It is hidden entry */
  220                                         continue;
  221                                 }
  222 
  223                                 d_namlen = entry_length(bp, ih, entry_num);
  224                                 d_name   = B_I_DEH_ENTRY_FILE_NAME(bp, ih, deh);
  225                                 if (!d_name[d_namlen - 1])
  226                                         d_namlen = strlen(d_name);
  227                                 reiserfs_log(LOG_DEBUG, "  - `%s' (len=%d)\n",
  228                                     d_name, d_namlen);
  229 
  230                                 if (d_namlen > REISERFS_MAX_NAME(
  231                                     ip->i_reiserfs->s_blocksize)) {
  232                                         /* Too big to send back to VFS */
  233                                         continue;
  234                                 }
  235 
  236 #if 0
  237                                 /* Ignore the .reiserfs_priv entry */
  238                                 if (reiserfs_xattrs(ip->i_reiserfs) &&
  239                                     !old_format_only(ip->i_reiserfs) &&
  240                                     filp->f_dentry == ip->i_reiserfs->s_root &&
  241                                     REISERFS_SB(ip->i_reiserfs)->priv_root &&
  242                                     REISERFS_SB(ip->i_reiserfs)->priv_root->d_inode &&
  243                                     deh_objectid(deh) ==
  244                                     le32toh(INODE_PKEY(REISERFS_SB(
  245                                     ip->i_reiserfs)->priv_root->d_inode)->k_objectid)) {
  246                                         continue;
  247                                 }
  248 #endif
  249 
  250                                 d_off = deh_offset(deh);
  251                                 d_ino = deh_objectid(deh);
  252                                 uio->uio_offset = d_off;
  253 
  254                                 /* Copy to user land */
  255                                 dstdp.d_fileno = d_ino;
  256                                 dstdp.d_type   = DT_UNKNOWN;
  257                                 dstdp.d_namlen = d_namlen;
  258                                 dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
  259                                 bcopy(d_name, dstdp.d_name, dstdp.d_namlen);
  260                                 bzero(dstdp.d_name + dstdp.d_namlen,
  261                                     dstdp.d_reclen -
  262                                     offsetof(struct dirent, d_name) -
  263                                     dstdp.d_namlen);
  264 
  265                                 if (d_namlen > 0) {
  266                                         if (dstdp.d_reclen <= uio->uio_resid) {
  267                                                 reiserfs_log(LOG_DEBUG, "     copying to user land\n");
  268                                                 error = uiomove(&dstdp,
  269                                                     dstdp.d_reclen, uio);
  270                                                 if (error)
  271                                                         goto end;
  272                                                 if (cookies != NULL) {
  273                                                         cookies[ncookies] =
  274                                                             d_off;
  275                                                         ncookies++;
  276                                                 }
  277                                         } else
  278                                                 break;
  279                                 } else {
  280                                         error = EIO;
  281                                         break;
  282                                 }
  283 
  284                                 next_pos = deh_offset(deh) + 1;
  285                         }
  286                         reiserfs_log(LOG_DEBUG, "...done\n");
  287                 }
  288 
  289                 reiserfs_log(LOG_DEBUG, "checking item num (%d == %d ?)\n",
  290                     item_num, B_NR_ITEMS(bp) - 1);
  291                 if (item_num != B_NR_ITEMS(bp) - 1) {
  292                         /* End of directory has been reached */
  293                         reiserfs_log(LOG_DEBUG, "end reached\n");
  294                         if (ap->a_eofflag)
  295                                 *ap->a_eofflag = 1;
  296                         goto end;
  297                 }
  298 
  299                 /*
  300                  * Item we went through is last item of node. Using right
  301                  * delimiting key check is it directory end
  302                  */
  303                 reiserfs_log(LOG_DEBUG, "get right key\n");
  304                 rkey = get_rkey(&path_to_entry, ip->i_reiserfs);
  305                 reiserfs_log(LOG_DEBUG, "right key = (objectid=%d, dirid=%d)\n",
  306                     rkey->k_objectid, rkey->k_dir_id);
  307 
  308                 reiserfs_log(LOG_DEBUG, "compare it to MIN_KEY\n");
  309                 reiserfs_log(LOG_DEBUG, "MIN KEY = (objectid=%d, dirid=%d)\n",
  310                     MIN_KEY.k_objectid, MIN_KEY.k_dir_id);
  311                 if (comp_le_keys(rkey, &MIN_KEY) == 0) {
  312                         /* Set pos_key to key, that is the smallest and greater
  313                          * that key of the last entry in the item */
  314                         reiserfs_log(LOG_DEBUG, "continuing on the right\n");
  315                         set_cpu_key_k_offset(&pos_key, next_pos);
  316                         continue;
  317                 }
  318 
  319                 reiserfs_log(LOG_DEBUG, "compare it to pos_key\n");
  320                 reiserfs_log(LOG_DEBUG, "pos key = (objectid=%d, dirid=%d)\n",
  321                     pos_key.on_disk_key.k_objectid,
  322                     pos_key.on_disk_key.k_dir_id);
  323                 if (COMP_SHORT_KEYS(rkey, &pos_key)) {
  324                         /* End of directory has been reached */
  325                         reiserfs_log(LOG_DEBUG, "end reached (right)\n");
  326                         if (ap->a_eofflag)
  327                                 *ap->a_eofflag = 1;
  328                         goto end;
  329                 }
  330 
  331                 /* Directory continues in the right neighboring block */
  332                 reiserfs_log(LOG_DEBUG, "continuing with a new offset\n");
  333                 set_cpu_key_k_offset(&pos_key,
  334                     le_key_k_offset(KEY_FORMAT_3_5, rkey));
  335                 reiserfs_log(LOG_DEBUG,
  336                     "new pos key = (objectid=%d, dirid=%d)\n",
  337                     pos_key.on_disk_key.k_objectid,
  338                     pos_key.on_disk_key.k_dir_id);
  339         }
  340 
  341 end:
  342         uio->uio_offset = next_pos;
  343         pathrelse(&path_to_entry);
  344         reiserfs_check_path(&path_to_entry);
  345 out:
  346         if (error && cookies != NULL) {
  347                 free(cookies, M_REISERFSCOOKIES);
  348         } else if (ap->a_ncookies != NULL && ap->a_cookies != NULL) {
  349                 *ap->a_ncookies = ncookies;
  350                 *ap->a_cookies  = cookies;
  351         }
  352         return (error);
  353 }
  354 
  355 /* -------------------------------------------------------------------
  356  * Functions from linux/fs/reiserfs/namei.c
  357  * -------------------------------------------------------------------*/
  358 
  359 
  360 /*
  361  * Directory item contains array of entry headers. This performs binary
  362  * search through that array.
  363  */
  364 static int
  365 bin_search_in_dir_item(struct reiserfs_dir_entry *de, off_t off)
  366 {
  367         struct item_head *ih = de->de_ih;
  368         struct reiserfs_de_head *deh = de->de_deh;
  369         int rbound, lbound, j;
  370 
  371         lbound = 0;
  372         rbound = I_ENTRY_COUNT(ih) - 1;
  373 
  374         for (j = (rbound + lbound) / 2; lbound <= rbound;
  375             j = (rbound + lbound) / 2) {
  376                 if (off < deh_offset(deh + j)) {
  377                         rbound = j - 1;
  378                         continue;
  379                 }
  380                 if (off > deh_offset(deh + j)) {
  381                         lbound = j + 1;
  382                         continue;
  383                 }
  384 
  385                 /* This is not name found, but matched third key component */
  386                 de->de_entry_num = j;
  387                 return (NAME_FOUND);
  388         }
  389 
  390         de->de_entry_num = lbound;
  391         return (NAME_NOT_FOUND);
  392 }
  393 
  394 /*
  395  * Comment?  Maybe something like set de to point to what the path
  396  * points to?
  397  */
  398 static inline void
  399 set_de_item_location(struct reiserfs_dir_entry *de, struct path *path)
  400 {
  401 
  402         de->de_bp       = get_last_bp(path);
  403         de->de_ih       = get_ih(path);
  404         de->de_deh      = B_I_DEH(de->de_bp, de->de_ih);
  405         de->de_item_num = PATH_LAST_POSITION(path);
  406 }
  407 
  408 /*
  409  * de_bh, de_ih, de_deh (points to first element of array), de_item_num
  410  * is set
  411  */
  412 void
  413 set_de_name_and_namelen(struct reiserfs_dir_entry *de)
  414 {
  415         struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num;
  416 
  417         if (de->de_entry_num >= ih_entry_count(de->de_ih)) {
  418                 reiserfs_log(LOG_DEBUG, "BUG\n");
  419                 return;
  420         }
  421 
  422         de->de_entrylen = entry_length(de->de_bp, de->de_ih, de->de_entry_num);
  423         de->de_namelen  = de->de_entrylen - (de_with_sd(deh) ? SD_SIZE : 0);
  424         de->de_name     = B_I_PITEM(de->de_bp, de->de_ih) + deh_location(deh);
  425         if (de->de_name[de->de_namelen - 1] == 0)
  426                 de->de_namelen = strlen(de->de_name);
  427 }
  428 
  429 /* What entry points to */
  430 static inline void
  431 set_de_object_key(struct reiserfs_dir_entry *de)
  432 {
  433 
  434         if (de->de_entry_num >= ih_entry_count(de->de_ih)) {
  435                 reiserfs_log(LOG_DEBUG, "BUG\n");
  436                 return;
  437         }
  438         de->de_dir_id   = deh_dir_id(&(de->de_deh[de->de_entry_num]));
  439         de->de_objectid = deh_objectid(&(de->de_deh[de->de_entry_num]));
  440 }
  441 
  442 static inline void
  443 store_de_entry_key(struct reiserfs_dir_entry *de)
  444 {
  445         struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num;
  446 
  447         if (de->de_entry_num >= ih_entry_count(de->de_ih)) {
  448                 reiserfs_log(LOG_DEBUG, "BUG\n"); 
  449                 return;
  450         }
  451 
  452         /* Store key of the found entry */
  453         de->de_entry_key.version = KEY_FORMAT_3_5;
  454         de->de_entry_key.on_disk_key.k_dir_id =
  455             le32toh(de->de_ih->ih_key.k_dir_id);
  456         de->de_entry_key.on_disk_key.k_objectid =
  457             le32toh(de->de_ih->ih_key.k_objectid);
  458         set_cpu_key_k_offset(&(de->de_entry_key), deh_offset(deh));
  459         set_cpu_key_k_type(&(de->de_entry_key), TYPE_DIRENTRY);
  460 }
  461 
  462 /*
  463  * We assign a key to each directory item, and place multiple entries in
  464  * a single directory item. A directory item has a key equal to the key
  465  * of the first directory entry in it.
  466  *
  467  * This function first calls search_by_key, then, if item whose first
  468  * entry matches is not found it looks for the entry inside directory
  469  * item found by search_by_key. Fills the path to the entry, and to the
  470  * entry position in the item
  471  */
  472 int
  473 search_by_entry_key(struct reiserfs_sb_info *sbi,
  474     const struct cpu_key *key, struct path *path,
  475     struct reiserfs_dir_entry *de)
  476 {
  477         int retval;
  478 
  479         reiserfs_log(LOG_DEBUG, "searching in (objectid=%d,dirid=%d)\n",
  480             key->on_disk_key.k_objectid, key->on_disk_key.k_dir_id);
  481         retval = search_item(sbi, key, path);
  482         switch (retval) {
  483         case ITEM_NOT_FOUND:
  484                 if (!PATH_LAST_POSITION(path)) {
  485                         reiserfs_log(LOG_DEBUG,
  486                             "search_by_key returned item position == 0");
  487                         pathrelse(path);
  488                         return (IO_ERROR);
  489                 }
  490                 PATH_LAST_POSITION(path)--;
  491                 reiserfs_log(LOG_DEBUG, "search_by_key did not found it\n");
  492                 break;
  493         case ITEM_FOUND:
  494                 reiserfs_log(LOG_DEBUG, "search_by_key found it\n");
  495                 break;
  496         case IO_ERROR:
  497                 return (retval);
  498         default:
  499                 pathrelse(path);
  500                 reiserfs_log(LOG_DEBUG, "no path to here");
  501                 return (IO_ERROR);
  502         }
  503 
  504         reiserfs_log(LOG_DEBUG, "set item location\n");
  505         set_de_item_location(de, path);
  506 
  507         /*
  508          * Binary search in directory item by third component of the
  509          * key. Sets de->de_entry_num of de
  510          */
  511         reiserfs_log(LOG_DEBUG, "bin_search_in_dir_item\n");
  512         retval = bin_search_in_dir_item(de, cpu_key_k_offset(key));
  513         path->pos_in_item = de->de_entry_num;
  514         if (retval != NAME_NOT_FOUND) {
  515                 /*
  516                  * Ugly, but rename needs de_bp, de_deh, de_name, de_namelen,
  517                  * de_objectid set
  518                  */
  519                 set_de_name_and_namelen(de);
  520                 set_de_object_key(de);
  521                 reiserfs_log(LOG_DEBUG, "set (objectid=%d,dirid=%d)\n",
  522                     de->de_objectid, de->de_dir_id);
  523         }
  524 
  525         return (retval);
  526 }
  527 
  528 static uint32_t
  529 get_third_component(struct reiserfs_sb_info *sbi, const char *name, int len)
  530 {
  531         uint32_t res;
  532 
  533         if (!len || (len == 1 && name[0] == '.'))
  534                 return (DOT_OFFSET);
  535 
  536         if (len == 2 && name[0] == '.' && name[1] == '.')
  537                 return (DOT_DOT_OFFSET);
  538 
  539         res = REISERFS_SB(sbi)->s_hash_function(name, len);
  540 
  541         /* Take bits from 7-th to 30-th including both bounds */
  542         res = GET_HASH_VALUE(res);
  543         if (res == 0)
  544                 /*
  545                  * Needed to have no names before "." and ".." those have hash
  546                  * value == 0 and generation counters 1 and 2 accordingly
  547                  */
  548                 res = 128;
  549 
  550         return (res + MAX_GENERATION_NUMBER);
  551 }
  552 
  553 static int
  554 reiserfs_match(struct reiserfs_dir_entry *de, const char *name, int namelen)
  555 {
  556         int retval = NAME_NOT_FOUND;
  557 
  558         if ((namelen == de->de_namelen) &&
  559             !memcmp(de->de_name, name, de->de_namelen))
  560                 retval = (de_visible(de->de_deh + de->de_entry_num) ?
  561                     NAME_FOUND : NAME_FOUND_INVISIBLE);
  562 
  563         return (retval);
  564 }
  565 
  566 /*
  567  * de's de_bh, de_ih, de_deh, de_item_num, de_entry_num are set already
  568  * Used when hash collisions exist
  569  */
  570 static int
  571 linear_search_in_dir_item(struct cpu_key *key, struct reiserfs_dir_entry *de,
  572     const char *name, int namelen)
  573 {
  574         int i;
  575         int retval;
  576         struct reiserfs_de_head * deh = de->de_deh;
  577 
  578         i = de->de_entry_num;
  579 
  580         if (i == I_ENTRY_COUNT(de->de_ih) ||
  581             GET_HASH_VALUE(deh_offset(deh + i)) !=
  582             GET_HASH_VALUE(cpu_key_k_offset(key))) {
  583                 i--;
  584         }
  585 
  586         /*RFALSE( de->de_deh != B_I_DEH (de->de_bh, de->de_ih),
  587           "vs-7010: array of entry headers not found");*/
  588 
  589         deh += i;
  590 
  591         for (; i >= 0; i--, deh--) {
  592                 if (GET_HASH_VALUE(deh_offset(deh)) !=
  593                     GET_HASH_VALUE(cpu_key_k_offset(key))) {
  594                         /*
  595                          * Hash value does not match, no need to check
  596                          * whole name
  597                          */
  598                         reiserfs_log(LOG_DEBUG, "name `%s' not found\n", name);
  599                         return (NAME_NOT_FOUND);
  600                 }
  601 
  602                 /* Mark that this generation number is used */
  603                 if (de->de_gen_number_bit_string)
  604                         set_bit(GET_GENERATION_NUMBER(deh_offset(deh)),
  605                             (unsigned long *)de->de_gen_number_bit_string);
  606 
  607                 /* Calculate pointer to name and namelen */
  608                 de->de_entry_num = i;
  609                 set_de_name_and_namelen(de);
  610 
  611                 if ((retval = reiserfs_match(de, name, namelen)) !=
  612                     NAME_NOT_FOUND) {
  613                         /*
  614                          * de's de_name, de_namelen, de_recordlen are set.
  615                          * Fill the rest:
  616                          */
  617                         /* key of pointed object */
  618                         set_de_object_key(de);
  619                         store_de_entry_key(de);
  620 
  621                         /* retval can be NAME_FOUND or NAME_FOUND_INVISIBLE */
  622                         reiserfs_log(LOG_DEBUG,
  623                             "reiserfs_match answered `%d'\n",
  624                             retval);
  625                         return (retval);
  626                 }
  627         }
  628 
  629         if (GET_GENERATION_NUMBER(le_ih_k_offset(de->de_ih)) == 0)
  630                 /*
  631                  * We have reached left most entry in the node. In common
  632                  * we have to go to the left neighbor, but if generation
  633                  * counter is 0 already, we know for sure, that there is
  634                  * no name with the same hash value
  635                  */
  636                 /* FIXME: this work correctly only because hash value can
  637                  * not be 0. Btw, in case of Yura's hash it is probably
  638                  * possible, so, this is a bug
  639                  */
  640                 return (NAME_NOT_FOUND);
  641 
  642         /*RFALSE(de->de_item_num,
  643             "vs-7015: two diritems of the same directory in one node?");*/
  644 
  645         return (GOTO_PREVIOUS_ITEM);
  646 }
  647 
  648 /*
  649  * May return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND
  650  * FIXME: should add something like IOERROR
  651  */
  652 static int
  653 reiserfs_find_entry(struct reiserfs_node *dp, const char *name, int namelen,
  654     struct path * path_to_entry, struct reiserfs_dir_entry *de)
  655 {
  656         struct cpu_key key_to_search;
  657         int retval;
  658 
  659         if (namelen > REISERFS_MAX_NAME(dp->i_reiserfs->s_blocksize))
  660                 return NAME_NOT_FOUND;
  661 
  662         /* We will search for this key in the tree */
  663         make_cpu_key(&key_to_search, dp,
  664             get_third_component(dp->i_reiserfs, name, namelen),
  665             TYPE_DIRENTRY, 3);
  666 
  667         while (1) {
  668                 reiserfs_log(LOG_DEBUG, "search by entry key\n");
  669                 retval = search_by_entry_key(dp->i_reiserfs, &key_to_search,
  670                     path_to_entry, de);
  671                 if (retval == IO_ERROR) {
  672                         reiserfs_log(LOG_DEBUG, "IO error in %s\n",
  673                             __FUNCTION__);
  674                         return IO_ERROR;
  675                 }
  676 
  677                 /* Compare names for all entries having given hash value */
  678                 reiserfs_log(LOG_DEBUG, "linear search for `%s'\n", name);
  679                 retval = linear_search_in_dir_item(&key_to_search, de,
  680                     name, namelen);
  681                 if (retval != GOTO_PREVIOUS_ITEM) {
  682                         /*
  683                          * There is no need to scan directory anymore.
  684                          * Given entry found or does not exist
  685                          */
  686                         reiserfs_log(LOG_DEBUG, "linear search returned "
  687                             "(objectid=%d,dirid=%d)\n",
  688                             de->de_objectid, de->de_dir_id);
  689                         path_to_entry->pos_in_item = de->de_entry_num;
  690                         return retval;
  691                 }
  692 
  693                 /*
  694                  * There is left neighboring item of this directory and
  695                  * given entry can be there
  696                  */
  697                 set_cpu_key_k_offset(&key_to_search,
  698                     le_ih_k_offset(de->de_ih) - 1);
  699                 pathrelse(path_to_entry);  
  700         } /* while (1) */
  701 }

Cache object: fbd71e1800e0b640ccd470d1b0a7cf5d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.