/* * Reclaim an inode so that it can be used for other purposes. */ int ufs_reclaim(struct vnode *vp, struct proc *p) { struct inode *ip; #ifdef DIAGNOSTIC extern int prtactive; if (prtactive && vp->v_usecount != 0) vprint("ufs_reclaim: pushing active", vp); #endif /* * Remove the inode from its hash chain. */ ip = VTOI(vp); ufs_ihashrem(ip); /* * Purge old data structures associated with the inode. */ cache_purge(vp); if (ip->i_devvp) { vrele(ip->i_devvp); } #ifdef UFS_DIRHASH if (ip->i_dirhash != NULL) ufsdirhash_free(ip); #endif ufs_quota_delete(ip); return (0); }
/* * Reclaim an inode so that it can be used for other purposes. */ int ufs_reclaim(struct vnode *vp, struct proc *p) { struct inode *ip; #ifdef DIAGNOSTIC extern int prtactive; if (prtactive && vp->v_usecount != 0) vprint("ufs_reclaim: pushing active", vp); #endif ip = VTOI(vp); /* * Stop deferring timestamp writes */ if (ip->i_flag & IN_LAZYMOD) { int err = UFS_WAPBL_BEGIN(vp->v_mount); if (err) return (err); ip->i_flag |= IN_MODIFIED; UFS_UPDATE(ip, 0); UFS_WAPBL_END(vp->v_mount); } /* * Remove the inode from its hash chain. */ ufs_ihashrem(ip); /* * Purge old data structures associated with the inode. */ cache_purge(vp); if (ip->i_devvp) { vrele(ip->i_devvp); } #ifdef UFS_DIRHASH if (ip->i_dirhash != NULL) ufsdirhash_free(ip); #endif ufs_quota_delete(ip); return (0); }
/* * Perform chown operation on inode ip; * inode must be locked prior to call. */ int ufs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred, struct proc *p) { struct inode *ip = VTOI(vp); uid_t ouid; gid_t ogid; int error = 0; daddr64_t change; enum ufs_quota_flags quota_flags = 0; if (uid == (uid_t)VNOVAL) uid = DIP(ip, uid); if (gid == (gid_t)VNOVAL) gid = DIP(ip, gid); /* * If we don't own the file, are trying to change the owner * of the file, or are not a member of the target group, * the caller must be superuser or the call fails. */ if ((cred->cr_uid != DIP(ip, uid) || uid != DIP(ip, uid) || (gid != DIP(ip, gid) && !groupmember((gid_t)gid, cred))) && (error = suser_ucred(cred))) return (error); ogid = DIP(ip, gid); ouid = DIP(ip, uid); change = DIP(ip, blocks); if (ouid == uid) quota_flags |= UFS_QUOTA_NOUID; if (ogid == gid) quota_flags |= UFS_QUOTA_NOGID; if ((error = getinoquota(ip)) != 0) return (error); (void) ufs_quota_free_blocks2(ip, change, cred, quota_flags); (void) ufs_quota_free_inode2(ip, cred, quota_flags); (void) ufs_quota_delete(ip); DIP_ASSIGN(ip, gid, gid); DIP_ASSIGN(ip, uid, uid); if ((error = getinoquota(ip)) != 0) goto error; if ((error = ufs_quota_alloc_blocks2(ip, change, cred, quota_flags)) != 0) goto error; if ((error = ufs_quota_alloc_inode2(ip, cred , quota_flags)) != 0) { (void)ufs_quota_free_blocks2(ip, change, cred, quota_flags); goto error; } if (getinoquota(ip)) panic("chown: lost quota"); if (ouid != uid || ogid != gid) ip->i_flag |= IN_CHANGE; if (ouid != uid && cred->cr_uid != 0) DIP_AND(ip, mode, ~ISUID); if (ogid != gid && cred->cr_uid != 0) DIP_AND(ip, mode, ~ISGID); return (0); error: (void) ufs_quota_delete(ip); DIP_ASSIGN(ip, gid, ogid); DIP_ASSIGN(ip, uid, ouid); if (getinoquota(ip) == 0) { (void) ufs_quota_alloc_blocks2(ip, change, cred, quota_flags | UFS_QUOTA_FORCE); (void) ufs_quota_alloc_inode2(ip, cred, quota_flags | UFS_QUOTA_FORCE); (void) getinoquota(ip); } return (error); }