diff options
Diffstat (limited to 'fs/xfs/xfs_attr_leaf.c')
| -rw-r--r-- | fs/xfs/xfs_attr_leaf.c | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index d4906e7c9787..c1b55e596551 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
| @@ -110,6 +110,7 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags) | |||
| 110 | /* | 110 | /* |
| 111 | * Query whether the requested number of additional bytes of extended | 111 | * Query whether the requested number of additional bytes of extended |
| 112 | * attribute space will be able to fit inline. | 112 | * attribute space will be able to fit inline. |
| 113 | * | ||
| 113 | * Returns zero if not, else the di_forkoff fork offset to be used in the | 114 | * Returns zero if not, else the di_forkoff fork offset to be used in the |
| 114 | * literal area for attribute data once the new bytes have been added. | 115 | * literal area for attribute data once the new bytes have been added. |
| 115 | * | 116 | * |
| @@ -122,7 +123,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) | |||
| 122 | int offset; | 123 | int offset; |
| 123 | int minforkoff; /* lower limit on valid forkoff locations */ | 124 | int minforkoff; /* lower limit on valid forkoff locations */ |
| 124 | int maxforkoff; /* upper limit on valid forkoff locations */ | 125 | int maxforkoff; /* upper limit on valid forkoff locations */ |
| 125 | int dsize; | 126 | int dsize; |
| 126 | xfs_mount_t *mp = dp->i_mount; | 127 | xfs_mount_t *mp = dp->i_mount; |
| 127 | 128 | ||
| 128 | offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ | 129 | offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ |
| @@ -136,47 +137,60 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) | |||
| 136 | return (offset >= minforkoff) ? minforkoff : 0; | 137 | return (offset >= minforkoff) ? minforkoff : 0; |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | if (!(mp->m_flags & XFS_MOUNT_ATTR2)) { | 140 | /* |
| 140 | if (bytes <= XFS_IFORK_ASIZE(dp)) | 141 | * If the requested numbers of bytes is smaller or equal to the |
| 141 | return dp->i_d.di_forkoff; | 142 | * current attribute fork size we can always proceed. |
| 143 | * | ||
| 144 | * Note that if_bytes in the data fork might actually be larger than | ||
| 145 | * the current data fork size is due to delalloc extents. In that | ||
| 146 | * case either the extent count will go down when they are converted | ||
| 147 | * to real extents, or the delalloc conversion will take care of the | ||
| 148 | * literal area rebalancing. | ||
| 149 | */ | ||
| 150 | if (bytes <= XFS_IFORK_ASIZE(dp)) | ||
| 151 | return dp->i_d.di_forkoff; | ||
| 152 | |||
| 153 | /* | ||
| 154 | * For attr2 we can try to move the forkoff if there is space in the | ||
| 155 | * literal area, but for the old format we are done if there is no | ||
| 156 | * space in the fixed attribute fork. | ||
| 157 | */ | ||
| 158 | if (!(mp->m_flags & XFS_MOUNT_ATTR2)) | ||
| 142 | return 0; | 159 | return 0; |
| 143 | } | ||
| 144 | 160 | ||
| 145 | dsize = dp->i_df.if_bytes; | 161 | dsize = dp->i_df.if_bytes; |
| 146 | 162 | ||
| 147 | switch (dp->i_d.di_format) { | 163 | switch (dp->i_d.di_format) { |
| 148 | case XFS_DINODE_FMT_EXTENTS: | 164 | case XFS_DINODE_FMT_EXTENTS: |
| 149 | /* | 165 | /* |
| 150 | * If there is no attr fork and the data fork is extents, | 166 | * If there is no attr fork and the data fork is extents, |
| 151 | * determine if creating the default attr fork will result | 167 | * determine if creating the default attr fork will result |
| 152 | * in the extents form migrating to btree. If so, the | 168 | * in the extents form migrating to btree. If so, the |
| 153 | * minimum offset only needs to be the space required for | 169 | * minimum offset only needs to be the space required for |
| 154 | * the btree root. | 170 | * the btree root. |
| 155 | */ | 171 | */ |
| 156 | if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > | 172 | if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > |
| 157 | xfs_default_attroffset(dp)) | 173 | xfs_default_attroffset(dp)) |
| 158 | dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); | 174 | dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); |
| 159 | break; | 175 | break; |
| 160 | |||
| 161 | case XFS_DINODE_FMT_BTREE: | 176 | case XFS_DINODE_FMT_BTREE: |
| 162 | /* | 177 | /* |
| 163 | * If have data btree then keep forkoff if we have one, | 178 | * If we have a data btree then keep forkoff if we have one, |
| 164 | * otherwise we are adding a new attr, so then we set | 179 | * otherwise we are adding a new attr, so then we set |
| 165 | * minforkoff to where the btree root can finish so we have | 180 | * minforkoff to where the btree root can finish so we have |
| 166 | * plenty of room for attrs | 181 | * plenty of room for attrs |
| 167 | */ | 182 | */ |
| 168 | if (dp->i_d.di_forkoff) { | 183 | if (dp->i_d.di_forkoff) { |
| 169 | if (offset < dp->i_d.di_forkoff) | 184 | if (offset < dp->i_d.di_forkoff) |
| 170 | return 0; | 185 | return 0; |
| 171 | else | 186 | return dp->i_d.di_forkoff; |
| 172 | return dp->i_d.di_forkoff; | 187 | } |
| 173 | } else | 188 | dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot); |
| 174 | dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot); | ||
| 175 | break; | 189 | break; |
| 176 | } | 190 | } |
| 177 | 191 | ||
| 178 | /* | 192 | /* |
| 179 | * A data fork btree root must have space for at least | 193 | * A data fork btree root must have space for at least |
| 180 | * MINDBTPTRS key/ptr pairs if the data fork is small or empty. | 194 | * MINDBTPTRS key/ptr pairs if the data fork is small or empty. |
| 181 | */ | 195 | */ |
| 182 | minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); | 196 | minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); |
| @@ -186,10 +200,10 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) | |||
| 186 | maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); | 200 | maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); |
| 187 | maxforkoff = maxforkoff >> 3; /* rounded down */ | 201 | maxforkoff = maxforkoff >> 3; /* rounded down */ |
| 188 | 202 | ||
| 189 | if (offset >= minforkoff && offset < maxforkoff) | ||
| 190 | return offset; | ||
| 191 | if (offset >= maxforkoff) | 203 | if (offset >= maxforkoff) |
| 192 | return maxforkoff; | 204 | return maxforkoff; |
| 205 | if (offset >= minforkoff) | ||
| 206 | return offset; | ||
| 193 | return 0; | 207 | return 0; |
| 194 | } | 208 | } |
| 195 | 209 | ||
