]> err.no Git - linux-2.6/blobdiff - fs/xfs/xfs_inode.c
[XFS] move linux/log2.h header to xfs_linux.h
[linux-2.6] / fs / xfs / xfs_inode.c
index 8fdd30d9ba56424791be59bafc804844ffa6d95c..bc9e7c8918091690b407c3d08dc1293c18c0e2fe 100644 (file)
@@ -48,8 +48,7 @@
 #include "xfs_dir2_trace.h"
 #include "xfs_quota.h"
 #include "xfs_acl.h"
-
-#include <linux/log2.h>
+#include "xfs_filestream.h"
 
 kmem_zone_t *xfs_ifork_zone;
 kmem_zone_t *xfs_inode_zone;
@@ -66,7 +65,6 @@ STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int);
 STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int);
 STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int);
 
-
 #ifdef DEBUG
 /*
  * Make sure that the extents in the given memory buffer
@@ -76,28 +74,23 @@ STATIC void
 xfs_validate_extents(
        xfs_ifork_t             *ifp,
        int                     nrecs,
-       int                     disk,
        xfs_exntfmt_t           fmt)
 {
-       xfs_bmbt_rec_t          *ep;
        xfs_bmbt_irec_t         irec;
-       xfs_bmbt_rec_t          rec;
+       xfs_bmbt_rec_host_t     rec;
        int                     i;
 
        for (i = 0; i < nrecs; i++) {
-               ep = xfs_iext_get_ext(ifp, i);
-               rec.l0 = get_unaligned((__uint64_t*)&ep->l0);
-               rec.l1 = get_unaligned((__uint64_t*)&ep->l1);
-               if (disk)
-                       xfs_bmbt_disk_get_all(&rec, &irec);
-               else
-                       xfs_bmbt_get_all(&rec, &irec);
+               xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
+               rec.l0 = get_unaligned(&ep->l0);
+               rec.l1 = get_unaligned(&ep->l1);
+               xfs_bmbt_get_all(&rec, &irec);
                if (fmt == XFS_EXTFMT_NOSTATE)
                        ASSERT(irec.br_state == XFS_EXT_NORM);
        }
 }
 #else /* DEBUG */
