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/fs/nandfs/nandfs_dir.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2010-2012 Semihalf
    5  * Copyright (c) 2008, 2009 Reinoud Zandijk
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/namei.h>
   37 #include <sys/kernel.h>
   38 #include <sys/stat.h>
   39 #include <sys/buf.h>
   40 #include <sys/bio.h>
   41 #include <sys/proc.h>
   42 #include <sys/mount.h>
   43 #include <sys/vnode.h>
   44 #include <sys/signalvar.h>
   45 #include <sys/malloc.h>
   46 #include <sys/dirent.h>
   47 #include <sys/lockf.h>
   48 
   49 #include <vm/vm.h>
   50 #include <vm/vm_extern.h>
   51 
   52 #include "nandfs_mount.h"
   53 #include "nandfs.h"
   54 #include "nandfs_subr.h"
   55 
   56 int
   57 nandfs_add_dirent(struct vnode *dvp, uint64_t ino, char *nameptr, long namelen,
   58     uint8_t type)
   59 {
   60         struct nandfs_node *dir_node = VTON(dvp);
   61         struct nandfs_dir_entry *dirent, *pdirent;
   62         uint32_t blocksize = dir_node->nn_nandfsdev->nd_blocksize;
   63         uint64_t filesize = dir_node->nn_inode.i_size;
   64         uint64_t inode_blks = dir_node->nn_inode.i_blocks;
   65         uint32_t off, rest;
   66         uint8_t *pos;
   67         struct buf *bp;
   68         int error;
   69 
   70         pdirent = NULL;
   71         bp = NULL;
   72         if (inode_blks) {
   73                 error = nandfs_bread(dir_node, inode_blks - 1, NOCRED, 0, &bp);
   74                 if (error) {
   75                         brelse(bp);
   76                         return (error);
   77                 }
   78 
   79                 pos = bp->b_data;
   80                 off = 0;
   81                 while (off < blocksize) {
   82                         pdirent = (struct nandfs_dir_entry *) (pos + off);
   83                         if (!pdirent->rec_len) {
   84                                 pdirent = NULL;
   85                                 break;
   86                         }
   87                         off += pdirent->rec_len;
   88                 }
   89 
   90                 if (pdirent)
   91                         rest = pdirent->rec_len -
   92                             NANDFS_DIR_REC_LEN(pdirent->name_len);
   93                 else
   94                         rest = blocksize;
   95 
   96                 if (rest < NANDFS_DIR_REC_LEN(namelen)) {
   97                         /* Do not update pdirent as new block is created */
   98                         pdirent = NULL;
   99                         brelse(bp);
  100                         /* Set to NULL to create new */
  101                         bp = NULL;
  102                         filesize += rest;
  103                 }
  104         }
  105 
  106         /* If no bp found create new */
  107         if (!bp) {
  108                 error = nandfs_bcreate(dir_node, inode_blks, NOCRED, 0, &bp);
  109                 if (error)
  110                         return (error);
  111                 off = 0;
  112                 pos = bp->b_data;
  113         }
  114 
  115         /* Modify pdirent if exists */
  116         if (pdirent) {
  117                 DPRINTF(LOOKUP, ("modify pdirent %p\n", pdirent));
  118                 /* modify last de */
  119                 off -= pdirent->rec_len;
  120                 pdirent->rec_len =
  121                     NANDFS_DIR_REC_LEN(pdirent->name_len);
  122                 off += pdirent->rec_len;
  123         }
  124 
  125         /* Create new dirent */
  126         dirent = (struct nandfs_dir_entry *) (pos + off);
  127         dirent->rec_len = blocksize - off;
  128         dirent->inode = ino;
  129         dirent->name_len = namelen;
  130         memset(dirent->name, 0, NANDFS_DIR_NAME_LEN(namelen));
  131         memcpy(dirent->name, nameptr, namelen);
  132         dirent->file_type = type;
  133 
  134         filesize += NANDFS_DIR_REC_LEN(dirent->name_len);
  135 
  136         DPRINTF(LOOKUP, ("create dir_entry '%.*s' at %p with size %x "
  137             "new filesize: %jx\n",
  138             (int)namelen, dirent->name, dirent, dirent->rec_len,
  139             (uintmax_t)filesize));
  140 
  141         error = nandfs_dirty_buf(bp, 0);
  142         if (error)
  143                 return (error);
  144 
  145         dir_node->nn_inode.i_size = filesize;
  146         dir_node->nn_flags |= IN_CHANGE | IN_UPDATE;
  147         vnode_pager_setsize(dvp, filesize);
  148 
  149         return (0);
  150 }
  151 
  152 int
  153 nandfs_remove_dirent(struct vnode *dvp, struct nandfs_node *node,
  154     struct componentname *cnp)
  155 {
  156         struct nandfs_node *dir_node;
  157         struct nandfs_dir_entry *dirent, *pdirent;
  158         struct buf *bp;
  159         uint64_t filesize, blocknr, ino, offset;
  160         uint32_t blocksize, limit, off;
  161         uint16_t newsize;
  162         uint8_t *pos;
  163         int error, found;
  164 
  165         dir_node = VTON(dvp);
  166         filesize = dir_node->nn_inode.i_size;
  167         if (!filesize)
  168                 return (0);
  169 
  170         if (node) {
  171                 offset = node->nn_diroff;
  172                 ino = node->nn_ino;
  173         } else {
  174                 offset = dir_node->nn_diroff;
  175                 ino = NANDFS_WHT_INO;
  176         }
  177 
  178         dirent = pdirent = NULL;
  179         blocksize = dir_node->nn_nandfsdev->nd_blocksize;
  180         blocknr = offset / blocksize;
  181 
  182         DPRINTF(LOOKUP, ("rm direntry dvp %p node %p ino %#jx at off %#jx\n",
  183             dvp, node, (uintmax_t)ino, (uintmax_t)offset));
  184 
  185         error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
  186         if (error) {
  187                 brelse(bp);
  188                 return (error);
  189         }
  190 
  191         pos = bp->b_data;
  192         off = 0;
  193         found = 0;
  194         limit = offset % blocksize;
  195         pdirent = (struct nandfs_dir_entry *) bp->b_data;
  196         while (off <= limit) {
  197                 dirent = (struct nandfs_dir_entry *) (pos + off);
  198 
  199                 if ((off == limit) &&
  200                     (dirent->inode == ino)) {
  201                         found = 1;
  202                         break;
  203                 }
  204                 if (dirent->inode != 0)
  205                         pdirent = dirent;
  206                 off += dirent->rec_len;
  207         }
  208 
  209         if (!found) {
  210                 nandfs_error("cannot find entry to remove");
  211                 brelse(bp);
  212                 return (error);
  213         }
  214         DPRINTF(LOOKUP,
  215             ("rm dirent ino %#jx at %#x with size %#x\n",
  216             (uintmax_t)dirent->inode, off, dirent->rec_len));
  217 
  218         newsize = (uintptr_t)dirent - (uintptr_t)pdirent;
  219         newsize += dirent->rec_len;
  220         pdirent->rec_len = newsize;
  221         dirent->inode = 0;
  222         error = nandfs_dirty_buf(bp, 0);
  223         if (error)
  224                 return (error);
  225 
  226         dir_node->nn_flags |= IN_CHANGE | IN_UPDATE;
  227         /* If last one modify filesize */
  228         if ((offset + NANDFS_DIR_REC_LEN(dirent->name_len)) == filesize) {
  229                 filesize = blocknr * blocksize +
  230                     ((uintptr_t)pdirent - (uintptr_t)pos) +
  231                     NANDFS_DIR_REC_LEN(pdirent->name_len);
  232                 dir_node->nn_inode.i_size = filesize;
  233         }
  234 
  235         return (0);
  236 }
  237 
  238 int
  239 nandfs_update_parent_dir(struct vnode *dvp, uint64_t newparent)
  240 {
  241         struct nandfs_dir_entry *dirent;
  242         struct nandfs_node *dir_node;
  243         struct buf *bp;
  244         int error;
  245 
  246         dir_node = VTON(dvp);
  247         error = nandfs_bread(dir_node, 0, NOCRED, 0, &bp);
  248         if (error) {
  249                 brelse(bp);
  250                 return (error);
  251         }
  252         dirent = (struct nandfs_dir_entry *)bp->b_data;
  253         dirent->inode = newparent;
  254         error = nandfs_dirty_buf(bp, 0);
  255         if (error)
  256                 return (error);
  257 
  258         return (0);
  259 }
  260 
  261 int
  262 nandfs_update_dirent(struct vnode *dvp, struct nandfs_node *fnode,
  263     struct nandfs_node *tnode)
  264 {
  265         struct nandfs_node *dir_node;
  266         struct nandfs_dir_entry *dirent;
  267         struct buf *bp;
  268         uint64_t file_size, blocknr;
  269         uint32_t blocksize, off;
  270         uint8_t *pos;
  271         int error;
  272 
  273         dir_node = VTON(dvp);
  274         file_size = dir_node->nn_inode.i_size;
  275         if (!file_size)
  276                 return (0);
  277 
  278         DPRINTF(LOOKUP,
  279             ("chg direntry dvp %p ino %#jx  to in %#jx at off %#jx\n",
  280             dvp, (uintmax_t)tnode->nn_ino, (uintmax_t)fnode->nn_ino,
  281             (uintmax_t)tnode->nn_diroff));
  282 
  283         blocksize = dir_node->nn_nandfsdev->nd_blocksize;
  284         blocknr = tnode->nn_diroff / blocksize;
  285         off = tnode->nn_diroff % blocksize;
  286         error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
  287         if (error) {
  288                 brelse(bp);
  289                 return (error);
  290         }
  291 
  292         pos = bp->b_data;
  293         dirent = (struct nandfs_dir_entry *) (pos + off);
  294         KASSERT((dirent->inode == tnode->nn_ino),
  295             ("direntry mismatch"));
  296 
  297         dirent->inode = fnode->nn_ino;
  298         error = nandfs_dirty_buf(bp, 0);
  299         if (error)
  300                 return (error);
  301 
  302         return (0);
  303 }
  304 
  305 int
  306 nandfs_init_dir(struct vnode *dvp, uint64_t ino, uint64_t parent_ino)
  307 {
  308 
  309         if (nandfs_add_dirent(dvp, parent_ino, "..", 2, DT_DIR) ||
  310             nandfs_add_dirent(dvp, ino, ".", 1, DT_DIR)) {
  311                 nandfs_error("%s: cannot initialize dir ino:%jd(pino:%jd)\n",
  312                     __func__, ino, parent_ino);
  313                 return (-1);
  314         }
  315         return (0);
  316 }

Cache object: fa10eafa8ff77bf7abcb775175cc1050


[ 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.