]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 10 Dec 2007 18:18:27 +0000 (10:18 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 10 Dec 2007 18:18:27 +0000 (10:18 -0800)
* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6:
  [XFS] Fix xfs_ichgtime()s broken usage of I_SYNC
  [XFS] Make xfsbufd threads freezable
  [XFS] revert to double-buffering readdir
  [XFS] Fix broken inode cluster setup.
  [XFS] Clear XBF_READ_AHEAD flag on I/O completion.
  [XFS] Fixed a few bugs in xfs_buf_associate_memory()
  [XFS] 971064 Various fixups for xfs_bulkstat().
  [XFS] Fix dbflush panic in xfs_qm_sync.

fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_ioctl32.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/quota/xfs_qm.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_itable.c

index b9c8589e05c2e937de37db78f1ea1f532c773f01..a49dd8d4b06974c9a9b8b20ca19bc0663dfe0471 100644 (file)
@@ -725,15 +725,15 @@ xfs_buf_associate_memory(
 {
        int                     rval;
        int                     i = 0;
-       size_t                  ptr;
-       size_t                  end, end_cur;
-       off_t                   offset;
+       unsigned long           pageaddr;
+       unsigned long           offset;
+       size_t                  buflen;
        int                     page_count;
 
-       page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT;
-       offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK);
-       if (offset && (len > PAGE_CACHE_SIZE))
-               page_count++;
+       pageaddr = (unsigned long)mem & PAGE_CACHE_MASK;
+       offset = (unsigned long)mem - pageaddr;
+       buflen = PAGE_CACHE_ALIGN(len + offset);
+       page_count = buflen >> PAGE_CACHE_SHIFT;
 
        /* Free any previous set of page pointers */
        if (bp->b_pages)
@@ -747,22 +747,15 @@ xfs_buf_associate_memory(
                return rval;
 
        bp->b_offset = offset;
-       ptr = (size_t) mem & PAGE_CACHE_MASK;
-       end = PAGE_CACHE_ALIGN((size_t) mem + len);
-       end_cur = end;
-       /* set up first page */
-       bp->b_pages[0] = mem_to_page(mem);
-
-       ptr += PAGE_CACHE_SIZE;
-       bp->b_page_count = ++i;
-       while (ptr < end) {
-               bp->b_pages[i] = mem_to_page((void *)ptr);
-               bp->b_page_count = ++i;
-               ptr += PAGE_CACHE_SIZE;
+
+       for (i = 0; i < bp->b_page_count; i++) {
+               bp->b_pages[i] = mem_to_page((void *)pageaddr);
+               pageaddr += PAGE_CACHE_SIZE;
        }
        bp->b_locked = 0;
 
-       bp->b_count_desired = bp->b_buffer_length = len;
+       bp->b_count_desired = len;
+       bp->b_buffer_length = buflen;
        bp->b_flags |= XBF_MAPPED;
 
        return 0;
@@ -1032,7 +1025,7 @@ xfs_buf_ioend(
        xfs_buf_t               *bp,
        int                     schedule)
 {
-       bp->b_flags &= ~(XBF_READ | XBF_WRITE);
+       bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD);
        if (bp->b_error == 0)
                bp->b_flags |= XBF_DONE;
 
@@ -1750,6 +1743,8 @@ xfsbufd(
 
        current->flags |= PF_MEMALLOC;
 
+       set_freezable();
+
        do {
                if (unlikely(freezing(current))) {
                        set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
index fb8dd34041eb1cfec27efb511c10b27613a95d42..54c564693d93d287fb030b6f44e945838b35b85f 100644 (file)
@@ -218,6 +218,15 @@ xfs_vm_fault(
 }
 #endif /* CONFIG_XFS_DMAPI */
 
+/*
+ * Unfortunately we can't just use the clean and simple readdir implementation
+ * below, because nfs might call back into ->lookup from the filldir callback
+ * and that will deadlock the low-level btree code.
+ *
+ * Hopefully we'll find a better workaround that allows to use the optimal
+ * version at least for local readdirs for 2.6.25.
+ */
+#if 0
 STATIC int
 xfs_file_readdir(
        struct file     *filp,
@@ -249,6 +258,121 @@ xfs_file_readdir(
                return -error;
        return 0;
 }
+#else
+
+struct hack_dirent {
+       int             namlen;
+       loff_t          offset;
+       u64             ino;
+       unsigned int    d_type;
+       char            name[];
+};
+
+struct hack_callback {
+       char            *dirent;
+       size_t          len;
+       size_t          used;
+};
+
+STATIC int
+xfs_hack_filldir(
+       void            *__buf,
+       const char      *name,
+       int             namlen,
+       loff_t          offset,
+       u64             ino,
+       unsigned int    d_type)
+{
+       struct hack_callback *buf = __buf;
+       struct hack_dirent *de = (struct hack_dirent *)(buf->dirent + buf->used);
+
+       if (buf->used + sizeof(struct hack_dirent) + namlen > buf->len)
+               return -EINVAL;
+
+       de->namlen = namlen;
+       de->offset = offset;
+       de->ino = ino;
+       de->d_type = d_type;
+       memcpy(de->name, name, namlen);
+       buf->used += sizeof(struct hack_dirent) + namlen;
+       return 0;
+}
+
+STATIC int
+xfs_file_readdir(
+       struct file     *filp,
+       void            *dirent,
+       filldir_t       filldir)
+{
+       struct inode    *inode = filp->f_path.dentry->d_inode;
+       xfs_inode_t     *ip = XFS_I(inode);
+       struct hack_callback buf;
+       struct hack_dirent *de;
+       int             error;
+       loff_t          size;
+       int             eof = 0;
+       xfs_off_t       start_offset, curr_offset, offset;
+
+       /*
+        * Try fairly hard to get memory
+        */
+       buf.len = PAGE_CACHE_SIZE;
+       do {
+               buf.dirent = kmalloc(buf.len, GFP_KERNEL);
+               if (buf.dirent)
+                       break;
+               buf.len >>= 1;
+       } while (buf.len >= 1024);
+
+       if (!buf.dirent)
+               return -ENOMEM;
+
+       curr_offset = filp->f_pos;
+       if (curr_offset == 0x7fffffff)
+               offset = 0xffffffff;
+       else
+               offset = filp->f_pos;
+
+       while (!eof) {
+               int reclen;
+               start_offset = offset;
+
+               buf.used = 0;
+               error = -xfs_readdir(ip, &buf, buf.len, &offset,
+                                    xfs_hack_filldir);
+               if (error || offset == start_offset) {
+                       size = 0;
+                       break;
+               }
+
+               size = buf.used;
+               de = (struct hack_dirent *)buf.dirent;
+               while (size > 0) {
+                       if (filldir(dirent, de->name, de->namlen,
+                                       curr_offset & 0x7fffffff,
+                                       de->ino, de->d_type)) {
+                               goto done;
+                       }
+
+                       reclen = sizeof(struct hack_dirent) + de->namlen;
+                       size -= reclen;
+                       curr_offset = de->offset /* & 0x7fffffff */;
+                       de = (struct hack_dirent *)((char *)de + reclen);
+               }
+       }
+
+ done:
+       if (!error) {
+               if (size == 0)
+                       filp->f_pos = offset & 0x7fffffff;
+               else if (de)
+                       filp->f_pos = curr_offset;
+       }
+
+       kfree(buf.dirent);
+       return error;
+}
+#endif
 
 STATIC int
 xfs_file_mmap(
index 2b34bad48b079c73da80bc47c696d92a51198bd4..98a56568bb24a942640729e47bd5d0e6a6d2234f 100644 (file)
@@ -1047,24 +1047,20 @@ xfs_ioc_bulkstat(
        if ((count = bulkreq.icount) <= 0)
                return -XFS_ERROR(EINVAL);
 
+       if (bulkreq.ubuffer == NULL)
+               return -XFS_ERROR(EINVAL);
+
        if (cmd == XFS_IOC_FSINUMBERS)
                error = xfs_inumbers(mp, &inlast, &count,
                                        bulkreq.ubuffer, xfs_inumbers_fmt);
        else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
                error = xfs_bulkstat_single(mp, &inlast,
                                                bulkreq.ubuffer, &done);
-       else {  /* XFS_IOC_FSBULKSTAT */
-               if (count == 1 && inlast != 0) {
-                       inlast++;
-                       error = xfs_bulkstat_single(mp, &inlast,
-                                       bulkreq.ubuffer, &done);
-               } else {
-                       error = xfs_bulkstat(mp, &inlast, &count,
-                               (bulkstat_one_pf)xfs_bulkstat_one, NULL,
-                               sizeof(xfs_bstat_t), bulkreq.ubuffer,
-                               BULKSTAT_FG_QUICK, &done);
-               }
-       }
+       else    /* XFS_IOC_FSBULKSTAT */
+               error = xfs_bulkstat(mp, &inlast, &count,
+                       (bulkstat_one_pf)xfs_bulkstat_one, NULL,
+                       sizeof(xfs_bstat_t), bulkreq.ubuffer,
+                       BULKSTAT_FG_QUICK, &done);
 
        if (error)
                return -error;
index 0046bdd5b7f11df4bf077e5144e306f01608e6ee..bf2a956b63c28490f4eae13cd8d58a09df17ce81 100644 (file)
@@ -291,6 +291,9 @@ xfs_ioc_bulkstat_compat(
        if ((count = bulkreq.icount) <= 0)
                return -XFS_ERROR(EINVAL);
 
+       if (bulkreq.ubuffer == NULL)
+               return -XFS_ERROR(EINVAL);
+
        if (cmd == XFS_IOC_FSINUMBERS)
                error = xfs_inumbers(mp, &inlast, &count,
                                bulkreq.ubuffer, xfs_inumbers_fmt_compat);
index ac50f8a37582acac8089ccbd7bbf382815b8e81d..37e116779eb187945edba30b9322b9b708518b5a 100644 (file)
@@ -117,7 +117,7 @@ xfs_ichgtime(
         */
        SYNCHRONIZE();
        ip->i_update_core = 1;
-       if (!(inode->i_state & I_SYNC))
+       if (!(inode->i_state & I_NEW))
                mark_inode_dirty_sync(inode);
 }
 
@@ -169,7 +169,7 @@ xfs_ichgtime_fast(
         */
        SYNCHRONIZE();
        ip->i_update_core = 1;
-       if (!(inode->i_state & I_SYNC))
+       if (!(inode->i_state & I_NEW))
                mark_inode_dirty_sync(inode);
 }
 
index b5f91281b70715e9d27c41b20d2d098b60689dc5..d488645f833d709f59fdb940bb6112e72d664655 100644 (file)
@@ -1008,6 +1008,9 @@ xfs_qm_sync(
        boolean_t       nowait;
        int             error;
 
+       if (! XFS_IS_QUOTA_ON(mp))
+               return 0;
+
        restarts = 0;
        /*
         * We won't block unless we are asked to.
index 488836e204a3493f968a9e473ce1b00eca67823d..fb69ef180b275f9d0300dc5faa23483e7936f5e7 100644 (file)
@@ -267,7 +267,7 @@ finish_inode:
        icl = NULL;
        if (radix_tree_gang_lookup(&pag->pag_ici_root, (void**)&iq,
                                                        first_index, 1)) {
-               if ((iq->i_ino & mask) == first_index)
+               if ((XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) == first_index)
                        icl = iq->i_cluster;
        }
 
index 9972992fd3c3ced53433cc81460ceba6ea7eaf8e..9fc4c288652980e4d81c2da25fc5470f13d8b664 100644 (file)
@@ -316,6 +316,8 @@ xfs_bulkstat_use_dinode(
        return 1;
 }
 
+#define XFS_BULKSTAT_UBLEFT(ubleft)    ((ubleft) >= statstruct_size)
+
 /*
  * Return stat information in bulk (by-inode) for the filesystem.
  */
@@ -353,7 +355,7 @@ xfs_bulkstat(
        xfs_inobt_rec_incore_t  *irbp;  /* current irec buffer pointer */
        xfs_inobt_rec_incore_t  *irbuf; /* start of irec buffer */
        xfs_inobt_rec_incore_t  *irbufend; /* end of good irec buffer entries */
-       xfs_ino_t               lastino=0; /* last inode number returned */
+       xfs_ino_t               lastino; /* last inode number returned */
        int                     nbcluster; /* # of blocks in a cluster */
        int                     nicluster; /* # of inodes in a cluster */
        int                     nimask; /* mask for inode clusters */
@@ -373,6 +375,7 @@ xfs_bulkstat(
         * Get the last inode value, see if there's nothing to do.
         */
        ino = (xfs_ino_t)*lastinop;
+       lastino = ino;
        dip = NULL;
        agno = XFS_INO_TO_AGNO(mp, ino);
        agino = XFS_INO_TO_AGINO(mp, ino);
@@ -382,6 +385,9 @@ xfs_bulkstat(
                *ubcountp = 0;
                return 0;
        }
+       if (!ubcountp || *ubcountp <= 0) {
+               return EINVAL;
+       }
        ubcount = *ubcountp; /* statstruct's */
        ubleft = ubcount * statstruct_size; /* bytes */
        *ubcountp = ubelem = 0;
@@ -402,7 +408,8 @@ xfs_bulkstat(
         * inode returned; 0 means start of the allocation group.
         */
        rval = 0;
-       while (ubleft >= statstruct_size && agno < mp->m_sb.sb_agcount) {
+       while (XFS_BULKSTAT_UBLEFT(ubleft) && agno < mp->m_sb.sb_agcount) {
+               cond_resched();
                bp = NULL;
                down_read(&mp->m_peraglock);
                error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
@@ -499,6 +506,7 @@ xfs_bulkstat(
                                        break;
                                error = xfs_inobt_lookup_ge(cur, agino, 0, 0,
                                                            &tmp);
+                               cond_resched();
                        }
                        /*
                         * If ran off the end of the ag either with an error,
@@ -542,6 +550,7 @@ xfs_bulkstat(
                         */
                        agino = gino + XFS_INODES_PER_CHUNK;
                        error = xfs_inobt_increment(cur, 0, &tmp);
+                       cond_resched();
                }
                /*
                 * Drop the btree buffers and the agi buffer.
@@ -555,12 +564,12 @@ xfs_bulkstat(
                 */
                irbufend = irbp;
                for (irbp = irbuf;
-                    irbp < irbufend && ubleft >= statstruct_size; irbp++) {
+                    irbp < irbufend && XFS_BULKSTAT_UBLEFT(ubleft); irbp++) {
                        /*
                         * Now process this chunk of inodes.
                         */
                        for (agino = irbp->ir_startino, chunkidx = clustidx = 0;
-                            ubleft > 0 &&
+                            XFS_BULKSTAT_UBLEFT(ubleft) &&
                                irbp->ir_freecount < XFS_INODES_PER_CHUNK;
                             chunkidx++, clustidx++, agino++) {
                                ASSERT(chunkidx < XFS_INODES_PER_CHUNK);
@@ -663,15 +672,13 @@ xfs_bulkstat(
                                                ubleft, private_data,
                                                bno, &ubused, dip, &fmterror);
                                if (fmterror == BULKSTAT_RV_NOTHING) {
-                                        if (error == EFAULT) {
-                                                ubleft = 0;
-                                                rval = error;
-                                                break;
-                                        }
-                                       else if (error == ENOMEM)
+                                       if (error && error != ENOENT &&
+                                               error != EINVAL) {
                                                ubleft = 0;
-                                       else
-                                               lastino = ino;
+                                               rval = error;
+                                               break;
+                                       }
+                                       lastino = ino;
                                        continue;
                                }
                                if (fmterror == BULKSTAT_RV_GIVEUP) {
@@ -686,6 +693,8 @@ xfs_bulkstat(
                                ubelem++;
                                lastino = ino;
                        }
+
+                       cond_resched();
                }
 
                if (bp)
@@ -694,11 +703,12 @@ xfs_bulkstat(
                /*
                 * Set up for the next loop iteration.
                 */
-               if (ubleft > 0) {
+               if (XFS_BULKSTAT_UBLEFT(ubleft)) {
                        if (end_of_ag) {
                                agno++;
                                agino = 0;
-                       }
+                       } else
+                               agino = XFS_INO_TO_AGINO(mp, lastino);
                } else
                        break;
        }
@@ -707,6 +717,11 @@ xfs_bulkstat(
         */
        kmem_free(irbuf, irbsize);
        *ubcountp = ubelem;
+       /*
+        * Found some inodes, return them now and return the error next time.
+        */
+       if (ubelem)
+               rval = 0;
        if (agno >= mp->m_sb.sb_agcount) {
                /*
                 * If we ran out of filesystem, mark lastino as off