1147476Sdumbbell/*- 2147476Sdumbbell * Copyright 2000 Hans Reiser 3147476Sdumbbell * See README for licensing and copyright details 4147476Sdumbbell * 5147476Sdumbbell * Ported to FreeBSD by Jean-S�bastien P�dron <jspedron@club-internet.fr> 6147476Sdumbbell * 7147476Sdumbbell * $FreeBSD$ 8147476Sdumbbell */ 9147476Sdumbbell 10147476Sdumbbell#include <gnu/fs/reiserfs/reiserfs_fs.h> 11147476Sdumbbell 12147476Sdumbbellstatic vop_access_t reiserfs_access; 13147476Sdumbbellstatic vop_bmap_t reiserfs_bmap; 14147476Sdumbbellstatic vop_getattr_t reiserfs_getattr; 15147476Sdumbbellstatic vop_open_t reiserfs_open; 16147476Sdumbbellstatic vop_pathconf_t reiserfs_pathconf; 17147476Sdumbbellstatic vop_readlink_t reiserfs_readlink; 18147476Sdumbbellstatic vop_strategy_t reiserfs_strategy; 19166774Spjdstatic vop_vptofh_t reiserfs_vptofh; 20147476Sdumbbell 21147476Sdumbbell/* Global vfs data structures for ReiserFS */ 22147476Sdumbbellstruct vop_vector reiserfs_vnodeops = { 23147476Sdumbbell .vop_default = &default_vnodeops, 24147476Sdumbbell 25147476Sdumbbell .vop_access = reiserfs_access, 26147476Sdumbbell .vop_bmap = reiserfs_bmap, 27147476Sdumbbell .vop_cachedlookup = reiserfs_lookup, 28147476Sdumbbell .vop_getattr = reiserfs_getattr, 29147476Sdumbbell .vop_inactive = reiserfs_inactive, 30147476Sdumbbell .vop_lookup = vfs_cache_lookup, 31147476Sdumbbell .vop_open = reiserfs_open, 32147476Sdumbbell .vop_reclaim = reiserfs_reclaim, 33147476Sdumbbell .vop_read = reiserfs_read, 34147476Sdumbbell .vop_readdir = reiserfs_readdir, 35147476Sdumbbell .vop_readlink = reiserfs_readlink, 36147476Sdumbbell .vop_pathconf = reiserfs_pathconf, 37147476Sdumbbell .vop_strategy = reiserfs_strategy, 38166774Spjd .vop_vptofh = reiserfs_vptofh, 39147476Sdumbbell}; 40147476Sdumbbell 41147476Sdumbbellstruct vop_vector reiserfs_specops = { 42147476Sdumbbell .vop_default = &default_vnodeops, 43147476Sdumbbell 44147476Sdumbbell .vop_access = reiserfs_access, 45147476Sdumbbell .vop_getattr = reiserfs_getattr, 46147476Sdumbbell .vop_inactive = reiserfs_inactive, 47147476Sdumbbell .vop_reclaim = reiserfs_reclaim, 48147476Sdumbbell}; 49147476Sdumbbell 50147476Sdumbbell/* ------------------------------------------------------------------- 51147476Sdumbbell * vnode operations 52147476Sdumbbell * -------------------------------------------------------------------*/ 53147476Sdumbbell 54147476Sdumbbellstatic int 55147476Sdumbbellreiserfs_access(struct vop_access_args *ap) 56147476Sdumbbell{ 57147476Sdumbbell int error; 58147476Sdumbbell struct vnode *vp = ap->a_vp; 59147476Sdumbbell struct reiserfs_node *ip = VTOI(vp); 60184413Strasz accmode_t accmode = ap->a_accmode; 61147476Sdumbbell 62147476Sdumbbell /* 63147476Sdumbbell * Disallow write attempts on read-only file systems; unless the file 64147476Sdumbbell * is a socket, fifo, or a block or character device resident on the 65147476Sdumbbell * file system. 66147476Sdumbbell */ 67184413Strasz if (accmode & VWRITE) { 68147476Sdumbbell switch (vp->v_type) { 69147476Sdumbbell case VDIR: 70147476Sdumbbell case VLNK: 71147476Sdumbbell case VREG: 72147476Sdumbbell if (vp->v_mount->mnt_flag & MNT_RDONLY) { 73147476Sdumbbell reiserfs_log(LOG_DEBUG, 74147476Sdumbbell "no write access (read-only fs)\n"); 75147476Sdumbbell return (EROFS); 76147476Sdumbbell } 77147476Sdumbbell break; 78147476Sdumbbell default: 79147476Sdumbbell break; 80147476Sdumbbell } 81147476Sdumbbell } 82147476Sdumbbell 83147476Sdumbbell /* If immutable bit set, nobody gets to write it. */ 84184413Strasz if ((accmode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT))) { 85147476Sdumbbell reiserfs_log(LOG_DEBUG, "no write access (immutable)\n"); 86147476Sdumbbell return (EPERM); 87147476Sdumbbell } 88147476Sdumbbell 89147476Sdumbbell error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, 90184413Strasz ap->a_accmode, ap->a_cred, NULL); 91147476Sdumbbell return (error); 92147476Sdumbbell} 93147476Sdumbbell 94147476Sdumbbellstatic int 95147476Sdumbbellreiserfs_getattr(struct vop_getattr_args *ap) 96147476Sdumbbell{ 97147476Sdumbbell struct vnode *vp = ap->a_vp; 98147476Sdumbbell struct vattr *vap = ap->a_vap; 99147476Sdumbbell struct reiserfs_node *ip = VTOI(vp); 100147476Sdumbbell 101147476Sdumbbell vap->va_fsid = dev2udev(ip->i_dev); 102147476Sdumbbell vap->va_fileid = ip->i_number; 103147476Sdumbbell vap->va_mode = ip->i_mode & ~S_IFMT; 104147476Sdumbbell vap->va_nlink = ip->i_nlink; 105147476Sdumbbell vap->va_uid = ip->i_uid; 106147476Sdumbbell vap->va_gid = ip->i_gid; 107147476Sdumbbell //XXX vap->va_rdev = ip->i_rdev; 108147476Sdumbbell vap->va_size = ip->i_size; 109147476Sdumbbell vap->va_atime = ip->i_atime; 110147476Sdumbbell vap->va_mtime = ip->i_mtime; 111147476Sdumbbell vap->va_ctime = ip->i_ctime; 112147476Sdumbbell vap->va_flags = ip->i_flags; 113147476Sdumbbell vap->va_gen = ip->i_generation; 114147476Sdumbbell vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; 115147476Sdumbbell vap->va_bytes = dbtob((u_quad_t)ip->i_blocks); 116147476Sdumbbell vap->va_type = vp->v_type; 117147476Sdumbbell //XXX vap->va_filerev = ip->i_modrev; 118147476Sdumbbell 119147476Sdumbbell return (0); 120147476Sdumbbell} 121147476Sdumbbell 122147476Sdumbbell/* Return POSIX pathconf information applicable to ReiserFS filesystems */ 123147476Sdumbbellstatic int 124147476Sdumbbellreiserfs_pathconf(struct vop_pathconf_args *ap) 125147476Sdumbbell{ 126147476Sdumbbell switch (ap->a_name) { 127147476Sdumbbell case _PC_LINK_MAX: 128147476Sdumbbell *ap->a_retval = REISERFS_LINK_MAX; 129147476Sdumbbell return (0); 130147476Sdumbbell case _PC_NAME_MAX: 131147476Sdumbbell *ap->a_retval = 132147476Sdumbbell REISERFS_MAX_NAME(VTOI(ap->a_vp)->i_reiserfs->s_blocksize); 133147476Sdumbbell return (0); 134147476Sdumbbell case _PC_PATH_MAX: 135147476Sdumbbell *ap->a_retval = PATH_MAX; 136147476Sdumbbell return (0); 137147476Sdumbbell case _PC_PIPE_BUF: 138147476Sdumbbell *ap->a_retval = PIPE_BUF; 139147476Sdumbbell return (0); 140147476Sdumbbell case _PC_CHOWN_RESTRICTED: 141147476Sdumbbell *ap->a_retval = 1; 142147476Sdumbbell return (0); 143147476Sdumbbell case _PC_NO_TRUNC: 144147476Sdumbbell *ap->a_retval = 1; 145147476Sdumbbell return (0); 146147476Sdumbbell default: 147147476Sdumbbell return (EINVAL); 148147476Sdumbbell } 149147476Sdumbbell} 150147476Sdumbbell 151147476Sdumbbellstatic int 152147476Sdumbbellreiserfs_open(struct vop_open_args *ap) 153147476Sdumbbell{ 154147476Sdumbbell /* Files marked append-only must be opened for appending. */ 155147476Sdumbbell if ((VTOI(ap->a_vp)->i_flags & APPEND) && 156147476Sdumbbell (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) 157147476Sdumbbell return (EPERM); 158147476Sdumbbell 159147476Sdumbbell vnode_create_vobject(ap->a_vp, VTOI(ap->a_vp)->i_size, ap->a_td); 160147476Sdumbbell 161147476Sdumbbell return (0); 162147476Sdumbbell} 163147476Sdumbbell 164147476Sdumbbell/* Return target name of a symbolic link */ 165147476Sdumbbellstatic int 166147476Sdumbbellreiserfs_readlink(struct vop_readlink_args *ap) 167147476Sdumbbell{ 168147476Sdumbbell struct vnode *vp = ap->a_vp; 169147476Sdumbbell 170147476Sdumbbell reiserfs_log(LOG_DEBUG, "redirect to VOP_READ()\n"); 171147476Sdumbbell return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); 172147476Sdumbbell} 173147476Sdumbbell 174147476Sdumbbell/* Bmap converts the logical block number of a file to its physical 175147476Sdumbbell * block number on the disk. */ 176147476Sdumbbellstatic int 177147476Sdumbbellreiserfs_bmap(ap) 178147476Sdumbbell struct vop_bmap_args /* { 179147476Sdumbbell struct vnode *a_vp; 180147476Sdumbbell daddr_t a_bn; 181147476Sdumbbell struct bufobj **a_bop; 182147476Sdumbbell daddr_t *a_bnp; 183147476Sdumbbell int *a_runp; 184147476Sdumbbell int *a_runb; 185147476Sdumbbell } */ *ap; 186147476Sdumbbell{ 187147476Sdumbbell daddr_t blkno; 188147476Sdumbbell struct buf *bp; 189147476Sdumbbell struct cpu_key key; 190147476Sdumbbell struct item_head *ih; 191147476Sdumbbell 192147476Sdumbbell struct vnode *vp = ap->a_vp; 193147476Sdumbbell struct reiserfs_node *ip = VTOI(vp); 194147476Sdumbbell struct reiserfs_sb_info *sbi = ip->i_reiserfs; 195147476Sdumbbell INITIALIZE_PATH(path); 196147476Sdumbbell 197147476Sdumbbell /* Prepare the key to look for the 'block'-th block of file 198147476Sdumbbell * (XXX we suppose that statfs.f_iosize == sbi->s_blocksize) */ 199147476Sdumbbell make_cpu_key(&key, ip, (off_t)ap->a_bn * sbi->s_blocksize + 1, 200147476Sdumbbell TYPE_ANY, 3); 201147476Sdumbbell 202147476Sdumbbell /* Search item */ 203147476Sdumbbell if (search_for_position_by_key(sbi, &key, &path) != POSITION_FOUND) { 204147476Sdumbbell reiserfs_log(LOG_DEBUG, "position not found\n"); 205147476Sdumbbell pathrelse(&path); 206147476Sdumbbell return (ENOENT); 207147476Sdumbbell } 208147476Sdumbbell 209147476Sdumbbell bp = get_last_bp(&path); 210147476Sdumbbell ih = get_ih(&path); 211147476Sdumbbell 212147476Sdumbbell if (is_indirect_le_ih(ih)) { 213147476Sdumbbell /* Indirect item can be read by the underlying layer, instead of 214147476Sdumbbell * VOP_STRATEGY. */ 215147476Sdumbbell int i; 216147476Sdumbbell uint32_t *ind_item = (uint32_t *)B_I_PITEM(bp, ih); 217147476Sdumbbell reiserfs_log(LOG_DEBUG, "found an INDIRECT item\n"); 218147476Sdumbbell blkno = get_block_num(ind_item, path.pos_in_item); 219147476Sdumbbell 220147476Sdumbbell /* Read-ahead */ 221147476Sdumbbell if (ap->a_runb) { 222147476Sdumbbell uint32_t count = 0; 223147476Sdumbbell for (i = path.pos_in_item - 1; i >= 0; --i) { 224147476Sdumbbell if ((blkno - get_block_num(ind_item, i)) != 225147476Sdumbbell count + 1) 226147476Sdumbbell break; 227147476Sdumbbell ++count; 228147476Sdumbbell } 229147476Sdumbbell 230147476Sdumbbell /* 231147476Sdumbbell * This count isn't expressed in DEV_BSIZE base but 232147476Sdumbbell * in fs' own block base 233147476Sdumbbell * (see sys/vm/vnode_pager.c:vnode_pager_addr()) 234147476Sdumbbell */ 235147476Sdumbbell *ap->a_runb = count; 236147476Sdumbbell reiserfs_log(LOG_DEBUG, 237147476Sdumbbell " read-ahead: %d blocks before\n", *ap->a_runb); 238147476Sdumbbell } 239147476Sdumbbell if (ap->a_runp) { 240147476Sdumbbell uint32_t count = 0; 241147476Sdumbbell /* 242147476Sdumbbell * ih is an uint32_t array, that's why we use 243147476Sdumbbell * its length (in bytes) divided by 4 to know 244147476Sdumbbell * the number of items 245147476Sdumbbell */ 246147476Sdumbbell for (i = path.pos_in_item + 1; 247147476Sdumbbell i < ih_item_len(ih) / 4; ++i) { 248147476Sdumbbell if ((get_block_num(ind_item, i) - blkno) != 249147476Sdumbbell count + 1) 250147476Sdumbbell break; 251147476Sdumbbell ++count; 252147476Sdumbbell } 253147476Sdumbbell 254147476Sdumbbell /* 255147476Sdumbbell * This count isn't expressed in DEV_BSIZE base but 256147476Sdumbbell * in fs' own block base 257147476Sdumbbell * (see sys/vm/vnode_pager.c:vnode_pager_addr()) */ 258147476Sdumbbell *ap->a_runp = count; 259147476Sdumbbell reiserfs_log(LOG_DEBUG, 260147476Sdumbbell " read-ahead: %d blocks after\n", *ap->a_runp); 261147476Sdumbbell } 262147476Sdumbbell 263147476Sdumbbell /* Indirect items can be read using the device VOP_STRATEGY */ 264147476Sdumbbell if (ap->a_bop) 265147476Sdumbbell *ap->a_bop = &VTOI(ap->a_vp)->i_devvp->v_bufobj; 266147476Sdumbbell 267147476Sdumbbell /* Convert the block number into DEV_BSIZE base */ 268147476Sdumbbell blkno *= btodb(sbi->s_blocksize); 269147476Sdumbbell } else { 270147476Sdumbbell /* 271147476Sdumbbell * Direct item are not DEV_BSIZE aligned, VOP_STRATEGY will 272147476Sdumbbell * have to handle this case specifically 273147476Sdumbbell */ 274147476Sdumbbell reiserfs_log(LOG_DEBUG, "found a DIRECT item\n"); 275147476Sdumbbell blkno = ap->a_bn; 276147476Sdumbbell 277147476Sdumbbell if (ap->a_runp) 278147476Sdumbbell *ap->a_runp = 0; 279147476Sdumbbell if (ap->a_runb) 280147476Sdumbbell *ap->a_runb = 0; 281147476Sdumbbell 282147476Sdumbbell /* Direct item must be read by reiserfs_strategy */ 283147476Sdumbbell if (ap->a_bop) 284147476Sdumbbell *ap->a_bop = &vp->v_bufobj; 285147476Sdumbbell } 286147476Sdumbbell 287147476Sdumbbell if (ap->a_bnp) 288147476Sdumbbell *ap->a_bnp = blkno; 289147476Sdumbbell 290147476Sdumbbell pathrelse(&path); 291147476Sdumbbell 292147476Sdumbbell if (ap->a_bnp) { 293147476Sdumbbell reiserfs_log(LOG_DEBUG, "logical block: %ju (%ju)," 294147476Sdumbbell " physical block: %ju (%ju)\n", 295147476Sdumbbell (intmax_t)ap->a_bn, 296147476Sdumbbell (intmax_t)(ap->a_bn / btodb(sbi->s_blocksize)), 297147476Sdumbbell (intmax_t)*ap->a_bnp, 298147476Sdumbbell (intmax_t)(*ap->a_bnp / btodb(sbi->s_blocksize))); 299147476Sdumbbell } 300147476Sdumbbell 301147476Sdumbbell return (0); 302147476Sdumbbell} 303147476Sdumbbell 304147476Sdumbbell/* Does simply the same as reiserfs_read. It's called when reiserfs_bmap find 305147476Sdumbbell * an direct item. */ 306147476Sdumbbellstatic int 307147476Sdumbbellreiserfs_strategy(struct vop_strategy_args /* { 308147476Sdumbbell struct vnode *a_vp; 309147476Sdumbbell struct buf *a_bp; 310147476Sdumbbell } */ *ap) 311147476Sdumbbell{ 312147476Sdumbbell int error; 313147476Sdumbbell struct uio auio; 314147476Sdumbbell struct iovec aiov; 315147476Sdumbbell struct reiserfs_node *ip; 316147476Sdumbbell struct buf *bp = ap->a_bp; 317147476Sdumbbell struct vnode *vp = ap->a_vp; 318147476Sdumbbell 319147476Sdumbbell reiserfs_log(LOG_DEBUG, "logical block: %ju," 320147476Sdumbbell " physical block: %ju\n", (intmax_t)bp->b_lblkno, 321147476Sdumbbell (intmax_t)bp->b_blkno); 322147476Sdumbbell 323147476Sdumbbell ip = VTOI(vp); 324147476Sdumbbell 325147476Sdumbbell if (bp->b_iocmd == BIO_READ) { 326147476Sdumbbell /* Prepare the uio structure */ 327147476Sdumbbell reiserfs_log(LOG_DEBUG, "prepare uio structure\n"); 328147476Sdumbbell aiov.iov_base = bp->b_data; 329147476Sdumbbell aiov.iov_len = MIN(bp->b_bcount, ip->i_size); 330147476Sdumbbell reiserfs_log(LOG_DEBUG, " vector length: %ju\n", 331147476Sdumbbell (intmax_t)aiov.iov_len); 332147476Sdumbbell 333147476Sdumbbell auio.uio_iov = &aiov; 334147476Sdumbbell auio.uio_iovcnt = 1; 335147476Sdumbbell auio.uio_offset = 0; 336147476Sdumbbell auio.uio_rw = UIO_READ; 337147476Sdumbbell auio.uio_segflg = UIO_SYSSPACE; 338147476Sdumbbell auio.uio_td = curthread; 339147476Sdumbbell auio.uio_resid = bp->b_bcount; 340147476Sdumbbell reiserfs_log(LOG_DEBUG, " buffer length: %u\n", 341147476Sdumbbell auio.uio_resid); 342147476Sdumbbell 343147476Sdumbbell reiserfs_log(LOG_DEBUG, "reading block #%ju\n", 344147476Sdumbbell (intmax_t)bp->b_blkno); 345147476Sdumbbell error = reiserfs_get_block(ip, bp->b_blkno, 0, &auio); 346147476Sdumbbell } else { 347147476Sdumbbell /* No write support yet */ 348147476Sdumbbell error = (EOPNOTSUPP); 349147476Sdumbbell bp->b_error = error; 350147476Sdumbbell bp->b_ioflags |= BIO_ERROR; 351147476Sdumbbell } 352147476Sdumbbell 353186194Strasz if (error) { 354186194Strasz bp->b_ioflags |= BIO_ERROR; 355186194Strasz bp->b_error = error; 356186194Strasz } 357186194Strasz 358147476Sdumbbell bufdone(bp); 359186194Strasz return (0); 360147476Sdumbbell} 361166774Spjd 362166774Spjd/* 363166774Spjd * Vnode pointer to File handle 364166774Spjd */ 365166774Spjdstatic int 366166774Spjdreiserfs_vptofh(struct vop_vptofh_args /* { 367166774Spjd struct vnode *a_vp; 368166774Spjd struct fid *a_fhp; 369166774Spjd } */ *ap) 370166774Spjd{ 371166774Spjd struct rfid *rfhp; 372166774Spjd struct reiserfs_node *ip; 373166774Spjd 374166774Spjd ip = VTOI(ap->a_vp); 375166774Spjd reiserfs_log(LOG_DEBUG, 376166774Spjd "fill *fhp with inode (dirid=%d, objectid=%d)\n", 377166774Spjd ip->i_ino, ip->i_number); 378166774Spjd 379166774Spjd rfhp = (struct rfid *)ap->a_fhp; 380166774Spjd rfhp->rfid_len = sizeof(struct rfid); 381166774Spjd rfhp->rfid_dirid = ip->i_ino; 382166774Spjd rfhp->rfid_objectid = ip->i_number; 383166774Spjd rfhp->rfid_gen = ip->i_generation; 384166774Spjd 385166774Spjd reiserfs_log(LOG_DEBUG, "return it\n"); 386166774Spjd return (0); 387166774Spjd} 388