static void hpfs_write_failed(struct address_space *mapping, loff_t to) { struct inode *inode = mapping->host; if (to > inode->i_size) { truncate_pagecache(inode, to, inode->i_size); hpfs_truncate(inode); } }
int hpfs_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = d_inode(dentry); int error = -EINVAL; hpfs_lock(inode->i_sb); if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root) goto out_unlock; if ((attr->ia_valid & ATTR_UID) && from_kuid(&init_user_ns, attr->ia_uid) >= 0x10000) goto out_unlock; if ((attr->ia_valid & ATTR_GID) && from_kgid(&init_user_ns, attr->ia_gid) >= 0x10000) goto out_unlock; if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) goto out_unlock; error = inode_change_ok(inode, attr); if (error) goto out_unlock; if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size != i_size_read(inode)) { error = inode_newsize_ok(inode, attr->ia_size); if (error) goto out_unlock; truncate_setsize(inode, attr->ia_size); hpfs_truncate(inode); } setattr_copy(inode, attr); hpfs_write_inode(inode); out_unlock: hpfs_unlock(inode->i_sb); return error; }
/* * XXXXX do we need hpfsnode locking inside? * * hpfs_setattr(struct vnode *a_vp, struct vattr *a_vap, struct ucred *a_cred) */ static int hpfs_setattr(struct vop_setattr_args *ap) { struct vnode *vp = ap->a_vp; struct hpfsnode *hp = VTOHP(vp); struct vattr *vap = ap->a_vap; struct ucred *cred = ap->a_cred; int error; dprintf(("hpfs_setattr(0x%x):\n", hp->h_no)); /* * Check for unsettable attributes. */ if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || (vap->va_blocksize != VNOVAL) || (vap->va_rmajor != VNOVAL) || (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { dprintf(("hpfs_setattr: changing nonsettable attr\n")); return (EINVAL); } /* Can't change flags XXX Could be implemented */ if (vap->va_flags != VNOVAL) { kprintf("hpfs_setattr: FLAGS CANNOT BE SET\n"); return (EINVAL); } /* Can't change uid/gid XXX Could be implemented */ if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { kprintf("hpfs_setattr: UID/GID CANNOT BE SET\n"); return (EINVAL); } /* Can't change mode XXX Could be implemented */ if (vap->va_mode != (mode_t)VNOVAL) { kprintf("hpfs_setattr: MODE CANNOT BE SET\n"); return (EINVAL); } /* Update times */ if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != hp->h_uid && (error = priv_check_cred(cred, PRIV_VFS_SETATTR, 0)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_EACCESS(vp, VWRITE, cred)))) return (error); if (vap->va_atime.tv_sec != VNOVAL) hp->h_atime = vap->va_atime.tv_sec; if (vap->va_mtime.tv_sec != VNOVAL) hp->h_mtime = vap->va_mtime.tv_sec; hp->h_flag |= H_PARCHANGE; } if (vap->va_size != VNOVAL) { switch (vp->v_type) { case VDIR: return (EISDIR); case VREG: if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); break; default: kprintf("hpfs_setattr: WRONG v_type\n"); return (EINVAL); } if (vap->va_size < hp->h_fn.fn_size) { #if defined(__DragonFly__) error = vtruncbuf(vp, vap->va_size, DEV_BSIZE); if (error) return (error); #else /* defined(__NetBSD__) */ #error Need alternation for vtruncbuf() #endif error = hpfs_truncate(hp, vap->va_size); if (error) return (error); } else if (vap->va_size > hp->h_fn.fn_size) { #if defined(__DragonFly__) vnode_pager_setsize(vp, vap->va_size); #endif error = hpfs_extend(hp, vap->va_size); if (error) return (error); } } return (0); }