Diff for /xfs-linux/dmapi/xfs_dm.c between versions 1.37 and 1.38

version 1.37, 2007/06/08 16:06:22 version 1.38, 2007/07/06 04:02:21
Line 2540  xfs_dm_mkdir_by_handle( Line 2540  xfs_dm_mkdir_by_handle(
 }  }
   
   
   /*
    * Probe and Punch
    *
    * Hole punching alignment is based on the underlying device base
    * allocation size or PAGE_CACHE_SIZE. Because it is not defined
    * in the DMAPI spec, we can align how we choose here. Round
    * inwards (offset up and length down) to the block, extent or
    * page size whichever is bigger. Our DMAPI implementation rounds
    * the hole geometry strictly inwards. If this is not possible,
    * return EINVAL for both for xfs_dm_probe_hole and xfs_dm_punch_hole
    * which differs from the DMAPI spec.
    * Note that length = 0 is special - it means "punch to EOF"
    * and at that point we treat the punch as remove everything
    * past offset (including preallocation past EOF).
    */
   
   STATIC int
   xfs_dm_round_hole(
           dm_off_t        offset,
           dm_size_t       length,
           dm_size_t       align,
           xfs_fsize_t     filesize,
           dm_off_t        *roff,
           dm_size_t       *rlen)
   {
   
           dm_off_t        off = offset;
           dm_size_t       len = length;
   
           /* Try to round offset up to the nearest boundary */
           *roff = roundup_64(off, align);
           if ((*roff >= filesize) || (len && (len < align)))
                   return -EINVAL;
   
           if ((len == 0) || ((off + len) == filesize)) {
                   /* punch to EOF */
                   *rlen = 0;
           } else {
                   /* Round length down to the nearest boundary. */
                   ASSERT(len >= align);
                   ASSERT(align > (*roff - off));
                   len -= *roff - off;
                   *rlen = len - do_mod(len, align);
                   if (*rlen == 0)
                           return -EINVAL; /* requested length is too small */
           }
   #ifdef CONFIG_DMAPI_DEBUG
           printk("xfs_dm_round_hole: off %lu, len %ld, align %lu, "
                  "filesize %llu, roff %ld, rlen %ld\n",
                  offset, length, align, filesize, *roff, *rlen);
   #endif
           return 0; /* hole geometry successfully rounded */
   }
   
 /* ARGSUSED */  /* ARGSUSED */
 STATIC int  STATIC int
 xfs_dm_probe_hole(  xfs_dm_probe_hole(
         struct inode    *inode,          struct inode    *inode,
         dm_right_t      right,          dm_right_t      right,
         dm_off_t        off,          dm_off_t        off,
         dm_size_t       len,            /* we ignore this for now */          dm_size_t       len,
         dm_off_t        __user  *roffp,          dm_off_t        __user  *roffp,
         dm_size_t       __user *rlenp)          dm_size_t       __user *rlenp)
 {  {
Line 2556  xfs_dm_probe_hole( Line 2610  xfs_dm_probe_hole(
         xfs_mount_t     *mp;          xfs_mount_t     *mp;
         uint            lock_flags;          uint            lock_flags;
         xfs_fsize_t     realsize;          xfs_fsize_t     realsize;
         u_int           bsize;          dm_size_t       align;
         bhv_vnode_t     *vp = vn_from_inode(inode);          bhv_vnode_t     *vp = vn_from_inode(inode);
           int             error;
   
         /* Returns negative errors to DMAPI */          /* Returns negative errors to DMAPI */
   
         if (right < DM_RIGHT_SHARED)          if (right < DM_RIGHT_SHARED)
                 return(-EACCES);                  return -EACCES;
   
         ip = xfs_vtoi(vp);          ip = xfs_vtoi(vp);
         if ((ip->i_d.di_mode & S_IFMT) != S_IFREG)          if ((ip->i_d.di_mode & S_IFMT) != S_IFREG)
                 return(-EINVAL);                  return -EINVAL;
   
         mp = ip->i_mount;          mp = ip->i_mount;
         bsize = mp->m_sb.sb_blocksize;  
   
         lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;          lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
         xfs_ilock(ip, lock_flags);          xfs_ilock(ip, lock_flags);
         realsize = ip->i_size;          realsize = ip->i_size;
         xfs_iunlock(ip, lock_flags);          xfs_iunlock(ip, lock_flags);
         if (off >= realsize)  
                 return(-E2BIG);  
   
         roff = (off + bsize-1) & ~(bsize-1);          if ((off + len) > realsize)
         rlen = 0;               /* Only support punches to EOF for now */                  return -E2BIG;
   
           align = xfs_get_extsz_hint(ip);
           if (align == 0)
                   align = 1;
           align <<= mp->m_sb.sb_blocklog;
           align = MAX(align, PAGE_CACHE_SIZE);
   
           error = xfs_dm_round_hole(off, len, align, realsize, &roff, &rlen);
           if (error)
                   return error;
   
         if (copy_to_user( roffp, &roff, sizeof(roff)))          if (copy_to_user( roffp, &roff, sizeof(roff)))
                 return(-EFAULT);                  return -EFAULT;
         if (copy_to_user( rlenp, &rlen, sizeof(rlen)))          if (copy_to_user( rlenp, &rlen, sizeof(rlen)))
                 return(-EFAULT);                  return -EFAULT;
         return(0);          return(0);
 }  }
   
Line 2598  xfs_dm_punch_hole( Line 2660  xfs_dm_punch_hole(
         xfs_flock64_t   bf;          xfs_flock64_t   bf;
         int             error = 0;          int             error = 0;
         bhv_desc_t      *xbdp;          bhv_desc_t      *xbdp;
         xfs_inode_t     *xip;          xfs_inode_t     *ip;
         xfs_mount_t     *mp;          xfs_mount_t     *mp;
         u_int           bsize;          dm_size_t       align;
         xfs_fsize_t     realsize;          xfs_fsize_t     realsize;
         bhv_vnode_t     *vp = vn_from_inode(inode);          bhv_vnode_t     *vp = vn_from_inode(inode);
         int             punch_to_eof = 0;          dm_off_t        roff;
           dm_size_t       rlen;
   
         /* Returns negative errors to DMAPI */          /* Returns negative errors to DMAPI */
   
Line 2623  xfs_dm_punch_hole( Line 2686  xfs_dm_punch_hole(
                         VNODE_POSITION_XFS, VNODE_POSITION_XFS);                          VNODE_POSITION_XFS, VNODE_POSITION_XFS);
         ASSERT(xbdp);          ASSERT(xbdp);
   
         xip = xfs_vtoi(vp);          ip = xfs_vtoi(vp);
         mp = xip->i_mount;          mp = ip->i_mount;
         bsize = mp->m_sb.sb_blocksize;  
         if (off & (bsize-1)) {  
                 error = -EAGAIN;  
                 goto put_and_out;  
         }  
         if (len & (bsize-1)) {  
                 error = -EAGAIN;  
                 goto put_and_out;  
         }  
   
         down_rw_sems(inode, DM_SEM_FLAG_WR);          down_rw_sems(inode, DM_SEM_FLAG_WR);
   
         xfs_ilock(xip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);          xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
         realsize = xip->i_size;          realsize = ip->i_size;
           xfs_iunlock(ip, XFS_ILOCK_EXCL);
           align = xfs_get_extsz_hint(ip);
           if (align == 0)
                   align = 1;
   
         if ((off >= realsize) || ((off + len) > realsize)) {          align <<= mp->m_sb.sb_blocklog;
                 xfs_iunlock(xip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);          align = MAX(align, PAGE_CACHE_SIZE);
   
           if ((off + len) > realsize) {
                   xfs_iunlock(ip, XFS_IOLOCK_EXCL);
                 error = -E2BIG;                  error = -E2BIG;
                 goto up_and_out;                  goto up_and_out;
         }          }
         if (len == 0)  
                 punch_to_eof = 1;  
   
         /*          if ((off + len) == realsize)
          * When we are punching to EOF, we have to make sure we punch the                  len = 0;
          * last partial block that contains EOF. Round up the length to  
          * make sure we punch the block and not just zero it.  
          */  
         if (punch_to_eof)  
                 len = roundup_64((realsize - off), bsize);  
   
         xfs_iunlock(xip, XFS_ILOCK_EXCL);          error = xfs_dm_round_hole(off, len, align, realsize, &roff, &rlen);
           if (error || (off != roff) || (len != rlen)) {
                   xfs_iunlock(ip, XFS_IOLOCK_EXCL);
                   error = -EINVAL;
                   goto up_and_out;
           }
   
         bf.l_type = 0;          bf.l_type = 0;
         bf.l_whence = 0;          bf.l_whence = 0;
         bf.l_start = (xfs_off_t)off;          bf.l_start = (xfs_off_t)off;
         bf.l_len = (xfs_off_t)len;          if (len) {
                   bf.l_len = len;
           }
           else {
                   /*
                    * When we are punching to EOF, we have to make sure we punch
                    * the last partial block that contains EOF. Round up
                    * the length to make sure we punch the block and not just
                    * zero it.
                    */
                   bf.l_len = roundup_64((realsize - off), mp->m_sb.sb_blocksize);
           }
   
   #ifdef CONFIG_DMAPI_DEBUG
           printk("xfs_dm_punch_hole: off %lu, len %ld, align %lu\n",
                   off, len, align);
   #endif
   
         error = xfs_change_file_space(xbdp, XFS_IOC_UNRESVSP, &bf,          error = xfs_change_file_space(xbdp, XFS_IOC_UNRESVSP, &bf,
                                 (xfs_off_t)off, sys_cred, ATTR_DMI|ATTR_NOLOCK);                                  (xfs_off_t)off, sys_cred, ATTR_DMI|ATTR_NOLOCK);
Line 2671  xfs_dm_punch_hole( Line 2746  xfs_dm_punch_hole(
          * may have been (speculatively) preallocated. No point in           * may have been (speculatively) preallocated. No point in
          * leaving them around if we are migrating the file....           * leaving them around if we are migrating the file....
          */           */
         if (!error && punch_to_eof) {          if (!error && (len == 0)) {
                 error = xfs_free_eofblocks(mp, xip, XFS_FREE_EOF_NOLOCK);                  error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_NOLOCK);
                 if (!error) {                  if (!error) {
                         /* Update linux inode block count after free above */                          /* Update linux inode block count after free above */
                         inode->i_blocks = XFS_FSB_TO_BB(mp,                          inode->i_blocks = XFS_FSB_TO_BB(mp,
                                 xip->i_d.di_nblocks + xip->i_delayed_blks);                                  ip->i_d.di_nblocks + ip->i_delayed_blks);
                 }                  }
         }          }
   
         /* Let threads in send_data_event know we punched the file. */          /* Let threads in send_data_event know we punched the file. */
         xip->i_iocore.io_dmstate++;          ip->i_iocore.io_dmstate++;
         xfs_iunlock(xip, XFS_IOLOCK_EXCL);          xfs_iunlock(ip, XFS_IOLOCK_EXCL);
         VMODIFY(vp);          VMODIFY(vp);
   
 up_and_out:  up_and_out:
         up_rw_sems(inode, DM_SEM_FLAG_WR);          up_rw_sems(inode, DM_SEM_FLAG_WR);
   
 put_and_out:  
         put_write_access(inode);          put_write_access(inode);
   
         return error;          return error;

Removed from v.1.37  
changed lines
  Added in v.1.38


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>