nfsd4: support putpubfh operation
[safe/jmp/linux-2.6] / fs / xfs / xfs_dir2_block.c
index c171767..e1f0a06 100644 (file)
@@ -215,7 +215,7 @@ xfs_dir2_block_addname(
        /*
         * If this isn't a real add, we're done with the buffer.
         */
-       if (args->justcheck)
+       if (args->op_flags & XFS_DA_OP_JUSTCHECK)
                xfs_da_brelse(tp, bp);
        /*
         * If we don't have space for the new entry & leaf ...
@@ -225,7 +225,7 @@ xfs_dir2_block_addname(
                 * Not trying to actually do anything, or don't have
                 * a space reservation: return no-space.
                 */
-               if (args->justcheck || args->total == 0)
+               if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
                        return XFS_ERROR(ENOSPC);
                /*
                 * Convert to the next larger format.
@@ -240,7 +240,7 @@ xfs_dir2_block_addname(
        /*
         * Just checking, and it would work, so say so.
         */
-       if (args->justcheck)
+       if (args->op_flags & XFS_DA_OP_JUSTCHECK)
                return 0;
        needlog = needscan = 0;
        /*
@@ -271,7 +271,7 @@ xfs_dir2_block_addname(
                }
                lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
                lfloghigh -= be32_to_cpu(btp->stale) - 1;
-               be32_add(&btp->count, -(be32_to_cpu(btp->stale) - 1));
+               be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
                xfs_dir2_data_make_free(tp, bp,
                        (xfs_dir2_data_aoff_t)((char *)blp - (char *)block),
                        (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
@@ -326,7 +326,7 @@ xfs_dir2_block_addname(
                /*
                 * Update the tail (entry count).
                 */
-               be32_add(&btp->count, 1);
+               be32_add_cpu(&btp->count, 1);
                /*
                 * If we now need to rebuild the bestfree map, do so.
                 * This needs to happen before the next call to use_free.
@@ -387,7 +387,7 @@ xfs_dir2_block_addname(
                        lfloglow = MIN(mid, lfloglow);
                        lfloghigh = MAX(highstale, lfloghigh);
                }
-               be32_add(&btp->stale, -1);
+               be32_add_cpu(&btp->stale, -1);
        }
        /*
         * Point to the new data entry.
@@ -508,7 +508,7 @@ xfs_dir2_block_getdents(
                        continue;
 
                cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
-                                                   ptr - (char *)block);
+                                           (char *)dep - (char *)block);
                ino = be64_to_cpu(dep->inumber);
 #if XFS_BIG_INUMS
                ino += mp->m_inoadd;
@@ -517,11 +517,9 @@ xfs_dir2_block_getdents(
                /*
                 * If it didn't fit, set the final offset to here & return.
                 */
-               if (filldir(dirent, dep->name, dep->namelen, cook,
+               if (filldir(dirent, dep->name, dep->namelen, cook & 0x7fffffff,
                            ino, DT_UNKNOWN)) {
-                       *offset = xfs_dir2_db_off_to_dataptr(mp,
-                                       mp->m_dirdatablk,
-                                       (char *)dep - (char *)block);
+                       *offset = cook & 0x7fffffff;
                        xfs_da_brelse(NULL, bp);
                        return 0;
                }
@@ -531,7 +529,8 @@ xfs_dir2_block_getdents(
         * Reached the end of the block.
         * Set the offset to a non-existent block 1 and return.
         */
-       *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
+       *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
+                       0x7fffffff;
        xfs_da_brelse(NULL, bp);
        return 0;
 }
@@ -612,14 +611,15 @@ xfs_dir2_block_lookup(
        /*
         * Get the offset from the leaf entry, to point to the data.
         */
-       dep = (xfs_dir2_data_entry_t *)
-             ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
+       dep = (xfs_dir2_data_entry_t *)((char *)block +
+               xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
        /*
-        * Fill in inode number, release the block.
+        * Fill in inode number, CI name if appropriate, release the block.
         */
        args->inumber = be64_to_cpu(dep->inumber);
+       error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
        xfs_da_brelse(args->trans, bp);
-       return XFS_ERROR(EEXIST);
+       return XFS_ERROR(error);
 }
 
 /*
@@ -645,6 +645,7 @@ xfs_dir2_block_lookup_int(
        int                     mid;            /* binary search current idx */
        xfs_mount_t             *mp;            /* filesystem mount point */
        xfs_trans_t             *tp;            /* transaction pointer */
+       enum xfs_dacmp          cmp;            /* comparison result */
 
        dp = args->dp;
        tp = args->trans;
@@ -675,7 +676,7 @@ xfs_dir2_block_lookup_int(
                else
                        high = mid - 1;
                if (low > high) {
-                       ASSERT(args->oknoent);
+                       ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
                        xfs_da_brelse(tp, bp);
                        return XFS_ERROR(ENOENT);
                }
@@ -699,20 +700,31 @@ xfs_dir2_block_lookup_int(
                dep = (xfs_dir2_data_entry_t *)
                        ((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
                /*
-                * Compare, if it's right give back buffer & entry number.
+                * Compare name and if it's an exact match, return the index
+                * and buffer. If it's the first case-insensitive match, store
+                * the index and buffer and continue looking for an exact match.
                 */
-               if (dep->namelen == args->namelen &&
-                   dep->name[0] == args->name[0] &&
-                   memcmp(dep->name, args->name, args->namelen) == 0) {
+               cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
+               if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
+                       args->cmpresult = cmp;
                        *bpp = bp;
                        *entno = mid;
-                       return 0;
+                       if (cmp == XFS_CMP_EXACT)
+                               return 0;
                }
-       } while (++mid < be32_to_cpu(btp->count) && be32_to_cpu(blp[mid].hashval) == hash);
+       } while (++mid < be32_to_cpu(btp->count) &&
+                       be32_to_cpu(blp[mid].hashval) == hash);
+
+       ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
+       /*
+        * Here, we can only be doing a lookup (not a rename or replace).
+        * If a case-insensitive match was found earlier, return success.
+        */
+       if (args->cmpresult == XFS_CMP_CASE)
+               return 0;
        /*
         * No match, release the buffer and return ENOENT.
         */
-       ASSERT(args->oknoent);
        xfs_da_brelse(tp, bp);
        return XFS_ERROR(ENOENT);
 }
@@ -769,7 +781,7 @@ xfs_dir2_block_removename(
        /*
         * Fix up the block tail.
         */
-       be32_add(&btp->stale, 1);
+       be32_add_cpu(&btp->stale, 1);
        xfs_dir2_block_log_tail(tp, bp);
        /*
         * Remove the leaf entry by marking it stale.
@@ -1035,6 +1047,7 @@ xfs_dir2_sf_to_block(
        xfs_dir2_sf_t           *sfp;           /* shortform structure */
        __be16                  *tagp;          /* end of data entry */
        xfs_trans_t             *tp;            /* transaction pointer */
+       struct xfs_name         name;
 
        xfs_dir2_trace_args("sf_to_block", args);
        dp = args->dp;
@@ -1073,7 +1086,7 @@ xfs_dir2_sf_to_block(
         */
        error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno);
        if (error) {
-               kmem_free(buf, buf_len);
+               kmem_free(buf);
                return error;
        }
        /*
@@ -1081,7 +1094,7 @@ xfs_dir2_sf_to_block(
         */
        error = xfs_dir2_data_init(args, blkno, &bp);
        if (error) {
-               kmem_free(buf, buf_len);
+               kmem_free(buf);
                return error;
        }
        block = bp->data;
@@ -1189,8 +1202,10 @@ xfs_dir2_sf_to_block(
                tagp = xfs_dir2_data_entry_tag_p(dep);
                *tagp = cpu_to_be16((char *)dep - (char *)block);
                xfs_dir2_data_log_entry(tp, bp, dep);
-               blp[2 + i].hashval = cpu_to_be32(xfs_da_hashname(
-                                       (char *)sfep->name, sfep->namelen));
+               name.name = sfep->name;
+               name.len = sfep->namelen;
+               blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->
+                                                       hashname(&name));
                blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
                                                 (char *)dep - (char *)block));
                offset = (int)((char *)(tagp + 1) - (char *)block);
@@ -1200,7 +1215,7 @@ xfs_dir2_sf_to_block(
                        sfep = xfs_dir2_sf_nextentry(sfp, sfep);
        }
        /* Done with the temporary buffer */
-       kmem_free(buf, buf_len);
+       kmem_free(buf);
        /*
         * Sort the leaf entries by hash value.
         */