fcntl: return -EFAULT if copy_to_user fails
[safe/jmp/linux-2.6] / fs / ocfs2 / ocfs2_fs.h
index 448aa8d..33f1c9a 100644 (file)
                                         | OCFS2_FEATURE_INCOMPAT_XATTR \
                                         | OCFS2_FEATURE_INCOMPAT_META_ECC \
                                         | OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS \
-                                        | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE)
+                                        | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE \
+                                        | OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG)
 #define OCFS2_FEATURE_RO_COMPAT_SUPP   (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
                                         | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
                                         | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
@@ -507,7 +508,10 @@ struct ocfs2_extent_block
                                           block group */
        __le32 h_fs_generation;         /* Must match super block */
        __le64 h_blkno;                 /* Offset on disk, in blocks */
-/*20*/ __le64 h_reserved3;
+/*20*/ __le64 h_suballoc_loc;          /* Suballocator block group this
+                                          eb belongs to.  Only valid
+                                          if allocated from a
+                                          discontiguous block group */
        __le64 h_next_leaf_blk;         /* Offset on disk, in blocks,
                                           of next leaf header pointing
                                           to data */
@@ -674,7 +678,11 @@ struct ocfs2_dinode {
 /*80*/ struct ocfs2_block_check i_check;       /* Error checking */
 /*88*/ __le64 i_dx_root;               /* Pointer to dir index root block */
 /*90*/ __le64 i_refcount_loc;
-       __le64 i_reserved2[4];
+       __le64 i_suballoc_loc;          /* Suballocator block group this
+                                          inode belongs to.  Only valid
+                                          if allocated from a
+                                          discontiguous block group */
+/*A0*/ __le64 i_reserved2[3];
 /*B8*/ union {
                __le64 i_pad1;          /* Generic way to refer to this
                                           64bit union */
@@ -809,7 +817,12 @@ struct ocfs2_dx_root_block {
        __le32          dr_reserved2;
        __le64          dr_free_blk;            /* Pointer to head of free
                                                 * unindexed block list. */
-       __le64          dr_reserved3[15];
+       __le64          dr_suballoc_loc;        /* Suballocator block group
+                                                  this root belongs to.
+                                                  Only valid if allocated
+                                                  from a discontiguous
+                                                  block group */
+       __le64          dr_reserved3[14];
        union {
                struct ocfs2_extent_list dr_list; /* Keep this aligned to 128
                                                   * bits for maximum space
@@ -929,7 +942,11 @@ struct ocfs2_refcount_block {
 /*40*/ __le32 rf_generation;           /* generation number. all be the same
                                         * for the same refcount tree. */
        __le32 rf_reserved0;
-       __le64 rf_reserved1[7];
+       __le64 rf_suballoc_loc;         /* Suballocator block group this
+                                          refcount block belongs to. Only
+                                          valid if allocated from a
+                                          discontiguous block group */
+/*50*/ __le64 rf_reserved1[6];
 /*80*/ union {
                struct ocfs2_refcount_list rf_records;  /* List of refcount
                                                          records */
@@ -1041,7 +1058,10 @@ struct ocfs2_xattr_block {
                                        real xattr or a xattr tree. */
        __le16  xb_reserved0;
        __le32  xb_reserved1;
-       __le64  xb_reserved2;
+       __le64  xb_suballoc_loc;        /* Suballocator block group this
+                                          xattr block belongs to. Only
+                                          valid if allocated from a
+                                          discontiguous block group */
 /*30*/ union {
                struct ocfs2_xattr_header xb_header; /* xattr header if this
                                                        block contains xattr */
@@ -1278,6 +1298,16 @@ static inline u16 ocfs2_extent_recs_per_eb(struct super_block *sb)
        return size / sizeof(struct ocfs2_extent_rec);
 }
 
+static inline u16 ocfs2_extent_recs_per_gd(struct super_block *sb)
+{
+       int size;
+
+       size = sb->s_blocksize -
+               offsetof(struct ocfs2_group_desc, bg_list.l_recs);
+
+       return size / sizeof(struct ocfs2_extent_rec);
+}
+
 static inline int ocfs2_dx_entries_per_leaf(struct super_block *sb)
 {
        int size;
@@ -1309,15 +1339,21 @@ static inline u16 ocfs2_local_alloc_size(struct super_block *sb)
 }
 
 static inline int ocfs2_group_bitmap_size(struct super_block *sb,
-                                         int suballocator)
+                                         int suballocator,
+                                         u32 feature_incompat)
 {
-       int size;
+       int size = sb->s_blocksize -
+               offsetof(struct ocfs2_group_desc, bg_bitmap);
 
-       if (suballocator)
+       /*
+        * The cluster allocator uses the entire block.  Suballocators have
+        * never used more than OCFS2_MAX_BG_BITMAP_SIZE.  Unfortunately, older
+        * code expects bg_size set to the maximum.  Thus we must keep
+        * bg_size as-is unless discontig_bg is enabled.
+        */
+       if (suballocator &&
+           (feature_incompat & OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG))
                size = OCFS2_MAX_BG_BITMAP_SIZE;
-       else
-               size = sb->s_blocksize -
-                       offsetof(struct ocfs2_group_desc, bg_bitmap);
 
        return size;
 }
@@ -1430,6 +1466,16 @@ static inline int ocfs2_extent_recs_per_eb(int blocksize)
        return size / sizeof(struct ocfs2_extent_rec);
 }
 
+static inline int ocfs2_extent_recs_per_gd(int blocksize)
+{
+       int size;
+
+       size = blocksize -
+               offsetof(struct ocfs2_group_desc, bg_list.l_recs);
+
+       return size / sizeof(struct ocfs2_extent_rec);
+}
+
 static inline int ocfs2_local_alloc_size(int blocksize)
 {
        int size;
@@ -1440,15 +1486,22 @@ static inline int ocfs2_local_alloc_size(int blocksize)
        return size;
 }
 
-static inline int ocfs2_group_bitmap_size(int blocksize, int suballocator)
+static inline int ocfs2_group_bitmap_size(int blocksize,
+                                         int suballocator,
+                                         uint32_t feature_incompat)
 {
-       int size;
+       int size = sb->s_blocksize -
+               offsetof(struct ocfs2_group_desc, bg_bitmap);
 
-       if (suballocator)
+       /*
+        * The cluster allocator uses the entire block.  Suballocators have
+        * never used more than OCFS2_MAX_BG_BITMAP_SIZE.  Unfortunately, older
+        * code expects bg_size set to the maximum.  Thus we must keep
+        * bg_size as-is unless discontig_bg is enabled.
+        */
+       if (suballocator &&
+           (feature_incompat & OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG))
                size = OCFS2_MAX_BG_BITMAP_SIZE;
-       else
-               size = blocksize -
-                       offsetof(struct ocfs2_group_desc, bg_bitmap);
 
        return size;
 }
@@ -1522,5 +1575,19 @@ static inline void ocfs2_set_de_type(struct ocfs2_dir_entry *de,
        de->file_type = ocfs2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
 }
 
+static inline int ocfs2_gd_is_discontig(struct ocfs2_group_desc *gd)
+{
+       if ((offsetof(struct ocfs2_group_desc, bg_bitmap) +
+            le16_to_cpu(gd->bg_size)) !=
+           offsetof(struct ocfs2_group_desc, bg_list))
+               return 0;
+       /*
+        * Only valid to check l_next_free_rec if
+        * bg_bitmap + bg_size == bg_list.
+        */
+       if (!gd->bg_list.l_next_free_rec)
+               return 0;
+       return 1;
+}
 #endif  /* _OCFS2_FS_H */