X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fzfs_vnops.c;h=262c1ed64120942056313096198e9d6550d6c50b;hb=f5fc4acaa77e2c1782a9495bbf1a39884b4c3940;hp=53d3194788092836b6358a3114cd929e87f901dc;hpb=f0b2486034f6a4d8cd1a139ff4604e6b9629a64e;p=zfs.git diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 53d3194..262c1ed 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -399,18 +399,14 @@ zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr) return (0); } -#ifdef HAVE_MANDLOCKS /* * Check for mandatory locks */ - if (MANDMODE(zp->z_mode)) { - if (error = chklock(ip, FREAD, - uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) { - ZFS_EXIT(zsb); - return (error); - } + if (mandatory_lock(ip) && + !lock_may_read(ip, uio->uio_loffset, uio->uio_resid)) { + ZFS_EXIT(zsb); + return (EAGAIN); } -#endif /* HAVE_MANDLOCK */ /* * If we're in FRSYNC mode, sync out this znode before reading it. @@ -581,17 +577,14 @@ zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr) return (EINVAL); } -#ifdef HAVE_MANDLOCKS /* * Check for mandatory locks before calling zfs_range_lock() * in order to prevent a deadlock with locks set via fcntl(). */ - if (MANDMODE((mode_t)zp->z_mode) && - (error = chklock(ip, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) { + if (mandatory_lock(ip) && !lock_may_write(ip, woff, n)) { ZFS_EXIT(zsb); - return (error); + return (EAGAIN); } -#endif /* HAVE_MANDLOCKS */ #ifdef HAVE_UIO_ZEROCOPY /* @@ -1120,14 +1113,6 @@ zfs_lookup(struct inode *dip, char *nm, struct inode **ipp, int flags, if (flags & LOOKUP_XATTR) { /* - * If the xattr property is off, refuse the lookup request. - */ - if (!(zsb->z_flags & ZSB_XATTR_USER)) { - ZFS_EXIT(zsb); - return (EINVAL); - } - - /* * We don't allow recursive attributes.. * Maybe someday we will. */ @@ -2298,6 +2283,44 @@ zfs_getattr(struct inode *ip, vattr_t *vap, int flags, cred_t *cr) EXPORT_SYMBOL(zfs_getattr); /* + * Get the basic file attributes and place them in the provided kstat + * structure. The inode is assumed to be the authoritative source + * for most of the attributes. However, the znode currently has the + * authoritative atime, blksize, and block count. + * + * IN: ip - inode of file. + * + * OUT: sp - kstat values. + * + * RETURN: 0 (always succeeds) + */ +/* ARGSUSED */ +int +zfs_getattr_fast(struct inode *ip, struct kstat *sp) +{ + znode_t *zp = ITOZ(ip); + zfs_sb_t *zsb = ITOZSB(ip); + + mutex_enter(&zp->z_lock); + + generic_fillattr(ip, sp); + ZFS_TIME_DECODE(&sp->atime, zp->z_atime); + + sa_object_size(zp->z_sa_hdl, (uint32_t *)&sp->blksize, &sp->blocks); + if (unlikely(zp->z_blksz == 0)) { + /* + * Block size hasn't been set; suggest maximal I/O transfers. + */ + sp->blksize = zsb->z_max_blksz; + } + + mutex_exit(&zp->z_lock); + + return (0); +} +EXPORT_SYMBOL(zfs_getattr_fast); + +/* * Set the file attributes to the values contained in the * vattr structure. * @@ -2420,7 +2443,7 @@ top: aclp = NULL; /* Can this be moved to before the top label? */ - if (zsb->z_vfs->mnt_flags & MNT_READONLY) { + if (zfs_is_readonly(zsb)) { err = EROFS; goto out3; } @@ -3815,7 +3838,6 @@ zfs_putpage(struct page *page, struct writeback_control *wbc, void *data) struct inode *ip = mapping->host; znode_t *zp = ITOZ(ip); zfs_sb_t *zsb = ITOZSB(ip); - rl_t *rl; u_offset_t io_off; size_t io_len; size_t len; @@ -3827,11 +3849,8 @@ zfs_putpage(struct page *page, struct writeback_control *wbc, void *data) ZFS_ENTER(zsb); ZFS_VERIFY_ZP(zp); - rl = zfs_range_lock(zp, io_off, io_len, RL_WRITER); - if (io_off > zp->z_size) { /* past end of file */ - zfs_range_unlock(rl); ZFS_EXIT(zsb); return (0); } @@ -3839,7 +3858,6 @@ zfs_putpage(struct page *page, struct writeback_control *wbc, void *data) len = MIN(io_len, P2ROUNDUP(zp->z_size, PAGESIZE) - io_off); error = zfs_putapage(ip, page, io_off, len); - zfs_range_unlock(rl); if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zsb->z_log, zp->z_id); @@ -3995,144 +4013,50 @@ zfs_getpage(struct inode *ip, struct page *pl[], int nr_pages) } EXPORT_SYMBOL(zfs_getpage); -#ifdef HAVE_MMAP /* - * Request a memory map for a section of a file. This code interacts - * with common code and the VM system as follows: - * - * common code calls mmap(), which ends up in smmap_common() - * - * this calls VOP_MAP(), which takes you into (say) zfs - * - * zfs_map() calls as_map(), passing segvn_create() as the callback + * Check ZFS specific permissions to memory map a section of a file. * - * segvn_create() creates the new segment and calls VOP_ADDMAP() + * IN: ip - inode of the file to mmap + * off - file offset + * addrp - start address in memory region + * len - length of memory region + * vm_flags- address flags * - * zfs_addmap() updates z_mapcnt + * RETURN: 0 if success + * error code if failure */ /*ARGSUSED*/ -static int -zfs_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp, - size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr) +int +zfs_map(struct inode *ip, offset_t off, caddr_t *addrp, size_t len, + unsigned long vm_flags) { - znode_t *zp = VTOZ(vp); - zfsvfs_t *zfsvfs = zp->z_zfsvfs; - segvn_crargs_t vn_a; - int error; + znode_t *zp = ITOZ(ip); + zfs_sb_t *zsb = ITOZSB(ip); - ZFS_ENTER(zfsvfs); + ZFS_ENTER(zsb); ZFS_VERIFY_ZP(zp); - if ((prot & PROT_WRITE) && (zp->z_pflags & + if ((vm_flags & VM_WRITE) && (zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY | ZFS_APPENDONLY))) { - ZFS_EXIT(zfsvfs); + ZFS_EXIT(zsb); return (EPERM); } - if ((prot & (PROT_READ | PROT_EXEC)) && + if ((vm_flags & (VM_READ | VM_EXEC)) && (zp->z_pflags & ZFS_AV_QUARANTINED)) { - ZFS_EXIT(zfsvfs); + ZFS_EXIT(zsb); return (EACCES); } - if (vp->v_flag & VNOMAP) { - ZFS_EXIT(zfsvfs); - return (ENOSYS); - } - if (off < 0 || len > MAXOFFSET_T - off) { - ZFS_EXIT(zfsvfs); + ZFS_EXIT(zsb); return (ENXIO); } - if (vp->v_type != VREG) { - ZFS_EXIT(zfsvfs); - return (ENODEV); - } - - /* - * If file is locked, disallow mapping. - */ - if (MANDMODE(zp->z_mode) && vn_has_flocks(vp)) { - ZFS_EXIT(zfsvfs); - return (EAGAIN); - } - - as_rangelock(as); - error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags); - if (error != 0) { - as_rangeunlock(as); - ZFS_EXIT(zfsvfs); - return (error); - } - - vn_a.vp = vp; - vn_a.offset = (u_offset_t)off; - vn_a.type = flags & MAP_TYPE; - vn_a.prot = prot; - vn_a.maxprot = maxprot; - vn_a.cred = cr; - vn_a.amp = NULL; - vn_a.flags = flags & ~MAP_TYPE; - vn_a.szc = 0; - vn_a.lgrp_mem_policy_flags = 0; - - error = as_map(as, *addrp, len, segvn_create, &vn_a); - - as_rangeunlock(as); - ZFS_EXIT(zfsvfs); - return (error); -} - -/* ARGSUSED */ -static int -zfs_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, - size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, cred_t *cr) -{ - uint64_t pages = btopr(len); - - atomic_add_64(&VTOZ(vp)->z_mapcnt, pages); - return (0); -} - -/* - * The reason we push dirty pages as part of zfs_delmap() is so that we get a - * more accurate mtime for the associated file. Since we don't have a way of - * detecting when the data was actually modified, we have to resort to - * heuristics. If an explicit msync() is done, then we mark the mtime when the - * last page is pushed. The problem occurs when the msync() call is omitted, - * which by far the most common case: - * - * open() - * mmap() - * - * munmap() - * close() - *