diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-18 13:02:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-18 13:02:46 -0400 |
| commit | ef38ff9d372d4fe69e415370939a0f1fb5783af1 (patch) | |
| tree | fcf38cbbd55298606a695adaf7f2ea97f3185c19 | |
| parent | fda31d7d4b5a9c663ac3ed1ba244018a88deecaf (diff) | |
| parent | 62be1f71677c53d5e51223807a06ac9052f49b0f (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (49 commits)
[GFS2] fix assertion in log_refund()
[GFS2] fix GFP_KERNEL misuses
[GFS2] test for IS_ERR rather than 0
[GFS2] Invalidate cache at correct point
[GFS2] fs/gfs2/recovery.c: suppress warnings
[GFS2] Faster gfs2_bitfit algorithm
[GFS2] Streamline quota lock/check for no-quota case
[GFS2] Remove drop of module ref where not needed
[GFS2] gfs2_adjust_quota has broken unstuffing code
[GFS2] possible null pointer dereference fixup
[GFS2] Need to ensure that sector_t is 64bits for GFS2
[GFS2] re-support special inode
[GFS2] remove gfs2_dev_iops
[GFS2] fix file_system_type leak on gfs2meta mount
[GFS2] Allow bmap to allocate extents
[GFS2] Fix a page lock / glock deadlock
[GFS2] proper extern for gfs2/locking/dlm/mount.c:gdlm_ops
[GFS2] gfs2/ops_file.c should #include "ops_inode.h"
[GFS2] be*_add_cpu conversion
[GFS2] Fix bug where we called drop_bh incorrectly
...
45 files changed, 1150 insertions, 1131 deletions
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index de8e64c03f73..7f7947e3dfbb 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config GFS2_FS | 1 | config GFS2_FS |
| 2 | tristate "GFS2 file system support" | 2 | tristate "GFS2 file system support" |
| 3 | depends on EXPERIMENTAL | 3 | depends on EXPERIMENTAL && (64BIT || (LSF && LBD)) |
| 4 | select FS_POSIX_ACL | 4 | select FS_POSIX_ACL |
| 5 | select CRC32 | 5 | select CRC32 |
| 6 | help | 6 | help |
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile index 8fff11058cee..e2350df02a07 100644 --- a/fs/gfs2/Makefile +++ b/fs/gfs2/Makefile | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | obj-$(CONFIG_GFS2_FS) += gfs2.o | 1 | obj-$(CONFIG_GFS2_FS) += gfs2.o |
| 2 | gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \ | 2 | gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \ |
| 3 | glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \ | 3 | glops.o inode.o log.o lops.o locking.o main.o meta_io.o \ |
| 4 | mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \ | 4 | mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \ |
| 5 | ops_fstype.o ops_inode.o ops_super.o quota.o \ | 5 | ops_fstype.o ops_inode.o ops_super.o quota.o \ |
| 6 | recovery.o rgrp.o super.o sys.o trans.o util.o | 6 | recovery.o rgrp.o super.o sys.o trans.o util.o |
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 1047a8c7226a..3e9bd46f27e3 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c | |||
| @@ -116,7 +116,7 @@ static int acl_get(struct gfs2_inode *ip, int access, struct posix_acl **acl, | |||
| 116 | goto out; | 116 | goto out; |
| 117 | 117 | ||
| 118 | er.er_data_len = GFS2_EA_DATA_LEN(el->el_ea); | 118 | er.er_data_len = GFS2_EA_DATA_LEN(el->el_ea); |
| 119 | er.er_data = kmalloc(er.er_data_len, GFP_KERNEL); | 119 | er.er_data = kmalloc(er.er_data_len, GFP_NOFS); |
| 120 | error = -ENOMEM; | 120 | error = -ENOMEM; |
| 121 | if (!er.er_data) | 121 | if (!er.er_data) |
| 122 | goto out; | 122 | goto out; |
| @@ -222,7 +222,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) | |||
| 222 | return error; | 222 | return error; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | clone = posix_acl_clone(acl, GFP_KERNEL); | 225 | clone = posix_acl_clone(acl, GFP_NOFS); |
| 226 | error = -ENOMEM; | 226 | error = -ENOMEM; |
| 227 | if (!clone) | 227 | if (!clone) |
| 228 | goto out; | 228 | goto out; |
| @@ -272,7 +272,7 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) | |||
| 272 | if (!acl) | 272 | if (!acl) |
| 273 | return gfs2_setattr_simple(ip, attr); | 273 | return gfs2_setattr_simple(ip, attr); |
| 274 | 274 | ||
| 275 | clone = posix_acl_clone(acl, GFP_KERNEL); | 275 | clone = posix_acl_clone(acl, GFP_NOFS); |
| 276 | error = -ENOMEM; | 276 | error = -ENOMEM; |
| 277 | if (!clone) | 277 | if (!clone) |
| 278 | goto out; | 278 | goto out; |
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index e9456ebd3bb6..c19184f2e70e 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | * keep it small. | 33 | * keep it small. |
| 34 | */ | 34 | */ |
| 35 | struct metapath { | 35 | struct metapath { |
| 36 | struct buffer_head *mp_bh[GFS2_MAX_META_HEIGHT]; | ||
| 36 | __u16 mp_list[GFS2_MAX_META_HEIGHT]; | 37 | __u16 mp_list[GFS2_MAX_META_HEIGHT]; |
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| @@ -135,9 +136,10 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
| 135 | /* Get a free block, fill it with the stuffed data, | 136 | /* Get a free block, fill it with the stuffed data, |
| 136 | and write it out to disk */ | 137 | and write it out to disk */ |
| 137 | 138 | ||
| 139 | unsigned int n = 1; | ||
| 140 | block = gfs2_alloc_block(ip, &n); | ||
| 138 | if (isdir) { | 141 | if (isdir) { |
| 139 | block = gfs2_alloc_meta(ip); | 142 | gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1); |
| 140 | |||
| 141 | error = gfs2_dir_get_new_buffer(ip, block, &bh); | 143 | error = gfs2_dir_get_new_buffer(ip, block, &bh); |
| 142 | if (error) | 144 | if (error) |
| 143 | goto out_brelse; | 145 | goto out_brelse; |
| @@ -145,8 +147,6 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
| 145 | dibh, sizeof(struct gfs2_dinode)); | 147 | dibh, sizeof(struct gfs2_dinode)); |
| 146 | brelse(bh); | 148 | brelse(bh); |
| 147 | } else { | 149 | } else { |
| 148 | block = gfs2_alloc_data(ip); | ||
| 149 | |||
| 150 | error = gfs2_unstuffer_page(ip, dibh, block, page); | 150 | error = gfs2_unstuffer_page(ip, dibh, block, page); |
| 151 | if (error) | 151 | if (error) |
| 152 | goto out_brelse; | 152 | goto out_brelse; |
| @@ -161,12 +161,11 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
| 161 | 161 | ||
| 162 | if (ip->i_di.di_size) { | 162 | if (ip->i_di.di_size) { |
| 163 | *(__be64 *)(di + 1) = cpu_to_be64(block); | 163 | *(__be64 *)(di + 1) = cpu_to_be64(block); |
| 164 | ip->i_di.di_blocks++; | 164 | gfs2_add_inode_blocks(&ip->i_inode, 1); |
| 165 | gfs2_set_inode_blocks(&ip->i_inode); | 165 | di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); |
| 166 | di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); | ||
| 167 | } | 166 | } |
| 168 | 167 | ||
| 169 | ip->i_di.di_height = 1; | 168 | ip->i_height = 1; |
| 170 | di->di_height = cpu_to_be16(1); | 169 | di->di_height = cpu_to_be16(1); |
| 171 | 170 | ||
| 172 | out_brelse: | 171 | out_brelse: |
| @@ -176,114 +175,13 @@ out: | |||
| 176 | return error; | 175 | return error; |
| 177 | } | 176 | } |
| 178 | 177 | ||
| 179 | /** | ||
| 180 | * calc_tree_height - Calculate the height of a metadata tree | ||
| 181 | * @ip: The GFS2 inode | ||
| 182 | * @size: The proposed size of the file | ||
| 183 | * | ||
| 184 | * Work out how tall a metadata tree needs to be in order to accommodate a | ||
| 185 | * file of a particular size. If size is less than the current size of | ||
| 186 | * the inode, then the current size of the inode is used instead of the | ||
| 187 | * supplied one. | ||
| 188 | * | ||
| 189 | * Returns: the height the tree should be | ||
| 190 | */ | ||
| 191 | |||
| 192 | static unsigned int calc_tree_height(struct gfs2_inode *ip, u64 size) | ||
| 193 | { | ||
| 194 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
| 195 | u64 *arr; | ||
| 196 | unsigned int max, height; | ||
| 197 | |||
| 198 | if (ip->i_di.di_size > size) | ||
| 199 | size = ip->i_di.di_size; | ||
| 200 | |||
| 201 | if (gfs2_is_dir(ip)) { | ||
| 202 | arr = sdp->sd_jheightsize; | ||
| 203 | max = sdp->sd_max_jheight; | ||
| 204 | } else { | ||
| 205 | arr = sdp->sd_heightsize; | ||
| 206 | max = sdp->sd_max_height; | ||
| 207 | } | ||
| 208 | |||
| 209 | for (height = 0; height < max; height++) | ||
| 210 | if (arr[height] >= size) | ||
| 211 | break; | ||
| 212 | |||
| 213 | return height; | ||
| 214 | } | ||
| 215 | |||
| 216 | /** | ||
| 217 | * build_height - Build a metadata tree of the requested height | ||
| 218 | * @ip: The GFS2 inode | ||
| 219 | * @height: The height to build to | ||
| 220 | * | ||
| 221 | * | ||
| 222 | * Returns: errno | ||
| 223 | */ | ||
| 224 | |||
| 225 | static int build_height(struct inode *inode, unsigned height) | ||
| 226 | { | ||
| 227 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 228 | unsigned new_height = height - ip->i_di.di_height; | ||
| 229 | struct buffer_head *dibh; | ||
| 230 | struct buffer_head *blocks[GFS2_MAX_META_HEIGHT]; | ||
| 231 | struct gfs2_dinode *di; | ||
| 232 | int error; | ||
| 233 | __be64 *bp; | ||
| 234 | u64 bn; | ||
| 235 | unsigned n; | ||
| 236 | |||
| 237 | if (height <= ip->i_di.di_height) | ||
| 238 | return 0; | ||
| 239 | |||
| 240 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
| 241 | if (error) | ||
| 242 | return error; | ||
| 243 | |||
| 244 | for(n = 0; n < new_height; n++) { | ||
| 245 | bn = gfs2_alloc_meta(ip); | ||
| 246 | blocks[n] = gfs2_meta_new(ip->i_gl, bn); | ||
| 247 | gfs2_trans_add_bh(ip->i_gl, blocks[n], 1); | ||
| 248 | } | ||
| 249 | |||
| 250 | n = 0; | ||
| 251 | bn = blocks[0]->b_blocknr; | ||
| 252 | if (new_height > 1) { | ||
| 253 | for(; n < new_height-1; n++) { | ||
| 254 | gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN, | ||
| 255 | GFS2_FORMAT_IN); | ||
| 256 | gfs2_buffer_clear_tail(blocks[n], | ||
| 257 | sizeof(struct gfs2_meta_header)); | ||
| 258 | bp = (__be64 *)(blocks[n]->b_data + | ||
| 259 | sizeof(struct gfs2_meta_header)); | ||
| 260 | *bp = cpu_to_be64(blocks[n+1]->b_blocknr); | ||
| 261 | brelse(blocks[n]); | ||
| 262 | blocks[n] = NULL; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN, GFS2_FORMAT_IN); | ||
| 266 | gfs2_buffer_copy_tail(blocks[n], sizeof(struct gfs2_meta_header), | ||
| 267 | dibh, sizeof(struct gfs2_dinode)); | ||
| 268 | brelse(blocks[n]); | ||
| 269 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 270 | di = (struct gfs2_dinode *)dibh->b_data; | ||
| 271 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); | ||
| 272 | *(__be64 *)(di + 1) = cpu_to_be64(bn); | ||
| 273 | ip->i_di.di_height += new_height; | ||
| 274 | ip->i_di.di_blocks += new_height; | ||
| 275 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 276 | di->di_height = cpu_to_be16(ip->i_di.di_height); | ||
| 277 | di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); | ||
| 278 | brelse(dibh); | ||
| 279 | return error; | ||
| 280 | } | ||
| 281 | 178 | ||
| 282 | /** | 179 | /** |
| 283 | * find_metapath - Find path through the metadata tree | 180 | * find_metapath - Find path through the metadata tree |
| 284 | * @ip: The inode pointer | 181 | * @sdp: The superblock |
| 285 | * @mp: The metapath to return the result in | 182 | * @mp: The metapath to return the result in |
| 286 | * @block: The disk block to look up | 183 | * @block: The disk block to look up |
| 184 | * @height: The pre-calculated height of the metadata tree | ||
| 287 | * | 185 | * |
| 288 | * This routine returns a struct metapath structure that defines a path | 186 | * This routine returns a struct metapath structure that defines a path |
| 289 | * through the metadata of inode "ip" to get to block "block". | 187 | * through the metadata of inode "ip" to get to block "block". |
| @@ -338,21 +236,29 @@ static int build_height(struct inode *inode, unsigned height) | |||
| 338 | * | 236 | * |
| 339 | */ | 237 | */ |
| 340 | 238 | ||
| 341 | static void find_metapath(struct gfs2_inode *ip, u64 block, | 239 | static void find_metapath(const struct gfs2_sbd *sdp, u64 block, |
| 342 | struct metapath *mp) | 240 | struct metapath *mp, unsigned int height) |
| 343 | { | 241 | { |
| 344 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
| 345 | u64 b = block; | ||
| 346 | unsigned int i; | 242 | unsigned int i; |
| 347 | 243 | ||
| 348 | for (i = ip->i_di.di_height; i--;) | 244 | for (i = height; i--;) |
| 349 | mp->mp_list[i] = do_div(b, sdp->sd_inptrs); | 245 | mp->mp_list[i] = do_div(block, sdp->sd_inptrs); |
| 246 | |||
| 247 | } | ||
| 350 | 248 | ||
| 249 | static inline unsigned int zero_metapath_length(const struct metapath *mp, | ||
| 250 | unsigned height) | ||
| 251 | { | ||
| 252 | unsigned int i; | ||
| 253 | for (i = 0; i < height - 1; i++) { | ||
| 254 | if (mp->mp_list[i] != 0) | ||
| 255 | return i; | ||
| 256 | } | ||
| 257 | return height; | ||
| 351 | } | 258 | } |
| 352 | 259 | ||
| 353 | /** | 260 | /** |
| 354 | * metapointer - Return pointer to start of metadata in a buffer | 261 | * metapointer - Return pointer to start of metadata in a buffer |
| 355 | * @bh: The buffer | ||
| 356 | * @height: The metadata height (0 = dinode) | 262 | * @height: The metadata height (0 = dinode) |
| 357 | * @mp: The metapath | 263 | * @mp: The metapath |
| 358 | * | 264 | * |
| @@ -361,93 +267,302 @@ static void find_metapath(struct gfs2_inode *ip, u64 block, | |||
| 361 | * metadata tree. | 267 | * metadata tree. |
| 362 | */ | 268 | */ |
| 363 | 269 | ||
| 364 | static inline __be64 *metapointer(struct buffer_head *bh, int *boundary, | 270 | static inline __be64 *metapointer(unsigned int height, const struct metapath *mp) |
| 365 | unsigned int height, const struct metapath *mp) | ||
| 366 | { | 271 | { |
| 272 | struct buffer_head *bh = mp->mp_bh[height]; | ||
| 367 | unsigned int head_size = (height > 0) ? | 273 | unsigned int head_size = (height > 0) ? |
| 368 | sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode); | 274 | sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode); |
| 369 | __be64 *ptr; | 275 | return ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height]; |
| 370 | *boundary = 0; | ||
| 371 | ptr = ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height]; | ||
| 372 | if (ptr + 1 == (__be64 *)(bh->b_data + bh->b_size)) | ||
| 373 | *boundary = 1; | ||
| 374 | return ptr; | ||
| 375 | } | 276 | } |
| 376 | 277 | ||
| 377 | /** | 278 | /** |
| 378 | * lookup_block - Get the next metadata block in metadata tree | 279 | * lookup_metapath - Walk the metadata tree to a specific point |
| 379 | * @ip: The GFS2 inode | 280 | * @ip: The inode |
| 380 | * @bh: Buffer containing the pointers to metadata blocks | ||
| 381 | * @height: The height of the tree (0 = dinode) | ||
| 382 | * @mp: The metapath | 281 | * @mp: The metapath |
| 383 | * @create: Non-zero if we may create a new meatdata block | ||
| 384 | * @new: Used to indicate if we did create a new metadata block | ||
| 385 | * @block: the returned disk block number | ||
| 386 | * | 282 | * |
| 387 | * Given a metatree, complete to a particular height, checks to see if the next | 283 | * Assumes that the inode's buffer has already been looked up and |
| 388 | * height of the tree exists. If not the next height of the tree is created. | 284 | * hooked onto mp->mp_bh[0] and that the metapath has been initialised |
| 389 | * The block number of the next height of the metadata tree is returned. | 285 | * by find_metapath(). |
| 286 | * | ||
| 287 | * If this function encounters part of the tree which has not been | ||
| 288 | * allocated, it returns the current height of the tree at the point | ||
| 289 | * at which it found the unallocated block. Blocks which are found are | ||
| 290 | * added to the mp->mp_bh[] list. | ||
| 390 | * | 291 | * |
| 292 | * Returns: error or height of metadata tree | ||
| 391 | */ | 293 | */ |
| 392 | 294 | ||
| 393 | static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, | 295 | static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp) |
| 394 | unsigned int height, struct metapath *mp, int create, | ||
| 395 | int *new, u64 *block) | ||
| 396 | { | 296 | { |
| 397 | int boundary; | 297 | unsigned int end_of_metadata = ip->i_height - 1; |
| 398 | __be64 *ptr = metapointer(bh, &boundary, height, mp); | 298 | unsigned int x; |
| 299 | __be64 *ptr; | ||
| 300 | u64 dblock; | ||
| 301 | int ret; | ||
| 399 | 302 | ||
| 400 | if (*ptr) { | 303 | for (x = 0; x < end_of_metadata; x++) { |
| 401 | *block = be64_to_cpu(*ptr); | 304 | ptr = metapointer(x, mp); |
| 402 | return boundary; | 305 | dblock = be64_to_cpu(*ptr); |
| 403 | } | 306 | if (!dblock) |
| 307 | return x + 1; | ||
| 404 | 308 | ||
| 405 | *block = 0; | 309 | ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, 0, &mp->mp_bh[x+1]); |
| 310 | if (ret) | ||
| 311 | return ret; | ||
| 312 | } | ||
| 406 | 313 | ||
| 407 | if (!create) | 314 | return ip->i_height; |
| 408 | return 0; | 315 | } |
| 409 | 316 | ||
| 410 | if (height == ip->i_di.di_height - 1 && !gfs2_is_dir(ip)) | 317 | static inline void release_metapath(struct metapath *mp) |
| 411 | *block = gfs2_alloc_data(ip); | 318 | { |
| 412 | else | 319 | int i; |
| 413 | *block = gfs2_alloc_meta(ip); | ||
| 414 | 320 | ||
| 415 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 321 | for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) { |
| 322 | if (mp->mp_bh[i] == NULL) | ||
| 323 | break; | ||
| 324 | brelse(mp->mp_bh[i]); | ||
| 325 | } | ||
| 326 | } | ||
| 416 | 327 | ||
| 417 | *ptr = cpu_to_be64(*block); | 328 | /** |
| 418 | ip->i_di.di_blocks++; | 329 | * gfs2_extent_length - Returns length of an extent of blocks |
| 419 | gfs2_set_inode_blocks(&ip->i_inode); | 330 | * @start: Start of the buffer |
| 331 | * @len: Length of the buffer in bytes | ||
| 332 | * @ptr: Current position in the buffer | ||
| 333 | * @limit: Max extent length to return (0 = unlimited) | ||
| 334 | * @eob: Set to 1 if we hit "end of block" | ||
| 335 | * | ||
| 336 | * If the first block is zero (unallocated) it will return the number of | ||
| 337 | * unallocated blocks in the extent, otherwise it will return the number | ||
| 338 | * of contiguous blocks in the extent. | ||
| 339 | * | ||
| 340 | * Returns: The length of the extent (minimum of one block) | ||
| 341 | */ | ||
| 420 | 342 | ||
| 421 | *new = 1; | 343 | static inline unsigned int gfs2_extent_length(void *start, unsigned int len, __be64 *ptr, unsigned limit, int *eob) |
| 422 | return 0; | 344 | { |
| 345 | const __be64 *end = (start + len); | ||
| 346 | const __be64 *first = ptr; | ||
| 347 | u64 d = be64_to_cpu(*ptr); | ||
| 348 | |||
| 349 | *eob = 0; | ||
| 350 | do { | ||
| 351 | ptr++; | ||
| 352 | if (ptr >= end) | ||
| 353 | break; | ||
| 354 | if (limit && --limit == 0) | ||
| 355 | break; | ||
| 356 | if (d) | ||
| 357 | d++; | ||
| 358 | } while(be64_to_cpu(*ptr) == d); | ||
| 359 | if (ptr >= end) | ||
| 360 | *eob = 1; | ||
| 361 | return (ptr - first); | ||
| 423 | } | 362 | } |
| 424 | 363 | ||
| 425 | static inline void bmap_lock(struct inode *inode, int create) | 364 | static inline void bmap_lock(struct gfs2_inode *ip, int create) |
| 426 | { | 365 | { |
| 427 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 428 | if (create) | 366 | if (create) |
| 429 | down_write(&ip->i_rw_mutex); | 367 | down_write(&ip->i_rw_mutex); |
| 430 | else | 368 | else |
| 431 | down_read(&ip->i_rw_mutex); | 369 | down_read(&ip->i_rw_mutex); |
| 432 | } | 370 | } |
| 433 | 371 | ||
| 434 | static inline void bmap_unlock(struct inode *inode, int create) | 372 | static inline void bmap_unlock(struct gfs2_inode *ip, int create) |
| 435 | { | 373 | { |
| 436 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 437 | if (create) | 374 | if (create) |
| 438 | up_write(&ip->i_rw_mutex); | 375 | up_write(&ip->i_rw_mutex); |
| 439 | else | 376 | else |
| 440 | up_read(&ip->i_rw_mutex); | 377 | up_read(&ip->i_rw_mutex); |
| 441 | } | 378 | } |
| 442 | 379 | ||
| 380 | static inline __be64 *gfs2_indirect_init(struct metapath *mp, | ||
| 381 | struct gfs2_glock *gl, unsigned int i, | ||
| 382 | unsigned offset, u64 bn) | ||
| 383 | { | ||
| 384 | __be64 *ptr = (__be64 *)(mp->mp_bh[i - 1]->b_data + | ||
| 385 | ((i > 1) ? sizeof(struct gfs2_meta_header) : | ||
| 386 | sizeof(struct gfs2_dinode))); | ||
| 387 | BUG_ON(i < 1); | ||
| 388 | BUG_ON(mp->mp_bh[i] != NULL); | ||
| 389 | mp->mp_bh[i] = gfs2_meta_new(gl, bn); | ||
| 390 | gfs2_trans_add_bh(gl, mp->mp_bh[i], 1); | ||
| 391 | gfs2_metatype_set(mp->mp_bh[i], GFS2_METATYPE_IN, GFS2_FORMAT_IN); | ||
| 392 | gfs2_buffer_clear_tail(mp->mp_bh[i], sizeof(struct gfs2_meta_header)); | ||
| 393 | ptr += offset; | ||
| 394 | *ptr = cpu_to_be64(bn); | ||
| 395 | return ptr; | ||
| 396 | } | ||
| 397 | |||
| 398 | enum alloc_state { | ||
| 399 | ALLOC_DATA = 0, | ||
| 400 | ALLOC_GROW_DEPTH = 1, | ||
| 401 | ALLOC_GROW_HEIGHT = 2, | ||
| 402 | /* ALLOC_UNSTUFF = 3, TBD and rather complicated */ | ||
| 403 | }; | ||
| 404 | |||
| 405 | /** | ||
| 406 | * gfs2_bmap_alloc - Build a metadata tree of the requested height | ||
| 407 | * @inode: The GFS2 inode | ||
| 408 | * @lblock: The logical starting block of the extent | ||
| 409 | * @bh_map: This is used to return the mapping details | ||
| 410 | * @mp: The metapath | ||
| 411 | * @sheight: The starting height (i.e. whats already mapped) | ||
| 412 | * @height: The height to build to | ||
| 413 | * @maxlen: The max number of data blocks to alloc | ||
| 414 | * | ||
| 415 | * In this routine we may have to alloc: | ||
| 416 | * i) Indirect blocks to grow the metadata tree height | ||
| 417 | * ii) Indirect blocks to fill in lower part of the metadata tree | ||
| 418 | * iii) Data blocks | ||
| 419 | * | ||
| 420 | * The function is in two parts. The first part works out the total | ||
| 421 | * number of blocks which we need. The second part does the actual | ||
| 422 | * allocation asking for an extent at a time (if enough contiguous free | ||
| 423 | * blocks are available, there will only be one request per bmap call) | ||
| 424 | * and uses the state machine to initialise the blocks in order. | ||
| 425 | * | ||
| 426 | * Returns: errno on error | ||
| 427 | */ | ||
| 428 | |||
| 429 | static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock, | ||
| 430 | struct buffer_head *bh_map, struct metapath *mp, | ||
| 431 | const unsigned int sheight, | ||
| 432 | const unsigned int height, | ||
| 433 | const unsigned int maxlen) | ||
| 434 | { | ||
| 435 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 436 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
| 437 | struct buffer_head *dibh = mp->mp_bh[0]; | ||
| 438 | u64 bn, dblock = 0; | ||
| 439 | unsigned n, i, blks, alloced = 0, iblks = 0, zmpl = 0; | ||
| 440 | unsigned dblks = 0; | ||
| 441 | unsigned ptrs_per_blk; | ||
| 442 | const unsigned end_of_metadata = height - 1; | ||
| 443 | int eob = 0; | ||
| 444 | enum alloc_state state; | ||
| 445 | __be64 *ptr; | ||
| 446 | __be64 zero_bn = 0; | ||
| 447 | |||
| 448 | BUG_ON(sheight < 1); | ||
| 449 | BUG_ON(dibh == NULL); | ||
| 450 | |||
| 451 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 452 | |||
| 453 | if (height == sheight) { | ||
| 454 | struct buffer_head *bh; | ||
| 455 | /* Bottom indirect block exists, find unalloced extent size */ | ||
| 456 | ptr = metapointer(end_of_metadata, mp); | ||
| 457 | bh = mp->mp_bh[end_of_metadata]; | ||
| 458 | dblks = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, | ||
| 459 | &eob); | ||
| 460 | BUG_ON(dblks < 1); | ||
| 461 | state = ALLOC_DATA; | ||
| 462 | } else { | ||
| 463 | /* Need to allocate indirect blocks */ | ||
| 464 | ptrs_per_blk = height > 1 ? sdp->sd_inptrs : sdp->sd_diptrs; | ||
| 465 | dblks = min(maxlen, ptrs_per_blk - mp->mp_list[end_of_metadata]); | ||
| 466 | if (height == ip->i_height) { | ||
| 467 | /* Writing into existing tree, extend tree down */ | ||
| 468 | iblks = height - sheight; | ||
| 469 | state = ALLOC_GROW_DEPTH; | ||
| 470 | } else { | ||
| 471 | /* Building up tree height */ | ||
| 472 | state = ALLOC_GROW_HEIGHT; | ||
| 473 | iblks = height - ip->i_height; | ||
| 474 | zmpl = zero_metapath_length(mp, height); | ||
| 475 | iblks -= zmpl; | ||
| 476 | iblks += height; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | |||
| 480 | /* start of the second part of the function (state machine) */ | ||
| 481 | |||
| 482 | blks = dblks + iblks; | ||
| 483 | i = sheight; | ||
| 484 | do { | ||
| 485 | n = blks - alloced; | ||
| 486 | bn = gfs2_alloc_block(ip, &n); | ||
| 487 | alloced += n; | ||
| 488 | if (state != ALLOC_DATA || gfs2_is_jdata(ip)) | ||
| 489 | gfs2_trans_add_unrevoke(sdp, bn, n); | ||
| 490 | switch (state) { | ||
| 491 | /* Growing height of tree */ | ||
| 492 | case ALLOC_GROW_HEIGHT: | ||
| 493 | if (i == 1) { | ||
| 494 | ptr = (__be64 *)(dibh->b_data + | ||
| 495 | sizeof(struct gfs2_dinode)); | ||
| 496 | zero_bn = *ptr; | ||
| 497 | } | ||
| 498 | for (; i - 1 < height - ip->i_height && n > 0; i++, n--) | ||
| 499 | gfs2_indirect_init(mp, ip->i_gl, i, 0, bn++); | ||
| 500 | if (i - 1 == height - ip->i_height) { | ||
| 501 | i--; | ||
| 502 | gfs2_buffer_copy_tail(mp->mp_bh[i], | ||
| 503 | sizeof(struct gfs2_meta_header), | ||
| 504 | dibh, sizeof(struct gfs2_dinode)); | ||
| 505 | gfs2_buffer_clear_tail(dibh, | ||
| 506 | sizeof(struct gfs2_dinode) + | ||
| 507 | sizeof(__be64)); | ||
| 508 | ptr = (__be64 *)(mp->mp_bh[i]->b_data + | ||
| 509 | sizeof(struct gfs2_meta_header)); | ||
| 510 | *ptr = zero_bn; | ||
| 511 | state = ALLOC_GROW_DEPTH; | ||
| 512 | for(i = zmpl; i < height; i++) { | ||
| 513 | if (mp->mp_bh[i] == NULL) | ||
| 514 | break; | ||
| 515 | brelse(mp->mp_bh[i]); | ||
| 516 | mp->mp_bh[i] = NULL; | ||
| 517 | } | ||
| 518 | i = zmpl; | ||
| 519 | } | ||
| 520 | if (n == 0) | ||
| 521 | break; | ||
| 522 | /* Branching from existing tree */ | ||
| 523 | case ALLOC_GROW_DEPTH: | ||
| 524 | if (i > 1 && i < height) | ||
| 525 | gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i-1], 1); | ||
| 526 | for (; i < height && n > 0; i++, n--) | ||
| 527 | gfs2_indirect_init(mp, ip->i_gl, i, | ||
| 528 | mp->mp_list[i-1], bn++); | ||
| 529 | if (i == height) | ||
| 530 | state = ALLOC_DATA; | ||
| 531 | if (n == 0) | ||
| 532 | break; | ||
| 533 | /* Tree complete, adding data blocks */ | ||
| 534 | case ALLOC_DATA: | ||
| 535 | BUG_ON(n > dblks); | ||
| 536 | BUG_ON(mp->mp_bh[end_of_metadata] == NULL); | ||
| 537 | gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[end_of_metadata], 1); | ||
| 538 | dblks = n; | ||
| 539 | ptr = metapointer(end_of_metadata, mp); | ||
| 540 | dblock = bn; | ||
| 541 | while (n-- > 0) | ||
| 542 | *ptr++ = cpu_to_be64(bn++); | ||
| 543 | break; | ||
| 544 | } | ||
| 545 | } while (state != ALLOC_DATA); | ||
| 546 | |||
| 547 | ip->i_height = height; | ||
| 548 | gfs2_add_inode_blocks(&ip->i_inode, alloced); | ||
| 549 | gfs2_dinode_out(ip, mp->mp_bh[0]->b_data); | ||
| 550 | map_bh(bh_map, inode->i_sb, dblock); | ||
| 551 | bh_map->b_size = dblks << inode->i_blkbits; | ||
| 552 | set_buffer_new(bh_map); | ||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | |||
| 443 | /** | 556 | /** |
| 444 | * gfs2_block_map - Map a block from an inode to a disk block | 557 | * gfs2_block_map - Map a block from an inode to a disk block |
| 445 | * @inode: The inode | 558 | * @inode: The inode |
| 446 | * @lblock: The logical block number | 559 | * @lblock: The logical block number |
| 447 | * @bh_map: The bh to be mapped | 560 | * @bh_map: The bh to be mapped |
| 561 | * @create: True if its ok to alloc blocks to satify the request | ||
| 448 | * | 562 | * |
| 449 | * Find the block number on the current device which corresponds to an | 563 | * Sets buffer_mapped() if successful, sets buffer_boundary() if a |
| 450 | * inode's block. If the block had to be created, "new" will be set. | 564 | * read of metadata will be required before the next block can be |
| 565 | * mapped. Sets buffer_new() if new blocks were allocated. | ||
| 451 | * | 566 | * |
| 452 | * Returns: errno | 567 | * Returns: errno |
| 453 | */ | 568 | */ |
| @@ -457,97 +572,78 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, | |||
| 457 | { | 572 | { |
| 458 | struct gfs2_inode *ip = GFS2_I(inode); | 573 | struct gfs2_inode *ip = GFS2_I(inode); |
| 459 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 574 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
| 460 | struct buffer_head *bh; | 575 | unsigned int bsize = sdp->sd_sb.sb_bsize; |
| 461 | unsigned int bsize; | 576 | const unsigned int maxlen = bh_map->b_size >> inode->i_blkbits; |
| 462 | unsigned int height; | 577 | const u64 *arr = sdp->sd_heightsize; |
| 463 | unsigned int end_of_metadata; | 578 | __be64 *ptr; |
| 464 | unsigned int x; | ||
| 465 | int error = 0; | ||
| 466 | int new = 0; | ||
| 467 | u64 dblock = 0; | ||
| 468 | int boundary; | ||
| 469 | unsigned int maxlen = bh_map->b_size >> inode->i_blkbits; | ||
| 470 | struct metapath mp; | ||
| 471 | u64 size; | 579 | u64 size; |
| 472 | struct buffer_head *dibh = NULL; | 580 | struct metapath mp; |
| 581 | int ret; | ||
| 582 | int eob; | ||
| 583 | unsigned int len; | ||
| 584 | struct buffer_head *bh; | ||
| 585 | u8 height; | ||
| 473 | 586 | ||
| 474 | BUG_ON(maxlen == 0); | 587 | BUG_ON(maxlen == 0); |
| 475 | 588 | ||
| 476 | if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip))) | 589 | memset(mp.mp_bh, 0, sizeof(mp.mp_bh)); |
| 477 | return 0; | 590 | bmap_lock(ip, create); |
| 478 | |||
| 479 | bmap_lock(inode, create); | ||
| 480 | clear_buffer_mapped(bh_map); | 591 | clear_buffer_mapped(bh_map); |
| 481 | clear_buffer_new(bh_map); | 592 | clear_buffer_new(bh_map); |
| 482 | clear_buffer_boundary(bh_map); | 593 | clear_buffer_boundary(bh_map); |
| 483 | bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize; | 594 | if (gfs2_is_dir(ip)) { |
| 484 | size = (lblock + 1) * bsize; | 595 | bsize = sdp->sd_jbsize; |
| 485 | 596 | arr = sdp->sd_jheightsize; | |
| 486 | if (size > ip->i_di.di_size) { | ||
| 487 | height = calc_tree_height(ip, size); | ||
| 488 | if (ip->i_di.di_height < height) { | ||
| 489 | if (!create) | ||
| 490 | goto out_ok; | ||
| 491 | |||
| 492 | error = build_height(inode, height); | ||
| 493 | if (error) | ||
| 494 | goto out_fail; | ||
| 495 | } | ||
| 496 | } | 597 | } |
| 497 | 598 | ||
| 498 | find_metapath(ip, lblock, &mp); | 599 | ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]); |
| 499 | end_of_metadata = ip->i_di.di_height - 1; | 600 | if (ret) |
| 500 | error = gfs2_meta_inode_buffer(ip, &bh); | 601 | goto out; |
| 501 | if (error) | ||
| 502 | goto out_fail; | ||
| 503 | dibh = bh; | ||
| 504 | get_bh(dibh); | ||
| 505 | 602 | ||
| 506 | for (x = 0; x < end_of_metadata; x++) { | 603 | height = ip->i_height; |
| 507 | lookup_block(ip, bh, x, &mp, create, &new, &dblock); | 604 | size = (lblock + 1) * bsize; |
| 508 | brelse(bh); | 605 | while (size > arr[height]) |
| 509 | if (!dblock) | 606 | height++; |
| 510 | goto out_ok; | 607 | find_metapath(sdp, lblock, &mp, height); |
| 608 | ret = 1; | ||
| 609 | if (height > ip->i_height || gfs2_is_stuffed(ip)) | ||
| 610 | goto do_alloc; | ||
| 611 | ret = lookup_metapath(ip, &mp); | ||
| 612 | if (ret < 0) | ||
| 613 | goto out; | ||
| 614 | if (ret != ip->i_height) | ||
| 615 | goto do_alloc; | ||
| 616 | ptr = metapointer(ip->i_height - 1, &mp); | ||
| 617 | if (*ptr == 0) | ||
| 618 | goto do_alloc; | ||
| 619 | map_bh(bh_map, inode->i_sb, be64_to_cpu(*ptr)); | ||
| 620 | bh = mp.mp_bh[ip->i_height - 1]; | ||
| 621 | len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, &eob); | ||
| 622 | bh_map->b_size = (len << inode->i_blkbits); | ||
| 623 | if (eob) | ||
| 624 | set_buffer_boundary(bh_map); | ||
| 625 | ret = 0; | ||
| 626 | out: | ||
| 627 | release_metapath(&mp); | ||
| 628 | bmap_unlock(ip, create); | ||
| 629 | return ret; | ||
| 511 | 630 | ||
| 512 | error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh); | 631 | do_alloc: |
| 513 | if (error) | 632 | /* All allocations are done here, firstly check create flag */ |
| 514 | goto out_fail; | 633 | if (!create) { |
| 634 | BUG_ON(gfs2_is_stuffed(ip)); | ||
| 635 | ret = 0; | ||
| 636 | goto out; | ||
| 515 | } | 637 | } |
| 516 | 638 | ||
| 517 | boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock); | 639 | /* At this point ret is the tree depth of already allocated blocks */ |
| 518 | if (dblock) { | 640 | ret = gfs2_bmap_alloc(inode, lblock, bh_map, &mp, ret, height, maxlen); |
| 519 | map_bh(bh_map, inode->i_sb, dblock); | 641 | goto out; |
| 520 | if (boundary) | ||
| 521 | set_buffer_boundary(bh_map); | ||
| 522 | if (new) { | ||
| 523 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 524 | gfs2_dinode_out(ip, dibh->b_data); | ||
| 525 | set_buffer_new(bh_map); | ||
| 526 | goto out_brelse; | ||
| 527 | } | ||
| 528 | while(--maxlen && !buffer_boundary(bh_map)) { | ||
| 529 | u64 eblock; | ||
| 530 | |||
| 531 | mp.mp_list[end_of_metadata]++; | ||
| 532 | boundary = lookup_block(ip, bh, end_of_metadata, &mp, 0, &new, &eblock); | ||
| 533 | if (eblock != ++dblock) | ||
| 534 | break; | ||
| 535 | bh_map->b_size += (1 << inode->i_blkbits); | ||
| 536 | if (boundary) | ||
| 537 | set_buffer_boundary(bh_map); | ||
| 538 | } | ||
| 539 | } | ||
| 540 | out_brelse: | ||
| 541 | brelse(bh); | ||
| 542 | out_ok: | ||
| 543 | error = 0; | ||
| 544 | out_fail: | ||
| 545 | if (dibh) | ||
| 546 | brelse(dibh); | ||
| 547 | bmap_unlock(inode, create); | ||
| 548 | return error; | ||
| 549 | } | 642 | } |
| 550 | 643 | ||
| 644 | /* | ||
| 645 | * Deprecated: do not use in new code | ||
| 646 | */ | ||
| 551 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen) | 647 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen) |
| 552 | { | 648 | { |
| 553 | struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 }; | 649 | struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 }; |
| @@ -558,7 +654,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi | |||
| 558 | BUG_ON(!dblock); | 654 | BUG_ON(!dblock); |
| 559 | BUG_ON(!new); | 655 | BUG_ON(!new); |
| 560 | 656 | ||
| 561 | bh.b_size = 1 << (inode->i_blkbits + 5); | 657 | bh.b_size = 1 << (inode->i_blkbits + (create ? 0 : 5)); |
| 562 | ret = gfs2_block_map(inode, lblock, &bh, create); | 658 | ret = gfs2_block_map(inode, lblock, &bh, create); |
| 563 | *extlen = bh.b_size >> inode->i_blkbits; | 659 | *extlen = bh.b_size >> inode->i_blkbits; |
| 564 | *dblock = bh.b_blocknr; | 660 | *dblock = bh.b_blocknr; |
| @@ -621,7 +717,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
| 621 | if (error) | 717 | if (error) |
| 622 | goto out; | 718 | goto out; |
| 623 | 719 | ||
| 624 | if (height < ip->i_di.di_height - 1) | 720 | if (height < ip->i_height - 1) |
| 625 | for (; top < bottom; top++, first = 0) { | 721 | for (; top < bottom; top++, first = 0) { |
| 626 | if (!*top) | 722 | if (!*top) |
| 627 | continue; | 723 | continue; |
| @@ -679,7 +775,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
| 679 | sm->sm_first = 0; | 775 | sm->sm_first = 0; |
| 680 | } | 776 | } |
| 681 | 777 | ||
| 682 | metadata = (height != ip->i_di.di_height - 1); | 778 | metadata = (height != ip->i_height - 1); |
| 683 | if (metadata) | 779 | if (metadata) |
| 684 | revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; | 780 | revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; |
| 685 | 781 | ||
| @@ -713,7 +809,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
| 713 | else | 809 | else |
| 714 | goto out; /* Nothing to do */ | 810 | goto out; /* Nothing to do */ |
| 715 | 811 | ||
| 716 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0); | 812 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE); |
| 717 | 813 | ||
| 718 | for (x = 0; x < rlist.rl_rgrps; x++) { | 814 | for (x = 0; x < rlist.rl_rgrps; x++) { |
| 719 | struct gfs2_rgrpd *rgd; | 815 | struct gfs2_rgrpd *rgd; |
| @@ -760,10 +856,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
| 760 | } | 856 | } |
| 761 | 857 | ||
| 762 | *p = 0; | 858 | *p = 0; |
| 763 | if (!ip->i_di.di_blocks) | 859 | gfs2_add_inode_blocks(&ip->i_inode, -1); |
| 764 | gfs2_consist_inode(ip); | ||
| 765 | ip->i_di.di_blocks--; | ||
| 766 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 767 | } | 860 | } |
| 768 | if (bstart) { | 861 | if (bstart) { |
| 769 | if (metadata) | 862 | if (metadata) |
| @@ -804,19 +897,16 @@ static int do_grow(struct gfs2_inode *ip, u64 size) | |||
| 804 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 897 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
| 805 | struct gfs2_alloc *al; | 898 | struct gfs2_alloc *al; |
| 806 | struct buffer_head *dibh; | 899 | struct buffer_head *dibh; |
| 807 | unsigned int h; | ||
| 808 | int error; | 900 | int error; |
| 809 | 901 | ||
| 810 | al = gfs2_alloc_get(ip); | 902 | al = gfs2_alloc_get(ip); |
| 903 | if (!al) | ||
| 904 | return -ENOMEM; | ||
| 811 | 905 | ||
| 812 | error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 906 | error = gfs2_quota_lock_check(ip); |
| 813 | if (error) | 907 | if (error) |
| 814 | goto out; | 908 | goto out; |
| 815 | 909 | ||
| 816 | error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); | ||
| 817 | if (error) | ||
| 818 | goto out_gunlock_q; | ||
| 819 | |||
| 820 | al->al_requested = sdp->sd_max_height + RES_DATA; | 910 | al->al_requested = sdp->sd_max_height + RES_DATA; |
| 821 | 911 | ||
| 822 | error = gfs2_inplace_reserve(ip); | 912 | error = gfs2_inplace_reserve(ip); |
| @@ -829,34 +919,25 @@ static int do_grow(struct gfs2_inode *ip, u64 size) | |||
| 829 | if (error) | 919 | if (error) |
| 830 | goto out_ipres; | 920 | goto out_ipres; |
| 831 | 921 | ||
| 922 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
| 923 | if (error) | ||
| 924 | goto out_end_trans; | ||
| 925 | |||
| 832 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { | 926 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { |
| 833 | if (gfs2_is_stuffed(ip)) { | 927 | if (gfs2_is_stuffed(ip)) { |
| 834 | error = gfs2_unstuff_dinode(ip, NULL); | 928 | error = gfs2_unstuff_dinode(ip, NULL); |
| 835 | if (error) | 929 | if (error) |
| 836 | goto out_end_trans; | 930 | goto out_brelse; |
| 837 | } | ||
| 838 | |||
| 839 | h = calc_tree_height(ip, size); | ||
| 840 | if (ip->i_di.di_height < h) { | ||
| 841 | down_write(&ip->i_rw_mutex); | ||
| 842 | error = build_height(&ip->i_inode, h); | ||
| 843 | up_write(&ip->i_rw_mutex); | ||
| 844 | if (error) | ||
| 845 | goto out_end_trans; | ||
| 846 | } | 931 | } |
| 847 | } | 932 | } |
| 848 | 933 | ||
| 849 | ip->i_di.di_size = size; | 934 | ip->i_di.di_size = size; |
| 850 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 935 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
| 851 | |||
| 852 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
| 853 | if (error) | ||
| 854 | goto out_end_trans; | ||
| 855 | |||
| 856 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 936 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
| 857 | gfs2_dinode_out(ip, dibh->b_data); | 937 | gfs2_dinode_out(ip, dibh->b_data); |
| 858 | brelse(dibh); | ||
| 859 | 938 | ||
| 939 | out_brelse: | ||
| 940 | brelse(dibh); | ||
| 860 | out_end_trans: | 941 | out_end_trans: |
| 861 | gfs2_trans_end(sdp); | 942 | gfs2_trans_end(sdp); |
| 862 | out_ipres: | 943 | out_ipres: |
| @@ -986,7 +1067,8 @@ out: | |||
| 986 | 1067 | ||
| 987 | static int trunc_dealloc(struct gfs2_inode *ip, u64 size) | 1068 | static int trunc_dealloc(struct gfs2_inode *ip, u64 size) |
| 988 | { | 1069 | { |
| 989 | unsigned int height = ip->i_di.di_height; | 1070 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
| 1071 | unsigned int height = ip->i_height; | ||
| 990 | u64 lblock; | 1072 | u64 lblock; |
| 991 | struct metapath mp; | 1073 | struct metapath mp; |
| 992 | int error; | 1074 | int error; |
| @@ -994,10 +1076,11 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size) | |||
| 994 | if (!size) | 1076 | if (!size) |
| 995 | lblock = 0; | 1077 | lblock = 0; |
| 996 | else | 1078 | else |
| 997 | lblock = (size - 1) >> GFS2_SB(&ip->i_inode)->sd_sb.sb_bsize_shift; | 1079 | lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift; |
| 998 | 1080 | ||
| 999 | find_metapath(ip, lblock, &mp); | 1081 | find_metapath(sdp, lblock, &mp, ip->i_height); |
| 1000 | gfs2_alloc_get(ip); | 1082 | if (!gfs2_alloc_get(ip)) |
| 1083 | return -ENOMEM; | ||
| 1001 | 1084 | ||
| 1002 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 1085 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); |
| 1003 | if (error) | 1086 | if (error) |
| @@ -1037,10 +1120,8 @@ static int trunc_end(struct gfs2_inode *ip) | |||
| 1037 | goto out; | 1120 | goto out; |
| 1038 | 1121 | ||
| 1039 | if (!ip->i_di.di_size) { | 1122 | if (!ip->i_di.di_size) { |
| 1040 | ip->i_di.di_height = 0; | 1123 | ip->i_height = 0; |
| 1041 | ip->i_di.di_goal_meta = | 1124 | ip->i_goal = ip->i_no_addr; |
| 1042 | ip->i_di.di_goal_data = | ||
| 1043 | ip->i_no_addr; | ||
| 1044 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); | 1125 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); |
| 1045 | } | 1126 | } |
| 1046 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 1127 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
| @@ -1197,10 +1278,9 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
| 1197 | unsigned int len, int *alloc_required) | 1278 | unsigned int len, int *alloc_required) |
| 1198 | { | 1279 | { |
| 1199 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1280 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
| 1200 | u64 lblock, lblock_stop, dblock; | 1281 | struct buffer_head bh; |
| 1201 | u32 extlen; | 1282 | unsigned int shift; |
| 1202 | int new = 0; | 1283 | u64 lblock, lblock_stop, size; |
| 1203 | int error = 0; | ||
| 1204 | 1284 | ||
| 1205 | *alloc_required = 0; | 1285 | *alloc_required = 0; |
| 1206 | 1286 | ||
| @@ -1214,6 +1294,8 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
| 1214 | return 0; | 1294 | return 0; |
| 1215 | } | 1295 | } |
| 1216 | 1296 | ||
| 1297 | *alloc_required = 1; | ||
| 1298 | shift = sdp->sd_sb.sb_bsize_shift; | ||
| 1217 | if (gfs2_is_dir(ip)) { | 1299 | if (gfs2_is_dir(ip)) { |
| 1218 | unsigned int bsize = sdp->sd_jbsize; | 1300 | unsigned int bsize = sdp->sd_jbsize; |
| 1219 | lblock = offset; | 1301 | lblock = offset; |
| @@ -1221,27 +1303,25 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
| 1221 | lblock_stop = offset + len + bsize - 1; | 1303 | lblock_stop = offset + len + bsize - 1; |
| 1222 | do_div(lblock_stop, bsize); | 1304 | do_div(lblock_stop, bsize); |
| 1223 | } else { | 1305 | } else { |
| 1224 | unsigned int shift = sdp->sd_sb.sb_bsize_shift; | ||
| 1225 | u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift; | 1306 | u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift; |
| 1226 | lblock = offset >> shift; | 1307 | lblock = offset >> shift; |
| 1227 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; | 1308 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; |
| 1228 | if (lblock_stop > end_of_file) { | 1309 | if (lblock_stop > end_of_file) |
| 1229 | *alloc_required = 1; | ||
| 1230 | return 0; | 1310 | return 0; |
| 1231 | } | ||
| 1232 | } | 1311 | } |
| 1233 | 1312 | ||
| 1234 | for (; lblock < lblock_stop; lblock += extlen) { | 1313 | size = (lblock_stop - lblock) << shift; |
| 1235 | error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen); | 1314 | do { |
| 1236 | if (error) | 1315 | bh.b_state = 0; |
| 1237 | return error; | 1316 | bh.b_size = size; |
| 1238 | 1317 | gfs2_block_map(&ip->i_inode, lblock, &bh, 0); | |
| 1239 | if (!dblock) { | 1318 | if (!buffer_mapped(&bh)) |
| 1240 | *alloc_required = 1; | ||
| 1241 | return 0; | 1319 | return 0; |
| 1242 | } | 1320 | size -= bh.b_size; |
| 1243 | } | 1321 | lblock += (bh.b_size >> ip->i_inode.i_blkbits); |
| 1322 | } while(size > 0); | ||
| 1244 | 1323 | ||
| 1324 | *alloc_required = 0; | ||
| 1245 | return 0; | 1325 | return 0; |
| 1246 | } | 1326 | } |
| 1247 | 1327 | ||
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index c34709512b19..eed040d8ba3a 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
| @@ -159,6 +159,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, | |||
| 159 | unsigned int o; | 159 | unsigned int o; |
| 160 | int copied = 0; | 160 | int copied = 0; |
| 161 | int error = 0; | 161 | int error = 0; |
| 162 | int new = 0; | ||
| 162 | 163 | ||
| 163 | if (!size) | 164 | if (!size) |
| 164 | return 0; | 165 | return 0; |
| @@ -183,7 +184,6 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, | |||
| 183 | while (copied < size) { | 184 | while (copied < size) { |
| 184 | unsigned int amount; | 185 | unsigned int amount; |
| 185 | struct buffer_head *bh; | 186 | struct buffer_head *bh; |
| 186 | int new = 0; | ||
| 187 | 187 | ||
| 188 | amount = size - copied; | 188 | amount = size - copied; |
| 189 | if (amount > sdp->sd_sb.sb_bsize - o) | 189 | if (amount > sdp->sd_sb.sb_bsize - o) |
| @@ -757,7 +757,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode, | |||
| 757 | 757 | ||
| 758 | if (ip->i_di.di_flags & GFS2_DIF_EXHASH) { | 758 | if (ip->i_di.di_flags & GFS2_DIF_EXHASH) { |
| 759 | struct gfs2_leaf *leaf; | 759 | struct gfs2_leaf *leaf; |
| 760 | unsigned hsize = 1 << ip->i_di.di_depth; | 760 | unsigned hsize = 1 << ip->i_depth; |
| 761 | unsigned index; | 761 | unsigned index; |
| 762 | u64 ln; | 762 | u64 ln; |
| 763 | if (hsize * sizeof(u64) != ip->i_di.di_size) { | 763 | if (hsize * sizeof(u64) != ip->i_di.di_size) { |
| @@ -765,7 +765,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode, | |||
| 765 | return ERR_PTR(-EIO); | 765 | return ERR_PTR(-EIO); |
| 766 | } | 766 | } |
| 767 | 767 | ||
| 768 | index = name->hash >> (32 - ip->i_di.di_depth); | 768 | index = name->hash >> (32 - ip->i_depth); |
| 769 | error = get_first_leaf(ip, index, &bh); | 769 | error = get_first_leaf(ip, index, &bh); |
| 770 | if (error) | 770 | if (error) |
| 771 | return ERR_PTR(error); | 771 | return ERR_PTR(error); |
| @@ -803,14 +803,15 @@ got_dent: | |||
| 803 | static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth) | 803 | static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth) |
| 804 | { | 804 | { |
| 805 | struct gfs2_inode *ip = GFS2_I(inode); | 805 | struct gfs2_inode *ip = GFS2_I(inode); |
| 806 | u64 bn = gfs2_alloc_meta(ip); | 806 | unsigned int n = 1; |
| 807 | u64 bn = gfs2_alloc_block(ip, &n); | ||
| 807 | struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn); | 808 | struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn); |
| 808 | struct gfs2_leaf *leaf; | 809 | struct gfs2_leaf *leaf; |
| 809 | struct gfs2_dirent *dent; | 810 | struct gfs2_dirent *dent; |
| 810 | struct qstr name = { .name = "", .len = 0, .hash = 0 }; | 811 | struct qstr name = { .name = "", .len = 0, .hash = 0 }; |
| 811 | if (!bh) | 812 | if (!bh) |
| 812 | return NULL; | 813 | return NULL; |
| 813 | 814 | gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, 1); | |
| 814 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 815 | gfs2_trans_add_bh(ip->i_gl, bh, 1); |
| 815 | gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF); | 816 | gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF); |
| 816 | leaf = (struct gfs2_leaf *)bh->b_data; | 817 | leaf = (struct gfs2_leaf *)bh->b_data; |
| @@ -905,12 +906,11 @@ static int dir_make_exhash(struct inode *inode) | |||
| 905 | *lp = cpu_to_be64(bn); | 906 | *lp = cpu_to_be64(bn); |
| 906 | 907 | ||
| 907 | dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2; | 908 | dip->i_di.di_size = sdp->sd_sb.sb_bsize / 2; |
| 908 | dip->i_di.di_blocks++; | 909 | gfs2_add_inode_blocks(&dip->i_inode, 1); |
| 909 | gfs2_set_inode_blocks(&dip->i_inode); | ||
| 910 | dip->i_di.di_flags |= GFS2_DIF_EXHASH; | 910 | dip->i_di.di_flags |= GFS2_DIF_EXHASH; |
| 911 | 911 | ||
| 912 | for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; | 912 | for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; |
| 913 | dip->i_di.di_depth = y; | 913 | dip->i_depth = y; |
| 914 | 914 | ||
| 915 | gfs2_dinode_out(dip, dibh->b_data); | 915 | gfs2_dinode_out(dip, dibh->b_data); |
| 916 | 916 | ||
| @@ -941,7 +941,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
| 941 | int x, moved = 0; | 941 | int x, moved = 0; |
| 942 | int error; | 942 | int error; |
| 943 | 943 | ||
| 944 | index = name->hash >> (32 - dip->i_di.di_depth); | 944 | index = name->hash >> (32 - dip->i_depth); |
| 945 | error = get_leaf_nr(dip, index, &leaf_no); | 945 | error = get_leaf_nr(dip, index, &leaf_no); |
| 946 | if (error) | 946 | if (error) |
| 947 | return error; | 947 | return error; |
| @@ -952,7 +952,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
| 952 | return error; | 952 | return error; |
| 953 | 953 | ||
| 954 | oleaf = (struct gfs2_leaf *)obh->b_data; | 954 | oleaf = (struct gfs2_leaf *)obh->b_data; |
| 955 | if (dip->i_di.di_depth == be16_to_cpu(oleaf->lf_depth)) { | 955 | if (dip->i_depth == be16_to_cpu(oleaf->lf_depth)) { |
| 956 | brelse(obh); | 956 | brelse(obh); |
| 957 | return 1; /* can't split */ | 957 | return 1; /* can't split */ |
| 958 | } | 958 | } |
| @@ -967,10 +967,10 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
| 967 | bn = nbh->b_blocknr; | 967 | bn = nbh->b_blocknr; |
| 968 | 968 | ||
| 969 | /* Compute the start and len of leaf pointers in the hash table. */ | 969 | /* Compute the start and len of leaf pointers in the hash table. */ |
| 970 | len = 1 << (dip->i_di.di_depth - be16_to_cpu(oleaf->lf_depth)); | 970 | len = 1 << (dip->i_depth - be16_to_cpu(oleaf->lf_depth)); |
| 971 | half_len = len >> 1; | 971 | half_len = len >> 1; |
| 972 | if (!half_len) { | 972 | if (!half_len) { |
| 973 | printk(KERN_WARNING "di_depth %u lf_depth %u index %u\n", dip->i_di.di_depth, be16_to_cpu(oleaf->lf_depth), index); | 973 | printk(KERN_WARNING "i_depth %u lf_depth %u index %u\n", dip->i_depth, be16_to_cpu(oleaf->lf_depth), index); |
| 974 | gfs2_consist_inode(dip); | 974 | gfs2_consist_inode(dip); |
| 975 | error = -EIO; | 975 | error = -EIO; |
| 976 | goto fail_brelse; | 976 | goto fail_brelse; |
| @@ -997,7 +997,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
| 997 | kfree(lp); | 997 | kfree(lp); |
| 998 | 998 | ||
| 999 | /* Compute the divider */ | 999 | /* Compute the divider */ |
| 1000 | divider = (start + half_len) << (32 - dip->i_di.di_depth); | 1000 | divider = (start + half_len) << (32 - dip->i_depth); |
| 1001 | 1001 | ||
| 1002 | /* Copy the entries */ | 1002 | /* Copy the entries */ |
| 1003 | dirent_first(dip, obh, &dent); | 1003 | dirent_first(dip, obh, &dent); |
| @@ -1021,13 +1021,13 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
| 1021 | 1021 | ||
| 1022 | new->de_inum = dent->de_inum; /* No endian worries */ | 1022 | new->de_inum = dent->de_inum; /* No endian worries */ |
| 1023 | new->de_type = dent->de_type; /* No endian worries */ | 1023 | new->de_type = dent->de_type; /* No endian worries */ |
| 1024 | nleaf->lf_entries = cpu_to_be16(be16_to_cpu(nleaf->lf_entries)+1); | 1024 | be16_add_cpu(&nleaf->lf_entries, 1); |
| 1025 | 1025 | ||
| 1026 | dirent_del(dip, obh, prev, dent); | 1026 | dirent_del(dip, obh, prev, dent); |
| 1027 | 1027 | ||
| 1028 | if (!oleaf->lf_entries) | 1028 | if (!oleaf->lf_entries) |
| 1029 | gfs2_consist_inode(dip); | 1029 | gfs2_consist_inode(dip); |
| 1030 | oleaf->lf_entries = cpu_to_be16(be16_to_cpu(oleaf->lf_entries)-1); | 1030 | be16_add_cpu(&oleaf->lf_entries, -1); |
| 1031 | 1031 | ||
| 1032 | if (!prev) | 1032 | if (!prev) |
| 1033 | prev = dent; | 1033 | prev = dent; |
| @@ -1044,8 +1044,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
| 1044 | error = gfs2_meta_inode_buffer(dip, &dibh); | 1044 | error = gfs2_meta_inode_buffer(dip, &dibh); |
| 1045 | if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) { | 1045 | if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) { |
| 1046 | gfs2_trans_add_bh(dip->i_gl, dibh, 1); | 1046 | gfs2_trans_add_bh(dip->i_gl, dibh, 1); |
| 1047 | dip->i_di.di_blocks++; | 1047 | gfs2_add_inode_blocks(&dip->i_inode, 1); |
| 1048 | gfs2_set_inode_blocks(&dip->i_inode); | ||
| 1049 | gfs2_dinode_out(dip, dibh->b_data); | 1048 | gfs2_dinode_out(dip, dibh->b_data); |
| 1050 | brelse(dibh); | 1049 | brelse(dibh); |
| 1051 | } | 1050 | } |
| @@ -1082,7 +1081,7 @@ static int dir_double_exhash(struct gfs2_inode *dip) | |||
| 1082 | int x; | 1081 | int x; |
| 1083 | int error = 0; | 1082 | int error = 0; |
| 1084 | 1083 | ||
| 1085 | hsize = 1 << dip->i_di.di_depth; | 1084 | hsize = 1 << dip->i_depth; |
| 1086 | if (hsize * sizeof(u64) != dip->i_di.di_size) { | 1085 | if (hsize * sizeof(u64) != dip->i_di.di_size) { |
| 1087 | gfs2_consist_inode(dip); | 1086 | gfs2_consist_inode(dip); |
| 1088 | return -EIO; | 1087 | return -EIO; |
| @@ -1090,7 +1089,7 @@ static int dir_double_exhash(struct gfs2_inode *dip) | |||
| 1090 | 1089 | ||
| 1091 | /* Allocate both the "from" and "to" buffers in one big chunk */ | 1090 | /* Allocate both the "from" and "to" buffers in one big chunk */ |
| 1092 | 1091 | ||
| 1093 | buf = kcalloc(3, sdp->sd_hash_bsize, GFP_KERNEL | __GFP_NOFAIL); | 1092 | buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS | __GFP_NOFAIL); |
| 1094 | 1093 | ||
| 1095 | for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) { | 1094 | for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) { |
| 1096 | error = gfs2_dir_read_data(dip, (char *)buf, | 1095 | error = gfs2_dir_read_data(dip, (char *)buf, |
| @@ -1125,7 +1124,7 @@ static int dir_double_exhash(struct gfs2_inode *dip) | |||
| 1125 | 1124 | ||
| 1126 | error = gfs2_meta_inode_buffer(dip, &dibh); | 1125 | error = gfs2_meta_inode_buffer(dip, &dibh); |
| 1127 | if (!gfs2_assert_withdraw(sdp, !error)) { | 1126 | if (!gfs2_assert_withdraw(sdp, !error)) { |
| 1128 | dip->i_di.di_depth++; | 1127 | dip->i_depth++; |
| 1129 | gfs2_dinode_out(dip, dibh->b_data); | 1128 | gfs2_dinode_out(dip, dibh->b_data); |
| 1130 | brelse(dibh); | 1129 | brelse(dibh); |
| 1131 | } | 1130 | } |
| @@ -1370,16 +1369,16 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, | |||
| 1370 | int error = 0; | 1369 | int error = 0; |
| 1371 | unsigned depth = 0; | 1370 | unsigned depth = 0; |
| 1372 | 1371 | ||
| 1373 | hsize = 1 << dip->i_di.di_depth; | 1372 | hsize = 1 << dip->i_depth; |
| 1374 | if (hsize * sizeof(u64) != dip->i_di.di_size) { | 1373 | if (hsize * sizeof(u64) != dip->i_di.di_size) { |
| 1375 | gfs2_consist_inode(dip); | 1374 | gfs2_consist_inode(dip); |
| 1376 | return -EIO; | 1375 | return -EIO; |
| 1377 | } | 1376 | } |
| 1378 | 1377 | ||
| 1379 | hash = gfs2_dir_offset2hash(*offset); | 1378 | hash = gfs2_dir_offset2hash(*offset); |
| 1380 | index = hash >> (32 - dip->i_di.di_depth); | 1379 | index = hash >> (32 - dip->i_depth); |
| 1381 | 1380 | ||
| 1382 | lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL); | 1381 | lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS); |
| 1383 | if (!lp) | 1382 | if (!lp) |
| 1384 | return -ENOMEM; | 1383 | return -ENOMEM; |
| 1385 | 1384 | ||
| @@ -1405,7 +1404,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, | |||
| 1405 | if (error) | 1404 | if (error) |
| 1406 | break; | 1405 | break; |
| 1407 | 1406 | ||
| 1408 | len = 1 << (dip->i_di.di_depth - depth); | 1407 | len = 1 << (dip->i_depth - depth); |
| 1409 | index = (index & ~(len - 1)) + len; | 1408 | index = (index & ~(len - 1)) + len; |
| 1410 | } | 1409 | } |
| 1411 | 1410 | ||
| @@ -1444,7 +1443,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | |||
| 1444 | 1443 | ||
| 1445 | error = -ENOMEM; | 1444 | error = -ENOMEM; |
| 1446 | /* 96 is max number of dirents which can be stuffed into an inode */ | 1445 | /* 96 is max number of dirents which can be stuffed into an inode */ |
| 1447 | darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_KERNEL); | 1446 | darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_NOFS); |
| 1448 | if (darr) { | 1447 | if (darr) { |
| 1449 | g.pdent = darr; | 1448 | g.pdent = darr; |
| 1450 | g.offset = 0; | 1449 | g.offset = 0; |
| @@ -1549,7 +1548,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) | |||
| 1549 | u32 index; | 1548 | u32 index; |
| 1550 | u64 bn; | 1549 | u64 bn; |
| 1551 | 1550 | ||
| 1552 | index = name->hash >> (32 - ip->i_di.di_depth); | 1551 | index = name->hash >> (32 - ip->i_depth); |
| 1553 | error = get_first_leaf(ip, index, &obh); | 1552 | error = get_first_leaf(ip, index, &obh); |
| 1554 | if (error) | 1553 | if (error) |
| 1555 | return error; | 1554 | return error; |
| @@ -1579,8 +1578,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) | |||
| 1579 | if (error) | 1578 | if (error) |
| 1580 | return error; | 1579 | return error; |
| 1581 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 1580 | gfs2_trans_add_bh(ip->i_gl, bh, 1); |
| 1582 | ip->i_di.di_blocks++; | 1581 | gfs2_add_inode_blocks(&ip->i_inode, 1); |
| 1583 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 1584 | gfs2_dinode_out(ip, bh->b_data); | 1582 | gfs2_dinode_out(ip, bh->b_data); |
| 1585 | brelse(bh); | 1583 | brelse(bh); |
| 1586 | return 0; | 1584 | return 0; |
| @@ -1616,7 +1614,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, | |||
| 1616 | dent->de_type = cpu_to_be16(type); | 1614 | dent->de_type = cpu_to_be16(type); |
| 1617 | if (ip->i_di.di_flags & GFS2_DIF_EXHASH) { | 1615 | if (ip->i_di.di_flags & GFS2_DIF_EXHASH) { |
| 1618 | leaf = (struct gfs2_leaf *)bh->b_data; | 1616 | leaf = (struct gfs2_leaf *)bh->b_data; |
| 1619 | leaf->lf_entries = cpu_to_be16(be16_to_cpu(leaf->lf_entries) + 1); | 1617 | be16_add_cpu(&leaf->lf_entries, 1); |
| 1620 | } | 1618 | } |
| 1621 | brelse(bh); | 1619 | brelse(bh); |
| 1622 | error = gfs2_meta_inode_buffer(ip, &bh); | 1620 | error = gfs2_meta_inode_buffer(ip, &bh); |
| @@ -1641,7 +1639,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, | |||
| 1641 | continue; | 1639 | continue; |
| 1642 | if (error < 0) | 1640 | if (error < 0) |
| 1643 | break; | 1641 | break; |
| 1644 | if (ip->i_di.di_depth < GFS2_DIR_MAX_DEPTH) { | 1642 | if (ip->i_depth < GFS2_DIR_MAX_DEPTH) { |
| 1645 | error = dir_double_exhash(ip); | 1643 | error = dir_double_exhash(ip); |
| 1646 | if (error) | 1644 | if (error) |
| 1647 | break; | 1645 | break; |
| @@ -1785,13 +1783,13 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data) | |||
| 1785 | u64 leaf_no; | 1783 | u64 leaf_no; |
| 1786 | int error = 0; | 1784 | int error = 0; |
| 1787 | 1785 | ||
| 1788 | hsize = 1 << dip->i_di.di_depth; | 1786 | hsize = 1 << dip->i_depth; |
| 1789 | if (hsize * sizeof(u64) != dip->i_di.di_size) { | 1787 | if (hsize * sizeof(u64) != dip->i_di.di_size) { |
| 1790 | gfs2_consist_inode(dip); | 1788 | gfs2_consist_inode(dip); |
| 1791 | return -EIO; | 1789 | return -EIO; |
| 1792 | } | 1790 | } |
| 1793 | 1791 | ||
| 1794 | lp = kmalloc(sdp->sd_hash_bsize, GFP_KERNEL); | 1792 | lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS); |
| 1795 | if (!lp) | 1793 | if (!lp) |
| 1796 | return -ENOMEM; | 1794 | return -ENOMEM; |
| 1797 | 1795 | ||
| @@ -1817,7 +1815,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data) | |||
| 1817 | if (error) | 1815 | if (error) |
| 1818 | goto out; | 1816 | goto out; |
| 1819 | leaf = (struct gfs2_leaf *)bh->b_data; | 1817 | leaf = (struct gfs2_leaf *)bh->b_data; |
| 1820 | len = 1 << (dip->i_di.di_depth - be16_to_cpu(leaf->lf_depth)); | 1818 | len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth)); |
| 1821 | brelse(bh); | 1819 | brelse(bh); |
| 1822 | 1820 | ||
| 1823 | error = lc(dip, index, len, leaf_no, data); | 1821 | error = lc(dip, index, len, leaf_no, data); |
| @@ -1866,15 +1864,18 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | |||
| 1866 | 1864 | ||
| 1867 | memset(&rlist, 0, sizeof(struct gfs2_rgrp_list)); | 1865 | memset(&rlist, 0, sizeof(struct gfs2_rgrp_list)); |
| 1868 | 1866 | ||
| 1869 | ht = kzalloc(size, GFP_KERNEL); | 1867 | ht = kzalloc(size, GFP_NOFS); |
| 1870 | if (!ht) | 1868 | if (!ht) |
| 1871 | return -ENOMEM; | 1869 | return -ENOMEM; |
| 1872 | 1870 | ||
| 1873 | gfs2_alloc_get(dip); | 1871 | if (!gfs2_alloc_get(dip)) { |
| 1872 | error = -ENOMEM; | ||
| 1873 | goto out; | ||
| 1874 | } | ||
| 1874 | 1875 | ||
| 1875 | error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 1876 | error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); |
| 1876 | if (error) | 1877 | if (error) |
| 1877 | goto out; | 1878 | goto out_put; |
| 1878 | 1879 | ||
| 1879 | error = gfs2_rindex_hold(sdp, &dip->i_alloc->al_ri_gh); | 1880 | error = gfs2_rindex_hold(sdp, &dip->i_alloc->al_ri_gh); |
| 1880 | if (error) | 1881 | if (error) |
| @@ -1894,7 +1895,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | |||
| 1894 | l_blocks++; | 1895 | l_blocks++; |
| 1895 | } | 1896 | } |
| 1896 | 1897 | ||
| 1897 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0); | 1898 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE); |
| 1898 | 1899 | ||
| 1899 | for (x = 0; x < rlist.rl_rgrps; x++) { | 1900 | for (x = 0; x < rlist.rl_rgrps; x++) { |
| 1900 | struct gfs2_rgrpd *rgd; | 1901 | struct gfs2_rgrpd *rgd; |
| @@ -1921,11 +1922,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | |||
| 1921 | brelse(bh); | 1922 | brelse(bh); |
| 1922 | 1923 | ||
| 1923 | gfs2_free_meta(dip, blk, 1); | 1924 | gfs2_free_meta(dip, blk, 1); |
| 1924 | 1925 | gfs2_add_inode_blocks(&dip->i_inode, -1); | |
| 1925 | if (!dip->i_di.di_blocks) | ||
| 1926 | gfs2_consist_inode(dip); | ||
| 1927 | dip->i_di.di_blocks--; | ||
| 1928 | gfs2_set_inode_blocks(&dip->i_inode); | ||
| 1929 | } | 1926 | } |
| 1930 | 1927 | ||
| 1931 | error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size); | 1928 | error = gfs2_dir_write_data(dip, ht, index * sizeof(u64), size); |
| @@ -1952,8 +1949,9 @@ out_rlist: | |||
| 1952 | gfs2_glock_dq_uninit(&dip->i_alloc->al_ri_gh); | 1949 | gfs2_glock_dq_uninit(&dip->i_alloc->al_ri_gh); |
| 1953 | out_qs: | 1950 | out_qs: |
| 1954 | gfs2_quota_unhold(dip); | 1951 | gfs2_quota_unhold(dip); |
| 1955 | out: | 1952 | out_put: |
| 1956 | gfs2_alloc_put(dip); | 1953 | gfs2_alloc_put(dip); |
| 1954 | out: | ||
| 1957 | kfree(ht); | 1955 | kfree(ht); |
| 1958 | return error; | 1956 | return error; |
| 1959 | } | 1957 | } |
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c index bee99704ea10..e3f76f451b0a 100644 --- a/fs/gfs2/eattr.c +++ b/fs/gfs2/eattr.c | |||
| @@ -277,10 +277,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, | |||
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | *dataptrs = 0; | 279 | *dataptrs = 0; |
| 280 | if (!ip->i_di.di_blocks) | 280 | gfs2_add_inode_blocks(&ip->i_inode, -1); |
| 281 | gfs2_consist_inode(ip); | ||
| 282 | ip->i_di.di_blocks--; | ||
| 283 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 284 | } | 281 | } |
| 285 | if (bstart) | 282 | if (bstart) |
| 286 | gfs2_free_meta(ip, bstart, blen); | 283 | gfs2_free_meta(ip, bstart, blen); |
| @@ -321,6 +318,8 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, | |||
| 321 | int error; | 318 | int error; |
| 322 | 319 | ||
| 323 | al = gfs2_alloc_get(ip); | 320 | al = gfs2_alloc_get(ip); |
| 321 | if (!al) | ||
| 322 | return -ENOMEM; | ||
| 324 | 323 | ||
| 325 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 324 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); |
| 326 | if (error) | 325 | if (error) |
| @@ -449,7 +448,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, | |||
| 449 | unsigned int x; | 448 | unsigned int x; |
| 450 | int error = 0; | 449 | int error = 0; |
| 451 | 450 | ||
| 452 | bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL); | 451 | bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS); |
| 453 | if (!bh) | 452 | if (!bh) |
| 454 | return -ENOMEM; | 453 | return -ENOMEM; |
| 455 | 454 | ||
| @@ -582,10 +581,11 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp) | |||
| 582 | { | 581 | { |
| 583 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 582 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
| 584 | struct gfs2_ea_header *ea; | 583 | struct gfs2_ea_header *ea; |
| 584 | unsigned int n = 1; | ||
| 585 | u64 block; | 585 | u64 block; |
| 586 | 586 | ||
| 587 | block = gfs2_alloc_meta(ip); | 587 | block = gfs2_alloc_block(ip, &n); |
| 588 | 588 | gfs2_trans_add_unrevoke(sdp, block, 1); | |
| 589 | *bhp = gfs2_meta_new(ip->i_gl, block); | 589 | *bhp = gfs2_meta_new(ip->i_gl, block); |
| 590 | gfs2_trans_add_bh(ip->i_gl, *bhp, 1); | 590 | gfs2_trans_add_bh(ip->i_gl, *bhp, 1); |
| 591 | gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA); | 591 | gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA); |
| @@ -597,8 +597,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp) | |||
| 597 | ea->ea_flags = GFS2_EAFLAG_LAST; | 597 | ea->ea_flags = GFS2_EAFLAG_LAST; |
| 598 | ea->ea_num_ptrs = 0; | 598 | ea->ea_num_ptrs = 0; |
| 599 | 599 | ||
| 600 | ip->i_di.di_blocks++; | 600 | gfs2_add_inode_blocks(&ip->i_inode, 1); |
| 601 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 602 | 601 | ||
| 603 | return 0; | 602 | return 0; |
| 604 | } | 603 | } |
| @@ -642,15 +641,15 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea, | |||
| 642 | struct buffer_head *bh; | 641 | struct buffer_head *bh; |
| 643 | u64 block; | 642 | u64 block; |
| 644 | int mh_size = sizeof(struct gfs2_meta_header); | 643 | int mh_size = sizeof(struct gfs2_meta_header); |
| 644 | unsigned int n = 1; | ||
| 645 | 645 | ||
| 646 | block = gfs2_alloc_meta(ip); | 646 | block = gfs2_alloc_block(ip, &n); |
| 647 | 647 | gfs2_trans_add_unrevoke(sdp, block, 1); | |
| 648 | bh = gfs2_meta_new(ip->i_gl, block); | 648 | bh = gfs2_meta_new(ip->i_gl, block); |
| 649 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 649 | gfs2_trans_add_bh(ip->i_gl, bh, 1); |
| 650 | gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED); | 650 | gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED); |
| 651 | 651 | ||
| 652 | ip->i_di.di_blocks++; | 652 | gfs2_add_inode_blocks(&ip->i_inode, 1); |
| 653 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 654 | 653 | ||
| 655 | copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize : | 654 | copy = data_len > sdp->sd_jbsize ? sdp->sd_jbsize : |
| 656 | data_len; | 655 | data_len; |
| @@ -684,15 +683,13 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er, | |||
| 684 | int error; | 683 | int error; |
| 685 | 684 | ||
| 686 | al = gfs2_alloc_get(ip); | 685 | al = gfs2_alloc_get(ip); |
| 686 | if (!al) | ||
| 687 | return -ENOMEM; | ||
| 687 | 688 | ||
| 688 | error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 689 | error = gfs2_quota_lock_check(ip); |
| 689 | if (error) | 690 | if (error) |
| 690 | goto out; | 691 | goto out; |
| 691 | 692 | ||
| 692 | error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); | ||
| 693 | if (error) | ||
| 694 | goto out_gunlock_q; | ||
| 695 | |||
| 696 | al->al_requested = blks; | 693 | al->al_requested = blks; |
| 697 | 694 | ||
| 698 | error = gfs2_inplace_reserve(ip); | 695 | error = gfs2_inplace_reserve(ip); |
| @@ -966,9 +963,9 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, | |||
| 966 | gfs2_trans_add_bh(ip->i_gl, indbh, 1); | 963 | gfs2_trans_add_bh(ip->i_gl, indbh, 1); |
| 967 | } else { | 964 | } else { |
| 968 | u64 blk; | 965 | u64 blk; |
| 969 | 966 | unsigned int n = 1; | |
| 970 | blk = gfs2_alloc_meta(ip); | 967 | blk = gfs2_alloc_block(ip, &n); |
| 971 | 968 | gfs2_trans_add_unrevoke(sdp, blk, 1); | |
| 972 | indbh = gfs2_meta_new(ip->i_gl, blk); | 969 | indbh = gfs2_meta_new(ip->i_gl, blk); |
| 973 | gfs2_trans_add_bh(ip->i_gl, indbh, 1); | 970 | gfs2_trans_add_bh(ip->i_gl, indbh, 1); |
| 974 | gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); | 971 | gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); |
| @@ -978,8 +975,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, | |||
| 978 | *eablk = cpu_to_be64(ip->i_di.di_eattr); | 975 | *eablk = cpu_to_be64(ip->i_di.di_eattr); |
| 979 | ip->i_di.di_eattr = blk; | 976 | ip->i_di.di_eattr = blk; |
| 980 | ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT; | 977 | ip->i_di.di_flags |= GFS2_DIF_EA_INDIRECT; |
| 981 | ip->i_di.di_blocks++; | 978 | gfs2_add_inode_blocks(&ip->i_inode, 1); |
| 982 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 983 | 979 | ||
| 984 | eablk++; | 980 | eablk++; |
| 985 | } | 981 | } |
| @@ -1210,7 +1206,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip, | |||
| 1210 | unsigned int x; | 1206 | unsigned int x; |
| 1211 | int error; | 1207 | int error; |
| 1212 | 1208 | ||
| 1213 | bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_KERNEL); | 1209 | bh = kcalloc(nptrs, sizeof(struct buffer_head *), GFP_NOFS); |
| 1214 | if (!bh) | 1210 | if (!bh) |
| 1215 | return -ENOMEM; | 1211 | return -ENOMEM; |
| 1216 | 1212 | ||
| @@ -1347,7 +1343,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) | |||
| 1347 | else | 1343 | else |
| 1348 | goto out; | 1344 | goto out; |
| 1349 | 1345 | ||
| 1350 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0); | 1346 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE); |
| 1351 | 1347 | ||
| 1352 | for (x = 0; x < rlist.rl_rgrps; x++) { | 1348 | for (x = 0; x < rlist.rl_rgrps; x++) { |
| 1353 | struct gfs2_rgrpd *rgd; | 1349 | struct gfs2_rgrpd *rgd; |
| @@ -1387,10 +1383,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) | |||
| 1387 | } | 1383 | } |
| 1388 | 1384 | ||
| 1389 | *eablk = 0; | 1385 | *eablk = 0; |
| 1390 | if (!ip->i_di.di_blocks) | 1386 | gfs2_add_inode_blocks(&ip->i_inode, -1); |
| 1391 | gfs2_consist_inode(ip); | ||
| 1392 | ip->i_di.di_blocks--; | ||
| 1393 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 1394 | } | 1387 | } |
| 1395 | if (bstart) | 1388 | if (bstart) |
| 1396 | gfs2_free_meta(ip, bstart, blen); | 1389 | gfs2_free_meta(ip, bstart, blen); |
| @@ -1442,10 +1435,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip) | |||
| 1442 | gfs2_free_meta(ip, ip->i_di.di_eattr, 1); | 1435 | gfs2_free_meta(ip, ip->i_di.di_eattr, 1); |
| 1443 | 1436 | ||
| 1444 | ip->i_di.di_eattr = 0; | 1437 | ip->i_di.di_eattr = 0; |
| 1445 | if (!ip->i_di.di_blocks) | 1438 | gfs2_add_inode_blocks(&ip->i_inode, -1); |
| 1446 | gfs2_consist_inode(ip); | ||
| 1447 | ip->i_di.di_blocks--; | ||
| 1448 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 1449 | 1439 | ||
| 1450 | error = gfs2_meta_inode_buffer(ip, &dibh); | 1440 | error = gfs2_meta_inode_buffer(ip, &dibh); |
| 1451 | if (!error) { | 1441 | if (!error) { |
| @@ -1474,6 +1464,8 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip) | |||
| 1474 | int error; | 1464 | int error; |
| 1475 | 1465 | ||
| 1476 | al = gfs2_alloc_get(ip); | 1466 | al = gfs2_alloc_get(ip); |
| 1467 | if (!al) | ||
| 1468 | return -ENOMEM; | ||
| 1477 | 1469 | ||
| 1478 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 1470 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); |
| 1479 | if (error) | 1471 | if (error) |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 7175a4d06435..d636b3e80f5d 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -35,7 +35,6 @@ | |||
| 35 | #include "glock.h" | 35 | #include "glock.h" |
| 36 | #include "glops.h" | 36 | #include "glops.h" |
| 37 | #include "inode.h" | 37 | #include "inode.h" |
| 38 | #include "lm.h" | ||
| 39 | #include "lops.h" | 38 | #include "lops.h" |
| 40 | #include "meta_io.h" | 39 | #include "meta_io.h" |
| 41 | #include "quota.h" | 40 | #include "quota.h" |
| @@ -183,7 +182,8 @@ static void glock_free(struct gfs2_glock *gl) | |||
| 183 | struct gfs2_sbd *sdp = gl->gl_sbd; | 182 | struct gfs2_sbd *sdp = gl->gl_sbd; |
| 184 | struct inode *aspace = gl->gl_aspace; | 183 | struct inode *aspace = gl->gl_aspace; |
| 185 | 184 | ||
| 186 | gfs2_lm_put_lock(sdp, gl->gl_lock); | 185 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
| 186 | sdp->sd_lockstruct.ls_ops->lm_put_lock(gl->gl_lock); | ||
| 187 | 187 | ||
| 188 | if (aspace) | 188 | if (aspace) |
| 189 | gfs2_aspace_put(aspace); | 189 | gfs2_aspace_put(aspace); |
| @@ -197,7 +197,7 @@ static void glock_free(struct gfs2_glock *gl) | |||
| 197 | * | 197 | * |
| 198 | */ | 198 | */ |
| 199 | 199 | ||
| 200 | void gfs2_glock_hold(struct gfs2_glock *gl) | 200 | static void gfs2_glock_hold(struct gfs2_glock *gl) |
| 201 | { | 201 | { |
| 202 | atomic_inc(&gl->gl_ref); | 202 | atomic_inc(&gl->gl_ref); |
| 203 | } | 203 | } |
| @@ -293,6 +293,16 @@ static void glock_work_func(struct work_struct *work) | |||
| 293 | gfs2_glock_put(gl); | 293 | gfs2_glock_put(gl); |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | static int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 297 | void **lockp) | ||
| 298 | { | ||
| 299 | int error = -EIO; | ||
| 300 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 301 | error = sdp->sd_lockstruct.ls_ops->lm_get_lock( | ||
| 302 | sdp->sd_lockstruct.ls_lockspace, name, lockp); | ||
| 303 | return error; | ||
| 304 | } | ||
| 305 | |||
| 296 | /** | 306 | /** |
| 297 | * gfs2_glock_get() - Get a glock, or create one if one doesn't exist | 307 | * gfs2_glock_get() - Get a glock, or create one if one doesn't exist |
| 298 | * @sdp: The GFS2 superblock | 308 | * @sdp: The GFS2 superblock |
| @@ -338,8 +348,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 338 | gl->gl_ip = 0; | 348 | gl->gl_ip = 0; |
| 339 | gl->gl_ops = glops; | 349 | gl->gl_ops = glops; |
| 340 | gl->gl_req_gh = NULL; | 350 | gl->gl_req_gh = NULL; |
| 341 | gl->gl_req_bh = NULL; | ||
| 342 | gl->gl_vn = 0; | ||
| 343 | gl->gl_stamp = jiffies; | 351 | gl->gl_stamp = jiffies; |
| 344 | gl->gl_tchange = jiffies; | 352 | gl->gl_tchange = jiffies; |
| 345 | gl->gl_object = NULL; | 353 | gl->gl_object = NULL; |
| @@ -595,11 +603,12 @@ static void run_queue(struct gfs2_glock *gl) | |||
| 595 | blocked = rq_mutex(gh); | 603 | blocked = rq_mutex(gh); |
| 596 | } else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) { | 604 | } else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) { |
| 597 | blocked = rq_demote(gl); | 605 | blocked = rq_demote(gl); |
| 598 | if (gl->gl_waiters2 && !blocked) { | 606 | if (test_bit(GLF_WAITERS2, &gl->gl_flags) && |
| 607 | !blocked) { | ||
| 599 | set_bit(GLF_DEMOTE, &gl->gl_flags); | 608 | set_bit(GLF_DEMOTE, &gl->gl_flags); |
| 600 | gl->gl_demote_state = LM_ST_UNLOCKED; | 609 | gl->gl_demote_state = LM_ST_UNLOCKED; |
| 601 | } | 610 | } |
| 602 | gl->gl_waiters2 = 0; | 611 | clear_bit(GLF_WAITERS2, &gl->gl_flags); |
| 603 | } else if (!list_empty(&gl->gl_waiters3)) { | 612 | } else if (!list_empty(&gl->gl_waiters3)) { |
| 604 | gh = list_entry(gl->gl_waiters3.next, | 613 | gh = list_entry(gl->gl_waiters3.next, |
| 605 | struct gfs2_holder, gh_list); | 614 | struct gfs2_holder, gh_list); |
| @@ -710,7 +719,7 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state, | |||
| 710 | } else if (gl->gl_demote_state != LM_ST_UNLOCKED && | 719 | } else if (gl->gl_demote_state != LM_ST_UNLOCKED && |
| 711 | gl->gl_demote_state != state) { | 720 | gl->gl_demote_state != state) { |
| 712 | if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)) | 721 | if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)) |
| 713 | gl->gl_waiters2 = 1; | 722 | set_bit(GLF_WAITERS2, &gl->gl_flags); |
| 714 | else | 723 | else |
| 715 | gl->gl_demote_state = LM_ST_UNLOCKED; | 724 | gl->gl_demote_state = LM_ST_UNLOCKED; |
| 716 | } | 725 | } |
| @@ -743,6 +752,43 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state) | |||
| 743 | } | 752 | } |
| 744 | 753 | ||
| 745 | /** | 754 | /** |
| 755 | * drop_bh - Called after a lock module unlock completes | ||
| 756 | * @gl: the glock | ||
| 757 | * @ret: the return status | ||
| 758 | * | ||
| 759 | * Doesn't wake up the process waiting on the struct gfs2_holder (if any) | ||
| 760 | * Doesn't drop the reference on the glock the top half took out | ||
| 761 | * | ||
| 762 | */ | ||
| 763 | |||
| 764 | static void drop_bh(struct gfs2_glock *gl, unsigned int ret) | ||
| 765 | { | ||
| 766 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
| 767 | struct gfs2_holder *gh = gl->gl_req_gh; | ||
| 768 | |||
| 769 | gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); | ||
| 770 | gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); | ||
| 771 | gfs2_assert_warn(sdp, !ret); | ||
| 772 | |||
| 773 | state_change(gl, LM_ST_UNLOCKED); | ||
| 774 | |||
| 775 | if (test_and_clear_bit(GLF_CONV_DEADLK, &gl->gl_flags)) { | ||
| 776 | spin_lock(&gl->gl_spin); | ||
| 777 | gh->gh_error = 0; | ||
| 778 | spin_unlock(&gl->gl_spin); | ||
| 779 | gfs2_glock_xmote_th(gl, gl->gl_req_gh); | ||
| 780 | gfs2_glock_put(gl); | ||
| 781 | return; | ||
| 782 | } | ||
| 783 | |||
| 784 | spin_lock(&gl->gl_spin); | ||
| 785 | gfs2_demote_wake(gl); | ||
| 786 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
| 787 | spin_unlock(&gl->gl_spin); | ||
| 788 | gfs2_glock_put(gl); | ||
| 789 | } | ||
| 790 | |||
| 791 | /** | ||
| 746 | * xmote_bh - Called after the lock module is done acquiring a lock | 792 | * xmote_bh - Called after the lock module is done acquiring a lock |
| 747 | * @gl: The glock in question | 793 | * @gl: The glock in question |
| 748 | * @ret: the int returned from the lock module | 794 | * @ret: the int returned from the lock module |
| @@ -754,25 +800,19 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) | |||
| 754 | struct gfs2_sbd *sdp = gl->gl_sbd; | 800 | struct gfs2_sbd *sdp = gl->gl_sbd; |
| 755 | const struct gfs2_glock_operations *glops = gl->gl_ops; | 801 | const struct gfs2_glock_operations *glops = gl->gl_ops; |
| 756 | struct gfs2_holder *gh = gl->gl_req_gh; | 802 | struct gfs2_holder *gh = gl->gl_req_gh; |
| 757 | int prev_state = gl->gl_state; | ||
| 758 | int op_done = 1; | 803 | int op_done = 1; |
| 759 | 804 | ||
| 805 | if (!gh && (ret & LM_OUT_ST_MASK) == LM_ST_UNLOCKED) { | ||
| 806 | drop_bh(gl, ret); | ||
| 807 | return; | ||
| 808 | } | ||
| 809 | |||
| 760 | gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); | 810 | gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); |
| 761 | gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); | 811 | gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); |
| 762 | gfs2_assert_warn(sdp, !(ret & LM_OUT_ASYNC)); | 812 | gfs2_assert_warn(sdp, !(ret & LM_OUT_ASYNC)); |
| 763 | 813 | ||
| 764 | state_change(gl, ret & LM_OUT_ST_MASK); | 814 | state_change(gl, ret & LM_OUT_ST_MASK); |
| 765 | 815 | ||
| 766 | if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) { | ||
| 767 | if (glops->go_inval) | ||
| 768 | glops->go_inval(gl, DIO_METADATA); | ||
| 769 | } else if (gl->gl_state == LM_ST_DEFERRED) { | ||
| 770 | /* We might not want to do this here. | ||
| 771 | Look at moving to the inode glops. */ | ||
| 772 | if (glops->go_inval) | ||
| 773 | glops->go_inval(gl, 0); | ||
| 774 | } | ||
| 775 | |||
| 776 | /* Deal with each possible exit condition */ | 816 | /* Deal with each possible exit condition */ |
| 777 | 817 | ||
| 778 | if (!gh) { | 818 | if (!gh) { |
| @@ -782,7 +822,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) | |||
| 782 | } else { | 822 | } else { |
| 783 | spin_lock(&gl->gl_spin); | 823 | spin_lock(&gl->gl_spin); |
| 784 | if (gl->gl_state != gl->gl_demote_state) { | 824 | if (gl->gl_state != gl->gl_demote_state) { |
| 785 | gl->gl_req_bh = NULL; | ||
| 786 | spin_unlock(&gl->gl_spin); | 825 | spin_unlock(&gl->gl_spin); |
| 787 | gfs2_glock_drop_th(gl); | 826 | gfs2_glock_drop_th(gl); |
| 788 | gfs2_glock_put(gl); | 827 | gfs2_glock_put(gl); |
| @@ -793,6 +832,14 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) | |||
| 793 | } | 832 | } |
| 794 | } else { | 833 | } else { |
| 795 | spin_lock(&gl->gl_spin); | 834 | spin_lock(&gl->gl_spin); |
| 835 | if (ret & LM_OUT_CONV_DEADLK) { | ||
| 836 | gh->gh_error = 0; | ||
| 837 | set_bit(GLF_CONV_DEADLK, &gl->gl_flags); | ||
| 838 | spin_unlock(&gl->gl_spin); | ||
| 839 | gfs2_glock_drop_th(gl); | ||
| 840 | gfs2_glock_put(gl); | ||
| 841 | return; | ||
| 842 | } | ||
| 796 | list_del_init(&gh->gh_list); | 843 | list_del_init(&gh->gh_list); |
| 797 | gh->gh_error = -EIO; | 844 | gh->gh_error = -EIO; |
| 798 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | 845 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
| @@ -824,7 +871,6 @@ out: | |||
| 824 | if (op_done) { | 871 | if (op_done) { |
| 825 | spin_lock(&gl->gl_spin); | 872 | spin_lock(&gl->gl_spin); |
| 826 | gl->gl_req_gh = NULL; | 873 | gl->gl_req_gh = NULL; |
| 827 | gl->gl_req_bh = NULL; | ||
| 828 | clear_bit(GLF_LOCK, &gl->gl_flags); | 874 | clear_bit(GLF_LOCK, &gl->gl_flags); |
| 829 | spin_unlock(&gl->gl_spin); | 875 | spin_unlock(&gl->gl_spin); |
| 830 | } | 876 | } |
| @@ -835,6 +881,17 @@ out: | |||
| 835 | gfs2_holder_wake(gh); | 881 | gfs2_holder_wake(gh); |
| 836 | } | 882 | } |
| 837 | 883 | ||
| 884 | static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, | ||
| 885 | unsigned int cur_state, unsigned int req_state, | ||
| 886 | unsigned int flags) | ||
| 887 | { | ||
| 888 | int ret = 0; | ||
| 889 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 890 | ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state, | ||
| 891 | req_state, flags); | ||
| 892 | return ret; | ||
| 893 | } | ||
| 894 | |||
| 838 | /** | 895 | /** |
| 839 | * gfs2_glock_xmote_th - Call into the lock module to acquire or change a glock | 896 | * gfs2_glock_xmote_th - Call into the lock module to acquire or change a glock |
| 840 | * @gl: The glock in question | 897 | * @gl: The glock in question |
| @@ -856,6 +913,8 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh) | |||
| 856 | 913 | ||
| 857 | if (glops->go_xmote_th) | 914 | if (glops->go_xmote_th) |
| 858 | glops->go_xmote_th(gl); | 915 | glops->go_xmote_th(gl); |
| 916 | if (state == LM_ST_DEFERRED && glops->go_inval) | ||
| 917 | glops->go_inval(gl, DIO_METADATA); | ||
| 859 | 918 | ||
| 860 | gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); | 919 | gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); |
| 861 | gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); | 920 | gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); |
| @@ -863,7 +922,6 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh) | |||
| 863 | gfs2_assert_warn(sdp, state != gl->gl_state); | 922 | gfs2_assert_warn(sdp, state != gl->gl_state); |
| 864 | 923 | ||
| 865 | gfs2_glock_hold(gl); | 924 | gfs2_glock_hold(gl); |
| 866 | gl->gl_req_bh = xmote_bh; | ||
| 867 | 925 | ||
| 868 | lck_ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, state, lck_flags); | 926 | lck_ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, state, lck_flags); |
| 869 | 927 | ||
| @@ -876,49 +934,13 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh) | |||
| 876 | xmote_bh(gl, lck_ret); | 934 | xmote_bh(gl, lck_ret); |
| 877 | } | 935 | } |
| 878 | 936 | ||
| 879 | /** | 937 | static unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock, |
| 880 | * drop_bh - Called after a lock module unlock completes | 938 | unsigned int cur_state) |
| 881 | * @gl: the glock | ||
| 882 | * @ret: the return status | ||
| 883 | * | ||
| 884 | * Doesn't wake up the process waiting on the struct gfs2_holder (if any) | ||
| 885 | * Doesn't drop the reference on the glock the top half took out | ||
| 886 | * | ||
| 887 | */ | ||
| 888 | |||
| 889 | static void drop_bh(struct gfs2_glock *gl, unsigned int ret) | ||
| 890 | { | 939 | { |
| 891 | struct gfs2_sbd *sdp = gl->gl_sbd; | 940 | int ret = 0; |
| 892 | const struct gfs2_glock_operations *glops = gl->gl_ops; | 941 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
| 893 | struct gfs2_holder *gh = gl->gl_req_gh; | 942 | ret = sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state); |
| 894 | 943 | return ret; | |
| 895 | gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); | ||
| 896 | gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); | ||
| 897 | gfs2_assert_warn(sdp, !ret); | ||
| 898 | |||
| 899 | state_change(gl, LM_ST_UNLOCKED); | ||
| 900 | |||
| 901 | if (glops->go_inval) | ||
| 902 | glops->go_inval(gl, DIO_METADATA); | ||
| 903 | |||
| 904 | if (gh) { | ||
| 905 | spin_lock(&gl->gl_spin); | ||
| 906 | list_del_init(&gh->gh_list); | ||
| 907 | gh->gh_error = 0; | ||
| 908 | spin_unlock(&gl->gl_spin); | ||
| 909 | } | ||
| 910 | |||
| 911 | spin_lock(&gl->gl_spin); | ||
| 912 | gfs2_demote_wake(gl); | ||
| 913 | gl->gl_req_gh = NULL; | ||
| 914 | gl->gl_req_bh = NULL; | ||
| 915 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
| 916 | spin_unlock(&gl->gl_spin); | ||
| 917 | |||
| 918 | gfs2_glock_put(gl); | ||
| 919 | |||
| 920 | if (gh) | ||
| 921 | gfs2_holder_wake(gh); | ||
| 922 | } | 944 | } |
| 923 | 945 | ||
| 924 | /** | 946 | /** |
| @@ -935,13 +957,14 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl) | |||
| 935 | 957 | ||
| 936 | if (glops->go_xmote_th) | 958 | if (glops->go_xmote_th) |
| 937 | glops->go_xmote_th(gl); | 959 | glops->go_xmote_th(gl); |
| 960 | if (glops->go_inval) | ||
| 961 | glops->go_inval(gl, DIO_METADATA); | ||
| 938 | 962 | ||
| 939 | gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); | 963 | gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags)); |
| 940 | gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); | 964 | gfs2_assert_warn(sdp, list_empty(&gl->gl_holders)); |
| 941 | gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED); | 965 | gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED); |
| 942 | 966 | ||
| 943 | gfs2_glock_hold(gl); | 967 | gfs2_glock_hold(gl); |
| 944 | gl->gl_req_bh = drop_bh; | ||
| 945 | 968 | ||
| 946 | ret = gfs2_lm_unlock(sdp, gl->gl_lock, gl->gl_state); | 969 | ret = gfs2_lm_unlock(sdp, gl->gl_lock, gl->gl_state); |
| 947 | 970 | ||
| @@ -964,16 +987,17 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl) | |||
| 964 | static void do_cancels(struct gfs2_holder *gh) | 987 | static void do_cancels(struct gfs2_holder *gh) |
| 965 | { | 988 | { |
| 966 | struct gfs2_glock *gl = gh->gh_gl; | 989 | struct gfs2_glock *gl = gh->gh_gl; |
| 990 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
| 967 | 991 | ||
| 968 | spin_lock(&gl->gl_spin); | 992 | spin_lock(&gl->gl_spin); |
| 969 | 993 | ||
| 970 | while (gl->gl_req_gh != gh && | 994 | while (gl->gl_req_gh != gh && |
| 971 | !test_bit(HIF_HOLDER, &gh->gh_iflags) && | 995 | !test_bit(HIF_HOLDER, &gh->gh_iflags) && |
| 972 | !list_empty(&gh->gh_list)) { | 996 | !list_empty(&gh->gh_list)) { |
| 973 | if (gl->gl_req_bh && !(gl->gl_req_gh && | 997 | if (!(gl->gl_req_gh && (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) { |
| 974 | (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) { | ||
| 975 | spin_unlock(&gl->gl_spin); | 998 | spin_unlock(&gl->gl_spin); |
| 976 | gfs2_lm_cancel(gl->gl_sbd, gl->gl_lock); | 999 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
| 1000 | sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock); | ||
| 977 | msleep(100); | 1001 | msleep(100); |
| 978 | spin_lock(&gl->gl_spin); | 1002 | spin_lock(&gl->gl_spin); |
| 979 | } else { | 1003 | } else { |
| @@ -1041,7 +1065,6 @@ static int glock_wait_internal(struct gfs2_holder *gh) | |||
| 1041 | 1065 | ||
| 1042 | spin_lock(&gl->gl_spin); | 1066 | spin_lock(&gl->gl_spin); |
| 1043 | gl->gl_req_gh = NULL; | 1067 | gl->gl_req_gh = NULL; |
| 1044 | gl->gl_req_bh = NULL; | ||
| 1045 | clear_bit(GLF_LOCK, &gl->gl_flags); | 1068 | clear_bit(GLF_LOCK, &gl->gl_flags); |
| 1046 | run_queue(gl); | 1069 | run_queue(gl); |
| 1047 | spin_unlock(&gl->gl_spin); | 1070 | spin_unlock(&gl->gl_spin); |
| @@ -1428,6 +1451,14 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs) | |||
| 1428 | gfs2_glock_dq_uninit(&ghs[x]); | 1451 | gfs2_glock_dq_uninit(&ghs[x]); |
| 1429 | } | 1452 | } |
| 1430 | 1453 | ||
| 1454 | static int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp) | ||
| 1455 | { | ||
| 1456 | int error = -EIO; | ||
| 1457 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 1458 | error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp); | ||
| 1459 | return error; | ||
| 1460 | } | ||
| 1461 | |||
| 1431 | /** | 1462 | /** |
| 1432 | * gfs2_lvb_hold - attach a LVB from a glock | 1463 | * gfs2_lvb_hold - attach a LVB from a glock |
| 1433 | * @gl: The glock in question | 1464 | * @gl: The glock in question |
| @@ -1463,12 +1494,15 @@ int gfs2_lvb_hold(struct gfs2_glock *gl) | |||
| 1463 | 1494 | ||
| 1464 | void gfs2_lvb_unhold(struct gfs2_glock *gl) | 1495 | void gfs2_lvb_unhold(struct gfs2_glock *gl) |
| 1465 | { | 1496 | { |
| 1497 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
| 1498 | |||
| 1466 | gfs2_glock_hold(gl); | 1499 | gfs2_glock_hold(gl); |
| 1467 | gfs2_glmutex_lock(gl); | 1500 | gfs2_glmutex_lock(gl); |
| 1468 | 1501 | ||
| 1469 | gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0); | 1502 | gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0); |
| 1470 | if (atomic_dec_and_test(&gl->gl_lvb_count)) { | 1503 | if (atomic_dec_and_test(&gl->gl_lvb_count)) { |
| 1471 | gfs2_lm_unhold_lvb(gl->gl_sbd, gl->gl_lock, gl->gl_lvb); | 1504 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
| 1505 | sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(gl->gl_lock, gl->gl_lvb); | ||
| 1472 | gl->gl_lvb = NULL; | 1506 | gl->gl_lvb = NULL; |
| 1473 | gfs2_glock_put(gl); | 1507 | gfs2_glock_put(gl); |
| 1474 | } | 1508 | } |
| @@ -1534,8 +1568,7 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data) | |||
| 1534 | gl = gfs2_glock_find(sdp, &async->lc_name); | 1568 | gl = gfs2_glock_find(sdp, &async->lc_name); |
| 1535 | if (gfs2_assert_warn(sdp, gl)) | 1569 | if (gfs2_assert_warn(sdp, gl)) |
| 1536 | return; | 1570 | return; |
| 1537 | if (!gfs2_assert_warn(sdp, gl->gl_req_bh)) | 1571 | xmote_bh(gl, async->lc_ret); |
| 1538 | gl->gl_req_bh(gl, async->lc_ret); | ||
| 1539 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 1572 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
| 1540 | gfs2_glock_put(gl); | 1573 | gfs2_glock_put(gl); |
| 1541 | up_read(&gfs2_umount_flush_sem); | 1574 | up_read(&gfs2_umount_flush_sem); |
| @@ -1594,10 +1627,10 @@ void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) | |||
| 1594 | gfs2_glock_hold(gl); | 1627 | gfs2_glock_hold(gl); |
| 1595 | list_add(&gl->gl_reclaim, &sdp->sd_reclaim_list); | 1628 | list_add(&gl->gl_reclaim, &sdp->sd_reclaim_list); |
| 1596 | atomic_inc(&sdp->sd_reclaim_count); | 1629 | atomic_inc(&sdp->sd_reclaim_count); |
| 1597 | } | 1630 | spin_unlock(&sdp->sd_reclaim_lock); |
| 1598 | spin_unlock(&sdp->sd_reclaim_lock); | 1631 | wake_up(&sdp->sd_reclaim_wq); |
| 1599 | 1632 | } else | |
| 1600 | wake_up(&sdp->sd_reclaim_wq); | 1633 | spin_unlock(&sdp->sd_reclaim_lock); |
| 1601 | } | 1634 | } |
| 1602 | 1635 | ||
| 1603 | /** | 1636 | /** |
| @@ -1897,7 +1930,6 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl) | |||
| 1897 | print_dbg(gi, " gl_owner = -1\n"); | 1930 | print_dbg(gi, " gl_owner = -1\n"); |
| 1898 | print_dbg(gi, " gl_ip = %lu\n", gl->gl_ip); | 1931 | print_dbg(gi, " gl_ip = %lu\n", gl->gl_ip); |
| 1899 | print_dbg(gi, " req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no"); | 1932 | print_dbg(gi, " req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no"); |
| 1900 | print_dbg(gi, " req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no"); | ||
| 1901 | print_dbg(gi, " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count)); | 1933 | print_dbg(gi, " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count)); |
| 1902 | print_dbg(gi, " object = %s\n", (gl->gl_object) ? "yes" : "no"); | 1934 | print_dbg(gi, " object = %s\n", (gl->gl_object) ? "yes" : "no"); |
| 1903 | print_dbg(gi, " reclaim = %s\n", | 1935 | print_dbg(gi, " reclaim = %s\n", |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 2f9c6d136b37..cdad3e6f8150 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
| @@ -32,24 +32,23 @@ | |||
| 32 | #define GLR_TRYFAILED 13 | 32 | #define GLR_TRYFAILED 13 |
| 33 | #define GLR_CANCELED 14 | 33 | #define GLR_CANCELED 14 |
| 34 | 34 | ||
| 35 | static inline int gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) | 35 | static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) |
| 36 | { | 36 | { |
| 37 | struct gfs2_holder *gh; | 37 | struct gfs2_holder *gh; |
| 38 | int locked = 0; | ||
| 39 | struct pid *pid; | 38 | struct pid *pid; |
| 40 | 39 | ||
| 41 | /* Look in glock's list of holders for one with current task as owner */ | 40 | /* Look in glock's list of holders for one with current task as owner */ |
| 42 | spin_lock(&gl->gl_spin); | 41 | spin_lock(&gl->gl_spin); |
| 43 | pid = task_pid(current); | 42 | pid = task_pid(current); |
| 44 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { | 43 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { |
| 45 | if (gh->gh_owner_pid == pid) { | 44 | if (gh->gh_owner_pid == pid) |
| 46 | locked = 1; | 45 | goto out; |
| 47 | break; | ||
| 48 | } | ||
| 49 | } | 46 | } |
| 47 | gh = NULL; | ||
| 48 | out: | ||
| 50 | spin_unlock(&gl->gl_spin); | 49 | spin_unlock(&gl->gl_spin); |
| 51 | 50 | ||
| 52 | return locked; | 51 | return gh; |
| 53 | } | 52 | } |
| 54 | 53 | ||
| 55 | static inline int gfs2_glock_is_held_excl(struct gfs2_glock *gl) | 54 | static inline int gfs2_glock_is_held_excl(struct gfs2_glock *gl) |
| @@ -79,7 +78,6 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl) | |||
| 79 | int gfs2_glock_get(struct gfs2_sbd *sdp, | 78 | int gfs2_glock_get(struct gfs2_sbd *sdp, |
| 80 | u64 number, const struct gfs2_glock_operations *glops, | 79 | u64 number, const struct gfs2_glock_operations *glops, |
| 81 | int create, struct gfs2_glock **glp); | 80 | int create, struct gfs2_glock **glp); |
| 82 | void gfs2_glock_hold(struct gfs2_glock *gl); | ||
| 83 | int gfs2_glock_put(struct gfs2_glock *gl); | 81 | int gfs2_glock_put(struct gfs2_glock *gl); |
| 84 | void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, | 82 | void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, |
| 85 | struct gfs2_holder *gh); | 83 | struct gfs2_holder *gh); |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index c663b7a0f410..d31badadef8f 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -126,7 +126,13 @@ static void meta_go_inval(struct gfs2_glock *gl, int flags) | |||
| 126 | return; | 126 | return; |
| 127 | 127 | ||
| 128 | gfs2_meta_inval(gl); | 128 | gfs2_meta_inval(gl); |
| 129 | gl->gl_vn++; | 129 | if (gl->gl_object == GFS2_I(gl->gl_sbd->sd_rindex)) |
| 130 | gl->gl_sbd->sd_rindex_uptodate = 0; | ||
| 131 | else if (gl->gl_ops == &gfs2_rgrp_glops && gl->gl_object) { | ||
| 132 | struct gfs2_rgrpd *rgd = (struct gfs2_rgrpd *)gl->gl_object; | ||
| 133 | |||
| 134 | rgd->rd_flags &= ~GFS2_RDF_UPTODATE; | ||
| 135 | } | ||
| 130 | } | 136 | } |
| 131 | 137 | ||
| 132 | /** | 138 | /** |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 525dcae352d6..9c2c0b90b22a 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -44,7 +44,6 @@ struct gfs2_log_header_host { | |||
| 44 | 44 | ||
| 45 | struct gfs2_log_operations { | 45 | struct gfs2_log_operations { |
| 46 | void (*lo_add) (struct gfs2_sbd *sdp, struct gfs2_log_element *le); | 46 | void (*lo_add) (struct gfs2_sbd *sdp, struct gfs2_log_element *le); |
| 47 | void (*lo_incore_commit) (struct gfs2_sbd *sdp, struct gfs2_trans *tr); | ||
| 48 | void (*lo_before_commit) (struct gfs2_sbd *sdp); | 47 | void (*lo_before_commit) (struct gfs2_sbd *sdp); |
| 49 | void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai); | 48 | void (*lo_after_commit) (struct gfs2_sbd *sdp, struct gfs2_ail *ai); |
| 50 | void (*lo_before_scan) (struct gfs2_jdesc *jd, | 49 | void (*lo_before_scan) (struct gfs2_jdesc *jd, |
| @@ -70,7 +69,6 @@ struct gfs2_bitmap { | |||
| 70 | }; | 69 | }; |
| 71 | 70 | ||
| 72 | struct gfs2_rgrp_host { | 71 | struct gfs2_rgrp_host { |
| 73 | u32 rg_flags; | ||
| 74 | u32 rg_free; | 72 | u32 rg_free; |
| 75 | u32 rg_dinodes; | 73 | u32 rg_dinodes; |
| 76 | u64 rg_igeneration; | 74 | u64 rg_igeneration; |
| @@ -87,17 +85,17 @@ struct gfs2_rgrpd { | |||
| 87 | u32 rd_data; /* num of data blocks in rgrp */ | 85 | u32 rd_data; /* num of data blocks in rgrp */ |
| 88 | u32 rd_bitbytes; /* number of bytes in data bitmaps */ | 86 | u32 rd_bitbytes; /* number of bytes in data bitmaps */ |
| 89 | struct gfs2_rgrp_host rd_rg; | 87 | struct gfs2_rgrp_host rd_rg; |
| 90 | u64 rd_rg_vn; | ||
| 91 | struct gfs2_bitmap *rd_bits; | 88 | struct gfs2_bitmap *rd_bits; |
| 92 | unsigned int rd_bh_count; | 89 | unsigned int rd_bh_count; |
| 93 | struct mutex rd_mutex; | 90 | struct mutex rd_mutex; |
| 94 | u32 rd_free_clone; | 91 | u32 rd_free_clone; |
| 95 | struct gfs2_log_element rd_le; | 92 | struct gfs2_log_element rd_le; |
| 96 | u32 rd_last_alloc_data; | 93 | u32 rd_last_alloc; |
| 97 | u32 rd_last_alloc_meta; | ||
| 98 | struct gfs2_sbd *rd_sbd; | 94 | struct gfs2_sbd *rd_sbd; |
| 99 | unsigned long rd_flags; | 95 | unsigned char rd_flags; |
| 100 | #define GFS2_RDF_CHECK 0x0001 /* Need to check for unlinked inodes */ | 96 | #define GFS2_RDF_CHECK 0x01 /* Need to check for unlinked inodes */ |
| 97 | #define GFS2_RDF_NOALLOC 0x02 /* rg prohibits allocation */ | ||
| 98 | #define GFS2_RDF_UPTODATE 0x04 /* rg is up to date */ | ||
| 101 | }; | 99 | }; |
| 102 | 100 | ||
| 103 | enum gfs2_state_bits { | 101 | enum gfs2_state_bits { |
| @@ -168,6 +166,8 @@ enum { | |||
| 168 | GLF_DIRTY = 5, | 166 | GLF_DIRTY = 5, |
| 169 | GLF_DEMOTE_IN_PROGRESS = 6, | 167 | GLF_DEMOTE_IN_PROGRESS = 6, |
| 170 | GLF_LFLUSH = 7, | 168 | GLF_LFLUSH = 7, |
| 169 | GLF_WAITERS2 = 8, | ||
| 170 | GLF_CONV_DEADLK = 9, | ||
| 171 | }; | 171 | }; |
| 172 | 172 | ||
| 173 | struct gfs2_glock { | 173 | struct gfs2_glock { |
| @@ -187,18 +187,15 @@ struct gfs2_glock { | |||
| 187 | struct list_head gl_holders; | 187 | struct list_head gl_holders; |
| 188 | struct list_head gl_waiters1; /* HIF_MUTEX */ | 188 | struct list_head gl_waiters1; /* HIF_MUTEX */ |
| 189 | struct list_head gl_waiters3; /* HIF_PROMOTE */ | 189 | struct list_head gl_waiters3; /* HIF_PROMOTE */ |
| 190 | int gl_waiters2; /* GIF_DEMOTE */ | ||
| 191 | 190 | ||
| 192 | const struct gfs2_glock_operations *gl_ops; | 191 | const struct gfs2_glock_operations *gl_ops; |
| 193 | 192 | ||
| 194 | struct gfs2_holder *gl_req_gh; | 193 | struct gfs2_holder *gl_req_gh; |
| 195 | gfs2_glop_bh_t gl_req_bh; | ||
| 196 | 194 | ||
| 197 | void *gl_lock; | 195 | void *gl_lock; |
| 198 | char *gl_lvb; | 196 | char *gl_lvb; |
| 199 | atomic_t gl_lvb_count; | 197 | atomic_t gl_lvb_count; |
| 200 | 198 | ||
| 201 | u64 gl_vn; | ||
| 202 | unsigned long gl_stamp; | 199 | unsigned long gl_stamp; |
| 203 | unsigned long gl_tchange; | 200 | unsigned long gl_tchange; |
| 204 | void *gl_object; | 201 | void *gl_object; |
| @@ -213,6 +210,8 @@ struct gfs2_glock { | |||
| 213 | struct delayed_work gl_work; | 210 | struct delayed_work gl_work; |
| 214 | }; | 211 | }; |
| 215 | 212 | ||
| 213 | #define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */ | ||
| 214 | |||
| 216 | struct gfs2_alloc { | 215 | struct gfs2_alloc { |
| 217 | /* Quota stuff */ | 216 | /* Quota stuff */ |
| 218 | 217 | ||
| @@ -241,14 +240,9 @@ enum { | |||
| 241 | 240 | ||
| 242 | struct gfs2_dinode_host { | 241 | struct gfs2_dinode_host { |
| 243 | u64 di_size; /* number of bytes in file */ | 242 | u64 di_size; /* number of bytes in file */ |
| 244 | u64 di_blocks; /* number of blocks in file */ | ||
| 245 | u64 di_goal_meta; /* rgrp to alloc from next */ | ||
| 246 | u64 di_goal_data; /* data block goal */ | ||
| 247 | u64 di_generation; /* generation number for NFS */ | 243 | u64 di_generation; /* generation number for NFS */ |
| 248 | u32 di_flags; /* GFS2_DIF_... */ | 244 | u32 di_flags; /* GFS2_DIF_... */ |
| 249 | u16 di_height; /* height of metadata */ | ||
| 250 | /* These only apply to directories */ | 245 | /* These only apply to directories */ |
| 251 | u16 di_depth; /* Number of bits in the table */ | ||
| 252 | u32 di_entries; /* The number of entries in the directory */ | 246 | u32 di_entries; /* The number of entries in the directory */ |
| 253 | u64 di_eattr; /* extended attribute block number */ | 247 | u64 di_eattr; /* extended attribute block number */ |
| 254 | }; | 248 | }; |
| @@ -265,9 +259,10 @@ struct gfs2_inode { | |||
| 265 | struct gfs2_holder i_iopen_gh; | 259 | struct gfs2_holder i_iopen_gh; |
| 266 | struct gfs2_holder i_gh; /* for prepare/commit_write only */ | 260 | struct gfs2_holder i_gh; /* for prepare/commit_write only */ |
| 267 | struct gfs2_alloc *i_alloc; | 261 | struct gfs2_alloc *i_alloc; |
| 268 | u64 i_last_rg_alloc; | 262 | u64 i_goal; /* goal block for allocations */ |
| 269 | |||
| 270 | struct rw_semaphore i_rw_mutex; | 263 | struct rw_semaphore i_rw_mutex; |
| 264 | u8 i_height; | ||
| 265 | u8 i_depth; | ||
| 271 | }; | 266 | }; |
| 272 | 267 | ||
| 273 | /* | 268 | /* |
| @@ -490,9 +485,9 @@ struct gfs2_sbd { | |||
| 490 | u32 sd_qc_per_block; | 485 | u32 sd_qc_per_block; |
| 491 | u32 sd_max_dirres; /* Max blocks needed to add a directory entry */ | 486 | u32 sd_max_dirres; /* Max blocks needed to add a directory entry */ |
| 492 | u32 sd_max_height; /* Max height of a file's metadata tree */ | 487 | u32 sd_max_height; /* Max height of a file's metadata tree */ |
| 493 | u64 sd_heightsize[GFS2_MAX_META_HEIGHT]; | 488 | u64 sd_heightsize[GFS2_MAX_META_HEIGHT + 1]; |
| 494 | u32 sd_max_jheight; /* Max height of journaled file's meta tree */ | 489 | u32 sd_max_jheight; /* Max height of journaled file's meta tree */ |
| 495 | u64 sd_jheightsize[GFS2_MAX_META_HEIGHT]; | 490 | u64 sd_jheightsize[GFS2_MAX_META_HEIGHT + 1]; |
| 496 | 491 | ||
| 497 | struct gfs2_args sd_args; /* Mount arguments */ | 492 | struct gfs2_args sd_args; /* Mount arguments */ |
| 498 | struct gfs2_tune sd_tune; /* Filesystem tuning structure */ | 493 | struct gfs2_tune sd_tune; /* Filesystem tuning structure */ |
| @@ -533,7 +528,7 @@ struct gfs2_sbd { | |||
| 533 | 528 | ||
| 534 | /* Resource group stuff */ | 529 | /* Resource group stuff */ |
| 535 | 530 | ||
| 536 | u64 sd_rindex_vn; | 531 | int sd_rindex_uptodate; |
| 537 | spinlock_t sd_rindex_spin; | 532 | spinlock_t sd_rindex_spin; |
| 538 | struct mutex sd_rindex_mutex; | 533 | struct mutex sd_rindex_mutex; |
| 539 | struct list_head sd_rindex_list; | 534 | struct list_head sd_rindex_list; |
| @@ -637,9 +632,6 @@ struct gfs2_sbd { | |||
| 637 | 632 | ||
| 638 | /* Counters */ | 633 | /* Counters */ |
| 639 | 634 | ||
| 640 | atomic_t sd_glock_count; | ||
| 641 | atomic_t sd_glock_held_count; | ||
| 642 | atomic_t sd_inode_count; | ||
| 643 | atomic_t sd_reclaimed; | 635 | atomic_t sd_reclaimed; |
| 644 | 636 | ||
| 645 | char sd_fsname[GFS2_FSNAME_LEN]; | 637 | char sd_fsname[GFS2_FSNAME_LEN]; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 37725ade3c51..3a9ef526c308 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -149,7 +149,8 @@ void gfs2_set_iop(struct inode *inode) | |||
| 149 | } else if (S_ISLNK(mode)) { | 149 | } else if (S_ISLNK(mode)) { |
| 150 | inode->i_op = &gfs2_symlink_iops; | 150 | inode->i_op = &gfs2_symlink_iops; |
| 151 | } else { | 151 | } else { |
| 152 | inode->i_op = &gfs2_dev_iops; | 152 | inode->i_op = &gfs2_file_iops; |
| 153 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | ||
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | unlock_new_inode(inode); | 156 | unlock_new_inode(inode); |
| @@ -248,12 +249,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | |||
| 248 | { | 249 | { |
| 249 | struct gfs2_dinode_host *di = &ip->i_di; | 250 | struct gfs2_dinode_host *di = &ip->i_di; |
| 250 | const struct gfs2_dinode *str = buf; | 251 | const struct gfs2_dinode *str = buf; |
| 252 | u16 height, depth; | ||
| 251 | 253 | ||
| 252 | if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) { | 254 | if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) |
| 253 | if (gfs2_consist_inode(ip)) | 255 | goto corrupt; |
| 254 | gfs2_dinode_print(ip); | ||
| 255 | return -EIO; | ||
| 256 | } | ||
| 257 | ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); | 256 | ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); |
| 258 | ip->i_inode.i_mode = be32_to_cpu(str->di_mode); | 257 | ip->i_inode.i_mode = be32_to_cpu(str->di_mode); |
| 259 | ip->i_inode.i_rdev = 0; | 258 | ip->i_inode.i_rdev = 0; |
| @@ -275,8 +274,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | |||
| 275 | ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink); | 274 | ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink); |
| 276 | di->di_size = be64_to_cpu(str->di_size); | 275 | di->di_size = be64_to_cpu(str->di_size); |
| 277 | i_size_write(&ip->i_inode, di->di_size); | 276 | i_size_write(&ip->i_inode, di->di_size); |
| 278 | di->di_blocks = be64_to_cpu(str->di_blocks); | 277 | gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); |
| 279 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 280 | ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); | 278 | ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); |
| 281 | ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); | 279 | ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); |
| 282 | ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); | 280 | ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); |
| @@ -284,15 +282,20 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | |||
| 284 | ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); | 282 | ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); |
| 285 | ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); | 283 | ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); |
| 286 | 284 | ||
| 287 | di->di_goal_meta = be64_to_cpu(str->di_goal_meta); | 285 | ip->i_goal = be64_to_cpu(str->di_goal_meta); |
| 288 | di->di_goal_data = be64_to_cpu(str->di_goal_data); | ||
| 289 | di->di_generation = be64_to_cpu(str->di_generation); | 286 | di->di_generation = be64_to_cpu(str->di_generation); |
| 290 | 287 | ||
| 291 | di->di_flags = be32_to_cpu(str->di_flags); | 288 | di->di_flags = be32_to_cpu(str->di_flags); |
| 292 | gfs2_set_inode_flags(&ip->i_inode); | 289 | gfs2_set_inode_flags(&ip->i_inode); |
| 293 | di->di_height = be16_to_cpu(str->di_height); | 290 | height = be16_to_cpu(str->di_height); |
| 294 | 291 | if (unlikely(height > GFS2_MAX_META_HEIGHT)) | |
| 295 | di->di_depth = be16_to_cpu(str->di_depth); | 292 | goto corrupt; |
| 293 | ip->i_height = (u8)height; | ||
| 294 | |||
| 295 | depth = be16_to_cpu(str->di_depth); | ||
| 296 | if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) | ||
| 297 | goto corrupt; | ||
| 298 | ip->i_depth = (u8)depth; | ||
| 296 | di->di_entries = be32_to_cpu(str->di_entries); | 299 | di->di_entries = be32_to_cpu(str->di_entries); |
| 297 | 300 | ||
| 298 | di->di_eattr = be64_to_cpu(str->di_eattr); | 301 | di->di_eattr = be64_to_cpu(str->di_eattr); |
| @@ -300,6 +303,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | |||
| 300 | gfs2_set_aops(&ip->i_inode); | 303 | gfs2_set_aops(&ip->i_inode); |
| 301 | 304 | ||
| 302 | return 0; | 305 | return 0; |
| 306 | corrupt: | ||
| 307 | if (gfs2_consist_inode(ip)) | ||
| 308 | gfs2_dinode_print(ip); | ||
| 309 | return -EIO; | ||
| 303 | } | 310 | } |
| 304 | 311 | ||
| 305 | /** | 312 | /** |
| @@ -337,13 +344,15 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip) | |||
| 337 | struct gfs2_rgrpd *rgd; | 344 | struct gfs2_rgrpd *rgd; |
| 338 | int error; | 345 | int error; |
| 339 | 346 | ||
| 340 | if (ip->i_di.di_blocks != 1) { | 347 | if (gfs2_get_inode_blocks(&ip->i_inode) != 1) { |
| 341 | if (gfs2_consist_inode(ip)) | 348 | if (gfs2_consist_inode(ip)) |
| 342 | gfs2_dinode_print(ip); | 349 | gfs2_dinode_print(ip); |
| 343 | return -EIO; | 350 | return -EIO; |
| 344 | } | 351 | } |
| 345 | 352 | ||
| 346 | al = gfs2_alloc_get(ip); | 353 | al = gfs2_alloc_get(ip); |
| 354 | if (!al) | ||
| 355 | return -ENOMEM; | ||
| 347 | 356 | ||
| 348 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 357 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); |
| 349 | if (error) | 358 | if (error) |
| @@ -487,7 +496,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
| 487 | return dir; | 496 | return dir; |
| 488 | } | 497 | } |
| 489 | 498 | ||
| 490 | if (gfs2_glock_is_locked_by_me(dip->i_gl) == 0) { | 499 | if (gfs2_glock_is_locked_by_me(dip->i_gl) == NULL) { |
| 491 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); | 500 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); |
| 492 | if (error) | 501 | if (error) |
| 493 | return ERR_PTR(error); | 502 | return ERR_PTR(error); |
| @@ -818,7 +827,8 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
| 818 | int error; | 827 | int error; |
| 819 | 828 | ||
| 820 | munge_mode_uid_gid(dip, &mode, &uid, &gid); | 829 | munge_mode_uid_gid(dip, &mode, &uid, &gid); |
| 821 | gfs2_alloc_get(dip); | 830 | if (!gfs2_alloc_get(dip)) |
| 831 | return -ENOMEM; | ||
| 822 | 832 | ||
| 823 | error = gfs2_quota_lock(dip, uid, gid); | 833 | error = gfs2_quota_lock(dip, uid, gid); |
| 824 | if (error) | 834 | if (error) |
| @@ -853,6 +863,8 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, | |||
| 853 | int error; | 863 | int error; |
| 854 | 864 | ||
| 855 | al = gfs2_alloc_get(dip); | 865 | al = gfs2_alloc_get(dip); |
| 866 | if (!al) | ||
| 867 | return -ENOMEM; | ||
| 856 | 868 | ||
| 857 | error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 869 | error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); |
| 858 | if (error) | 870 | if (error) |
| @@ -1219,7 +1231,7 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len) | |||
| 1219 | 1231 | ||
| 1220 | x = ip->i_di.di_size + 1; | 1232 | x = ip->i_di.di_size + 1; |
| 1221 | if (x > *len) { | 1233 | if (x > *len) { |
| 1222 | *buf = kmalloc(x, GFP_KERNEL); | 1234 | *buf = kmalloc(x, GFP_NOFS); |
| 1223 | if (!*buf) { | 1235 | if (!*buf) { |
| 1224 | error = -ENOMEM; | 1236 | error = -ENOMEM; |
| 1225 | goto out_brelse; | 1237 | goto out_brelse; |
| @@ -1391,21 +1403,21 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) | |||
| 1391 | str->di_gid = cpu_to_be32(ip->i_inode.i_gid); | 1403 | str->di_gid = cpu_to_be32(ip->i_inode.i_gid); |
| 1392 | str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); | 1404 | str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); |
| 1393 | str->di_size = cpu_to_be64(di->di_size); | 1405 | str->di_size = cpu_to_be64(di->di_size); |
| 1394 | str->di_blocks = cpu_to_be64(di->di_blocks); | 1406 | str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); |
| 1395 | str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); | 1407 | str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); |
| 1396 | str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); | 1408 | str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); |
| 1397 | str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec); | 1409 | str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec); |
| 1398 | 1410 | ||
| 1399 | str->di_goal_meta = cpu_to_be64(di->di_goal_meta); | 1411 | str->di_goal_meta = cpu_to_be64(ip->i_goal); |
| 1400 | str->di_goal_data = cpu_to_be64(di->di_goal_data); | 1412 | str->di_goal_data = cpu_to_be64(ip->i_goal); |
| 1401 | str->di_generation = cpu_to_be64(di->di_generation); | 1413 | str->di_generation = cpu_to_be64(di->di_generation); |
| 1402 | 1414 | ||
| 1403 | str->di_flags = cpu_to_be32(di->di_flags); | 1415 | str->di_flags = cpu_to_be32(di->di_flags); |
| 1404 | str->di_height = cpu_to_be16(di->di_height); | 1416 | str->di_height = cpu_to_be16(ip->i_height); |
| 1405 | str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && | 1417 | str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && |
| 1406 | !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ? | 1418 | !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ? |
| 1407 | GFS2_FORMAT_DE : 0); | 1419 | GFS2_FORMAT_DE : 0); |
| 1408 | str->di_depth = cpu_to_be16(di->di_depth); | 1420 | str->di_depth = cpu_to_be16(ip->i_depth); |
| 1409 | str->di_entries = cpu_to_be32(di->di_entries); | 1421 | str->di_entries = cpu_to_be32(di->di_entries); |
| 1410 | 1422 | ||
| 1411 | str->di_eattr = cpu_to_be64(di->di_eattr); | 1423 | str->di_eattr = cpu_to_be64(di->di_eattr); |
| @@ -1423,15 +1435,13 @@ void gfs2_dinode_print(const struct gfs2_inode *ip) | |||
| 1423 | printk(KERN_INFO " no_addr = %llu\n", | 1435 | printk(KERN_INFO " no_addr = %llu\n", |
| 1424 | (unsigned long long)ip->i_no_addr); | 1436 | (unsigned long long)ip->i_no_addr); |
| 1425 | printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size); | 1437 | printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size); |
| 1426 | printk(KERN_INFO " di_blocks = %llu\n", | 1438 | printk(KERN_INFO " blocks = %llu\n", |
| 1427 | (unsigned long long)di->di_blocks); | 1439 | (unsigned long long)gfs2_get_inode_blocks(&ip->i_inode)); |
| 1428 | printk(KERN_INFO " di_goal_meta = %llu\n", | 1440 | printk(KERN_INFO " i_goal = %llu\n", |
| 1429 | (unsigned long long)di->di_goal_meta); | 1441 | (unsigned long long)ip->i_goal); |
| 1430 | printk(KERN_INFO " di_goal_data = %llu\n", | ||
| 1431 | (unsigned long long)di->di_goal_data); | ||
| 1432 | printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags); | 1442 | printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags); |
| 1433 | printk(KERN_INFO " di_height = %u\n", di->di_height); | 1443 | printk(KERN_INFO " i_height = %u\n", ip->i_height); |
| 1434 | printk(KERN_INFO " di_depth = %u\n", di->di_depth); | 1444 | printk(KERN_INFO " i_depth = %u\n", ip->i_depth); |
| 1435 | printk(KERN_INFO " di_entries = %u\n", di->di_entries); | 1445 | printk(KERN_INFO " di_entries = %u\n", di->di_entries); |
| 1436 | printk(KERN_INFO " di_eattr = %llu\n", | 1446 | printk(KERN_INFO " di_eattr = %llu\n", |
| 1437 | (unsigned long long)di->di_eattr); | 1447 | (unsigned long long)di->di_eattr); |
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index d44650662615..580da454b38f 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
| @@ -10,9 +10,11 @@ | |||
| 10 | #ifndef __INODE_DOT_H__ | 10 | #ifndef __INODE_DOT_H__ |
| 11 | #define __INODE_DOT_H__ | 11 | #define __INODE_DOT_H__ |
| 12 | 12 | ||
| 13 | #include "util.h" | ||
| 14 | |||
| 13 | static inline int gfs2_is_stuffed(const struct gfs2_inode *ip) | 15 | static inline int gfs2_is_stuffed(const struct gfs2_inode *ip) |
| 14 | { | 16 | { |
| 15 | return !ip->i_di.di_height; | 17 | return !ip->i_height; |
| 16 | } | 18 | } |
| 17 | 19 | ||
| 18 | static inline int gfs2_is_jdata(const struct gfs2_inode *ip) | 20 | static inline int gfs2_is_jdata(const struct gfs2_inode *ip) |
| @@ -37,13 +39,25 @@ static inline int gfs2_is_dir(const struct gfs2_inode *ip) | |||
| 37 | return S_ISDIR(ip->i_inode.i_mode); | 39 | return S_ISDIR(ip->i_inode.i_mode); |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 40 | static inline void gfs2_set_inode_blocks(struct inode *inode) | 42 | static inline void gfs2_set_inode_blocks(struct inode *inode, u64 blocks) |
| 43 | { | ||
| 44 | inode->i_blocks = blocks << | ||
| 45 | (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); | ||
| 46 | } | ||
| 47 | |||
| 48 | static inline u64 gfs2_get_inode_blocks(const struct inode *inode) | ||
| 41 | { | 49 | { |
| 42 | struct gfs2_inode *ip = GFS2_I(inode); | 50 | return inode->i_blocks >> |
| 43 | inode->i_blocks = ip->i_di.di_blocks << | ||
| 44 | (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); | 51 | (GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); |
| 45 | } | 52 | } |
| 46 | 53 | ||
| 54 | static inline void gfs2_add_inode_blocks(struct inode *inode, s64 change) | ||
| 55 | { | ||
| 56 | gfs2_assert(GFS2_SB(inode), (change >= 0 || inode->i_blocks > -change)); | ||
| 57 | change *= (GFS2_SB(inode)->sd_sb.sb_bsize/GFS2_BASIC_BLOCK); | ||
| 58 | inode->i_blocks += change; | ||
| 59 | } | ||
| 60 | |||
| 47 | static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr, | 61 | static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr, |
| 48 | u64 no_formal_ino) | 62 | u64 no_formal_ino) |
| 49 | { | 63 | { |
diff --git a/fs/gfs2/lm.c b/fs/gfs2/lm.c deleted file mode 100644 index cfcc39b86a53..000000000000 --- a/fs/gfs2/lm.c +++ /dev/null | |||
| @@ -1,210 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
| 3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | ||
| 4 | * | ||
| 5 | * This copyrighted material is made available to anyone wishing to use, | ||
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | ||
| 7 | * of the GNU General Public License version 2. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/slab.h> | ||
| 11 | #include <linux/spinlock.h> | ||
| 12 | #include <linux/completion.h> | ||
| 13 | #include <linux/buffer_head.h> | ||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/gfs2_ondisk.h> | ||
| 16 | #include <linux/lm_interface.h> | ||
| 17 | |||
| 18 | #include "gfs2.h" | ||
| 19 | #include "incore.h" | ||
| 20 | #include "glock.h" | ||
| 21 | #include "lm.h" | ||
| 22 | #include "super.h" | ||
| 23 | #include "util.h" | ||
| 24 | |||
| 25 | /** | ||
| 26 | * gfs2_lm_mount - mount a locking protocol | ||
| 27 | * @sdp: the filesystem | ||
| 28 | * @args: mount arguements | ||
| 29 | * @silent: if 1, don't complain if the FS isn't a GFS2 fs | ||
| 30 | * | ||
| 31 | * Returns: errno | ||
| 32 | */ | ||
| 33 | |||
| 34 | int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) | ||
| 35 | { | ||
| 36 | char *proto = sdp->sd_proto_name; | ||
| 37 | char *table = sdp->sd_table_name; | ||
| 38 | int flags = 0; | ||
| 39 | int error; | ||
| 40 | |||
| 41 | if (sdp->sd_args.ar_spectator) | ||
| 42 | flags |= LM_MFLAG_SPECTATOR; | ||
| 43 | |||
| 44 | fs_info(sdp, "Trying to join cluster \"%s\", \"%s\"\n", proto, table); | ||
| 45 | |||
| 46 | error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata, | ||
| 47 | gfs2_glock_cb, sdp, | ||
| 48 | GFS2_MIN_LVB_SIZE, flags, | ||
| 49 | &sdp->sd_lockstruct, &sdp->sd_kobj); | ||
| 50 | if (error) { | ||
| 51 | fs_info(sdp, "can't mount proto=%s, table=%s, hostdata=%s\n", | ||
| 52 | proto, table, sdp->sd_args.ar_hostdata); | ||
| 53 | goto out; | ||
| 54 | } | ||
| 55 | |||
| 56 | if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) || | ||
| 57 | gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) || | ||
| 58 | gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >= | ||
| 59 | GFS2_MIN_LVB_SIZE)) { | ||
| 60 | gfs2_unmount_lockproto(&sdp->sd_lockstruct); | ||
| 61 | goto out; | ||
| 62 | } | ||
| 63 | |||
| 64 | if (sdp->sd_args.ar_spectator) | ||
| 65 | snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.s", table); | ||
| 66 | else | ||
| 67 | snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.%u", table, | ||
| 68 | sdp->sd_lockstruct.ls_jid); | ||
| 69 | |||
| 70 | fs_info(sdp, "Joined cluster. Now mounting FS...\n"); | ||
| 71 | |||
| 72 | if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) && | ||
| 73 | !sdp->sd_args.ar_ignore_local_fs) { | ||
| 74 | sdp->sd_args.ar_localflocks = 1; | ||
| 75 | sdp->sd_args.ar_localcaching = 1; | ||
| 76 | } | ||
| 77 | |||
| 78 | out: | ||
| 79 | return error; | ||
| 80 | } | ||
| 81 | |||
| 82 | void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp) | ||
| 83 | { | ||
| 84 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 85 | sdp->sd_lockstruct.ls_ops->lm_others_may_mount( | ||
| 86 | sdp->sd_lockstruct.ls_lockspace); | ||
| 87 | } | ||
| 88 | |||
| 89 | void gfs2_lm_unmount(struct gfs2_sbd *sdp) | ||
| 90 | { | ||
| 91 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 92 | gfs2_unmount_lockproto(&sdp->sd_lockstruct); | ||
| 93 | } | ||
| 94 | |||
| 95 | int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) | ||
| 96 | { | ||
| 97 | va_list args; | ||
| 98 | |||
| 99 | if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | ||
| 100 | return 0; | ||
| 101 | |||
| 102 | va_start(args, fmt); | ||
| 103 | vprintk(fmt, args); | ||
| 104 | va_end(args); | ||
| 105 | |||
| 106 | fs_err(sdp, "about to withdraw this file system\n"); | ||
| 107 | BUG_ON(sdp->sd_args.ar_debug); | ||
| 108 | |||
| 109 | fs_err(sdp, "telling LM to withdraw\n"); | ||
| 110 | gfs2_withdraw_lockproto(&sdp->sd_lockstruct); | ||
| 111 | fs_err(sdp, "withdrawn\n"); | ||
| 112 | dump_stack(); | ||
| 113 | |||
| 114 | return -1; | ||
| 115 | } | ||
| 116 | |||
| 117 | int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 118 | void **lockp) | ||
| 119 | { | ||
| 120 | int error = -EIO; | ||
| 121 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 122 | error = sdp->sd_lockstruct.ls_ops->lm_get_lock( | ||
| 123 | sdp->sd_lockstruct.ls_lockspace, name, lockp); | ||
| 124 | return error; | ||
| 125 | } | ||
| 126 | |||
| 127 | void gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock) | ||
| 128 | { | ||
| 129 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 130 | sdp->sd_lockstruct.ls_ops->lm_put_lock(lock); | ||
| 131 | } | ||
| 132 | |||
| 133 | unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, | ||
| 134 | unsigned int cur_state, unsigned int req_state, | ||
| 135 | unsigned int flags) | ||
| 136 | { | ||
| 137 | int ret = 0; | ||
| 138 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 139 | ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state, | ||
| 140 | req_state, flags); | ||
| 141 | return ret; | ||
| 142 | } | ||
| 143 | |||
| 144 | unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock, | ||
| 145 | unsigned int cur_state) | ||
| 146 | { | ||
| 147 | int ret = 0; | ||
| 148 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 149 | ret = sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state); | ||
| 150 | return ret; | ||
| 151 | } | ||
| 152 | |||
| 153 | void gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock) | ||
| 154 | { | ||
| 155 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 156 | sdp->sd_lockstruct.ls_ops->lm_cancel(lock); | ||
| 157 | } | ||
| 158 | |||
| 159 | int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp) | ||
| 160 | { | ||
| 161 | int error = -EIO; | ||
| 162 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 163 | error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp); | ||
| 164 | return error; | ||
| 165 | } | ||
| 166 | |||
| 167 | void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb) | ||
| 168 | { | ||
| 169 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 170 | sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(lock, lvb); | ||
| 171 | } | ||
| 172 | |||
| 173 | int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 174 | struct file *file, struct file_lock *fl) | ||
| 175 | { | ||
| 176 | int error = -EIO; | ||
| 177 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 178 | error = sdp->sd_lockstruct.ls_ops->lm_plock_get( | ||
| 179 | sdp->sd_lockstruct.ls_lockspace, name, file, fl); | ||
| 180 | return error; | ||
| 181 | } | ||
| 182 | |||
| 183 | int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 184 | struct file *file, int cmd, struct file_lock *fl) | ||
| 185 | { | ||
| 186 | int error = -EIO; | ||
| 187 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 188 | error = sdp->sd_lockstruct.ls_ops->lm_plock( | ||
| 189 | sdp->sd_lockstruct.ls_lockspace, name, file, cmd, fl); | ||
| 190 | return error; | ||
| 191 | } | ||
| 192 | |||
| 193 | int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 194 | struct file *file, struct file_lock *fl) | ||
| 195 | { | ||
| 196 | int error = -EIO; | ||
| 197 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 198 | error = sdp->sd_lockstruct.ls_ops->lm_punlock( | ||
| 199 | sdp->sd_lockstruct.ls_lockspace, name, file, fl); | ||
| 200 | return error; | ||
| 201 | } | ||
| 202 | |||
| 203 | void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid, | ||
| 204 | unsigned int message) | ||
| 205 | { | ||
| 206 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 207 | sdp->sd_lockstruct.ls_ops->lm_recovery_done( | ||
| 208 | sdp->sd_lockstruct.ls_lockspace, jid, message); | ||
| 209 | } | ||
| 210 | |||
diff --git a/fs/gfs2/lm.h b/fs/gfs2/lm.h deleted file mode 100644 index 21cdc30ee08c..000000000000 --- a/fs/gfs2/lm.h +++ /dev/null | |||
| @@ -1,42 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
| 3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | ||
| 4 | * | ||
| 5 | * This copyrighted material is made available to anyone wishing to use, | ||
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | ||
| 7 | * of the GNU General Public License version 2. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef __LM_DOT_H__ | ||
| 11 | #define __LM_DOT_H__ | ||
| 12 | |||
| 13 | struct gfs2_sbd; | ||
| 14 | |||
| 15 | #define GFS2_MIN_LVB_SIZE 32 | ||
| 16 | |||
| 17 | int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent); | ||
| 18 | void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp); | ||
| 19 | void gfs2_lm_unmount(struct gfs2_sbd *sdp); | ||
| 20 | int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) | ||
| 21 | __attribute__ ((format(printf, 2, 3))); | ||
| 22 | int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 23 | void **lockp); | ||
| 24 | void gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock); | ||
| 25 | unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, | ||
| 26 | unsigned int cur_state, unsigned int req_state, | ||
| 27 | unsigned int flags); | ||
| 28 | unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock, | ||
| 29 | unsigned int cur_state); | ||
| 30 | void gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock); | ||
| 31 | int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp); | ||
| 32 | void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb); | ||
| 33 | int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 34 | struct file *file, struct file_lock *fl); | ||
| 35 | int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 36 | struct file *file, int cmd, struct file_lock *fl); | ||
| 37 | int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 38 | struct file *file, struct file_lock *fl); | ||
| 39 | void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid, | ||
| 40 | unsigned int message); | ||
| 41 | |||
| 42 | #endif /* __LM_DOT_H__ */ | ||
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c index 542a797ac89a..cf7ea8abec87 100644 --- a/fs/gfs2/locking/dlm/lock.c +++ b/fs/gfs2/locking/dlm/lock.c | |||
| @@ -137,7 +137,8 @@ static inline unsigned int make_flags(struct gdlm_lock *lp, | |||
| 137 | 137 | ||
| 138 | /* Conversion deadlock avoidance by DLM */ | 138 | /* Conversion deadlock avoidance by DLM */ |
| 139 | 139 | ||
| 140 | if (!test_bit(LFL_FORCE_PROMOTE, &lp->flags) && | 140 | if (!(lp->ls->fsflags & LM_MFLAG_CONV_NODROP) && |
| 141 | !test_bit(LFL_FORCE_PROMOTE, &lp->flags) && | ||
| 141 | !(lkf & DLM_LKF_NOQUEUE) && | 142 | !(lkf & DLM_LKF_NOQUEUE) && |
| 142 | cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req) | 143 | cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req) |
| 143 | lkf |= DLM_LKF_CONVDEADLK; | 144 | lkf |= DLM_LKF_CONVDEADLK; |
| @@ -164,7 +165,7 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name, | |||
| 164 | { | 165 | { |
| 165 | struct gdlm_lock *lp; | 166 | struct gdlm_lock *lp; |
| 166 | 167 | ||
| 167 | lp = kzalloc(sizeof(struct gdlm_lock), GFP_KERNEL); | 168 | lp = kzalloc(sizeof(struct gdlm_lock), GFP_NOFS); |
| 168 | if (!lp) | 169 | if (!lp) |
| 169 | return -ENOMEM; | 170 | return -ENOMEM; |
| 170 | 171 | ||
| @@ -382,7 +383,7 @@ static int gdlm_add_lvb(struct gdlm_lock *lp) | |||
| 382 | { | 383 | { |
| 383 | char *lvb; | 384 | char *lvb; |
| 384 | 385 | ||
| 385 | lvb = kzalloc(GDLM_LVB_SIZE, GFP_KERNEL); | 386 | lvb = kzalloc(GDLM_LVB_SIZE, GFP_NOFS); |
| 386 | if (!lvb) | 387 | if (!lvb) |
| 387 | return -ENOMEM; | 388 | return -ENOMEM; |
| 388 | 389 | ||
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h index 9e8265d28377..58fcf8c5bf39 100644 --- a/fs/gfs2/locking/dlm/lock_dlm.h +++ b/fs/gfs2/locking/dlm/lock_dlm.h | |||
| @@ -183,5 +183,10 @@ int gdlm_plock_get(void *, struct lm_lockname *, struct file *, | |||
| 183 | struct file_lock *); | 183 | struct file_lock *); |
| 184 | int gdlm_punlock(void *, struct lm_lockname *, struct file *, | 184 | int gdlm_punlock(void *, struct lm_lockname *, struct file *, |
| 185 | struct file_lock *); | 185 | struct file_lock *); |
| 186 | |||
| 187 | /* mount.c */ | ||
| 188 | |||
| 189 | extern const struct lm_lockops gdlm_ops; | ||
| 190 | |||
| 186 | #endif | 191 | #endif |
| 187 | 192 | ||
diff --git a/fs/gfs2/locking/dlm/main.c b/fs/gfs2/locking/dlm/main.c index a0e7eda643ed..36a225850bd8 100644 --- a/fs/gfs2/locking/dlm/main.c +++ b/fs/gfs2/locking/dlm/main.c | |||
| @@ -11,8 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | #include "lock_dlm.h" | 12 | #include "lock_dlm.h" |
| 13 | 13 | ||
| 14 | extern struct lm_lockops gdlm_ops; | ||
| 15 | |||
| 16 | static int __init init_lock_dlm(void) | 14 | static int __init init_lock_dlm(void) |
| 17 | { | 15 | { |
| 18 | int error; | 16 | int error; |
diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c index a87b09839761..8479da47049c 100644 --- a/fs/gfs2/locking/dlm/sysfs.c +++ b/fs/gfs2/locking/dlm/sysfs.c | |||
| @@ -12,8 +12,6 @@ | |||
| 12 | 12 | ||
| 13 | #include "lock_dlm.h" | 13 | #include "lock_dlm.h" |
| 14 | 14 | ||
| 15 | extern struct lm_lockops gdlm_ops; | ||
| 16 | |||
| 17 | static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf) | 15 | static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf) |
| 18 | { | 16 | { |
| 19 | return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name); | 17 | return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name); |
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c index 521694fc19d6..e53db6fd28ab 100644 --- a/fs/gfs2/locking/dlm/thread.c +++ b/fs/gfs2/locking/dlm/thread.c | |||
| @@ -135,7 +135,15 @@ static void process_complete(struct gdlm_lock *lp) | |||
| 135 | lp->lksb.sb_status, lp->lockname.ln_type, | 135 | lp->lksb.sb_status, lp->lockname.ln_type, |
| 136 | (unsigned long long)lp->lockname.ln_number, | 136 | (unsigned long long)lp->lockname.ln_number, |
| 137 | lp->flags); | 137 | lp->flags); |
| 138 | return; | 138 | if (lp->lksb.sb_status == -EDEADLOCK && |
| 139 | lp->ls->fsflags & LM_MFLAG_CONV_NODROP) { | ||
| 140 | lp->req = lp->cur; | ||
| 141 | acb.lc_ret |= LM_OUT_CONV_DEADLK; | ||
| 142 | if (lp->cur == DLM_LOCK_IV) | ||
| 143 | lp->lksb.sb_lkid = 0; | ||
| 144 | goto out; | ||
| 145 | } else | ||
| 146 | return; | ||
| 139 | } | 147 | } |
| 140 | 148 | ||
| 141 | /* | 149 | /* |
diff --git a/fs/gfs2/locking/nolock/main.c b/fs/gfs2/locking/nolock/main.c index d3b8ce6fbbe3..284a5ece8d94 100644 --- a/fs/gfs2/locking/nolock/main.c +++ b/fs/gfs2/locking/nolock/main.c | |||
| @@ -140,7 +140,7 @@ static int nolock_hold_lvb(void *lock, char **lvbp) | |||
| 140 | struct nolock_lockspace *nl = lock; | 140 | struct nolock_lockspace *nl = lock; |
| 141 | int error = 0; | 141 | int error = 0; |
| 142 | 142 | ||
| 143 | *lvbp = kzalloc(nl->nl_lvb_size, GFP_KERNEL); | 143 | *lvbp = kzalloc(nl->nl_lvb_size, GFP_NOFS); |
| 144 | if (!*lvbp) | 144 | if (!*lvbp) |
| 145 | error = -ENOMEM; | 145 | error = -ENOMEM; |
| 146 | 146 | ||
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 161ab6f2058e..548264b1836d 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
| @@ -769,8 +769,8 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
| 769 | sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; | 769 | sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm; |
| 770 | gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); | 770 | gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0); |
| 771 | reserved = calc_reserved(sdp); | 771 | reserved = calc_reserved(sdp); |
| 772 | gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved); | ||
| 772 | unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved; | 773 | unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved; |
| 773 | gfs2_assert_withdraw(sdp, unused >= 0); | ||
| 774 | atomic_add(unused, &sdp->sd_log_blks_free); | 774 | atomic_add(unused, &sdp->sd_log_blks_free); |
| 775 | gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= | 775 | gfs2_assert_withdraw(sdp, atomic_read(&sdp->sd_log_blks_free) <= |
| 776 | sdp->sd_jdesc->jd_blocks); | 776 | sdp->sd_jdesc->jd_blocks); |
| @@ -779,6 +779,21 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
| 779 | gfs2_log_unlock(sdp); | 779 | gfs2_log_unlock(sdp); |
| 780 | } | 780 | } |
| 781 | 781 | ||
| 782 | static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | ||
| 783 | { | ||
| 784 | struct list_head *head = &tr->tr_list_buf; | ||
| 785 | struct gfs2_bufdata *bd; | ||
| 786 | |||
| 787 | gfs2_log_lock(sdp); | ||
| 788 | while (!list_empty(head)) { | ||
| 789 | bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr); | ||
| 790 | list_del_init(&bd->bd_list_tr); | ||
| 791 | tr->tr_num_buf--; | ||
| 792 | } | ||
| 793 | gfs2_log_unlock(sdp); | ||
| 794 | gfs2_assert_warn(sdp, !tr->tr_num_buf); | ||
| 795 | } | ||
| 796 | |||
| 782 | /** | 797 | /** |
| 783 | * gfs2_log_commit - Commit a transaction to the log | 798 | * gfs2_log_commit - Commit a transaction to the log |
| 784 | * @sdp: the filesystem | 799 | * @sdp: the filesystem |
| @@ -790,7 +805,7 @@ static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | |||
| 790 | void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 805 | void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
| 791 | { | 806 | { |
| 792 | log_refund(sdp, tr); | 807 | log_refund(sdp, tr); |
| 793 | lops_incore_commit(sdp, tr); | 808 | buf_lo_incore_commit(sdp, tr); |
| 794 | 809 | ||
| 795 | sdp->sd_vfs->s_dirt = 1; | 810 | sdp->sd_vfs->s_dirt = 1; |
| 796 | up_read(&sdp->sd_log_flush_lock); | 811 | up_read(&sdp->sd_log_flush_lock); |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index fae59d69d01a..4390f6f4047d 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
| @@ -152,21 +152,6 @@ out: | |||
| 152 | unlock_buffer(bd->bd_bh); | 152 | unlock_buffer(bd->bd_bh); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | ||
| 156 | { | ||
| 157 | struct list_head *head = &tr->tr_list_buf; | ||
| 158 | struct gfs2_bufdata *bd; | ||
| 159 | |||
| 160 | gfs2_log_lock(sdp); | ||
| 161 | while (!list_empty(head)) { | ||
| 162 | bd = list_entry(head->next, struct gfs2_bufdata, bd_list_tr); | ||
| 163 | list_del_init(&bd->bd_list_tr); | ||
| 164 | tr->tr_num_buf--; | ||
| 165 | } | ||
| 166 | gfs2_log_unlock(sdp); | ||
| 167 | gfs2_assert_warn(sdp, !tr->tr_num_buf); | ||
| 168 | } | ||
| 169 | |||
| 170 | static void buf_lo_before_commit(struct gfs2_sbd *sdp) | 155 | static void buf_lo_before_commit(struct gfs2_sbd *sdp) |
| 171 | { | 156 | { |
| 172 | struct buffer_head *bh; | 157 | struct buffer_head *bh; |
| @@ -419,8 +404,10 @@ static int revoke_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, | |||
| 419 | blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset)); | 404 | blkno = be64_to_cpu(*(__be64 *)(bh->b_data + offset)); |
| 420 | 405 | ||
| 421 | error = gfs2_revoke_add(sdp, blkno, start); | 406 | error = gfs2_revoke_add(sdp, blkno, start); |
| 422 | if (error < 0) | 407 | if (error < 0) { |
| 408 | brelse(bh); | ||
| 423 | return error; | 409 | return error; |
| 410 | } | ||
| 424 | else if (error) | 411 | else if (error) |
| 425 | sdp->sd_found_revokes++; | 412 | sdp->sd_found_revokes++; |
| 426 | 413 | ||
| @@ -737,7 +724,6 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
| 737 | 724 | ||
| 738 | const struct gfs2_log_operations gfs2_buf_lops = { | 725 | const struct gfs2_log_operations gfs2_buf_lops = { |
| 739 | .lo_add = buf_lo_add, | 726 | .lo_add = buf_lo_add, |
| 740 | .lo_incore_commit = buf_lo_incore_commit, | ||
| 741 | .lo_before_commit = buf_lo_before_commit, | 727 | .lo_before_commit = buf_lo_before_commit, |
| 742 | .lo_after_commit = buf_lo_after_commit, | 728 | .lo_after_commit = buf_lo_after_commit, |
| 743 | .lo_before_scan = buf_lo_before_scan, | 729 | .lo_before_scan = buf_lo_before_scan, |
| @@ -763,7 +749,6 @@ const struct gfs2_log_operations gfs2_rg_lops = { | |||
| 763 | 749 | ||
| 764 | const struct gfs2_log_operations gfs2_databuf_lops = { | 750 | const struct gfs2_log_operations gfs2_databuf_lops = { |
| 765 | .lo_add = databuf_lo_add, | 751 | .lo_add = databuf_lo_add, |
| 766 | .lo_incore_commit = buf_lo_incore_commit, | ||
| 767 | .lo_before_commit = databuf_lo_before_commit, | 752 | .lo_before_commit = databuf_lo_before_commit, |
| 768 | .lo_after_commit = databuf_lo_after_commit, | 753 | .lo_after_commit = databuf_lo_after_commit, |
| 769 | .lo_scan_elements = databuf_lo_scan_elements, | 754 | .lo_scan_elements = databuf_lo_scan_elements, |
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h index 41a00df75587..3c0b2737658a 100644 --- a/fs/gfs2/lops.h +++ b/fs/gfs2/lops.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -57,15 +57,6 @@ static inline void lops_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
| 57 | le->le_ops->lo_add(sdp, le); | 57 | le->le_ops->lo_add(sdp, le); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static inline void lops_incore_commit(struct gfs2_sbd *sdp, | ||
| 61 | struct gfs2_trans *tr) | ||
| 62 | { | ||
| 63 | int x; | ||
| 64 | for (x = 0; gfs2_log_ops[x]; x++) | ||
| 65 | if (gfs2_log_ops[x]->lo_incore_commit) | ||
| 66 | gfs2_log_ops[x]->lo_incore_commit(sdp, tr); | ||
| 67 | } | ||
| 68 | |||
| 69 | static inline void lops_before_commit(struct gfs2_sbd *sdp) | 60 | static inline void lops_before_commit(struct gfs2_sbd *sdp) |
| 70 | { | 61 | { |
| 71 | int x; | 62 | int x; |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 9c7765c12d62..053e2ebbbd50 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
| @@ -89,6 +89,12 @@ static int __init init_gfs2_fs(void) | |||
| 89 | if (!gfs2_bufdata_cachep) | 89 | if (!gfs2_bufdata_cachep) |
| 90 | goto fail; | 90 | goto fail; |
| 91 | 91 | ||
| 92 | gfs2_rgrpd_cachep = kmem_cache_create("gfs2_rgrpd", | ||
| 93 | sizeof(struct gfs2_rgrpd), | ||
| 94 | 0, 0, NULL); | ||
| 95 | if (!gfs2_rgrpd_cachep) | ||
| 96 | goto fail; | ||
| 97 | |||
| 92 | error = register_filesystem(&gfs2_fs_type); | 98 | error = register_filesystem(&gfs2_fs_type); |
| 93 | if (error) | 99 | if (error) |
| 94 | goto fail; | 100 | goto fail; |
| @@ -108,6 +114,9 @@ fail_unregister: | |||
| 108 | fail: | 114 | fail: |
| 109 | gfs2_glock_exit(); | 115 | gfs2_glock_exit(); |
| 110 | 116 | ||
| 117 | if (gfs2_rgrpd_cachep) | ||
| 118 | kmem_cache_destroy(gfs2_rgrpd_cachep); | ||
| 119 | |||
| 111 | if (gfs2_bufdata_cachep) | 120 | if (gfs2_bufdata_cachep) |
| 112 | kmem_cache_destroy(gfs2_bufdata_cachep); | 121 | kmem_cache_destroy(gfs2_bufdata_cachep); |
| 113 | 122 | ||
| @@ -133,6 +142,7 @@ static void __exit exit_gfs2_fs(void) | |||
| 133 | unregister_filesystem(&gfs2_fs_type); | 142 | unregister_filesystem(&gfs2_fs_type); |
| 134 | unregister_filesystem(&gfs2meta_fs_type); | 143 | unregister_filesystem(&gfs2meta_fs_type); |
| 135 | 144 | ||
| 145 | kmem_cache_destroy(gfs2_rgrpd_cachep); | ||
| 136 | kmem_cache_destroy(gfs2_bufdata_cachep); | 146 | kmem_cache_destroy(gfs2_bufdata_cachep); |
| 137 | kmem_cache_destroy(gfs2_inode_cachep); | 147 | kmem_cache_destroy(gfs2_inode_cachep); |
| 138 | kmem_cache_destroy(gfs2_glock_cachep); | 148 | kmem_cache_destroy(gfs2_glock_cachep); |
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index ac772b6d9dbb..90a04a6e3789 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <linux/gfs2_ondisk.h> | 21 | #include <linux/gfs2_ondisk.h> |
| 22 | #include <linux/lm_interface.h> | 22 | #include <linux/lm_interface.h> |
| 23 | #include <linux/backing-dev.h> | 23 | #include <linux/backing-dev.h> |
| 24 | #include <linux/pagevec.h> | ||
| 25 | 24 | ||
| 26 | #include "gfs2.h" | 25 | #include "gfs2.h" |
| 27 | #include "incore.h" | 26 | #include "incore.h" |
| @@ -104,11 +103,9 @@ static int gfs2_writepage_common(struct page *page, | |||
| 104 | loff_t i_size = i_size_read(inode); | 103 | loff_t i_size = i_size_read(inode); |
| 105 | pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; | 104 | pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; |
| 106 | unsigned offset; | 105 | unsigned offset; |
| 107 | int ret = -EIO; | ||
| 108 | 106 | ||
| 109 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl))) | 107 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl))) |
| 110 | goto out; | 108 | goto out; |
| 111 | ret = 0; | ||
| 112 | if (current->journal_info) | 109 | if (current->journal_info) |
| 113 | goto redirty; | 110 | goto redirty; |
| 114 | /* Is the page fully outside i_size? (truncate in progress) */ | 111 | /* Is the page fully outside i_size? (truncate in progress) */ |
| @@ -280,7 +277,7 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping, | |||
| 280 | int i; | 277 | int i; |
| 281 | int ret; | 278 | int ret; |
| 282 | 279 | ||
| 283 | ret = gfs2_trans_begin(sdp, nrblocks, 0); | 280 | ret = gfs2_trans_begin(sdp, nrblocks, nrblocks); |
| 284 | if (ret < 0) | 281 | if (ret < 0) |
| 285 | return ret; | 282 | return ret; |
| 286 | 283 | ||
| @@ -510,23 +507,26 @@ static int __gfs2_readpage(void *file, struct page *page) | |||
| 510 | static int gfs2_readpage(struct file *file, struct page *page) | 507 | static int gfs2_readpage(struct file *file, struct page *page) |
| 511 | { | 508 | { |
| 512 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | 509 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); |
| 513 | struct gfs2_holder gh; | 510 | struct gfs2_holder *gh; |
| 514 | int error; | 511 | int error; |
| 515 | 512 | ||
| 516 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh); | 513 | gh = gfs2_glock_is_locked_by_me(ip->i_gl); |
| 517 | error = gfs2_glock_nq_atime(&gh); | 514 | if (!gh) { |
| 518 | if (unlikely(error)) { | 515 | gh = kmalloc(sizeof(struct gfs2_holder), GFP_NOFS); |
| 516 | if (!gh) | ||
| 517 | return -ENOBUFS; | ||
| 518 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, gh); | ||
| 519 | unlock_page(page); | 519 | unlock_page(page); |
| 520 | goto out; | 520 | error = gfs2_glock_nq_atime(gh); |
| 521 | if (likely(error != 0)) | ||
| 522 | goto out; | ||
| 523 | return AOP_TRUNCATED_PAGE; | ||
| 521 | } | 524 | } |
| 522 | error = __gfs2_readpage(file, page); | 525 | error = __gfs2_readpage(file, page); |
| 523 | gfs2_glock_dq(&gh); | 526 | gfs2_glock_dq(gh); |
| 524 | out: | 527 | out: |
| 525 | gfs2_holder_uninit(&gh); | 528 | gfs2_holder_uninit(gh); |
| 526 | if (error == GLR_TRYFAILED) { | 529 | kfree(gh); |
| 527 | yield(); | ||
| 528 | return AOP_TRUNCATED_PAGE; | ||
| 529 | } | ||
| 530 | return error; | 530 | return error; |
| 531 | } | 531 | } |
| 532 | 532 | ||
| @@ -648,15 +648,15 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 648 | 648 | ||
| 649 | if (alloc_required) { | 649 | if (alloc_required) { |
| 650 | al = gfs2_alloc_get(ip); | 650 | al = gfs2_alloc_get(ip); |
| 651 | if (!al) { | ||
| 652 | error = -ENOMEM; | ||
| 653 | goto out_unlock; | ||
| 654 | } | ||
| 651 | 655 | ||
| 652 | error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 656 | error = gfs2_quota_lock_check(ip); |
| 653 | if (error) | 657 | if (error) |
| 654 | goto out_alloc_put; | 658 | goto out_alloc_put; |
| 655 | 659 | ||
| 656 | error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); | ||
| 657 | if (error) | ||
| 658 | goto out_qunlock; | ||
| 659 | |||
| 660 | al->al_requested = data_blocks + ind_blocks; | 660 | al->al_requested = data_blocks + ind_blocks; |
| 661 | error = gfs2_inplace_reserve(ip); | 661 | error = gfs2_inplace_reserve(ip); |
| 662 | if (error) | 662 | if (error) |
| @@ -828,7 +828,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
| 828 | unsigned int to = from + len; | 828 | unsigned int to = from + len; |
| 829 | int ret; | 829 | int ret; |
| 830 | 830 | ||
| 831 | BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == 0); | 831 | BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL); |
| 832 | 832 | ||
| 833 | ret = gfs2_meta_inode_buffer(ip, &dibh); | 833 | ret = gfs2_meta_inode_buffer(ip, &dibh); |
| 834 | if (unlikely(ret)) { | 834 | if (unlikely(ret)) { |
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c index 793e334d098e..4a5e676b4420 100644 --- a/fs/gfs2/ops_dentry.c +++ b/fs/gfs2/ops_dentry.c | |||
| @@ -43,7 +43,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 43 | struct gfs2_holder d_gh; | 43 | struct gfs2_holder d_gh; |
| 44 | struct gfs2_inode *ip = NULL; | 44 | struct gfs2_inode *ip = NULL; |
| 45 | int error; | 45 | int error; |
| 46 | int had_lock=0; | 46 | int had_lock = 0; |
| 47 | 47 | ||
| 48 | if (inode) { | 48 | if (inode) { |
| 49 | if (is_bad_inode(inode)) | 49 | if (is_bad_inode(inode)) |
| @@ -54,7 +54,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 54 | if (sdp->sd_args.ar_localcaching) | 54 | if (sdp->sd_args.ar_localcaching) |
| 55 | goto valid; | 55 | goto valid; |
| 56 | 56 | ||
| 57 | had_lock = gfs2_glock_is_locked_by_me(dip->i_gl); | 57 | had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL); |
| 58 | if (!had_lock) { | 58 | if (!had_lock) { |
| 59 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); | 59 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); |
| 60 | if (error) | 60 | if (error) |
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index 334c7f85351b..990d9f4bc463 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c | |||
| @@ -204,8 +204,6 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, | |||
| 204 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, | 204 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, |
| 205 | inum->no_addr, | 205 | inum->no_addr, |
| 206 | 0, 0); | 206 | 0, 0); |
| 207 | if (!inode) | ||
| 208 | goto fail; | ||
| 209 | if (IS_ERR(inode)) { | 207 | if (IS_ERR(inode)) { |
| 210 | error = PTR_ERR(inode); | 208 | error = PTR_ERR(inode); |
| 211 | goto fail; | 209 | goto fail; |
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index f4842f2548cd..e1b7d525a066 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include "glock.h" | 30 | #include "glock.h" |
| 31 | #include "glops.h" | 31 | #include "glops.h" |
| 32 | #include "inode.h" | 32 | #include "inode.h" |
| 33 | #include "lm.h" | ||
| 34 | #include "log.h" | 33 | #include "log.h" |
| 35 | #include "meta_io.h" | 34 | #include "meta_io.h" |
| 36 | #include "quota.h" | 35 | #include "quota.h" |
| @@ -39,6 +38,7 @@ | |||
| 39 | #include "util.h" | 38 | #include "util.h" |
| 40 | #include "eaops.h" | 39 | #include "eaops.h" |
| 41 | #include "ops_address.h" | 40 | #include "ops_address.h" |
| 41 | #include "ops_inode.h" | ||
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * gfs2_llseek - seek to a location in a file | 44 | * gfs2_llseek - seek to a location in a file |
| @@ -369,12 +369,9 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
| 369 | if (al == NULL) | 369 | if (al == NULL) |
| 370 | goto out_unlock; | 370 | goto out_unlock; |
| 371 | 371 | ||
| 372 | ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 372 | ret = gfs2_quota_lock_check(ip); |
| 373 | if (ret) | 373 | if (ret) |
| 374 | goto out_alloc_put; | 374 | goto out_alloc_put; |
| 375 | ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); | ||
| 376 | if (ret) | ||
| 377 | goto out_quota_unlock; | ||
| 378 | al->al_requested = data_blocks + ind_blocks; | 375 | al->al_requested = data_blocks + ind_blocks; |
| 379 | ret = gfs2_inplace_reserve(ip); | 376 | ret = gfs2_inplace_reserve(ip); |
| 380 | if (ret) | 377 | if (ret) |
| @@ -596,6 +593,36 @@ static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl) | |||
| 596 | return generic_setlease(file, arg, fl); | 593 | return generic_setlease(file, arg, fl); |
| 597 | } | 594 | } |
| 598 | 595 | ||
| 596 | static int gfs2_lm_plock_get(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 597 | struct file *file, struct file_lock *fl) | ||
| 598 | { | ||
| 599 | int error = -EIO; | ||
| 600 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 601 | error = sdp->sd_lockstruct.ls_ops->lm_plock_get( | ||
| 602 | sdp->sd_lockstruct.ls_lockspace, name, file, fl); | ||
| 603 | return error; | ||
| 604 | } | ||
| 605 | |||
| 606 | static int gfs2_lm_plock(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 607 | struct file *file, int cmd, struct file_lock *fl) | ||
| 608 | { | ||
| 609 | int error = -EIO; | ||
| 610 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 611 | error = sdp->sd_lockstruct.ls_ops->lm_plock( | ||
| 612 | sdp->sd_lockstruct.ls_lockspace, name, file, cmd, fl); | ||
| 613 | return error; | ||
| 614 | } | ||
| 615 | |||
| 616 | static int gfs2_lm_punlock(struct gfs2_sbd *sdp, struct lm_lockname *name, | ||
| 617 | struct file *file, struct file_lock *fl) | ||
| 618 | { | ||
| 619 | int error = -EIO; | ||
| 620 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 621 | error = sdp->sd_lockstruct.ls_ops->lm_punlock( | ||
| 622 | sdp->sd_lockstruct.ls_lockspace, name, file, fl); | ||
| 623 | return error; | ||
| 624 | } | ||
| 625 | |||
| 599 | /** | 626 | /** |
| 600 | * gfs2_lock - acquire/release a posix lock on a file | 627 | * gfs2_lock - acquire/release a posix lock on a file |
| 601 | * @file: the file pointer | 628 | * @file: the file pointer |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 4bee6aa845e4..ef9c6c4f80f6 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -26,7 +26,6 @@ | |||
| 26 | #include "glock.h" | 26 | #include "glock.h" |
| 27 | #include "glops.h" | 27 | #include "glops.h" |
| 28 | #include "inode.h" | 28 | #include "inode.h" |
| 29 | #include "lm.h" | ||
| 30 | #include "mount.h" | 29 | #include "mount.h" |
| 31 | #include "ops_fstype.h" | 30 | #include "ops_fstype.h" |
| 32 | #include "ops_dentry.h" | 31 | #include "ops_dentry.h" |
| @@ -363,6 +362,13 @@ static int map_journal_extents(struct gfs2_sbd *sdp) | |||
| 363 | return rc; | 362 | return rc; |
| 364 | } | 363 | } |
| 365 | 364 | ||
| 365 | static void gfs2_lm_others_may_mount(struct gfs2_sbd *sdp) | ||
| 366 | { | ||
| 367 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 368 | sdp->sd_lockstruct.ls_ops->lm_others_may_mount( | ||
| 369 | sdp->sd_lockstruct.ls_lockspace); | ||
| 370 | } | ||
| 371 | |||
| 366 | static int init_journal(struct gfs2_sbd *sdp, int undo) | 372 | static int init_journal(struct gfs2_sbd *sdp, int undo) |
| 367 | { | 373 | { |
| 368 | struct gfs2_holder ji_gh; | 374 | struct gfs2_holder ji_gh; |
| @@ -542,7 +548,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo) | |||
| 542 | } | 548 | } |
| 543 | ip = GFS2_I(sdp->sd_rindex); | 549 | ip = GFS2_I(sdp->sd_rindex); |
| 544 | set_bit(GLF_STICKY, &ip->i_gl->gl_flags); | 550 | set_bit(GLF_STICKY, &ip->i_gl->gl_flags); |
| 545 | sdp->sd_rindex_vn = ip->i_gl->gl_vn - 1; | 551 | sdp->sd_rindex_uptodate = 0; |
| 546 | 552 | ||
| 547 | /* Read in the quota inode */ | 553 | /* Read in the quota inode */ |
| 548 | sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota"); | 554 | sdp->sd_quota_inode = gfs2_lookup_simple(sdp->sd_master_dir, "quota"); |
| @@ -705,6 +711,69 @@ fail: | |||
| 705 | } | 711 | } |
| 706 | 712 | ||
| 707 | /** | 713 | /** |
| 714 | * gfs2_lm_mount - mount a locking protocol | ||
| 715 | * @sdp: the filesystem | ||
| 716 | * @args: mount arguements | ||
| 717 | * @silent: if 1, don't complain if the FS isn't a GFS2 fs | ||
| 718 | * | ||
| 719 | * Returns: errno | ||
| 720 | */ | ||
| 721 | |||
| 722 | static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) | ||
| 723 | { | ||
| 724 | char *proto = sdp->sd_proto_name; | ||
| 725 | char *table = sdp->sd_table_name; | ||
| 726 | int flags = LM_MFLAG_CONV_NODROP; | ||
| 727 | int error; | ||
| 728 | |||
| 729 | if (sdp->sd_args.ar_spectator) | ||
| 730 | flags |= LM_MFLAG_SPECTATOR; | ||
| 731 | |||
| 732 | fs_info(sdp, "Trying to join cluster \"%s\", \"%s\"\n", proto, table); | ||
| 733 | |||
| 734 | error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata, | ||
| 735 | gfs2_glock_cb, sdp, | ||
| 736 | GFS2_MIN_LVB_SIZE, flags, | ||
| 737 | &sdp->sd_lockstruct, &sdp->sd_kobj); | ||
| 738 | if (error) { | ||
| 739 | fs_info(sdp, "can't mount proto=%s, table=%s, hostdata=%s\n", | ||
| 740 | proto, table, sdp->sd_args.ar_hostdata); | ||
| 741 | goto out; | ||
| 742 | } | ||
| 743 | |||
| 744 | if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) || | ||
| 745 | gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) || | ||
| 746 | gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >= | ||
| 747 | GFS2_MIN_LVB_SIZE)) { | ||
| 748 | gfs2_unmount_lockproto(&sdp->sd_lockstruct); | ||
| 749 | goto out; | ||
| 750 | } | ||
| 751 | |||
| 752 | if (sdp->sd_args.ar_spectator) | ||
| 753 | snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.s", table); | ||
| 754 | else | ||
| 755 | snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s.%u", table, | ||
| 756 | sdp->sd_lockstruct.ls_jid); | ||
| 757 | |||
| 758 | fs_info(sdp, "Joined cluster. Now mounting FS...\n"); | ||
| 759 | |||
| 760 | if ((sdp->sd_lockstruct.ls_flags & LM_LSFLAG_LOCAL) && | ||
| 761 | !sdp->sd_args.ar_ignore_local_fs) { | ||
| 762 | sdp->sd_args.ar_localflocks = 1; | ||
| 763 | sdp->sd_args.ar_localcaching = 1; | ||
| 764 | } | ||
| 765 | |||
| 766 | out: | ||
| 767 | return error; | ||
| 768 | } | ||
| 769 | |||
| 770 | void gfs2_lm_unmount(struct gfs2_sbd *sdp) | ||
| 771 | { | ||
| 772 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 773 | gfs2_unmount_lockproto(&sdp->sd_lockstruct); | ||
| 774 | } | ||
| 775 | |||
| 776 | /** | ||
| 708 | * fill_super - Read in superblock | 777 | * fill_super - Read in superblock |
| 709 | * @sb: The VFS superblock | 778 | * @sb: The VFS superblock |
| 710 | * @data: Mount options | 779 | * @data: Mount options |
| @@ -874,7 +943,6 @@ static struct super_block* get_gfs2_sb(const char *dev_name) | |||
| 874 | { | 943 | { |
| 875 | struct kstat stat; | 944 | struct kstat stat; |
| 876 | struct nameidata nd; | 945 | struct nameidata nd; |
| 877 | struct file_system_type *fstype; | ||
| 878 | struct super_block *sb = NULL, *s; | 946 | struct super_block *sb = NULL, *s; |
| 879 | int error; | 947 | int error; |
| 880 | 948 | ||
| @@ -886,8 +954,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name) | |||
| 886 | } | 954 | } |
| 887 | error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat); | 955 | error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat); |
| 888 | 956 | ||
| 889 | fstype = get_fs_type("gfs2"); | 957 | list_for_each_entry(s, &gfs2_fs_type.fs_supers, s_instances) { |
| 890 | list_for_each_entry(s, &fstype->fs_supers, s_instances) { | ||
| 891 | if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || | 958 | if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || |
| 892 | (S_ISDIR(stat.mode) && | 959 | (S_ISDIR(stat.mode) && |
| 893 | s == nd.path.dentry->d_inode->i_sb)) { | 960 | s == nd.path.dentry->d_inode->i_sb)) { |
| @@ -931,7 +998,6 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, | |||
| 931 | error = PTR_ERR(new); | 998 | error = PTR_ERR(new); |
| 932 | goto error; | 999 | goto error; |
| 933 | } | 1000 | } |
| 934 | module_put(fs_type->owner); | ||
| 935 | new->s_flags = flags; | 1001 | new->s_flags = flags; |
| 936 | strlcpy(new->s_id, sb->s_id, sizeof(new->s_id)); | 1002 | strlcpy(new->s_id, sb->s_id, sizeof(new->s_id)); |
| 937 | sb_set_blocksize(new, sb->s_blocksize); | 1003 | sb_set_blocksize(new, sb->s_blocksize); |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index e87412902bed..2686ad4c0029 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
| @@ -200,15 +200,15 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | |||
| 200 | 200 | ||
| 201 | if (alloc_required) { | 201 | if (alloc_required) { |
| 202 | struct gfs2_alloc *al = gfs2_alloc_get(dip); | 202 | struct gfs2_alloc *al = gfs2_alloc_get(dip); |
| 203 | if (!al) { | ||
| 204 | error = -ENOMEM; | ||
| 205 | goto out_gunlock; | ||
| 206 | } | ||
| 203 | 207 | ||
| 204 | error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 208 | error = gfs2_quota_lock_check(dip); |
| 205 | if (error) | 209 | if (error) |
| 206 | goto out_alloc; | 210 | goto out_alloc; |
| 207 | 211 | ||
| 208 | error = gfs2_quota_check(dip, dip->i_inode.i_uid, dip->i_inode.i_gid); | ||
| 209 | if (error) | ||
| 210 | goto out_gunlock_q; | ||
| 211 | |||
| 212 | al->al_requested = sdp->sd_max_dirres; | 212 | al->al_requested = sdp->sd_max_dirres; |
| 213 | 213 | ||
| 214 | error = gfs2_inplace_reserve(dip); | 214 | error = gfs2_inplace_reserve(dip); |
| @@ -716,15 +716,15 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
| 716 | 716 | ||
| 717 | if (alloc_required) { | 717 | if (alloc_required) { |
| 718 | struct gfs2_alloc *al = gfs2_alloc_get(ndip); | 718 | struct gfs2_alloc *al = gfs2_alloc_get(ndip); |
| 719 | if (!al) { | ||
| 720 | error = -ENOMEM; | ||
| 721 | goto out_gunlock; | ||
| 722 | } | ||
| 719 | 723 | ||
| 720 | error = gfs2_quota_lock(ndip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 724 | error = gfs2_quota_lock_check(ndip); |
| 721 | if (error) | 725 | if (error) |
| 722 | goto out_alloc; | 726 | goto out_alloc; |
| 723 | 727 | ||
| 724 | error = gfs2_quota_check(ndip, ndip->i_inode.i_uid, ndip->i_inode.i_gid); | ||
| 725 | if (error) | ||
| 726 | goto out_gunlock_q; | ||
| 727 | |||
| 728 | al->al_requested = sdp->sd_max_dirres; | 728 | al->al_requested = sdp->sd_max_dirres; |
| 729 | 729 | ||
| 730 | error = gfs2_inplace_reserve(ndip); | 730 | error = gfs2_inplace_reserve(ndip); |
| @@ -898,7 +898,7 @@ static int gfs2_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
| 898 | int error; | 898 | int error; |
| 899 | int unlock = 0; | 899 | int unlock = 0; |
| 900 | 900 | ||
| 901 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) { | 901 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { |
| 902 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | 902 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); |
| 903 | if (error) | 903 | if (error) |
| 904 | return error; | 904 | return error; |
| @@ -953,7 +953,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) | |||
| 953 | if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) | 953 | if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) |
| 954 | ogid = ngid = NO_QUOTA_CHANGE; | 954 | ogid = ngid = NO_QUOTA_CHANGE; |
| 955 | 955 | ||
| 956 | gfs2_alloc_get(ip); | 956 | if (!gfs2_alloc_get(ip)) |
| 957 | return -ENOMEM; | ||
| 957 | 958 | ||
| 958 | error = gfs2_quota_lock(ip, nuid, ngid); | 959 | error = gfs2_quota_lock(ip, nuid, ngid); |
| 959 | if (error) | 960 | if (error) |
| @@ -981,8 +982,9 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) | |||
| 981 | brelse(dibh); | 982 | brelse(dibh); |
| 982 | 983 | ||
| 983 | if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { | 984 | if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { |
| 984 | gfs2_quota_change(ip, -ip->i_di.di_blocks, ouid, ogid); | 985 | u64 blocks = gfs2_get_inode_blocks(&ip->i_inode); |
| 985 | gfs2_quota_change(ip, ip->i_di.di_blocks, nuid, ngid); | 986 | gfs2_quota_change(ip, -blocks, ouid, ogid); |
| 987 | gfs2_quota_change(ip, blocks, nuid, ngid); | ||
| 986 | } | 988 | } |
| 987 | 989 | ||
| 988 | out_end_trans: | 990 | out_end_trans: |
| @@ -1064,7 +1066,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 1064 | int error; | 1066 | int error; |
| 1065 | int unlock = 0; | 1067 | int unlock = 0; |
| 1066 | 1068 | ||
| 1067 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == 0) { | 1069 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { |
| 1068 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | 1070 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); |
| 1069 | if (error) | 1071 | if (error) |
| 1070 | return error; | 1072 | return error; |
| @@ -1148,16 +1150,6 @@ const struct inode_operations gfs2_file_iops = { | |||
| 1148 | .removexattr = gfs2_removexattr, | 1150 | .removexattr = gfs2_removexattr, |
| 1149 | }; | 1151 | }; |
| 1150 | 1152 | ||
| 1151 | const struct inode_operations gfs2_dev_iops = { | ||
| 1152 | .permission = gfs2_permission, | ||
| 1153 | .setattr = gfs2_setattr, | ||
| 1154 | .getattr = gfs2_getattr, | ||
| 1155 | .setxattr = gfs2_setxattr, | ||
| 1156 | .getxattr = gfs2_getxattr, | ||
| 1157 | .listxattr = gfs2_listxattr, | ||
| 1158 | .removexattr = gfs2_removexattr, | ||
| 1159 | }; | ||
| 1160 | |||
| 1161 | const struct inode_operations gfs2_dir_iops = { | 1153 | const struct inode_operations gfs2_dir_iops = { |
| 1162 | .create = gfs2_create, | 1154 | .create = gfs2_create, |
| 1163 | .lookup = gfs2_lookup, | 1155 | .lookup = gfs2_lookup, |
diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h index fd8cee231e1d..14b4b797622a 100644 --- a/fs/gfs2/ops_inode.h +++ b/fs/gfs2/ops_inode.h | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | extern const struct inode_operations gfs2_file_iops; | 15 | extern const struct inode_operations gfs2_file_iops; |
| 16 | extern const struct inode_operations gfs2_dir_iops; | 16 | extern const struct inode_operations gfs2_dir_iops; |
| 17 | extern const struct inode_operations gfs2_symlink_iops; | 17 | extern const struct inode_operations gfs2_symlink_iops; |
| 18 | extern const struct inode_operations gfs2_dev_iops; | ||
| 19 | extern const struct file_operations gfs2_file_fops; | 18 | extern const struct file_operations gfs2_file_fops; |
| 20 | extern const struct file_operations gfs2_dir_fops; | 19 | extern const struct file_operations gfs2_dir_fops; |
| 21 | extern const struct file_operations gfs2_file_fops_nolock; | 20 | extern const struct file_operations gfs2_file_fops_nolock; |
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 5e524217944a..2278c68b7e35 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include "incore.h" | 25 | #include "incore.h" |
| 26 | #include "glock.h" | 26 | #include "glock.h" |
| 27 | #include "inode.h" | 27 | #include "inode.h" |
| 28 | #include "lm.h" | ||
| 29 | #include "log.h" | 28 | #include "log.h" |
| 30 | #include "mount.h" | 29 | #include "mount.h" |
| 31 | #include "ops_super.h" | 30 | #include "ops_super.h" |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index a08dabd6ce90..56aaf915c59a 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
| @@ -94,7 +94,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, | |||
| 94 | struct gfs2_quota_data *qd; | 94 | struct gfs2_quota_data *qd; |
| 95 | int error; | 95 | int error; |
| 96 | 96 | ||
| 97 | qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_KERNEL); | 97 | qd = kzalloc(sizeof(struct gfs2_quota_data), GFP_NOFS); |
| 98 | if (!qd) | 98 | if (!qd) |
| 99 | return -ENOMEM; | 99 | return -ENOMEM; |
| 100 | 100 | ||
| @@ -616,16 +616,9 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
| 616 | s64 value; | 616 | s64 value; |
| 617 | int err = -EIO; | 617 | int err = -EIO; |
| 618 | 618 | ||
| 619 | if (gfs2_is_stuffed(ip)) { | 619 | if (gfs2_is_stuffed(ip)) |
| 620 | struct gfs2_alloc *al = NULL; | ||
| 621 | al = gfs2_alloc_get(ip); | ||
| 622 | /* just request 1 blk */ | ||
| 623 | al->al_requested = 1; | ||
| 624 | gfs2_inplace_reserve(ip); | ||
| 625 | gfs2_unstuff_dinode(ip, NULL); | 620 | gfs2_unstuff_dinode(ip, NULL); |
| 626 | gfs2_inplace_release(ip); | 621 | |
| 627 | gfs2_alloc_put(ip); | ||
| 628 | } | ||
| 629 | page = grab_cache_page(mapping, index); | 622 | page = grab_cache_page(mapping, index); |
| 630 | if (!page) | 623 | if (!page) |
| 631 | return -ENOMEM; | 624 | return -ENOMEM; |
| @@ -690,14 +683,14 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
| 690 | unsigned int qx, x; | 683 | unsigned int qx, x; |
| 691 | struct gfs2_quota_data *qd; | 684 | struct gfs2_quota_data *qd; |
| 692 | loff_t offset; | 685 | loff_t offset; |
| 693 | unsigned int nalloc = 0; | 686 | unsigned int nalloc = 0, blocks; |
| 694 | struct gfs2_alloc *al = NULL; | 687 | struct gfs2_alloc *al = NULL; |
| 695 | int error; | 688 | int error; |
| 696 | 689 | ||
| 697 | gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota), | 690 | gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota), |
| 698 | &data_blocks, &ind_blocks); | 691 | &data_blocks, &ind_blocks); |
| 699 | 692 | ||
| 700 | ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_KERNEL); | 693 | ghs = kcalloc(num_qd, sizeof(struct gfs2_holder), GFP_NOFS); |
| 701 | if (!ghs) | 694 | if (!ghs) |
| 702 | return -ENOMEM; | 695 | return -ENOMEM; |
| 703 | 696 | ||
| @@ -727,30 +720,33 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
| 727 | nalloc++; | 720 | nalloc++; |
| 728 | } | 721 | } |
| 729 | 722 | ||
| 730 | if (nalloc) { | 723 | al = gfs2_alloc_get(ip); |
| 731 | al = gfs2_alloc_get(ip); | 724 | if (!al) { |
| 725 | error = -ENOMEM; | ||
| 726 | goto out_gunlock; | ||
| 727 | } | ||
| 728 | /* | ||
| 729 | * 1 blk for unstuffing inode if stuffed. We add this extra | ||
| 730 | * block to the reservation unconditionally. If the inode | ||
| 731 | * doesn't need unstuffing, the block will be released to the | ||
| 732 | * rgrp since it won't be allocated during the transaction | ||
| 733 | */ | ||
| 734 | al->al_requested = 1; | ||
| 735 | /* +1 in the end for block requested above for unstuffing */ | ||
| 736 | blocks = num_qd * data_blocks + RES_DINODE + num_qd + 1; | ||
| 732 | 737 | ||
| 733 | al->al_requested = nalloc * (data_blocks + ind_blocks); | 738 | if (nalloc) |
| 739 | al->al_requested += nalloc * (data_blocks + ind_blocks); | ||
| 740 | error = gfs2_inplace_reserve(ip); | ||
| 741 | if (error) | ||
| 742 | goto out_alloc; | ||
| 734 | 743 | ||
| 735 | error = gfs2_inplace_reserve(ip); | 744 | if (nalloc) |
| 736 | if (error) | 745 | blocks += al->al_rgd->rd_length + nalloc * ind_blocks + RES_STATFS; |
| 737 | goto out_alloc; | 746 | |
| 738 | 747 | error = gfs2_trans_begin(sdp, blocks, 0); | |
| 739 | error = gfs2_trans_begin(sdp, | 748 | if (error) |
| 740 | al->al_rgd->rd_length + | 749 | goto out_ipres; |
| 741 | num_qd * data_blocks + | ||
| 742 | nalloc * ind_blocks + | ||
| 743 | RES_DINODE + num_qd + | ||
| 744 | RES_STATFS, 0); | ||
| 745 | if (error) | ||
| 746 | goto out_ipres; | ||
| 747 | } else { | ||
| 748 | error = gfs2_trans_begin(sdp, | ||
| 749 | num_qd * data_blocks + | ||
| 750 | RES_DINODE + num_qd, 0); | ||
| 751 | if (error) | ||
| 752 | goto out_gunlock; | ||
| 753 | } | ||
| 754 | 750 | ||
| 755 | for (x = 0; x < num_qd; x++) { | 751 | for (x = 0; x < num_qd; x++) { |
| 756 | qd = qda[x]; | 752 | qd = qda[x]; |
| @@ -769,11 +765,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
| 769 | out_end_trans: | 765 | out_end_trans: |
| 770 | gfs2_trans_end(sdp); | 766 | gfs2_trans_end(sdp); |
| 771 | out_ipres: | 767 | out_ipres: |
| 772 | if (nalloc) | 768 | gfs2_inplace_release(ip); |
| 773 | gfs2_inplace_release(ip); | ||
| 774 | out_alloc: | 769 | out_alloc: |
| 775 | if (nalloc) | 770 | gfs2_alloc_put(ip); |
| 776 | gfs2_alloc_put(ip); | ||
| 777 | out_gunlock: | 771 | out_gunlock: |
| 778 | gfs2_glock_dq_uninit(&i_gh); | 772 | gfs2_glock_dq_uninit(&i_gh); |
| 779 | out: | 773 | out: |
| @@ -1124,12 +1118,12 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) | |||
| 1124 | error = -ENOMEM; | 1118 | error = -ENOMEM; |
| 1125 | 1119 | ||
| 1126 | sdp->sd_quota_bitmap = kcalloc(sdp->sd_quota_chunks, | 1120 | sdp->sd_quota_bitmap = kcalloc(sdp->sd_quota_chunks, |
| 1127 | sizeof(unsigned char *), GFP_KERNEL); | 1121 | sizeof(unsigned char *), GFP_NOFS); |
| 1128 | if (!sdp->sd_quota_bitmap) | 1122 | if (!sdp->sd_quota_bitmap) |
| 1129 | return error; | 1123 | return error; |
| 1130 | 1124 | ||
| 1131 | for (x = 0; x < sdp->sd_quota_chunks; x++) { | 1125 | for (x = 0; x < sdp->sd_quota_chunks; x++) { |
| 1132 | sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_KERNEL); | 1126 | sdp->sd_quota_bitmap[x] = kzalloc(PAGE_SIZE, GFP_NOFS); |
| 1133 | if (!sdp->sd_quota_bitmap[x]) | 1127 | if (!sdp->sd_quota_bitmap[x]) |
| 1134 | goto fail; | 1128 | goto fail; |
| 1135 | } | 1129 | } |
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index a8be1417051f..3b7f4b0e5dfe 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h | |||
| @@ -32,4 +32,21 @@ int gfs2_quota_init(struct gfs2_sbd *sdp); | |||
| 32 | void gfs2_quota_scan(struct gfs2_sbd *sdp); | 32 | void gfs2_quota_scan(struct gfs2_sbd *sdp); |
| 33 | void gfs2_quota_cleanup(struct gfs2_sbd *sdp); | 33 | void gfs2_quota_cleanup(struct gfs2_sbd *sdp); |
| 34 | 34 | ||
| 35 | static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) | ||
| 36 | { | ||
| 37 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
| 38 | int ret; | ||
| 39 | if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) | ||
| 40 | return 0; | ||
| 41 | ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | ||
| 42 | if (ret) | ||
| 43 | return ret; | ||
| 44 | if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON) | ||
| 45 | return 0; | ||
| 46 | ret = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); | ||
| 47 | if (ret) | ||
| 48 | gfs2_quota_unlock(ip); | ||
| 49 | return ret; | ||
| 50 | } | ||
| 51 | |||
| 35 | #endif /* __QUOTA_DOT_H__ */ | 52 | #endif /* __QUOTA_DOT_H__ */ |
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 6fb07d67ca8a..2888e4b4b1c5 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c | |||
| @@ -20,7 +20,6 @@ | |||
| 20 | #include "bmap.h" | 20 | #include "bmap.h" |
| 21 | #include "glock.h" | 21 | #include "glock.h" |
| 22 | #include "glops.h" | 22 | #include "glops.h" |
| 23 | #include "lm.h" | ||
| 24 | #include "lops.h" | 23 | #include "lops.h" |
| 25 | #include "meta_io.h" | 24 | #include "meta_io.h" |
| 26 | #include "recovery.h" | 25 | #include "recovery.h" |
| @@ -69,7 +68,7 @@ int gfs2_revoke_add(struct gfs2_sbd *sdp, u64 blkno, unsigned int where) | |||
| 69 | return 0; | 68 | return 0; |
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_KERNEL); | 71 | rr = kmalloc(sizeof(struct gfs2_revoke_replay), GFP_NOFS); |
| 73 | if (!rr) | 72 | if (!rr) |
| 74 | return -ENOMEM; | 73 | return -ENOMEM; |
| 75 | 74 | ||
| @@ -150,7 +149,7 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, | |||
| 150 | struct gfs2_log_header_host *head) | 149 | struct gfs2_log_header_host *head) |
| 151 | { | 150 | { |
| 152 | struct buffer_head *bh; | 151 | struct buffer_head *bh; |
| 153 | struct gfs2_log_header_host lh; | 152 | struct gfs2_log_header_host uninitialized_var(lh); |
| 154 | const u32 nothing = 0; | 153 | const u32 nothing = 0; |
| 155 | u32 hash; | 154 | u32 hash; |
| 156 | int error; | 155 | int error; |
| @@ -425,6 +424,16 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea | |||
| 425 | return error; | 424 | return error; |
| 426 | } | 425 | } |
| 427 | 426 | ||
| 427 | |||
| 428 | static void gfs2_lm_recovery_done(struct gfs2_sbd *sdp, unsigned int jid, | ||
| 429 | unsigned int message) | ||
| 430 | { | ||
| 431 | if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
| 432 | sdp->sd_lockstruct.ls_ops->lm_recovery_done( | ||
| 433 | sdp->sd_lockstruct.ls_lockspace, jid, message); | ||
| 434 | } | ||
| 435 | |||
| 436 | |||
| 428 | /** | 437 | /** |
| 429 | * gfs2_recover_journal - recovery a given journal | 438 | * gfs2_recover_journal - recovery a given journal |
| 430 | * @jd: the struct gfs2_jdesc describing the journal | 439 | * @jd: the struct gfs2_jdesc describing the journal |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 3552110b2e5f..7e8f0b1d6c6e 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
| 15 | #include <linux/gfs2_ondisk.h> | 15 | #include <linux/gfs2_ondisk.h> |
| 16 | #include <linux/lm_interface.h> | 16 | #include <linux/lm_interface.h> |
| 17 | #include <linux/prefetch.h> | ||
| 17 | 18 | ||
| 18 | #include "gfs2.h" | 19 | #include "gfs2.h" |
| 19 | #include "incore.h" | 20 | #include "incore.h" |
| @@ -33,6 +34,16 @@ | |||
| 33 | #define BFITNOENT ((u32)~0) | 34 | #define BFITNOENT ((u32)~0) |
| 34 | #define NO_BLOCK ((u64)~0) | 35 | #define NO_BLOCK ((u64)~0) |
| 35 | 36 | ||
| 37 | #if BITS_PER_LONG == 32 | ||
| 38 | #define LBITMASK (0x55555555UL) | ||
| 39 | #define LBITSKIP55 (0x55555555UL) | ||
| 40 | #define LBITSKIP00 (0x00000000UL) | ||
| 41 | #else | ||
| 42 | #define LBITMASK (0x5555555555555555UL) | ||
| 43 | #define LBITSKIP55 (0x5555555555555555UL) | ||
| 44 | #define LBITSKIP00 (0x0000000000000000UL) | ||
| 45 | #endif | ||
| 46 | |||
| 36 | /* | 47 | /* |
| 37 | * These routines are used by the resource group routines (rgrp.c) | 48 | * These routines are used by the resource group routines (rgrp.c) |
| 38 | * to keep track of block allocation. Each block is represented by two | 49 | * to keep track of block allocation. Each block is represented by two |
| @@ -53,7 +64,8 @@ static const char valid_change[16] = { | |||
| 53 | }; | 64 | }; |
| 54 | 65 | ||
| 55 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | 66 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, |
| 56 | unsigned char old_state, unsigned char new_state); | 67 | unsigned char old_state, unsigned char new_state, |
| 68 | unsigned int *n); | ||
| 57 | 69 | ||
| 58 | /** | 70 | /** |
| 59 | * gfs2_setbit - Set a bit in the bitmaps | 71 | * gfs2_setbit - Set a bit in the bitmaps |
| @@ -64,26 +76,32 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
| 64 | * | 76 | * |
| 65 | */ | 77 | */ |
| 66 | 78 | ||
| 67 | static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer, | 79 | static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1, |
| 68 | unsigned int buflen, u32 block, | 80 | unsigned char *buf2, unsigned int offset, |
| 69 | unsigned char new_state) | 81 | unsigned int buflen, u32 block, |
| 82 | unsigned char new_state) | ||
| 70 | { | 83 | { |
| 71 | unsigned char *byte, *end, cur_state; | 84 | unsigned char *byte1, *byte2, *end, cur_state; |
| 72 | unsigned int bit; | 85 | const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE; |
| 73 | 86 | ||
| 74 | byte = buffer + (block / GFS2_NBBY); | 87 | byte1 = buf1 + offset + (block / GFS2_NBBY); |
| 75 | bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE; | 88 | end = buf1 + offset + buflen; |
| 76 | end = buffer + buflen; | ||
| 77 | 89 | ||
| 78 | gfs2_assert(rgd->rd_sbd, byte < end); | 90 | BUG_ON(byte1 >= end); |
| 79 | 91 | ||
| 80 | cur_state = (*byte >> bit) & GFS2_BIT_MASK; | 92 | cur_state = (*byte1 >> bit) & GFS2_BIT_MASK; |
| 81 | 93 | ||
| 82 | if (valid_change[new_state * 4 + cur_state]) { | 94 | if (unlikely(!valid_change[new_state * 4 + cur_state])) { |
| 83 | *byte ^= cur_state << bit; | ||
| 84 | *byte |= new_state << bit; | ||
| 85 | } else | ||
| 86 | gfs2_consist_rgrpd(rgd); | 95 | gfs2_consist_rgrpd(rgd); |
| 96 | return; | ||
| 97 | } | ||
| 98 | *byte1 ^= (cur_state ^ new_state) << bit; | ||
| 99 | |||
| 100 | if (buf2) { | ||
| 101 | byte2 = buf2 + offset + (block / GFS2_NBBY); | ||
| 102 | cur_state = (*byte2 >> bit) & GFS2_BIT_MASK; | ||
| 103 | *byte2 ^= (cur_state ^ new_state) << bit; | ||
| 104 | } | ||
| 87 | } | 105 | } |
| 88 | 106 | ||
| 89 | /** | 107 | /** |
| @@ -94,10 +112,12 @@ static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer, | |||
| 94 | * | 112 | * |
| 95 | */ | 113 | */ |
| 96 | 114 | ||
| 97 | static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer, | 115 | static inline unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, |
| 98 | unsigned int buflen, u32 block) | 116 | const unsigned char *buffer, |
| 117 | unsigned int buflen, u32 block) | ||
| 99 | { | 118 | { |
| 100 | unsigned char *byte, *end, cur_state; | 119 | const unsigned char *byte, *end; |
| 120 | unsigned char cur_state; | ||
| 101 | unsigned int bit; | 121 | unsigned int bit; |
| 102 | 122 | ||
| 103 | byte = buffer + (block / GFS2_NBBY); | 123 | byte = buffer + (block / GFS2_NBBY); |
| @@ -126,47 +146,66 @@ static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer, | |||
| 126 | * Return: the block number (bitmap buffer scope) that was found | 146 | * Return: the block number (bitmap buffer scope) that was found |
| 127 | */ | 147 | */ |
| 128 | 148 | ||
| 129 | static u32 gfs2_bitfit(unsigned char *buffer, unsigned int buflen, u32 goal, | 149 | static u32 gfs2_bitfit(const u8 *buffer, unsigned int buflen, u32 goal, |
| 130 | unsigned char old_state) | 150 | u8 old_state) |
| 131 | { | 151 | { |
| 132 | unsigned char *byte; | 152 | const u8 *byte, *start, *end; |
| 133 | u32 blk = goal; | 153 | int bit, startbit; |
| 134 | unsigned int bit, bitlong; | 154 | u32 g1, g2, misaligned; |
| 135 | unsigned long *plong, plong55; | 155 | unsigned long *plong; |
| 136 | 156 | unsigned long lskipval; | |
| 137 | byte = buffer + (goal / GFS2_NBBY); | 157 | |
| 138 | plong = (unsigned long *)(buffer + (goal / GFS2_NBBY)); | 158 | lskipval = (old_state & GFS2_BLKST_USED) ? LBITSKIP00 : LBITSKIP55; |
| 139 | bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE; | 159 | g1 = (goal / GFS2_NBBY); |
| 140 | bitlong = bit; | 160 | start = buffer + g1; |
| 141 | #if BITS_PER_LONG == 32 | 161 | byte = start; |
| 142 | plong55 = 0x55555555; | 162 | end = buffer + buflen; |
| 143 | #else | 163 | g2 = ALIGN(g1, sizeof(unsigned long)); |
| 144 | plong55 = 0x5555555555555555; | 164 | plong = (unsigned long *)(buffer + g2); |
| 145 | #endif | 165 | startbit = bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE; |
| 146 | while (byte < buffer + buflen) { | 166 | misaligned = g2 - g1; |
| 147 | 167 | if (!misaligned) | |
| 148 | if (bitlong == 0 && old_state == 0 && *plong == plong55) { | 168 | goto ulong_aligned; |
| 149 | plong++; | 169 | /* parse the bitmap a byte at a time */ |
| 150 | byte += sizeof(unsigned long); | 170 | misaligned: |
| 151 | blk += sizeof(unsigned long) * GFS2_NBBY; | 171 | while (byte < end) { |
| 152 | continue; | 172 | if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) { |
| 173 | return goal + | ||
| 174 | (((byte - start) * GFS2_NBBY) + | ||
| 175 | ((bit - startbit) >> 1)); | ||
| 153 | } | 176 | } |
| 154 | if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) | ||
| 155 | return blk; | ||
| 156 | bit += GFS2_BIT_SIZE; | 177 | bit += GFS2_BIT_SIZE; |
| 157 | if (bit >= 8) { | 178 | if (bit >= GFS2_NBBY * GFS2_BIT_SIZE) { |
| 158 | bit = 0; | 179 | bit = 0; |
| 159 | byte++; | 180 | byte++; |
| 181 | misaligned--; | ||
| 182 | if (!misaligned) { | ||
| 183 | plong = (unsigned long *)byte; | ||
| 184 | goto ulong_aligned; | ||
| 185 | } | ||
| 160 | } | 186 | } |
| 161 | bitlong += GFS2_BIT_SIZE; | ||
| 162 | if (bitlong >= sizeof(unsigned long) * 8) { | ||
| 163 | bitlong = 0; | ||
| 164 | plong++; | ||
| 165 | } | ||
| 166 | |||
| 167 | blk++; | ||
| 168 | } | 187 | } |
| 188 | return BFITNOENT; | ||
| 169 | 189 | ||
| 190 | /* parse the bitmap a unsigned long at a time */ | ||
| 191 | ulong_aligned: | ||
| 192 | /* Stop at "end - 1" or else prefetch can go past the end and segfault. | ||
| 193 | We could "if" it but we'd lose some of the performance gained. | ||
| 194 | This way will only slow down searching the very last 4/8 bytes | ||
| 195 | depending on architecture. I've experimented with several ways | ||
| 196 | of writing this section such as using an else before the goto | ||
| 197 | but this one seems to be the fastest. */ | ||
| 198 | while ((unsigned char *)plong < end - 1) { | ||
| 199 | prefetch(plong + 1); | ||
| 200 | if (((*plong) & LBITMASK) != lskipval) | ||
| 201 | break; | ||
| 202 | plong++; | ||
| 203 | } | ||
| 204 | if ((unsigned char *)plong < end) { | ||
| 205 | byte = (const u8 *)plong; | ||
| 206 | misaligned += sizeof(unsigned long) - 1; | ||
| 207 | goto misaligned; | ||
| 208 | } | ||
| 170 | return BFITNOENT; | 209 | return BFITNOENT; |
| 171 | } | 210 | } |
| 172 | 211 | ||
| @@ -179,14 +218,14 @@ static u32 gfs2_bitfit(unsigned char *buffer, unsigned int buflen, u32 goal, | |||
| 179 | * Returns: The number of bits | 218 | * Returns: The number of bits |
| 180 | */ | 219 | */ |
| 181 | 220 | ||
| 182 | static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, unsigned char *buffer, | 221 | static u32 gfs2_bitcount(struct gfs2_rgrpd *rgd, const u8 *buffer, |
| 183 | unsigned int buflen, unsigned char state) | 222 | unsigned int buflen, u8 state) |
| 184 | { | 223 | { |
| 185 | unsigned char *byte = buffer; | 224 | const u8 *byte = buffer; |
| 186 | unsigned char *end = buffer + buflen; | 225 | const u8 *end = buffer + buflen; |
| 187 | unsigned char state1 = state << 2; | 226 | const u8 state1 = state << 2; |
| 188 | unsigned char state2 = state << 4; | 227 | const u8 state2 = state << 4; |
| 189 | unsigned char state3 = state << 6; | 228 | const u8 state3 = state << 6; |
| 190 | u32 count = 0; | 229 | u32 count = 0; |
| 191 | 230 | ||
| 192 | for (; byte < end; byte++) { | 231 | for (; byte < end; byte++) { |
| @@ -353,7 +392,7 @@ static void clear_rgrpdi(struct gfs2_sbd *sdp) | |||
| 353 | } | 392 | } |
| 354 | 393 | ||
| 355 | kfree(rgd->rd_bits); | 394 | kfree(rgd->rd_bits); |
| 356 | kfree(rgd); | 395 | kmem_cache_free(gfs2_rgrpd_cachep, rgd); |
| 357 | } | 396 | } |
| 358 | } | 397 | } |
| 359 | 398 | ||
| @@ -516,7 +555,7 @@ static int read_rindex_entry(struct gfs2_inode *ip, | |||
| 516 | return error; | 555 | return error; |
| 517 | } | 556 | } |
| 518 | 557 | ||
| 519 | rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS); | 558 | rgd = kmem_cache_zalloc(gfs2_rgrpd_cachep, GFP_NOFS); |
| 520 | error = -ENOMEM; | 559 | error = -ENOMEM; |
| 521 | if (!rgd) | 560 | if (!rgd) |
| 522 | return error; | 561 | return error; |
| @@ -539,7 +578,7 @@ static int read_rindex_entry(struct gfs2_inode *ip, | |||
| 539 | return error; | 578 | return error; |
| 540 | 579 | ||
| 541 | rgd->rd_gl->gl_object = rgd; | 580 | rgd->rd_gl->gl_object = rgd; |
| 542 | rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; | 581 | rgd->rd_flags &= ~GFS2_RDF_UPTODATE; |
| 543 | rgd->rd_flags |= GFS2_RDF_CHECK; | 582 | rgd->rd_flags |= GFS2_RDF_CHECK; |
| 544 | return error; | 583 | return error; |
| 545 | } | 584 | } |
| @@ -575,7 +614,7 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
| 575 | } | 614 | } |
| 576 | } | 615 | } |
| 577 | 616 | ||
| 578 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; | 617 | sdp->sd_rindex_uptodate = 1; |
| 579 | return 0; | 618 | return 0; |
| 580 | } | 619 | } |
| 581 | 620 | ||
| @@ -609,7 +648,7 @@ static int gfs2_ri_update_special(struct gfs2_inode *ip) | |||
| 609 | } | 648 | } |
| 610 | } | 649 | } |
| 611 | 650 | ||
| 612 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; | 651 | sdp->sd_rindex_uptodate = 1; |
| 613 | return 0; | 652 | return 0; |
| 614 | } | 653 | } |
| 615 | 654 | ||
| @@ -642,9 +681,9 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh) | |||
| 642 | return error; | 681 | return error; |
| 643 | 682 | ||
| 644 | /* Read new copy from disk if we don't have the latest */ | 683 | /* Read new copy from disk if we don't have the latest */ |
| 645 | if (sdp->sd_rindex_vn != gl->gl_vn) { | 684 | if (!sdp->sd_rindex_uptodate) { |
| 646 | mutex_lock(&sdp->sd_rindex_mutex); | 685 | mutex_lock(&sdp->sd_rindex_mutex); |
| 647 | if (sdp->sd_rindex_vn != gl->gl_vn) { | 686 | if (!sdp->sd_rindex_uptodate) { |
| 648 | error = gfs2_ri_update(ip); | 687 | error = gfs2_ri_update(ip); |
| 649 | if (error) | 688 | if (error) |
| 650 | gfs2_glock_dq_uninit(ri_gh); | 689 | gfs2_glock_dq_uninit(ri_gh); |
| @@ -655,21 +694,31 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh) | |||
| 655 | return error; | 694 | return error; |
| 656 | } | 695 | } |
| 657 | 696 | ||
| 658 | static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf) | 697 | static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf) |
| 659 | { | 698 | { |
| 660 | const struct gfs2_rgrp *str = buf; | 699 | const struct gfs2_rgrp *str = buf; |
| 700 | struct gfs2_rgrp_host *rg = &rgd->rd_rg; | ||
| 701 | u32 rg_flags; | ||
| 661 | 702 | ||
| 662 | rg->rg_flags = be32_to_cpu(str->rg_flags); | 703 | rg_flags = be32_to_cpu(str->rg_flags); |
| 704 | if (rg_flags & GFS2_RGF_NOALLOC) | ||
| 705 | rgd->rd_flags |= GFS2_RDF_NOALLOC; | ||
| 706 | else | ||
| 707 | rgd->rd_flags &= ~GFS2_RDF_NOALLOC; | ||
| 663 | rg->rg_free = be32_to_cpu(str->rg_free); | 708 | rg->rg_free = be32_to_cpu(str->rg_free); |
| 664 | rg->rg_dinodes = be32_to_cpu(str->rg_dinodes); | 709 | rg->rg_dinodes = be32_to_cpu(str->rg_dinodes); |
| 665 | rg->rg_igeneration = be64_to_cpu(str->rg_igeneration); | 710 | rg->rg_igeneration = be64_to_cpu(str->rg_igeneration); |
| 666 | } | 711 | } |
| 667 | 712 | ||
| 668 | static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf) | 713 | static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf) |
| 669 | { | 714 | { |
| 670 | struct gfs2_rgrp *str = buf; | 715 | struct gfs2_rgrp *str = buf; |
| 716 | struct gfs2_rgrp_host *rg = &rgd->rd_rg; | ||
| 717 | u32 rg_flags = 0; | ||
| 671 | 718 | ||
| 672 | str->rg_flags = cpu_to_be32(rg->rg_flags); | 719 | if (rgd->rd_flags & GFS2_RDF_NOALLOC) |
| 720 | rg_flags |= GFS2_RGF_NOALLOC; | ||
| 721 | str->rg_flags = cpu_to_be32(rg_flags); | ||
| 673 | str->rg_free = cpu_to_be32(rg->rg_free); | 722 | str->rg_free = cpu_to_be32(rg->rg_free); |
| 674 | str->rg_dinodes = cpu_to_be32(rg->rg_dinodes); | 723 | str->rg_dinodes = cpu_to_be32(rg->rg_dinodes); |
| 675 | str->__pad = cpu_to_be32(0); | 724 | str->__pad = cpu_to_be32(0); |
| @@ -726,9 +775,9 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) | |||
| 726 | } | 775 | } |
| 727 | } | 776 | } |
| 728 | 777 | ||
| 729 | if (rgd->rd_rg_vn != gl->gl_vn) { | 778 | if (!(rgd->rd_flags & GFS2_RDF_UPTODATE)) { |
| 730 | gfs2_rgrp_in(&rgd->rd_rg, (rgd->rd_bits[0].bi_bh)->b_data); | 779 | gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data); |
| 731 | rgd->rd_rg_vn = gl->gl_vn; | 780 | rgd->rd_flags |= GFS2_RDF_UPTODATE; |
| 732 | } | 781 | } |
| 733 | 782 | ||
| 734 | spin_lock(&sdp->sd_rindex_spin); | 783 | spin_lock(&sdp->sd_rindex_spin); |
| @@ -840,7 +889,7 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) | |||
| 840 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 889 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
| 841 | int ret = 0; | 890 | int ret = 0; |
| 842 | 891 | ||
| 843 | if (rgd->rd_rg.rg_flags & GFS2_RGF_NOALLOC) | 892 | if (rgd->rd_flags & GFS2_RDF_NOALLOC) |
| 844 | return 0; | 893 | return 0; |
| 845 | 894 | ||
| 846 | spin_lock(&sdp->sd_rindex_spin); | 895 | spin_lock(&sdp->sd_rindex_spin); |
| @@ -866,13 +915,15 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | |||
| 866 | u32 goal = 0, block; | 915 | u32 goal = 0, block; |
| 867 | u64 no_addr; | 916 | u64 no_addr; |
| 868 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 917 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
| 918 | unsigned int n; | ||
| 869 | 919 | ||
| 870 | for(;;) { | 920 | for(;;) { |
| 871 | if (goal >= rgd->rd_data) | 921 | if (goal >= rgd->rd_data) |
| 872 | break; | 922 | break; |
| 873 | down_write(&sdp->sd_log_flush_lock); | 923 | down_write(&sdp->sd_log_flush_lock); |
| 924 | n = 1; | ||
| 874 | block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, | 925 | block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, |
| 875 | GFS2_BLKST_UNLINKED); | 926 | GFS2_BLKST_UNLINKED, &n); |
| 876 | up_write(&sdp->sd_log_flush_lock); | 927 | up_write(&sdp->sd_log_flush_lock); |
| 877 | if (block == BFITNOENT) | 928 | if (block == BFITNOENT) |
| 878 | break; | 929 | break; |
| @@ -904,24 +955,20 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | |||
| 904 | static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp, | 955 | static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp, |
| 905 | u64 rglast) | 956 | u64 rglast) |
| 906 | { | 957 | { |
| 907 | struct gfs2_rgrpd *rgd = NULL; | 958 | struct gfs2_rgrpd *rgd; |
| 908 | 959 | ||
| 909 | spin_lock(&sdp->sd_rindex_spin); | 960 | spin_lock(&sdp->sd_rindex_spin); |
| 910 | 961 | ||
| 911 | if (list_empty(&sdp->sd_rindex_recent_list)) | 962 | if (rglast) { |
| 912 | goto out; | 963 | list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) { |
| 913 | 964 | if (rgrp_contains_block(rgd, rglast)) | |
| 914 | if (!rglast) | 965 | goto out; |
| 915 | goto first; | 966 | } |
| 916 | |||
| 917 | list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) { | ||
| 918 | if (rgd->rd_addr == rglast) | ||
| 919 | goto out; | ||
| 920 | } | 967 | } |
| 921 | 968 | rgd = NULL; | |
| 922 | first: | 969 | if (!list_empty(&sdp->sd_rindex_recent_list)) |
| 923 | rgd = list_entry(sdp->sd_rindex_recent_list.next, struct gfs2_rgrpd, | 970 | rgd = list_entry(sdp->sd_rindex_recent_list.next, |
| 924 | rd_recent); | 971 | struct gfs2_rgrpd, rd_recent); |
| 925 | out: | 972 | out: |
| 926 | spin_unlock(&sdp->sd_rindex_spin); | 973 | spin_unlock(&sdp->sd_rindex_spin); |
| 927 | return rgd; | 974 | return rgd; |
| @@ -1067,7 +1114,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
| 1067 | 1114 | ||
| 1068 | /* Try recently successful rgrps */ | 1115 | /* Try recently successful rgrps */ |
| 1069 | 1116 | ||
| 1070 | rgd = recent_rgrp_first(sdp, ip->i_last_rg_alloc); | 1117 | rgd = recent_rgrp_first(sdp, ip->i_goal); |
| 1071 | 1118 | ||
| 1072 | while (rgd) { | 1119 | while (rgd) { |
| 1073 | rg_locked = 0; | 1120 | rg_locked = 0; |
| @@ -1151,8 +1198,6 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
| 1151 | } | 1198 | } |
| 1152 | 1199 | ||
| 1153 | out: | 1200 | out: |
| 1154 | ip->i_last_rg_alloc = rgd->rd_addr; | ||
| 1155 | |||
| 1156 | if (begin) { | 1201 | if (begin) { |
| 1157 | recent_rgrp_add(rgd); | 1202 | recent_rgrp_add(rgd); |
| 1158 | rgd = gfs2_rgrpd_get_next(rgd); | 1203 | rgd = gfs2_rgrpd_get_next(rgd); |
| @@ -1275,6 +1320,7 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | |||
| 1275 | * @goal: the goal block within the RG (start here to search for avail block) | 1320 | * @goal: the goal block within the RG (start here to search for avail block) |
| 1276 | * @old_state: GFS2_BLKST_XXX the before-allocation state to find | 1321 | * @old_state: GFS2_BLKST_XXX the before-allocation state to find |
| 1277 | * @new_state: GFS2_BLKST_XXX the after-allocation block state | 1322 | * @new_state: GFS2_BLKST_XXX the after-allocation block state |
| 1323 | * @n: The extent length | ||
| 1278 | * | 1324 | * |
| 1279 | * Walk rgrp's bitmap to find bits that represent a block in @old_state. | 1325 | * Walk rgrp's bitmap to find bits that represent a block in @old_state. |
| 1280 | * Add the found bitmap buffer to the transaction. | 1326 | * Add the found bitmap buffer to the transaction. |
| @@ -1290,13 +1336,17 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | |||
| 1290 | */ | 1336 | */ |
| 1291 | 1337 | ||
| 1292 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | 1338 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, |
| 1293 | unsigned char old_state, unsigned char new_state) | 1339 | unsigned char old_state, unsigned char new_state, |
| 1340 | unsigned int *n) | ||
| 1294 | { | 1341 | { |
| 1295 | struct gfs2_bitmap *bi = NULL; | 1342 | struct gfs2_bitmap *bi = NULL; |
| 1296 | u32 length = rgd->rd_length; | 1343 | const u32 length = rgd->rd_length; |
| 1297 | u32 blk = 0; | 1344 | u32 blk = 0; |
| 1298 | unsigned int buf, x; | 1345 | unsigned int buf, x; |
| 1346 | const unsigned int elen = *n; | ||
| 1347 | const u8 *buffer; | ||
| 1299 | 1348 | ||
| 1349 | *n = 0; | ||
| 1300 | /* Find bitmap block that contains bits for goal block */ | 1350 | /* Find bitmap block that contains bits for goal block */ |
| 1301 | for (buf = 0; buf < length; buf++) { | 1351 | for (buf = 0; buf < length; buf++) { |
| 1302 | bi = rgd->rd_bits + buf; | 1352 | bi = rgd->rd_bits + buf; |
| @@ -1317,12 +1367,11 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
| 1317 | for (x = 0; x <= length; x++) { | 1367 | for (x = 0; x <= length; x++) { |
| 1318 | /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone | 1368 | /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone |
| 1319 | bitmaps, so we must search the originals for that. */ | 1369 | bitmaps, so we must search the originals for that. */ |
| 1370 | buffer = bi->bi_bh->b_data + bi->bi_offset; | ||
| 1320 | if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone) | 1371 | if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone) |
| 1321 | blk = gfs2_bitfit(bi->bi_clone + bi->bi_offset, | 1372 | buffer = bi->bi_clone + bi->bi_offset; |
| 1322 | bi->bi_len, goal, old_state); | 1373 | |
| 1323 | else | 1374 | blk = gfs2_bitfit(buffer, bi->bi_len, goal, old_state); |
| 1324 | blk = gfs2_bitfit(bi->bi_bh->b_data + bi->bi_offset, | ||
| 1325 | bi->bi_len, goal, old_state); | ||
| 1326 | if (blk != BFITNOENT) | 1375 | if (blk != BFITNOENT) |
| 1327 | break; | 1376 | break; |
| 1328 | 1377 | ||
| @@ -1333,12 +1382,23 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
| 1333 | } | 1382 | } |
| 1334 | 1383 | ||
| 1335 | if (blk != BFITNOENT && old_state != new_state) { | 1384 | if (blk != BFITNOENT && old_state != new_state) { |
| 1385 | *n = 1; | ||
| 1336 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1386 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
| 1337 | gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, | 1387 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, |
| 1338 | bi->bi_len, blk, new_state); | 1388 | bi->bi_len, blk, new_state); |
| 1339 | if (bi->bi_clone) | 1389 | goal = blk; |
| 1340 | gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset, | 1390 | while (*n < elen) { |
| 1341 | bi->bi_len, blk, new_state); | 1391 | goal++; |
| 1392 | if (goal >= (bi->bi_len * GFS2_NBBY)) | ||
| 1393 | break; | ||
| 1394 | if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) != | ||
| 1395 | GFS2_BLKST_FREE) | ||
| 1396 | break; | ||
| 1397 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, | ||
| 1398 | bi->bi_offset, bi->bi_len, goal, | ||
| 1399 | new_state); | ||
| 1400 | (*n)++; | ||
| 1401 | } | ||
| 1342 | } | 1402 | } |
| 1343 | 1403 | ||
| 1344 | return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk; | 1404 | return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk; |
| @@ -1393,7 +1453,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, | |||
| 1393 | bi->bi_len); | 1453 | bi->bi_len); |
| 1394 | } | 1454 | } |
| 1395 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1455 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
| 1396 | gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, | 1456 | gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset, |
| 1397 | bi->bi_len, buf_blk, new_state); | 1457 | bi->bi_len, buf_blk, new_state); |
| 1398 | } | 1458 | } |
| 1399 | 1459 | ||
| @@ -1401,13 +1461,13 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, | |||
| 1401 | } | 1461 | } |
| 1402 | 1462 | ||
| 1403 | /** | 1463 | /** |
| 1404 | * gfs2_alloc_data - Allocate a data block | 1464 | * gfs2_alloc_block - Allocate a block |
| 1405 | * @ip: the inode to allocate the data block for | 1465 | * @ip: the inode to allocate the block for |
| 1406 | * | 1466 | * |
| 1407 | * Returns: the allocated block | 1467 | * Returns: the allocated block |
| 1408 | */ | 1468 | */ |
| 1409 | 1469 | ||
| 1410 | u64 gfs2_alloc_data(struct gfs2_inode *ip) | 1470 | u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n) |
| 1411 | { | 1471 | { |
| 1412 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1472 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
| 1413 | struct gfs2_alloc *al = ip->i_alloc; | 1473 | struct gfs2_alloc *al = ip->i_alloc; |
| @@ -1415,77 +1475,31 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip) | |||
| 1415 | u32 goal, blk; | 1475 | u32 goal, blk; |
| 1416 | u64 block; | 1476 | u64 block; |
| 1417 | 1477 | ||
| 1418 | if (rgrp_contains_block(rgd, ip->i_di.di_goal_data)) | 1478 | if (rgrp_contains_block(rgd, ip->i_goal)) |
| 1419 | goal = ip->i_di.di_goal_data - rgd->rd_data0; | 1479 | goal = ip->i_goal - rgd->rd_data0; |
| 1420 | else | 1480 | else |
| 1421 | goal = rgd->rd_last_alloc_data; | 1481 | goal = rgd->rd_last_alloc; |
| 1422 | 1482 | ||
| 1423 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); | 1483 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n); |
| 1424 | BUG_ON(blk == BFITNOENT); | 1484 | BUG_ON(blk == BFITNOENT); |
| 1425 | rgd->rd_last_alloc_data = blk; | ||
| 1426 | 1485 | ||
| 1486 | rgd->rd_last_alloc = blk; | ||
| 1427 | block = rgd->rd_data0 + blk; | 1487 | block = rgd->rd_data0 + blk; |
| 1428 | ip->i_di.di_goal_data = block; | 1488 | ip->i_goal = block; |
| 1429 | 1489 | ||
| 1430 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); | 1490 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free >= *n); |
| 1431 | rgd->rd_rg.rg_free--; | 1491 | rgd->rd_rg.rg_free -= *n; |
| 1432 | 1492 | ||
| 1433 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1493 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
| 1434 | gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data); | 1494 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
| 1435 | 1495 | ||
| 1436 | al->al_alloced++; | 1496 | al->al_alloced += *n; |
| 1437 | 1497 | ||
| 1438 | gfs2_statfs_change(sdp, 0, -1, 0); | 1498 | gfs2_statfs_change(sdp, 0, -*n, 0); |
| 1439 | gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid); | 1499 | gfs2_quota_change(ip, *n, ip->i_inode.i_uid, ip->i_inode.i_gid); |
| 1440 | 1500 | ||
| 1441 | spin_lock(&sdp->sd_rindex_spin); | 1501 | spin_lock(&sdp->sd_rindex_spin); |
| 1442 | rgd->rd_free_clone--; | 1502 | rgd->rd_free_clone -= *n; |
| 1443 | spin_unlock(&sdp->sd_rindex_spin); | ||
| 1444 | |||
| 1445 | return block; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | /** | ||
| 1449 | * gfs2_alloc_meta - Allocate a metadata block | ||
| 1450 | * @ip: the inode to allocate the metadata block for | ||
| 1451 | * | ||
| 1452 | * Returns: the allocated block | ||
| 1453 | */ | ||
| 1454 | |||
| 1455 | u64 gfs2_alloc_meta(struct gfs2_inode *ip) | ||
| 1456 | { | ||
| 1457 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
| 1458 | struct gfs2_alloc *al = ip->i_alloc; | ||
| 1459 | struct gfs2_rgrpd *rgd = al->al_rgd; | ||
| 1460 | u32 goal, blk; | ||
| 1461 | u64 block; | ||
| 1462 | |||
| 1463 | if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta)) | ||
| 1464 | goal = ip->i_di.di_goal_meta - rgd->rd_data0; | ||
| 1465 | else | ||
| 1466 | goal = rgd->rd_last_alloc_meta; | ||
| 1467 | |||
| 1468 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); | ||
| 1469 | BUG_ON(blk == BFITNOENT); | ||
| 1470 | rgd->rd_last_alloc_meta = blk; | ||
| 1471 | |||
| 1472 | block = rgd->rd_data0 + blk; | ||
| 1473 | ip->i_di.di_goal_meta = block; | ||
| 1474 | |||
| 1475 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); | ||
| 1476 | rgd->rd_rg.rg_free--; | ||
| 1477 | |||
| 1478 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | ||
| 1479 | gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data); | ||
| 1480 | |||
| 1481 | al->al_alloced++; | ||
| 1482 | |||
| 1483 | gfs2_statfs_change(sdp, 0, -1, 0); | ||
| 1484 | gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid); | ||
| 1485 | gfs2_trans_add_unrevoke(sdp, block); | ||
| 1486 | |||
| 1487 | spin_lock(&sdp->sd_rindex_spin); | ||
| 1488 | rgd->rd_free_clone--; | ||
| 1489 | spin_unlock(&sdp->sd_rindex_spin); | 1503 | spin_unlock(&sdp->sd_rindex_spin); |
| 1490 | 1504 | ||
| 1491 | return block; | 1505 | return block; |
| @@ -1505,12 +1519,13 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) | |||
| 1505 | struct gfs2_rgrpd *rgd = al->al_rgd; | 1519 | struct gfs2_rgrpd *rgd = al->al_rgd; |
| 1506 | u32 blk; | 1520 | u32 blk; |
| 1507 | u64 block; | 1521 | u64 block; |
| 1522 | unsigned int n = 1; | ||
| 1508 | 1523 | ||
| 1509 | blk = rgblk_search(rgd, rgd->rd_last_alloc_meta, | 1524 | blk = rgblk_search(rgd, rgd->rd_last_alloc, |
| 1510 | GFS2_BLKST_FREE, GFS2_BLKST_DINODE); | 1525 | GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n); |
| 1511 | BUG_ON(blk == BFITNOENT); | 1526 | BUG_ON(blk == BFITNOENT); |
| 1512 | 1527 | ||
| 1513 | rgd->rd_last_alloc_meta = blk; | 1528 | rgd->rd_last_alloc = blk; |
| 1514 | 1529 | ||
| 1515 | block = rgd->rd_data0 + blk; | 1530 | block = rgd->rd_data0 + blk; |
| 1516 | 1531 | ||
| @@ -1519,12 +1534,12 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) | |||
| 1519 | rgd->rd_rg.rg_dinodes++; | 1534 | rgd->rd_rg.rg_dinodes++; |
| 1520 | *generation = rgd->rd_rg.rg_igeneration++; | 1535 | *generation = rgd->rd_rg.rg_igeneration++; |
| 1521 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1536 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
| 1522 | gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data); | 1537 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
| 1523 | 1538 | ||
| 1524 | al->al_alloced++; | 1539 | al->al_alloced++; |
| 1525 | 1540 | ||
| 1526 | gfs2_statfs_change(sdp, 0, -1, +1); | 1541 | gfs2_statfs_change(sdp, 0, -1, +1); |
| 1527 | gfs2_trans_add_unrevoke(sdp, block); | 1542 | gfs2_trans_add_unrevoke(sdp, block, 1); |
| 1528 | 1543 | ||
| 1529 | spin_lock(&sdp->sd_rindex_spin); | 1544 | spin_lock(&sdp->sd_rindex_spin); |
| 1530 | rgd->rd_free_clone--; | 1545 | rgd->rd_free_clone--; |
| @@ -1553,7 +1568,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen) | |||
| 1553 | rgd->rd_rg.rg_free += blen; | 1568 | rgd->rd_rg.rg_free += blen; |
| 1554 | 1569 | ||
| 1555 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1570 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
| 1556 | gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data); | 1571 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
| 1557 | 1572 | ||
| 1558 | gfs2_trans_add_rg(rgd); | 1573 | gfs2_trans_add_rg(rgd); |
| 1559 | 1574 | ||
| @@ -1581,7 +1596,7 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen) | |||
| 1581 | rgd->rd_rg.rg_free += blen; | 1596 | rgd->rd_rg.rg_free += blen; |
| 1582 | 1597 | ||
| 1583 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1598 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
| 1584 | gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data); | 1599 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
| 1585 | 1600 | ||
| 1586 | gfs2_trans_add_rg(rgd); | 1601 | gfs2_trans_add_rg(rgd); |
| 1587 | 1602 | ||
| @@ -1601,7 +1616,7 @@ void gfs2_unlink_di(struct inode *inode) | |||
| 1601 | if (!rgd) | 1616 | if (!rgd) |
| 1602 | return; | 1617 | return; |
| 1603 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1618 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
| 1604 | gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data); | 1619 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
| 1605 | gfs2_trans_add_rg(rgd); | 1620 | gfs2_trans_add_rg(rgd); |
| 1606 | } | 1621 | } |
| 1607 | 1622 | ||
| @@ -1621,7 +1636,7 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) | |||
| 1621 | rgd->rd_rg.rg_free++; | 1636 | rgd->rd_rg.rg_free++; |
| 1622 | 1637 | ||
| 1623 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1638 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
| 1624 | gfs2_rgrp_out(&rgd->rd_rg, rgd->rd_bits[0].bi_bh->b_data); | 1639 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
| 1625 | 1640 | ||
| 1626 | gfs2_statfs_change(sdp, 0, +1, -1); | 1641 | gfs2_statfs_change(sdp, 0, +1, -1); |
| 1627 | gfs2_trans_add_rg(rgd); | 1642 | gfs2_trans_add_rg(rgd); |
| @@ -1699,8 +1714,7 @@ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist, | |||
| 1699 | * | 1714 | * |
| 1700 | */ | 1715 | */ |
| 1701 | 1716 | ||
| 1702 | void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state, | 1717 | void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state) |
| 1703 | int flags) | ||
| 1704 | { | 1718 | { |
| 1705 | unsigned int x; | 1719 | unsigned int x; |
| 1706 | 1720 | ||
| @@ -1708,7 +1722,7 @@ void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state, | |||
| 1708 | GFP_NOFS | __GFP_NOFAIL); | 1722 | GFP_NOFS | __GFP_NOFAIL); |
| 1709 | for (x = 0; x < rlist->rl_rgrps; x++) | 1723 | for (x = 0; x < rlist->rl_rgrps; x++) |
| 1710 | gfs2_holder_init(rlist->rl_rgd[x]->rd_gl, | 1724 | gfs2_holder_init(rlist->rl_rgd[x]->rd_gl, |
| 1711 | state, flags, | 1725 | state, 0, |
| 1712 | &rlist->rl_ghs[x]); | 1726 | &rlist->rl_ghs[x]); |
| 1713 | } | 1727 | } |
| 1714 | 1728 | ||
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index 149bb161f4b6..3181c7e624bf 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
| 6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -46,8 +46,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip); | |||
| 46 | 46 | ||
| 47 | unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block); | 47 | unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block); |
| 48 | 48 | ||
| 49 | u64 gfs2_alloc_data(struct gfs2_inode *ip); | 49 | u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n); |
| 50 | u64 gfs2_alloc_meta(struct gfs2_inode *ip); | ||
| 51 | u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation); | 50 | u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation); |
| 52 | 51 | ||
| 53 | void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen); | 52 | void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen); |
| @@ -64,8 +63,7 @@ struct gfs2_rgrp_list { | |||
| 64 | 63 | ||
| 65 | void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist, | 64 | void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist, |
| 66 | u64 block); | 65 | u64 block); |
| 67 | void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state, | 66 | void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state); |
| 68 | int flags); | ||
| 69 | void gfs2_rlist_free(struct gfs2_rgrp_list *rlist); | 67 | void gfs2_rlist_free(struct gfs2_rgrp_list *rlist); |
| 70 | u64 gfs2_ri_total(struct gfs2_sbd *sdp); | 68 | u64 gfs2_ri_total(struct gfs2_sbd *sdp); |
| 71 | 69 | ||
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index ef0562c3bc71..7aeacbc65f35 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
| @@ -210,7 +210,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) | |||
| 210 | struct page *page; | 210 | struct page *page; |
| 211 | struct bio *bio; | 211 | struct bio *bio; |
| 212 | 212 | ||
| 213 | page = alloc_page(GFP_KERNEL); | 213 | page = alloc_page(GFP_NOFS); |
| 214 | if (unlikely(!page)) | 214 | if (unlikely(!page)) |
| 215 | return -ENOBUFS; | 215 | return -ENOBUFS; |
| 216 | 216 | ||
| @@ -218,7 +218,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) | |||
| 218 | ClearPageDirty(page); | 218 | ClearPageDirty(page); |
| 219 | lock_page(page); | 219 | lock_page(page); |
| 220 | 220 | ||
| 221 | bio = bio_alloc(GFP_KERNEL, 1); | 221 | bio = bio_alloc(GFP_NOFS, 1); |
| 222 | if (unlikely(!bio)) { | 222 | if (unlikely(!bio)) { |
| 223 | __free_page(page); | 223 | __free_page(page); |
| 224 | return -ENOBUFS; | 224 | return -ENOBUFS; |
| @@ -316,6 +316,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) | |||
| 316 | sdp->sd_heightsize[x] = space; | 316 | sdp->sd_heightsize[x] = space; |
| 317 | } | 317 | } |
| 318 | sdp->sd_max_height = x; | 318 | sdp->sd_max_height = x; |
| 319 | sdp->sd_heightsize[x] = ~0; | ||
| 319 | gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT); | 320 | gfs2_assert(sdp, sdp->sd_max_height <= GFS2_MAX_META_HEIGHT); |
| 320 | 321 | ||
| 321 | sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - | 322 | sdp->sd_jheightsize[0] = sdp->sd_sb.sb_bsize - |
| @@ -334,6 +335,7 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent) | |||
| 334 | sdp->sd_jheightsize[x] = space; | 335 | sdp->sd_jheightsize[x] = space; |
| 335 | } | 336 | } |
| 336 | sdp->sd_max_jheight = x; | 337 | sdp->sd_max_jheight = x; |
| 338 | sdp->sd_jheightsize[x] = ~0; | ||
| 337 | gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT); | 339 | gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT); |
| 338 | 340 | ||
| 339 | return 0; | 341 | return 0; |
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index 60a870e430be..44361ecc44f7 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h | |||
| @@ -17,6 +17,7 @@ void gfs2_tune_init(struct gfs2_tune *gt); | |||
| 17 | int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent); | 17 | int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent); |
| 18 | int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent); | 18 | int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent); |
| 19 | int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector); | 19 | int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector); |
| 20 | void gfs2_lm_unmount(struct gfs2_sbd *sdp); | ||
| 20 | 21 | ||
| 21 | static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) | 22 | static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) |
| 22 | { | 23 | { |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index eaa3b7b2f99e..9ab9fc85ecd0 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
| @@ -20,7 +20,6 @@ | |||
| 20 | 20 | ||
| 21 | #include "gfs2.h" | 21 | #include "gfs2.h" |
| 22 | #include "incore.h" | 22 | #include "incore.h" |
| 23 | #include "lm.h" | ||
| 24 | #include "sys.h" | 23 | #include "sys.h" |
| 25 | #include "super.h" | 24 | #include "super.h" |
| 26 | #include "glock.h" | 25 | #include "glock.h" |
| @@ -328,15 +327,9 @@ static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf) \ | |||
| 328 | } \ | 327 | } \ |
| 329 | static struct counters_attr counters_attr_##name = __ATTR_RO(name) | 328 | static struct counters_attr counters_attr_##name = __ATTR_RO(name) |
| 330 | 329 | ||
| 331 | COUNTERS_ATTR(glock_count, "%u\n"); | ||
| 332 | COUNTERS_ATTR(glock_held_count, "%u\n"); | ||
| 333 | COUNTERS_ATTR(inode_count, "%u\n"); | ||
| 334 | COUNTERS_ATTR(reclaimed, "%u\n"); | 330 | COUNTERS_ATTR(reclaimed, "%u\n"); |
| 335 | 331 | ||
| 336 | static struct attribute *counters_attrs[] = { | 332 | static struct attribute *counters_attrs[] = { |
| 337 | &counters_attr_glock_count.attr, | ||
| 338 | &counters_attr_glock_held_count.attr, | ||
| 339 | &counters_attr_inode_count.attr, | ||
| 340 | &counters_attr_reclaimed.attr, | 333 | &counters_attr_reclaimed.attr, |
| 341 | NULL, | 334 | NULL, |
| 342 | }; | 335 | }; |
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 73e5d92a657c..f677b8a83f0c 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c | |||
| @@ -146,30 +146,25 @@ void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) | |||
| 146 | lops_add(sdp, &bd->bd_le); | 146 | lops_add(sdp, &bd->bd_le); |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno) | 149 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len) |
| 150 | { | 150 | { |
| 151 | struct gfs2_bufdata *bd; | 151 | struct gfs2_bufdata *bd, *tmp; |
| 152 | int found = 0; | 152 | struct gfs2_trans *tr = current->journal_info; |
| 153 | unsigned int n = len; | ||
| 153 | 154 | ||
| 154 | gfs2_log_lock(sdp); | 155 | gfs2_log_lock(sdp); |
| 155 | 156 | list_for_each_entry_safe(bd, tmp, &sdp->sd_log_le_revoke, bd_le.le_list) { | |
| 156 | list_for_each_entry(bd, &sdp->sd_log_le_revoke, bd_le.le_list) { | 157 | if ((bd->bd_blkno >= blkno) && (bd->bd_blkno < (blkno + len))) { |
| 157 | if (bd->bd_blkno == blkno) { | ||
| 158 | list_del_init(&bd->bd_le.le_list); | 158 | list_del_init(&bd->bd_le.le_list); |
| 159 | gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); | 159 | gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke); |
| 160 | sdp->sd_log_num_revoke--; | 160 | sdp->sd_log_num_revoke--; |
| 161 | found = 1; | 161 | kmem_cache_free(gfs2_bufdata_cachep, bd); |
| 162 | break; | 162 | tr->tr_num_revoke_rm++; |
| 163 | if (--n == 0) | ||
| 164 | break; | ||
| 163 | } | 165 | } |
| 164 | } | 166 | } |
| 165 | |||
| 166 | gfs2_log_unlock(sdp); | 167 | gfs2_log_unlock(sdp); |
| 167 | |||
| 168 | if (found) { | ||
| 169 | struct gfs2_trans *tr = current->journal_info; | ||
| 170 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
| 171 | tr->tr_num_revoke_rm++; | ||
| 172 | } | ||
| 173 | } | 168 | } |
| 174 | 169 | ||
| 175 | void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd) | 170 | void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd) |
diff --git a/fs/gfs2/trans.h b/fs/gfs2/trans.h index e826f0dab80a..edf9d4bd908e 100644 --- a/fs/gfs2/trans.h +++ b/fs/gfs2/trans.h | |||
| @@ -32,7 +32,7 @@ void gfs2_trans_end(struct gfs2_sbd *sdp); | |||
| 32 | 32 | ||
| 33 | void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta); | 33 | void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta); |
| 34 | void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); | 34 | void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd); |
| 35 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno); | 35 | void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len); |
| 36 | void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd); | 36 | void gfs2_trans_add_rg(struct gfs2_rgrpd *rgd); |
| 37 | 37 | ||
| 38 | #endif /* __TRANS_DOT_H__ */ | 38 | #endif /* __TRANS_DOT_H__ */ |
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index 424a0774eda8..d31e355c61fb 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c | |||
| @@ -19,12 +19,12 @@ | |||
| 19 | #include "gfs2.h" | 19 | #include "gfs2.h" |
| 20 | #include "incore.h" | 20 | #include "incore.h" |
| 21 | #include "glock.h" | 21 | #include "glock.h" |
| 22 | #include "lm.h" | ||
| 23 | #include "util.h" | 22 | #include "util.h" |
| 24 | 23 | ||
| 25 | struct kmem_cache *gfs2_glock_cachep __read_mostly; | 24 | struct kmem_cache *gfs2_glock_cachep __read_mostly; |
| 26 | struct kmem_cache *gfs2_inode_cachep __read_mostly; | 25 | struct kmem_cache *gfs2_inode_cachep __read_mostly; |
| 27 | struct kmem_cache *gfs2_bufdata_cachep __read_mostly; | 26 | struct kmem_cache *gfs2_bufdata_cachep __read_mostly; |
| 27 | struct kmem_cache *gfs2_rgrpd_cachep __read_mostly; | ||
| 28 | 28 | ||
| 29 | void gfs2_assert_i(struct gfs2_sbd *sdp) | 29 | void gfs2_assert_i(struct gfs2_sbd *sdp) |
| 30 | { | 30 | { |
| @@ -32,6 +32,28 @@ void gfs2_assert_i(struct gfs2_sbd *sdp) | |||
| 32 | sdp->sd_fsname); | 32 | sdp->sd_fsname); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) | ||
| 36 | { | ||
| 37 | va_list args; | ||
| 38 | |||
| 39 | if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags)) | ||
| 40 | return 0; | ||
| 41 | |||
| 42 | va_start(args, fmt); | ||
| 43 | vprintk(fmt, args); | ||
| 44 | va_end(args); | ||
| 45 | |||
| 46 | fs_err(sdp, "about to withdraw this file system\n"); | ||
| 47 | BUG_ON(sdp->sd_args.ar_debug); | ||
| 48 | |||
| 49 | fs_err(sdp, "telling LM to withdraw\n"); | ||
| 50 | gfs2_withdraw_lockproto(&sdp->sd_lockstruct); | ||
| 51 | fs_err(sdp, "withdrawn\n"); | ||
| 52 | dump_stack(); | ||
| 53 | |||
| 54 | return -1; | ||
| 55 | } | ||
| 56 | |||
| 35 | /** | 57 | /** |
| 36 | * gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false | 58 | * gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false |
| 37 | * Returns: -1 if this call withdrew the machine, | 59 | * Returns: -1 if this call withdrew the machine, |
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h index 28938a46cf47..509c5d60bd80 100644 --- a/fs/gfs2/util.h +++ b/fs/gfs2/util.h | |||
| @@ -147,6 +147,7 @@ gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__); | |||
| 147 | extern struct kmem_cache *gfs2_glock_cachep; | 147 | extern struct kmem_cache *gfs2_glock_cachep; |
| 148 | extern struct kmem_cache *gfs2_inode_cachep; | 148 | extern struct kmem_cache *gfs2_inode_cachep; |
| 149 | extern struct kmem_cache *gfs2_bufdata_cachep; | 149 | extern struct kmem_cache *gfs2_bufdata_cachep; |
| 150 | extern struct kmem_cache *gfs2_rgrpd_cachep; | ||
| 150 | 151 | ||
| 151 | static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt, | 152 | static inline unsigned int gfs2_tune_get_i(struct gfs2_tune *gt, |
| 152 | unsigned int *p) | 153 | unsigned int *p) |
| @@ -163,6 +164,7 @@ gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field) | |||
| 163 | 164 | ||
| 164 | void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap, | 165 | void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap, |
| 165 | unsigned int bit, int new_value); | 166 | unsigned int bit, int new_value); |
| 167 | int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...); | ||
| 166 | 168 | ||
| 167 | #endif /* __UTIL_DOT_H__ */ | 169 | #endif /* __UTIL_DOT_H__ */ |
| 168 | 170 | ||
diff --git a/include/linux/lm_interface.h b/include/linux/lm_interface.h index 1418fdc9ac02..f274997bc283 100644 --- a/include/linux/lm_interface.h +++ b/include/linux/lm_interface.h | |||
| @@ -21,9 +21,15 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data); | |||
| 21 | * modify the filesystem. The lock module shouldn't assign a journal to the FS | 21 | * modify the filesystem. The lock module shouldn't assign a journal to the FS |
| 22 | * mount. It shouldn't send recovery callbacks to the FS mount. If the node | 22 | * mount. It shouldn't send recovery callbacks to the FS mount. If the node |
| 23 | * dies or withdraws, all locks can be wiped immediately. | 23 | * dies or withdraws, all locks can be wiped immediately. |
| 24 | * | ||
| 25 | * LM_MFLAG_CONV_NODROP | ||
| 26 | * Do not allow the dlm to internally resolve conversion deadlocks by demoting | ||
| 27 | * the lock to unlocked and then reacquiring it in the requested mode. Instead, | ||
| 28 | * it should cancel the request and return LM_OUT_CONV_DEADLK. | ||
| 24 | */ | 29 | */ |
| 25 | 30 | ||
| 26 | #define LM_MFLAG_SPECTATOR 0x00000001 | 31 | #define LM_MFLAG_SPECTATOR 0x00000001 |
| 32 | #define LM_MFLAG_CONV_NODROP 0x00000002 | ||
| 27 | 33 | ||
| 28 | /* | 34 | /* |
| 29 | * lm_lockstruct flags | 35 | * lm_lockstruct flags |
| @@ -110,6 +116,9 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data); | |||
| 110 | * | 116 | * |
| 111 | * LM_OUT_ASYNC | 117 | * LM_OUT_ASYNC |
| 112 | * The result of the request will be returned in an LM_CB_ASYNC callback. | 118 | * The result of the request will be returned in an LM_CB_ASYNC callback. |
| 119 | * | ||
| 120 | * LM_OUT_CONV_DEADLK | ||
| 121 | * The lock request was canceled do to a conversion deadlock. | ||
| 113 | */ | 122 | */ |
| 114 | 123 | ||
| 115 | #define LM_OUT_ST_MASK 0x00000003 | 124 | #define LM_OUT_ST_MASK 0x00000003 |
| @@ -117,6 +126,7 @@ typedef void (*lm_callback_t) (void *ptr, unsigned int type, void *data); | |||
| 117 | #define LM_OUT_CANCELED 0x00000008 | 126 | #define LM_OUT_CANCELED 0x00000008 |
| 118 | #define LM_OUT_ASYNC 0x00000080 | 127 | #define LM_OUT_ASYNC 0x00000080 |
| 119 | #define LM_OUT_ERROR 0x00000100 | 128 | #define LM_OUT_ERROR 0x00000100 |
| 129 | #define LM_OUT_CONV_DEADLK 0x00000200 | ||
| 120 | 130 | ||
| 121 | /* | 131 | /* |
| 122 | * lm_callback_t types | 132 | * lm_callback_t types |
