FreeBSD/sys/ufs/ufs/ufs_extattr.c
/*
 * Real work associated with removing an extended attribute from a vnode.
 * Assumes the attribute lock has already been grabbed.
 */
Real work associated with removing an extended attribute from a vnode.
Assumes the attribute lock has already been grabbed.
Real work associated with removing an extended attribute from a vnode . Assumes the attribute lock has already been grabbed .
static int
ufs_extattr_rm(struct vnode *vp, int attrnamespace, const char *name,
    struct ucred *cred, struct thread *td)
{
	struct ufs_extattr_list_entry *attribute;
	struct ufs_extattr_header ueh;
	struct iovec local_aiov;
	struct uio local_aio;
	struct mount *mp = vp->v_mount;
	struct ufsmount *ump = VFSTOUFS(mp);
	struct inode *ip = VTOI(vp);
	off_t base_offset;
	int error = 0, ioflag;
	if (vp->v_mount->mnt_flag & MNT_RDONLY)  
		return (EROFS);
	if (!(ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED))
		return (EOPNOTSUPP);
	if (!ufs_extattr_valid_attrname(attrnamespace, name))
		return (EINVAL);
	error = extattr_check_cred(vp, attrnamespace, cred, td, VWRITE);
	if (error)
		return (error);
	attribute = ufs_extattr_find_attr(ump, attrnamespace, name);
	if (!attribute)
		return (ENOATTR);
	base_offset = sizeof(struct ufs_extattr_fileheader) +
	    ip->i_number * (sizeof(struct ufs_extattr_header) +
	    attribute->uele_fileheader.uef_size);
	bzero(&ueh, sizeof(struct ufs_extattr_header));
	local_aiov.iov_base = (caddr_t) &ueh;
	local_aiov.iov_len = sizeof(struct ufs_extattr_header);
	local_aio.uio_iov = &local_aiov;
	local_aio.uio_iovcnt = 1;
	local_aio.uio_rw = UIO_READ;
	local_aio.uio_segflg = UIO_SYSSPACE;
	local_aio.uio_td = td;
	local_aio.uio_offset = base_offset;
	local_aio.uio_resid = sizeof(struct ufs_extattr_header);
	if (attribute->uele_backing_vnode != vp)
		vn_lock(attribute->uele_backing_vnode, LK_EXCLUSIVE | LK_RETRY);
	error = VOP_READ(attribute->uele_backing_vnode, &local_aio,
	    IO_NODELOCKED, ump->um_extattr.uepm_ucred);
	if (error)
		goto vopunlock_exit;
	if ((ueh.ueh_flags & UFS_EXTATTR_ATTR_FLAG_INUSE) == 0) {
		error = ENOATTR;
		goto vopunlock_exit;
	}
	if (ueh.ueh_i_gen != ip->i_gen) {
		printf("ufs_extattr_rm (%s): inode number inconsistency (%d, %jd)\n",
		    mp->mnt_stat.f_mntonname, ueh.ueh_i_gen, (intmax_t)ip->i_gen);
		error = ENOATTR;
		goto vopunlock_exit;
	}
	ueh.ueh_flags = 0;
	ueh.ueh_len = 0;
	local_aiov.iov_base = (caddr_t) &ueh;
	local_aiov.iov_len = sizeof(struct ufs_extattr_header);
	local_aio.uio_iov = &local_aiov;
	local_aio.uio_iovcnt = 1;
	local_aio.uio_rw = UIO_WRITE;
	local_aio.uio_segflg = UIO_SYSSPACE;
	local_aio.uio_td = td;
	local_aio.uio_offset = base_offset;
	local_aio.uio_resid = sizeof(struct ufs_extattr_header);
	ioflag = IO_NODELOCKED;
	if (ufs_extattr_sync)
		ioflag |= IO_SYNC;
	error = VOP_WRITE(attribute->uele_backing_vnode, &local_aio, ioflag,
	    ump->um_extattr.uepm_ucred);
	if (error)
		goto vopunlock_exit;
	if (local_aio.uio_resid != 0)
		error = ENXIO;
vopunlock_exit:
	VOP_UNLOCK(attribute->uele_backing_vnode, 0);
	return (error);
}
static int ufs_extattr_rm ( struct vnode * vp , int attrnamespace , const char * name , struct ucred * cred , struct thread * td ) { struct ufs_extattr_list_entry * attribute ; struct ufs_extattr_header ueh ; struct iovec local_aiov ; struct uio local_aio ; struct mount * mp = vp -> v_mount ; struct ufsmount * ump = VFSTOUFS ( mp ) ; struct inode * ip = VTOI ( vp ) ; off_t base_offset ; int error = 0 , ioflag ; if ( vp -> v_mount -> mnt_flag & MNT_RDONLY ) return ( EROFS ) ; if ( ! ( ump -> um_extattr . uepm_flags & UFS_EXTATTR_UEPM_STARTED ) ) return ( EOPNOTSUPP ) ; if ( ! ufs_extattr_valid_attrname ( attrnamespace , name ) ) return ( EINVAL ) ; error = extattr_check_cred ( vp , attrnamespace , cred , td , VWRITE ) ; if ( error ) return ( error ) ; attribute = ufs_extattr_find_attr ( ump , attrnamespace , name ) ; if ( ! attribute ) return ( ENOATTR ) ; base_offset = sizeof ( struct ufs_extattr_fileheader ) + ip -> i_number * ( sizeof ( struct ufs_extattr_header ) + attribute -> uele_fileheader . uef_size ) ; bzero ( & ueh , sizeof ( struct ufs_extattr_header ) ) ; local_aiov . iov_base = ( caddr_t ) & ueh ; local_aiov . iov_len = sizeof ( struct ufs_extattr_header ) ; local_aio . uio_iov = & local_aiov ; local_aio . uio_iovcnt = 1 ; local_aio . uio_rw = UIO_READ ; local_aio . uio_segflg = UIO_SYSSPACE ; local_aio . uio_td = td ; local_aio . uio_offset = base_offset ; local_aio . uio_resid = sizeof ( struct ufs_extattr_header ) ; if ( attribute -> uele_backing_vnode != vp ) vn_lock ( attribute -> uele_backing_vnode , LK_EXCLUSIVE | LK_RETRY ) ; error = VOP_READ ( attribute -> uele_backing_vnode , & local_aio , IO_NODELOCKED , ump -> um_extattr . uepm_ucred ) ; if ( error ) goto vopunlock_exit ; if ( ( ueh . ueh_flags & UFS_EXTATTR_ATTR_FLAG_INUSE ) == 0 ) { error = ENOATTR ; goto vopunlock_exit ; } if ( ueh . ueh_i_gen != ip -> i_gen ) { printf ( " \n " , mp -> mnt_stat . f_mntonname , ueh . ueh_i_gen , ( intmax_t ) ip -> i_gen ) ; error = ENOATTR ; goto vopunlock_exit ; } ueh . ueh_flags = 0 ; ueh . ueh_len = 0 ; local_aiov . iov_base = ( caddr_t ) & ueh ; local_aiov . iov_len = sizeof ( struct ufs_extattr_header ) ; local_aio . uio_iov = & local_aiov ; local_aio . uio_iovcnt = 1 ; local_aio . uio_rw = UIO_WRITE ; local_aio . uio_segflg = UIO_SYSSPACE ; local_aio . uio_td = td ; local_aio . uio_offset = base_offset ; local_aio . uio_resid = sizeof ( struct ufs_extattr_header ) ; ioflag = IO_NODELOCKED ; if ( ufs_extattr_sync ) ioflag |= IO_SYNC ; error = VOP_WRITE ( attribute -> uele_backing_vnode , & local_aio , ioflag , ump -> um_extattr . uepm_ucred ) ; if ( error ) goto vopunlock_exit ; if ( local_aio . uio_resid != 0 ) error = ENXIO ; vopunlock_exit : VOP_UNLOCK ( attribute -> uele_backing_vnode , 0 ) ; return ( error ) ; }
Real work associated with removing an extended attribute from a vnode.
Real work associated with removing an extended attribute from a vnode .
/*
	 * Find base offset of header in file based on file header size, and
	 * data header size + maximum data size, indexed by inode number.
	 */ /*
	 * Check to see if currently defined.
	 */ /*
	 * Don't need to get the lock on the backing vnode if the vnode we're
	 * modifying is it, as we already hold the lock.
	 */ /* Defined? */ /* Valid for the current inode generation? */ /*
		 * The inode itself has a different generation number than
		 * the attribute data.  For now, the best solution is to
		 * coerce this to undefined, and let it get cleaned up by
		 * the next write or extattrctl clean.
		 */ /* Flag it as not in use. */