-#define xfs_validate_extents(ifp, nrecs, disk, fmt)
+#define xfs_validate_extents(ifp, nrecs, fmt)
 #endif /* DEBUG */
 
 /*
@@ -601,7 +594,7 @@ xfs_iformat_extents(
        xfs_dinode_t    *dip,
        int             whichfork)
 {
-       xfs_bmbt_rec_t  *ep, *dp;
+       xfs_bmbt_rec_t  *dp;
        xfs_ifork_t     *ifp;
        int             nex;
        int             size;
@@ -636,16 +629,13 @@ xfs_iformat_extents(
        ifp->if_bytes = size;
        if (size) {
                dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
-               xfs_validate_extents(ifp, nex, 1, XFS_EXTFMT_INODE(ip));
+               xfs_validate_extents(ifp, nex, XFS_EXTFMT_INODE(ip));
                for (i = 0; i < nex; i++, dp++) {
-                       ep = xfs_iext_get_ext(ifp, i);
-                       ep->l0 = INT_GET(get_unaligned((__uint64_t*)&dp->l0),
-                                                               ARCH_CONVERT);
-                       ep->l1 = INT_GET(get_unaligned((__uint64_t*)&dp->l1),
-                                                               ARCH_CONVERT);
+                       xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
+                       ep->l0 = be64_to_cpu(get_unaligned(&dp->l0));
+                       ep->l1 = be64_to_cpu(get_unaligned(&dp->l1));
                }
-               xfs_bmap_trace_exlist("xfs_iformat_extents", ip, nex,
-                       whichfork);
+               XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork);
                if (whichfork != XFS_DATA_FORK ||
                        XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE)
                                if (unlikely(xfs_check_nostate_extents(
@@ -818,6 +808,8 @@ _xfs_dic2xflags(
                        flags |= XFS_XFLAG_EXTSZINHERIT;
                if (di_flags & XFS_DIFLAG_NODEFRAG)
                        flags |= XFS_XFLAG_NODEFRAG;
+               if (di_flags & XFS_DIFLAG_FILESTREAM)
+                       flags |= XFS_XFLAG_FILESTREAM;
        }
 
        return flags;
@@ -1046,7 +1038,7 @@ xfs_iread_extents(
                ifp->if_flags &= ~XFS_IFEXTENTS;
                return error;
        }
-       xfs_validate_extents(ifp, nextents, 0, XFS_EXTFMT_INODE(ip));
+       xfs_validate_extents(ifp, nextents, XFS_EXTFMT_INODE(ip));
        return 0;
 }
 
@@ -1075,6 +1067,11 @@ xfs_iread_extents(
  * also returns the [locked] bp pointing to the head of the freelist
  * as ialloc_context.  The caller should hold this buffer across
  * the commit and pass it back into this routine on the second call.
+ *
+ * If we are allocating quota inodes, we do not have a parent inode
+ * to attach to or associate with (i.e. pip == NULL) because they
+ * are not linked into the directory structure - they are attached
+ * directly to the superblock - and so have no parent.
  */
 int
 xfs_ialloc(
@@ -1100,7 +1097,7 @@ xfs_ialloc(
         * Call the space management code to pick
         * the on-disk inode to be allocated.
         */
-       error = xfs_dialloc(tp, pip->i_ino, mode, okalloc,
+       error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc,
                            ialloc_context, call_again, &ino);
        if (error != 0) {
                return error;
@@ -1151,10 +1148,10 @@ xfs_ialloc(
        /*
         * Project ids won't be stored on disk if we are using a version 1 inode.
         */
-       if ( (prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
+       if ((prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
                xfs_bump_ino_vers2(tp, ip);
 
-       if (XFS_INHERIT_GID(pip, vp->v_vfsp)) {
+       if (pip && XFS_INHERIT_GID(pip, vp->v_vfsp)) {
                ip->i_d.di_gid = pip->i_d.di_gid;
                if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
                        ip->i_d.di_mode |= S_ISGID;
@@ -1196,8 +1193,16 @@ xfs_ialloc(
                flags |= XFS_ILOG_DEV;
                break;
        case S_IFREG:
+               if (pip && xfs_inode_is_filestream(pip)) {
+                       error = xfs_filestream_associate(pip, ip);
+                       if (error < 0)
+                               return -error;
+                       if (!error)
+                               xfs_iflags_set(ip, XFS_IFILESTREAM);
+               }
+               /* fall through */
        case S_IFDIR:
-               if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
+               if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
                        uint    di_flags = 0;
 
                        if ((mode & S_IFMT) == S_IFDIR) {
@@ -1234,6 +1239,8 @@ xfs_ialloc(
                        if ((pip->i_d.di_flags & XFS_DIFLAG_NODEFRAG) &&
                            xfs_inherit_nodefrag)
                                di_flags |= XFS_DIFLAG_NODEFRAG;
+                       if (pip->i_d.di_flags & XFS_DIFLAG_FILESTREAM)
+                               di_flags |= XFS_DIFLAG_FILESTREAM;
                        ip->i_d.di_flags |= di_flags;
                }
                /* FALLTHROUGH */
@@ -2870,15 +2877,10 @@ xfs_iunpin_wait(
 int
 xfs_iextents_copy(
        xfs_inode_t             *ip,
-       xfs_bmbt_rec_t          *buffer,
+       xfs_bmbt_rec_t          *dp,
        int                     whichfork)
 {
        int                     copied;
-       xfs_bmbt_rec_t          *dest_ep;
-       xfs_bmbt_rec_t          *ep;
-#ifdef XFS_BMAP_TRACE
-       static char             fname[] = "xfs_iextents_copy";
-#endif
        int                     i;
        xfs_ifork_t             *ifp;
        int                     nrecs;
@@ -2889,7 +2891,7 @@ xfs_iextents_copy(
        ASSERT(ifp->if_bytes > 0);
 
        nrecs = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
-       xfs_bmap_trace_exlist(fname, ip, nrecs, whichfork);
+       XFS_BMAP_TRACE_EXLIST(ip, nrecs, whichfork);
        ASSERT(nrecs > 0);
 
        /*
@@ -2898,10 +2900,9 @@ xfs_iextents_copy(
         * the delayed ones.  There must be at least one
         * non-delayed extent.
         */
-       dest_ep = buffer;
        copied = 0;
        for (i = 0; i < nrecs; i++) {
-               ep = xfs_iext_get_ext(ifp, i);
+               xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
                start_block = xfs_bmbt_get_startblock(ep);
                if (ISNULLSTARTBLOCK(start_block)) {
                        /*
@@ -2911,15 +2912,13 @@ xfs_iextents_copy(
                }
 
                /* Translate to on disk format */
-               put_unaligned(INT_GET(ep->l0, ARCH_CONVERT),
-                             (__uint64_t*)&dest_ep->l0);
-               put_unaligned(INT_GET(ep->l1, ARCH_CONVERT),
-                             (__uint64_t*)&dest_ep->l1);
-               dest_ep++;
+               put_unaligned(cpu_to_be64(ep->l0), &dp->l0);
+               put_unaligned(cpu_to_be64(ep->l1), &dp->l1);
+               dp++;
                copied++;
        }
        ASSERT(copied != 0);
-       xfs_validate_extents(ifp, copied, 1, XFS_EXTFMT_INODE(ip));
+       xfs_validate_extents(ifp, copied, XFS_EXTFMT_INODE(ip));
 
        return (copied * (uint)sizeof(xfs_bmbt_rec_t));
 }
@@ -3697,7 +3696,7 @@ xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra)
 /*
  * Return a pointer to the extent record at file index idx.
  */
-xfs_bmbt_rec_t *
+xfs_bmbt_rec_host_t *
 xfs_iext_get_ext(
        xfs_ifork_t     *ifp,           /* inode fork pointer */
        xfs_extnum_t    idx)            /* index of target extent */
@@ -3730,15 +3729,12 @@ xfs_iext_insert(
        xfs_extnum_t    count,          /* number of inserted items */
        xfs_bmbt_irec_t *new)           /* items to insert */
 {
-       xfs_bmbt_rec_t  *ep;            /* extent record pointer */
        xfs_extnum_t    i;              /* extent record index */
 
        ASSERT(ifp->if_flags & XFS_IFEXTENTS);
        xfs_iext_add(ifp, idx, count);
-       for (i = idx; i < idx + count; i++, new++) {
-               ep = xfs_iext_get_ext(ifp, i);
-               xfs_bmbt_set_all(ep, new);
-       }
+       for (i = idx; i < idx + count; i++, new++)
+               xfs_bmbt_set_all(xfs_iext_get_ext(ifp, i), new);
 }
 
 /*
@@ -4189,7 +4185,7 @@ xfs_iext_realloc_direct(
                        rnew_size = xfs_iroundup(new_size);
                }
                if (rnew_size != ifp->if_real_bytes) {
-                       ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
+                       ifp->if_u1.if_extents =
                                kmem_realloc(ifp->if_u1.if_extents,
                                                rnew_size,
                                                ifp->if_real_bytes,
@@ -4252,8 +4248,7 @@ xfs_iext_inline_to_direct(
        xfs_ifork_t     *ifp,           /* inode fork pointer */
        int             new_size)       /* number of extents in file */
 {
-       ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
-               kmem_alloc(new_size, KM_SLEEP);
+       ifp->if_u1.if_extents = kmem_alloc(new_size, KM_SLEEP);
        memset(ifp->if_u1.if_extents, 0, new_size);
        if (ifp->if_bytes) {
                memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext,
@@ -4296,7 +4291,7 @@ void
 xfs_iext_indirect_to_direct(
         xfs_ifork_t    *ifp)           /* inode fork pointer */
 {
-       xfs_bmbt_rec_t  *ep;            /* extent record pointer */
+       xfs_bmbt_rec_host_t *ep;        /* extent record pointer */
        xfs_extnum_t    nextents;       /* number of extents in file */
        int             size;           /* size of file extents */
 
@@ -4348,15 +4343,15 @@ xfs_iext_destroy(
 /*
  * Return a pointer to the extent record for file system block bno.
  */
-xfs_bmbt_rec_t *                       /* pointer to found extent record */
+xfs_bmbt_rec_host_t *                  /* pointer to found extent record */
 xfs_iext_bno_to_ext(
        xfs_ifork_t     *ifp,           /* inode fork pointer */
        xfs_fileoff_t   bno,            /* block number to search for */
        xfs_extnum_t    *idxp)          /* index of target extent */
 {
-       xfs_bmbt_rec_t  *base;          /* pointer to first extent */
+       xfs_bmbt_rec_host_t *base;      /* pointer to first extent */
        xfs_filblks_t   blockcount = 0; /* number of blocks in extent */
-       xfs_bmbt_rec_t  *ep = NULL;     /* pointer to target extent */
+       xfs_bmbt_rec_host_t *ep = NULL; /* pointer to target extent */
        xfs_ext_irec_t  *erp = NULL;    /* indirection array pointer */
        int             high;           /* upper boundary in search */
        xfs_extnum_t    idx = 0;        /* index of target extent */
@@ -4531,8 +4526,7 @@ xfs_iext_irec_init(
                kmem_alloc(sizeof(xfs_ext_irec_t), KM_SLEEP);
 
        if (nextents == 0) {
-               ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
-                       kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
+               ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
        } else if (!ifp->if_real_bytes) {
                xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ);
        } else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) {
@@ -4580,8 +4574,7 @@ xfs_iext_irec_new(
 
        /* Initialize new extent record */
        erp = ifp->if_u1.if_ext_irec;
-       erp[erp_idx].er_extbuf = (xfs_bmbt_rec_t *)
-               kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
+       erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
        ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ;
        memset(erp[erp_idx].er_extbuf, 0, XFS_IEXT_BUFSZ);
        erp[erp_idx].er_extcount = 0;
@@ -4713,7 +4706,7 @@ void
 xfs_iext_irec_compact_full(
        xfs_ifork_t     *ifp)                   /* inode fork pointer */
 {
-       xfs_bmbt_rec_t  *ep, *ep_next;          /* extent record pointers */
+       xfs_bmbt_rec_host_t *ep, *ep_next;      /* extent record pointers */
        xfs_ext_irec_t  *erp, *erp_next;        /* extent irec pointers */
        int             erp_idx = 0;            /* extent irec index */
        int             ext_avail;              /* empty entries in ex list */