diff options
| -rw-r--r-- | Documentation/filesystems/configfs/configfs.txt | 10 | ||||
| -rw-r--r-- | Documentation/filesystems/configfs/configfs_example.c | 14 | ||||
| -rw-r--r-- | drivers/net/netconsole.c | 10 | ||||
| -rw-r--r-- | fs/Kconfig | 8 | ||||
| -rw-r--r-- | fs/configfs/configfs_internal.h | 4 | ||||
| -rw-r--r-- | fs/configfs/dir.c | 147 | ||||
| -rw-r--r-- | fs/configfs/inode.c | 2 | ||||
| -rw-r--r-- | fs/configfs/symlink.c | 16 | ||||
| -rw-r--r-- | fs/dlm/config.c | 45 | ||||
| -rw-r--r-- | fs/ocfs2/aops.c | 13 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/heartbeat.c | 17 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/netdebug.c | 8 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/nodemanager.c | 45 | ||||
| -rw-r--r-- | fs/ocfs2/dlmglue.c | 122 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/journal.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/localalloc.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2.h | 12 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 2 | ||||
| -rw-r--r-- | fs/ocfs2/stack_user.c | 19 | ||||
| -rw-r--r-- | fs/ocfs2/super.c | 6 | ||||
| -rw-r--r-- | include/linux/configfs.h | 4 |
22 files changed, 383 insertions, 127 deletions
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt index 44c97e6accb2..15838d706ea2 100644 --- a/Documentation/filesystems/configfs/configfs.txt +++ b/Documentation/filesystems/configfs/configfs.txt | |||
| @@ -233,10 +233,12 @@ accomplished via the group operations specified on the group's | |||
| 233 | config_item_type. | 233 | config_item_type. |
| 234 | 234 | ||
| 235 | struct configfs_group_operations { | 235 | struct configfs_group_operations { |
| 236 | struct config_item *(*make_item)(struct config_group *group, | 236 | int (*make_item)(struct config_group *group, |
| 237 | const char *name); | 237 | const char *name, |
| 238 | struct config_group *(*make_group)(struct config_group *group, | 238 | struct config_item **new_item); |
| 239 | const char *name); | 239 | int (*make_group)(struct config_group *group, |
| 240 | const char *name, | ||
| 241 | struct config_group **new_group); | ||
| 240 | int (*commit_item)(struct config_item *item); | 242 | int (*commit_item)(struct config_item *item); |
| 241 | void (*disconnect_notify)(struct config_group *group, | 243 | void (*disconnect_notify)(struct config_group *group, |
| 242 | struct config_item *item); | 244 | struct config_item *item); |
diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example.c index 25151fd5c2c6..0b422acd470c 100644 --- a/Documentation/filesystems/configfs/configfs_example.c +++ b/Documentation/filesystems/configfs/configfs_example.c | |||
| @@ -273,13 +273,13 @@ static inline struct simple_children *to_simple_children(struct config_item *ite | |||
| 273 | return item ? container_of(to_config_group(item), struct simple_children, group) : NULL; | 273 | return item ? container_of(to_config_group(item), struct simple_children, group) : NULL; |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | static struct config_item *simple_children_make_item(struct config_group *group, const char *name) | 276 | static int simple_children_make_item(struct config_group *group, const char *name, struct config_item **new_item) |
| 277 | { | 277 | { |
| 278 | struct simple_child *simple_child; | 278 | struct simple_child *simple_child; |
| 279 | 279 | ||
| 280 | simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL); | 280 | simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL); |
| 281 | if (!simple_child) | 281 | if (!simple_child) |
| 282 | return NULL; | 282 | return -ENOMEM; |
| 283 | 283 | ||
| 284 | 284 | ||
| 285 | config_item_init_type_name(&simple_child->item, name, | 285 | config_item_init_type_name(&simple_child->item, name, |
| @@ -287,7 +287,8 @@ static struct config_item *simple_children_make_item(struct config_group *group, | |||
| 287 | 287 | ||
| 288 | simple_child->storeme = 0; | 288 | simple_child->storeme = 0; |
| 289 | 289 | ||
| 290 | return &simple_child->item; | 290 | *new_item = &simple_child->item; |
| 291 | return 0; | ||
| 291 | } | 292 | } |
| 292 | 293 | ||
| 293 | static struct configfs_attribute simple_children_attr_description = { | 294 | static struct configfs_attribute simple_children_attr_description = { |
| @@ -359,20 +360,21 @@ static struct configfs_subsystem simple_children_subsys = { | |||
| 359 | * children of its own. | 360 | * children of its own. |
| 360 | */ | 361 | */ |
| 361 | 362 | ||
| 362 | static struct config_group *group_children_make_group(struct config_group *group, const char *name) | 363 | static int group_children_make_group(struct config_group *group, const char *name, struct config_group **new_group) |
| 363 | { | 364 | { |
| 364 | struct simple_children *simple_children; | 365 | struct simple_children *simple_children; |
| 365 | 366 | ||
| 366 | simple_children = kzalloc(sizeof(struct simple_children), | 367 | simple_children = kzalloc(sizeof(struct simple_children), |
| 367 | GFP_KERNEL); | 368 | GFP_KERNEL); |
| 368 | if (!simple_children) | 369 | if (!simple_children) |
| 369 | return NULL; | 370 | return -ENOMEM; |
| 370 | 371 | ||
| 371 | 372 | ||
| 372 | config_group_init_type_name(&simple_children->group, name, | 373 | config_group_init_type_name(&simple_children->group, name, |
| 373 | &simple_children_type); | 374 | &simple_children_type); |
| 374 | 375 | ||
| 375 | return &simple_children->group; | 376 | *new_group = &simple_children->group; |
| 377 | return 0; | ||
| 376 | } | 378 | } |
| 377 | 379 | ||
| 378 | static struct configfs_attribute group_children_attr_description = { | 380 | static struct configfs_attribute group_children_attr_description = { |
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 665341e43055..387a13395015 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c | |||
| @@ -585,8 +585,9 @@ static struct config_item_type netconsole_target_type = { | |||
| 585 | * Group operations and type for netconsole_subsys. | 585 | * Group operations and type for netconsole_subsys. |
| 586 | */ | 586 | */ |
| 587 | 587 | ||
| 588 | static struct config_item *make_netconsole_target(struct config_group *group, | 588 | static int make_netconsole_target(struct config_group *group, |
| 589 | const char *name) | 589 | const char *name, |
| 590 | struct config_item **new_item) | ||
| 590 | { | 591 | { |
| 591 | unsigned long flags; | 592 | unsigned long flags; |
| 592 | struct netconsole_target *nt; | 593 | struct netconsole_target *nt; |
| @@ -598,7 +599,7 @@ static struct config_item *make_netconsole_target(struct config_group *group, | |||
| 598 | nt = kzalloc(sizeof(*nt), GFP_KERNEL); | 599 | nt = kzalloc(sizeof(*nt), GFP_KERNEL); |
| 599 | if (!nt) { | 600 | if (!nt) { |
| 600 | printk(KERN_ERR "netconsole: failed to allocate memory\n"); | 601 | printk(KERN_ERR "netconsole: failed to allocate memory\n"); |
| 601 | return NULL; | 602 | return -ENOMEM; |
| 602 | } | 603 | } |
| 603 | 604 | ||
| 604 | nt->np.name = "netconsole"; | 605 | nt->np.name = "netconsole"; |
| @@ -615,7 +616,8 @@ static struct config_item *make_netconsole_target(struct config_group *group, | |||
| 615 | list_add(&nt->list, &target_list); | 616 | list_add(&nt->list, &target_list); |
| 616 | spin_unlock_irqrestore(&target_list_lock, flags); | 617 | spin_unlock_irqrestore(&target_list_lock, flags); |
| 617 | 618 | ||
| 618 | return &nt->item; | 619 | *new_item = &nt->item; |
| 620 | return 0; | ||
| 619 | } | 621 | } |
| 620 | 622 | ||
| 621 | static void drop_netconsole_target(struct config_group *group, | 623 | static void drop_netconsole_target(struct config_group *group, |
diff --git a/fs/Kconfig b/fs/Kconfig index 17216ba99c85..37db79a2ff95 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -470,6 +470,14 @@ config OCFS2_FS_USERSPACE_CLUSTER | |||
| 470 | It is safe to say Y, as the clustering method is run-time | 470 | It is safe to say Y, as the clustering method is run-time |
| 471 | selectable. | 471 | selectable. |
| 472 | 472 | ||
| 473 | config OCFS2_FS_STATS | ||
| 474 | bool "OCFS2 statistics" | ||
| 475 | depends on OCFS2_FS | ||
| 476 | default y | ||
| 477 | help | ||
| 478 | This option allows some fs statistics to be captured. Enabling | ||
| 479 | this option may increase the memory consumption. | ||
| 480 | |||
| 473 | config OCFS2_DEBUG_MASKLOG | 481 | config OCFS2_DEBUG_MASKLOG |
| 474 | bool "OCFS2 logging support" | 482 | bool "OCFS2 logging support" |
| 475 | depends on OCFS2_FS | 483 | depends on OCFS2_FS |
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index cca98609aa7f..da015c12e3ea 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
| 29 | #include <linux/spinlock.h> | ||
| 29 | 30 | ||
| 30 | struct configfs_dirent { | 31 | struct configfs_dirent { |
| 31 | atomic_t s_count; | 32 | atomic_t s_count; |
| @@ -47,8 +48,11 @@ struct configfs_dirent { | |||
| 47 | #define CONFIGFS_USET_DIR 0x0040 | 48 | #define CONFIGFS_USET_DIR 0x0040 |
| 48 | #define CONFIGFS_USET_DEFAULT 0x0080 | 49 | #define CONFIGFS_USET_DEFAULT 0x0080 |
| 49 | #define CONFIGFS_USET_DROPPING 0x0100 | 50 | #define CONFIGFS_USET_DROPPING 0x0100 |
| 51 | #define CONFIGFS_USET_IN_MKDIR 0x0200 | ||
| 50 | #define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR) | 52 | #define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR) |
| 51 | 53 | ||
| 54 | extern spinlock_t configfs_dirent_lock; | ||
| 55 | |||
| 52 | extern struct vfsmount * configfs_mount; | 56 | extern struct vfsmount * configfs_mount; |
| 53 | extern struct kmem_cache *configfs_dir_cachep; | 57 | extern struct kmem_cache *configfs_dir_cachep; |
| 54 | 58 | ||
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index a48dc7dd8765..0e64312a084c 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
| @@ -30,11 +30,25 @@ | |||
| 30 | #include <linux/mount.h> | 30 | #include <linux/mount.h> |
| 31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/err.h> | ||
| 33 | 34 | ||
| 34 | #include <linux/configfs.h> | 35 | #include <linux/configfs.h> |
| 35 | #include "configfs_internal.h" | 36 | #include "configfs_internal.h" |
| 36 | 37 | ||
| 37 | DECLARE_RWSEM(configfs_rename_sem); | 38 | DECLARE_RWSEM(configfs_rename_sem); |
| 39 | /* | ||
| 40 | * Protects mutations of configfs_dirent linkage together with proper i_mutex | ||
| 41 | * Also protects mutations of symlinks linkage to target configfs_dirent | ||
| 42 | * Mutators of configfs_dirent linkage must *both* have the proper inode locked | ||
| 43 | * and configfs_dirent_lock locked, in that order. | ||
| 44 | * This allows one to safely traverse configfs_dirent trees and symlinks without | ||
| 45 | * having to lock inodes. | ||
| 46 | * | ||
| 47 | * Protects setting of CONFIGFS_USET_DROPPING: checking the flag | ||
| 48 | * unlocked is not reliable unless in detach_groups() called from | ||
| 49 | * rmdir()/unregister() and from configfs_attach_group() | ||
| 50 | */ | ||
| 51 | DEFINE_SPINLOCK(configfs_dirent_lock); | ||
| 38 | 52 | ||
| 39 | static void configfs_d_iput(struct dentry * dentry, | 53 | static void configfs_d_iput(struct dentry * dentry, |
| 40 | struct inode * inode) | 54 | struct inode * inode) |
| @@ -74,13 +88,20 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare | |||
| 74 | 88 | ||
| 75 | sd = kmem_cache_zalloc(configfs_dir_cachep, GFP_KERNEL); | 89 | sd = kmem_cache_zalloc(configfs_dir_cachep, GFP_KERNEL); |
| 76 | if (!sd) | 90 | if (!sd) |
| 77 | return NULL; | 91 | return ERR_PTR(-ENOMEM); |
| 78 | 92 | ||
| 79 | atomic_set(&sd->s_count, 1); | 93 | atomic_set(&sd->s_count, 1); |
| 80 | INIT_LIST_HEAD(&sd->s_links); | 94 | INIT_LIST_HEAD(&sd->s_links); |
| 81 | INIT_LIST_HEAD(&sd->s_children); | 95 | INIT_LIST_HEAD(&sd->s_children); |
| 82 | list_add(&sd->s_sibling, &parent_sd->s_children); | ||
| 83 | sd->s_element = element; | 96 | sd->s_element = element; |
| 97 | spin_lock(&configfs_dirent_lock); | ||
| 98 | if (parent_sd->s_type & CONFIGFS_USET_DROPPING) { | ||
| 99 | spin_unlock(&configfs_dirent_lock); | ||
| 100 | kmem_cache_free(configfs_dir_cachep, sd); | ||
| 101 | return ERR_PTR(-ENOENT); | ||
| 102 | } | ||
| 103 | list_add(&sd->s_sibling, &parent_sd->s_children); | ||
| 104 | spin_unlock(&configfs_dirent_lock); | ||
| 84 | 105 | ||
| 85 | return sd; | 106 | return sd; |
| 86 | } | 107 | } |
| @@ -118,8 +139,8 @@ int configfs_make_dirent(struct configfs_dirent * parent_sd, | |||
| 118 | struct configfs_dirent * sd; | 139 | struct configfs_dirent * sd; |
| 119 | 140 | ||
| 120 | sd = configfs_new_dirent(parent_sd, element); | 141 | sd = configfs_new_dirent(parent_sd, element); |
| 121 | if (!sd) | 142 | if (IS_ERR(sd)) |
| 122 | return -ENOMEM; | 143 | return PTR_ERR(sd); |
| 123 | 144 | ||
| 124 | sd->s_mode = mode; | 145 | sd->s_mode = mode; |
| 125 | sd->s_type = type; | 146 | sd->s_type = type; |
| @@ -173,7 +194,9 @@ static int create_dir(struct config_item * k, struct dentry * p, | |||
| 173 | } else { | 194 | } else { |
| 174 | struct configfs_dirent *sd = d->d_fsdata; | 195 | struct configfs_dirent *sd = d->d_fsdata; |
| 175 | if (sd) { | 196 | if (sd) { |
| 197 | spin_lock(&configfs_dirent_lock); | ||
| 176 | list_del_init(&sd->s_sibling); | 198 | list_del_init(&sd->s_sibling); |
| 199 | spin_unlock(&configfs_dirent_lock); | ||
| 177 | configfs_put(sd); | 200 | configfs_put(sd); |
| 178 | } | 201 | } |
| 179 | } | 202 | } |
| @@ -224,7 +247,9 @@ int configfs_create_link(struct configfs_symlink *sl, | |||
| 224 | else { | 247 | else { |
| 225 | struct configfs_dirent *sd = dentry->d_fsdata; | 248 | struct configfs_dirent *sd = dentry->d_fsdata; |
| 226 | if (sd) { | 249 | if (sd) { |
| 250 | spin_lock(&configfs_dirent_lock); | ||
| 227 | list_del_init(&sd->s_sibling); | 251 | list_del_init(&sd->s_sibling); |
| 252 | spin_unlock(&configfs_dirent_lock); | ||
| 228 | configfs_put(sd); | 253 | configfs_put(sd); |
| 229 | } | 254 | } |
| 230 | } | 255 | } |
| @@ -238,7 +263,9 @@ static void remove_dir(struct dentry * d) | |||
| 238 | struct configfs_dirent * sd; | 263 | struct configfs_dirent * sd; |
| 239 | 264 | ||
| 240 | sd = d->d_fsdata; | 265 | sd = d->d_fsdata; |
| 266 | spin_lock(&configfs_dirent_lock); | ||
| 241 | list_del_init(&sd->s_sibling); | 267 | list_del_init(&sd->s_sibling); |
| 268 | spin_unlock(&configfs_dirent_lock); | ||
| 242 | configfs_put(sd); | 269 | configfs_put(sd); |
| 243 | if (d->d_inode) | 270 | if (d->d_inode) |
| 244 | simple_rmdir(parent->d_inode,d); | 271 | simple_rmdir(parent->d_inode,d); |
| @@ -331,13 +358,13 @@ static struct dentry * configfs_lookup(struct inode *dir, | |||
| 331 | 358 | ||
| 332 | /* | 359 | /* |
| 333 | * Only subdirectories count here. Files (CONFIGFS_NOT_PINNED) are | 360 | * Only subdirectories count here. Files (CONFIGFS_NOT_PINNED) are |
| 334 | * attributes and are removed by rmdir(). We recurse, taking i_mutex | 361 | * attributes and are removed by rmdir(). We recurse, setting |
| 335 | * on all children that are candidates for default detach. If the | 362 | * CONFIGFS_USET_DROPPING on all children that are candidates for |
| 336 | * result is clean, then configfs_detach_group() will handle dropping | 363 | * default detach. |
| 337 | * i_mutex. If there is an error, the caller will clean up the i_mutex | 364 | * If there is an error, the caller will reset the flags via |
| 338 | * holders via configfs_detach_rollback(). | 365 | * configfs_detach_rollback(). |
| 339 | */ | 366 | */ |
| 340 | static int configfs_detach_prep(struct dentry *dentry) | 367 | static int configfs_detach_prep(struct dentry *dentry, struct mutex **wait_mutex) |
| 341 | { | 368 | { |
| 342 | struct configfs_dirent *parent_sd = dentry->d_fsdata; | 369 | struct configfs_dirent *parent_sd = dentry->d_fsdata; |
| 343 | struct configfs_dirent *sd; | 370 | struct configfs_dirent *sd; |
| @@ -352,15 +379,20 @@ static int configfs_detach_prep(struct dentry *dentry) | |||
| 352 | if (sd->s_type & CONFIGFS_NOT_PINNED) | 379 | if (sd->s_type & CONFIGFS_NOT_PINNED) |
| 353 | continue; | 380 | continue; |
| 354 | if (sd->s_type & CONFIGFS_USET_DEFAULT) { | 381 | if (sd->s_type & CONFIGFS_USET_DEFAULT) { |
| 355 | mutex_lock(&sd->s_dentry->d_inode->i_mutex); | 382 | /* Abort if racing with mkdir() */ |
| 356 | /* Mark that we've taken i_mutex */ | 383 | if (sd->s_type & CONFIGFS_USET_IN_MKDIR) { |
| 384 | if (wait_mutex) | ||
| 385 | *wait_mutex = &sd->s_dentry->d_inode->i_mutex; | ||
| 386 | return -EAGAIN; | ||
| 387 | } | ||
| 388 | /* Mark that we're trying to drop the group */ | ||
| 357 | sd->s_type |= CONFIGFS_USET_DROPPING; | 389 | sd->s_type |= CONFIGFS_USET_DROPPING; |
| 358 | 390 | ||
| 359 | /* | 391 | /* |
| 360 | * Yup, recursive. If there's a problem, blame | 392 | * Yup, recursive. If there's a problem, blame |
| 361 | * deep nesting of default_groups | 393 | * deep nesting of default_groups |
| 362 | */ | 394 | */ |
| 363 | ret = configfs_detach_prep(sd->s_dentry); | 395 | ret = configfs_detach_prep(sd->s_dentry, wait_mutex); |
| 364 | if (!ret) | 396 | if (!ret) |
| 365 | continue; | 397 | continue; |
| 366 | } else | 398 | } else |
| @@ -374,7 +406,7 @@ out: | |||
| 374 | } | 406 | } |
| 375 | 407 | ||
| 376 | /* | 408 | /* |
| 377 | * Walk the tree, dropping i_mutex wherever CONFIGFS_USET_DROPPING is | 409 | * Walk the tree, resetting CONFIGFS_USET_DROPPING wherever it was |
| 378 | * set. | 410 | * set. |
| 379 | */ | 411 | */ |
| 380 | static void configfs_detach_rollback(struct dentry *dentry) | 412 | static void configfs_detach_rollback(struct dentry *dentry) |
| @@ -385,11 +417,7 @@ static void configfs_detach_rollback(struct dentry *dentry) | |||
| 385 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | 417 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { |
| 386 | if (sd->s_type & CONFIGFS_USET_DEFAULT) { | 418 | if (sd->s_type & CONFIGFS_USET_DEFAULT) { |
| 387 | configfs_detach_rollback(sd->s_dentry); | 419 | configfs_detach_rollback(sd->s_dentry); |
| 388 | 420 | sd->s_type &= ~CONFIGFS_USET_DROPPING; | |
| 389 | if (sd->s_type & CONFIGFS_USET_DROPPING) { | ||
| 390 | sd->s_type &= ~CONFIGFS_USET_DROPPING; | ||
| 391 | mutex_unlock(&sd->s_dentry->d_inode->i_mutex); | ||
| 392 | } | ||
| 393 | } | 421 | } |
| 394 | } | 422 | } |
| 395 | } | 423 | } |
| @@ -410,7 +438,9 @@ static void detach_attrs(struct config_item * item) | |||
| 410 | list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { | 438 | list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { |
| 411 | if (!sd->s_element || !(sd->s_type & CONFIGFS_NOT_PINNED)) | 439 | if (!sd->s_element || !(sd->s_type & CONFIGFS_NOT_PINNED)) |
| 412 | continue; | 440 | continue; |
| 441 | spin_lock(&configfs_dirent_lock); | ||
| 413 | list_del_init(&sd->s_sibling); | 442 | list_del_init(&sd->s_sibling); |
| 443 | spin_unlock(&configfs_dirent_lock); | ||
| 414 | configfs_drop_dentry(sd, dentry); | 444 | configfs_drop_dentry(sd, dentry); |
| 415 | configfs_put(sd); | 445 | configfs_put(sd); |
| 416 | } | 446 | } |
| @@ -466,16 +496,12 @@ static void detach_groups(struct config_group *group) | |||
| 466 | 496 | ||
| 467 | child = sd->s_dentry; | 497 | child = sd->s_dentry; |
| 468 | 498 | ||
| 499 | mutex_lock(&child->d_inode->i_mutex); | ||
| 500 | |||
| 469 | configfs_detach_group(sd->s_element); | 501 | configfs_detach_group(sd->s_element); |
| 470 | child->d_inode->i_flags |= S_DEAD; | 502 | child->d_inode->i_flags |= S_DEAD; |
| 471 | 503 | ||
| 472 | /* | 504 | mutex_unlock(&child->d_inode->i_mutex); |
| 473 | * From rmdir/unregister, a configfs_detach_prep() pass | ||
| 474 | * has taken our i_mutex for us. Drop it. | ||
| 475 | * From mkdir/register cleanup, there is no sem held. | ||
| 476 | */ | ||
| 477 | if (sd->s_type & CONFIGFS_USET_DROPPING) | ||
| 478 | mutex_unlock(&child->d_inode->i_mutex); | ||
| 479 | 505 | ||
| 480 | d_delete(child); | 506 | d_delete(child); |
| 481 | dput(child); | 507 | dput(child); |
| @@ -1047,25 +1073,24 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 1047 | group = NULL; | 1073 | group = NULL; |
| 1048 | item = NULL; | 1074 | item = NULL; |
| 1049 | if (type->ct_group_ops->make_group) { | 1075 | if (type->ct_group_ops->make_group) { |
| 1050 | group = type->ct_group_ops->make_group(to_config_group(parent_item), name); | 1076 | ret = type->ct_group_ops->make_group(to_config_group(parent_item), name, &group); |
| 1051 | if (group) { | 1077 | if (!ret) { |
| 1052 | link_group(to_config_group(parent_item), group); | 1078 | link_group(to_config_group(parent_item), group); |
| 1053 | item = &group->cg_item; | 1079 | item = &group->cg_item; |
| 1054 | } | 1080 | } |
| 1055 | } else { | 1081 | } else { |
| 1056 | item = type->ct_group_ops->make_item(to_config_group(parent_item), name); | 1082 | ret = type->ct_group_ops->make_item(to_config_group(parent_item), name, &item); |
| 1057 | if (item) | 1083 | if (!ret) |
| 1058 | link_obj(parent_item, item); | 1084 | link_obj(parent_item, item); |
| 1059 | } | 1085 | } |
| 1060 | mutex_unlock(&subsys->su_mutex); | 1086 | mutex_unlock(&subsys->su_mutex); |
| 1061 | 1087 | ||
| 1062 | kfree(name); | 1088 | kfree(name); |
| 1063 | if (!item) { | 1089 | if (ret) { |
| 1064 | /* | 1090 | /* |
| 1065 | * If item == NULL, then link_obj() was never called. | 1091 | * If ret != 0, then link_obj() was never called. |
| 1066 | * There are no extra references to clean up. | 1092 | * There are no extra references to clean up. |
| 1067 | */ | 1093 | */ |
| 1068 | ret = -ENOMEM; | ||
| 1069 | goto out_put; | 1094 | goto out_put; |
| 1070 | } | 1095 | } |
| 1071 | 1096 | ||
| @@ -1093,11 +1118,26 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 1093 | */ | 1118 | */ |
| 1094 | module_got = 1; | 1119 | module_got = 1; |
| 1095 | 1120 | ||
| 1121 | /* | ||
| 1122 | * Make racing rmdir() fail if it did not tag parent with | ||
| 1123 | * CONFIGFS_USET_DROPPING | ||
| 1124 | * Note: if CONFIGFS_USET_DROPPING is already set, attach_group() will | ||
| 1125 | * fail and let rmdir() terminate correctly | ||
| 1126 | */ | ||
| 1127 | spin_lock(&configfs_dirent_lock); | ||
| 1128 | /* This will make configfs_detach_prep() fail */ | ||
| 1129 | sd->s_type |= CONFIGFS_USET_IN_MKDIR; | ||
| 1130 | spin_unlock(&configfs_dirent_lock); | ||
| 1131 | |||
| 1096 | if (group) | 1132 | if (group) |
| 1097 | ret = configfs_attach_group(parent_item, item, dentry); | 1133 | ret = configfs_attach_group(parent_item, item, dentry); |
| 1098 | else | 1134 | else |
| 1099 | ret = configfs_attach_item(parent_item, item, dentry); | 1135 | ret = configfs_attach_item(parent_item, item, dentry); |
| 1100 | 1136 | ||
| 1137 | spin_lock(&configfs_dirent_lock); | ||
| 1138 | sd->s_type &= ~CONFIGFS_USET_IN_MKDIR; | ||
| 1139 | spin_unlock(&configfs_dirent_lock); | ||
| 1140 | |||
| 1101 | out_unlink: | 1141 | out_unlink: |
| 1102 | if (ret) { | 1142 | if (ret) { |
| 1103 | /* Tear down everything we built up */ | 1143 | /* Tear down everything we built up */ |
| @@ -1161,12 +1201,27 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 1161 | return -EINVAL; | 1201 | return -EINVAL; |
| 1162 | } | 1202 | } |
| 1163 | 1203 | ||
| 1164 | ret = configfs_detach_prep(dentry); | 1204 | spin_lock(&configfs_dirent_lock); |
| 1165 | if (ret) { | 1205 | do { |
| 1166 | configfs_detach_rollback(dentry); | 1206 | struct mutex *wait_mutex; |
| 1167 | config_item_put(parent_item); | 1207 | |
| 1168 | return ret; | 1208 | ret = configfs_detach_prep(dentry, &wait_mutex); |
| 1169 | } | 1209 | if (ret) { |
| 1210 | configfs_detach_rollback(dentry); | ||
| 1211 | spin_unlock(&configfs_dirent_lock); | ||
| 1212 | if (ret != -EAGAIN) { | ||
| 1213 | config_item_put(parent_item); | ||
| 1214 | return ret; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | /* Wait until the racing operation terminates */ | ||
| 1218 | mutex_lock(wait_mutex); | ||
| 1219 | mutex_unlock(wait_mutex); | ||
| 1220 | |||
| 1221 | spin_lock(&configfs_dirent_lock); | ||
| 1222 | } | ||
| 1223 | } while (ret == -EAGAIN); | ||
| 1224 | spin_unlock(&configfs_dirent_lock); | ||
| 1170 | 1225 | ||
| 1171 | /* Get a working ref for the duration of this function */ | 1226 | /* Get a working ref for the duration of this function */ |
| 1172 | item = configfs_get_config_item(dentry); | 1227 | item = configfs_get_config_item(dentry); |
| @@ -1258,7 +1313,7 @@ static int configfs_dir_open(struct inode *inode, struct file *file) | |||
| 1258 | file->private_data = configfs_new_dirent(parent_sd, NULL); | 1313 | file->private_data = configfs_new_dirent(parent_sd, NULL); |
| 1259 | mutex_unlock(&dentry->d_inode->i_mutex); | 1314 | mutex_unlock(&dentry->d_inode->i_mutex); |
| 1260 | 1315 | ||
| 1261 | return file->private_data ? 0 : -ENOMEM; | 1316 | return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0; |
| 1262 | 1317 | ||
| 1263 | } | 1318 | } |
| 1264 | 1319 | ||
| @@ -1268,7 +1323,9 @@ static int configfs_dir_close(struct inode *inode, struct file *file) | |||
| 1268 | struct configfs_dirent * cursor = file->private_data; | 1323 | struct configfs_dirent * cursor = file->private_data; |
| 1269 | 1324 | ||
| 1270 | mutex_lock(&dentry->d_inode->i_mutex); | 1325 | mutex_lock(&dentry->d_inode->i_mutex); |
| 1326 | spin_lock(&configfs_dirent_lock); | ||
| 1271 | list_del_init(&cursor->s_sibling); | 1327 | list_del_init(&cursor->s_sibling); |
| 1328 | spin_unlock(&configfs_dirent_lock); | ||
| 1272 | mutex_unlock(&dentry->d_inode->i_mutex); | 1329 | mutex_unlock(&dentry->d_inode->i_mutex); |
| 1273 | 1330 | ||
| 1274 | release_configfs_dirent(cursor); | 1331 | release_configfs_dirent(cursor); |
| @@ -1308,7 +1365,9 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
| 1308 | /* fallthrough */ | 1365 | /* fallthrough */ |
| 1309 | default: | 1366 | default: |
| 1310 | if (filp->f_pos == 2) { | 1367 | if (filp->f_pos == 2) { |
| 1368 | spin_lock(&configfs_dirent_lock); | ||
| 1311 | list_move(q, &parent_sd->s_children); | 1369 | list_move(q, &parent_sd->s_children); |
| 1370 | spin_unlock(&configfs_dirent_lock); | ||
| 1312 | } | 1371 | } |
| 1313 | for (p=q->next; p!= &parent_sd->s_children; p=p->next) { | 1372 | for (p=q->next; p!= &parent_sd->s_children; p=p->next) { |
| 1314 | struct configfs_dirent *next; | 1373 | struct configfs_dirent *next; |
| @@ -1331,7 +1390,9 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
| 1331 | dt_type(next)) < 0) | 1390 | dt_type(next)) < 0) |
| 1332 | return 0; | 1391 | return 0; |
| 1333 | 1392 | ||
| 1393 | spin_lock(&configfs_dirent_lock); | ||
| 1334 | list_move(q, p); | 1394 | list_move(q, p); |
| 1395 | spin_unlock(&configfs_dirent_lock); | ||
| 1335 | p = q; | 1396 | p = q; |
| 1336 | filp->f_pos++; | 1397 | filp->f_pos++; |
| 1337 | } | 1398 | } |
| @@ -1362,6 +1423,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
| 1362 | struct list_head *p; | 1423 | struct list_head *p; |
| 1363 | loff_t n = file->f_pos - 2; | 1424 | loff_t n = file->f_pos - 2; |
| 1364 | 1425 | ||
| 1426 | spin_lock(&configfs_dirent_lock); | ||
| 1365 | list_del(&cursor->s_sibling); | 1427 | list_del(&cursor->s_sibling); |
| 1366 | p = sd->s_children.next; | 1428 | p = sd->s_children.next; |
| 1367 | while (n && p != &sd->s_children) { | 1429 | while (n && p != &sd->s_children) { |
| @@ -1373,6 +1435,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
| 1373 | p = p->next; | 1435 | p = p->next; |
| 1374 | } | 1436 | } |
| 1375 | list_add_tail(&cursor->s_sibling, p); | 1437 | list_add_tail(&cursor->s_sibling, p); |
| 1438 | spin_unlock(&configfs_dirent_lock); | ||
| 1376 | } | 1439 | } |
| 1377 | } | 1440 | } |
| 1378 | mutex_unlock(&dentry->d_inode->i_mutex); | 1441 | mutex_unlock(&dentry->d_inode->i_mutex); |
| @@ -1448,9 +1511,11 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys) | |||
| 1448 | mutex_lock_nested(&configfs_sb->s_root->d_inode->i_mutex, | 1511 | mutex_lock_nested(&configfs_sb->s_root->d_inode->i_mutex, |
| 1449 | I_MUTEX_PARENT); | 1512 | I_MUTEX_PARENT); |
| 1450 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); | 1513 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); |
| 1451 | if (configfs_detach_prep(dentry)) { | 1514 | spin_lock(&configfs_dirent_lock); |
| 1515 | if (configfs_detach_prep(dentry, NULL)) { | ||
| 1452 | printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n"); | 1516 | printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n"); |
| 1453 | } | 1517 | } |
| 1518 | spin_unlock(&configfs_dirent_lock); | ||
| 1454 | configfs_detach_group(&group->cg_item); | 1519 | configfs_detach_group(&group->cg_item); |
| 1455 | dentry->d_inode->i_flags |= S_DEAD; | 1520 | dentry->d_inode->i_flags |= S_DEAD; |
| 1456 | mutex_unlock(&dentry->d_inode->i_mutex); | 1521 | mutex_unlock(&dentry->d_inode->i_mutex); |
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index b9a1d810346d..4803ccc94480 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c | |||
| @@ -247,7 +247,9 @@ void configfs_hash_and_remove(struct dentry * dir, const char * name) | |||
| 247 | if (!sd->s_element) | 247 | if (!sd->s_element) |
| 248 | continue; | 248 | continue; |
| 249 | if (!strcmp(configfs_get_name(sd), name)) { | 249 | if (!strcmp(configfs_get_name(sd), name)) { |
| 250 | spin_lock(&configfs_dirent_lock); | ||
| 250 | list_del_init(&sd->s_sibling); | 251 | list_del_init(&sd->s_sibling); |
| 252 | spin_unlock(&configfs_dirent_lock); | ||
| 251 | configfs_drop_dentry(sd, dir); | 253 | configfs_drop_dentry(sd, dir); |
| 252 | configfs_put(sd); | 254 | configfs_put(sd); |
| 253 | break; | 255 | break; |
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 2a731ef5f305..0004d18c40ac 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c | |||
| @@ -77,12 +77,15 @@ static int create_link(struct config_item *parent_item, | |||
| 77 | sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); | 77 | sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); |
| 78 | if (sl) { | 78 | if (sl) { |
| 79 | sl->sl_target = config_item_get(item); | 79 | sl->sl_target = config_item_get(item); |
| 80 | /* FIXME: needs a lock, I'd bet */ | 80 | spin_lock(&configfs_dirent_lock); |
| 81 | list_add(&sl->sl_list, &target_sd->s_links); | 81 | list_add(&sl->sl_list, &target_sd->s_links); |
| 82 | spin_unlock(&configfs_dirent_lock); | ||
| 82 | ret = configfs_create_link(sl, parent_item->ci_dentry, | 83 | ret = configfs_create_link(sl, parent_item->ci_dentry, |
| 83 | dentry); | 84 | dentry); |
| 84 | if (ret) { | 85 | if (ret) { |
| 86 | spin_lock(&configfs_dirent_lock); | ||
| 85 | list_del_init(&sl->sl_list); | 87 | list_del_init(&sl->sl_list); |
| 88 | spin_unlock(&configfs_dirent_lock); | ||
| 86 | config_item_put(item); | 89 | config_item_put(item); |
| 87 | kfree(sl); | 90 | kfree(sl); |
| 88 | } | 91 | } |
| @@ -137,8 +140,12 @@ int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna | |||
| 137 | goto out_put; | 140 | goto out_put; |
| 138 | 141 | ||
| 139 | ret = type->ct_item_ops->allow_link(parent_item, target_item); | 142 | ret = type->ct_item_ops->allow_link(parent_item, target_item); |
| 140 | if (!ret) | 143 | if (!ret) { |
| 141 | ret = create_link(parent_item, target_item, dentry); | 144 | ret = create_link(parent_item, target_item, dentry); |
| 145 | if (ret && type->ct_item_ops->drop_link) | ||
| 146 | type->ct_item_ops->drop_link(parent_item, | ||
| 147 | target_item); | ||
| 148 | } | ||
| 142 | 149 | ||
| 143 | config_item_put(target_item); | 150 | config_item_put(target_item); |
| 144 | path_put(&nd.path); | 151 | path_put(&nd.path); |
| @@ -169,7 +176,9 @@ int configfs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 169 | parent_item = configfs_get_config_item(dentry->d_parent); | 176 | parent_item = configfs_get_config_item(dentry->d_parent); |
| 170 | type = parent_item->ci_type; | 177 | type = parent_item->ci_type; |
| 171 | 178 | ||
| 179 | spin_lock(&configfs_dirent_lock); | ||
| 172 | list_del_init(&sd->s_sibling); | 180 | list_del_init(&sd->s_sibling); |
| 181 | spin_unlock(&configfs_dirent_lock); | ||
| 173 | configfs_drop_dentry(sd, dentry->d_parent); | 182 | configfs_drop_dentry(sd, dentry->d_parent); |
| 174 | dput(dentry); | 183 | dput(dentry); |
| 175 | configfs_put(sd); | 184 | configfs_put(sd); |
| @@ -184,8 +193,9 @@ int configfs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 184 | type->ct_item_ops->drop_link(parent_item, | 193 | type->ct_item_ops->drop_link(parent_item, |
| 185 | sl->sl_target); | 194 | sl->sl_target); |
| 186 | 195 | ||
| 187 | /* FIXME: Needs lock */ | 196 | spin_lock(&configfs_dirent_lock); |
| 188 | list_del_init(&sl->sl_list); | 197 | list_del_init(&sl->sl_list); |
| 198 | spin_unlock(&configfs_dirent_lock); | ||
| 189 | 199 | ||
| 190 | /* Put reference from create_link() */ | 200 | /* Put reference from create_link() */ |
| 191 | config_item_put(sl->sl_target); | 201 | config_item_put(sl->sl_target); |
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index eac23bd288b2..492d8caaaf25 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c | |||
| @@ -41,16 +41,20 @@ struct comm; | |||
| 41 | struct nodes; | 41 | struct nodes; |
| 42 | struct node; | 42 | struct node; |
| 43 | 43 | ||
| 44 | static struct config_group *make_cluster(struct config_group *, const char *); | 44 | static int make_cluster(struct config_group *, const char *, |
| 45 | struct config_group **); | ||
| 45 | static void drop_cluster(struct config_group *, struct config_item *); | 46 | static void drop_cluster(struct config_group *, struct config_item *); |
| 46 | static void release_cluster(struct config_item *); | 47 | static void release_cluster(struct config_item *); |
| 47 | static struct config_group *make_space(struct config_group *, const char *); | 48 | static int make_space(struct config_group *, const char *, |
| 49 | struct config_group **); | ||
| 48 | static void drop_space(struct config_group *, struct config_item *); | 50 | static void drop_space(struct config_group *, struct config_item *); |
| 49 | static void release_space(struct config_item *); | 51 | static void release_space(struct config_item *); |
| 50 | static struct config_item *make_comm(struct config_group *, const char *); | 52 | static int make_comm(struct config_group *, const char *, |
| 53 | struct config_item **); | ||
| 51 | static void drop_comm(struct config_group *, struct config_item *); | 54 | static void drop_comm(struct config_group *, struct config_item *); |
| 52 | static void release_comm(struct config_item *); | 55 | static void release_comm(struct config_item *); |
| 53 | static struct config_item *make_node(struct config_group *, const char *); | 56 | static int make_node(struct config_group *, const char *, |
| 57 | struct config_item **); | ||
| 54 | static void drop_node(struct config_group *, struct config_item *); | 58 | static void drop_node(struct config_group *, struct config_item *); |
| 55 | static void release_node(struct config_item *); | 59 | static void release_node(struct config_item *); |
| 56 | 60 | ||
| @@ -392,8 +396,8 @@ static struct node *to_node(struct config_item *i) | |||
| 392 | return i ? container_of(i, struct node, item) : NULL; | 396 | return i ? container_of(i, struct node, item) : NULL; |
| 393 | } | 397 | } |
| 394 | 398 | ||
| 395 | static struct config_group *make_cluster(struct config_group *g, | 399 | static int make_cluster(struct config_group *g, const char *name, |
| 396 | const char *name) | 400 | struct config_group **new_g) |
| 397 | { | 401 | { |
| 398 | struct cluster *cl = NULL; | 402 | struct cluster *cl = NULL; |
| 399 | struct spaces *sps = NULL; | 403 | struct spaces *sps = NULL; |
| @@ -431,14 +435,15 @@ static struct config_group *make_cluster(struct config_group *g, | |||
| 431 | 435 | ||
| 432 | space_list = &sps->ss_group; | 436 | space_list = &sps->ss_group; |
| 433 | comm_list = &cms->cs_group; | 437 | comm_list = &cms->cs_group; |
| 434 | return &cl->group; | 438 | *new_g = &cl->group; |
| 439 | return 0; | ||
| 435 | 440 | ||
| 436 | fail: | 441 | fail: |
| 437 | kfree(cl); | 442 | kfree(cl); |
| 438 | kfree(gps); | 443 | kfree(gps); |
| 439 | kfree(sps); | 444 | kfree(sps); |
| 440 | kfree(cms); | 445 | kfree(cms); |
| 441 | return NULL; | 446 | return -ENOMEM; |
| 442 | } | 447 | } |
| 443 | 448 | ||
| 444 | static void drop_cluster(struct config_group *g, struct config_item *i) | 449 | static void drop_cluster(struct config_group *g, struct config_item *i) |
| @@ -466,7 +471,8 @@ static void release_cluster(struct config_item *i) | |||
| 466 | kfree(cl); | 471 | kfree(cl); |
| 467 | } | 472 | } |
| 468 | 473 | ||
| 469 | static struct config_group *make_space(struct config_group *g, const char *name) | 474 | static int make_space(struct config_group *g, const char *name, |
| 475 | struct config_group **new_g) | ||
| 470 | { | 476 | { |
| 471 | struct space *sp = NULL; | 477 | struct space *sp = NULL; |
| 472 | struct nodes *nds = NULL; | 478 | struct nodes *nds = NULL; |
| @@ -489,13 +495,14 @@ static struct config_group *make_space(struct config_group *g, const char *name) | |||
| 489 | INIT_LIST_HEAD(&sp->members); | 495 | INIT_LIST_HEAD(&sp->members); |
| 490 | mutex_init(&sp->members_lock); | 496 | mutex_init(&sp->members_lock); |
| 491 | sp->members_count = 0; | 497 | sp->members_count = 0; |
| 492 | return &sp->group; | 498 | *new_g = &sp->group; |
| 499 | return 0; | ||
| 493 | 500 | ||
| 494 | fail: | 501 | fail: |
| 495 | kfree(sp); | 502 | kfree(sp); |
| 496 | kfree(gps); | 503 | kfree(gps); |
| 497 | kfree(nds); | 504 | kfree(nds); |
| 498 | return NULL; | 505 | return -ENOMEM; |
| 499 | } | 506 | } |
| 500 | 507 | ||
| 501 | static void drop_space(struct config_group *g, struct config_item *i) | 508 | static void drop_space(struct config_group *g, struct config_item *i) |
| @@ -522,19 +529,21 @@ static void release_space(struct config_item *i) | |||
| 522 | kfree(sp); | 529 | kfree(sp); |
| 523 | } | 530 | } |
| 524 | 531 | ||
| 525 | static struct config_item *make_comm(struct config_group *g, const char *name) | 532 | static int make_comm(struct config_group *g, const char *name, |
| 533 | struct config_item **new_i) | ||
| 526 | { | 534 | { |
| 527 | struct comm *cm; | 535 | struct comm *cm; |
| 528 | 536 | ||
| 529 | cm = kzalloc(sizeof(struct comm), GFP_KERNEL); | 537 | cm = kzalloc(sizeof(struct comm), GFP_KERNEL); |
| 530 | if (!cm) | 538 | if (!cm) |
| 531 | return NULL; | 539 | return -ENOMEM; |
| 532 | 540 | ||
| 533 | config_item_init_type_name(&cm->item, name, &comm_type); | 541 | config_item_init_type_name(&cm->item, name, &comm_type); |
| 534 | cm->nodeid = -1; | 542 | cm->nodeid = -1; |
| 535 | cm->local = 0; | 543 | cm->local = 0; |
| 536 | cm->addr_count = 0; | 544 | cm->addr_count = 0; |
| 537 | return &cm->item; | 545 | *new_i = &cm->item; |
| 546 | return 0; | ||
| 538 | } | 547 | } |
| 539 | 548 | ||
| 540 | static void drop_comm(struct config_group *g, struct config_item *i) | 549 | static void drop_comm(struct config_group *g, struct config_item *i) |
| @@ -554,14 +563,15 @@ static void release_comm(struct config_item *i) | |||
| 554 | kfree(cm); | 563 | kfree(cm); |
| 555 | } | 564 | } |
| 556 | 565 | ||
| 557 | static struct config_item *make_node(struct config_group *g, const char *name) | 566 | static int make_node(struct config_group *g, const char *name, |
| 567 | struct config_item **new_i) | ||
| 558 | { | 568 | { |
| 559 | struct space *sp = to_space(g->cg_item.ci_parent); | 569 | struct space *sp = to_space(g->cg_item.ci_parent); |
| 560 | struct node *nd; | 570 | struct node *nd; |
| 561 | 571 | ||
| 562 | nd = kzalloc(sizeof(struct node), GFP_KERNEL); | 572 | nd = kzalloc(sizeof(struct node), GFP_KERNEL); |
| 563 | if (!nd) | 573 | if (!nd) |
| 564 | return NULL; | 574 | return -ENOMEM; |
| 565 | 575 | ||
| 566 | config_item_init_type_name(&nd->item, name, &node_type); | 576 | config_item_init_type_name(&nd->item, name, &node_type); |
| 567 | nd->nodeid = -1; | 577 | nd->nodeid = -1; |
| @@ -573,7 +583,8 @@ static struct config_item *make_node(struct config_group *g, const char *name) | |||
| 573 | sp->members_count++; | 583 | sp->members_count++; |
| 574 | mutex_unlock(&sp->members_lock); | 584 | mutex_unlock(&sp->members_lock); |
| 575 | 585 | ||
| 576 | return &nd->item; | 586 | *new_i = &nd->item; |
| 587 | return 0; | ||
| 577 | } | 588 | } |
| 578 | 589 | ||
| 579 | static void drop_node(struct config_group *g, struct config_item *i) | 590 | static void drop_node(struct config_group *g, struct config_item *i) |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 17964c0505a9..1db080135c6d 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -174,10 +174,17 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock, | |||
| 174 | * need to use BH_New is when we're extending i_size on a file | 174 | * need to use BH_New is when we're extending i_size on a file |
| 175 | * system which doesn't support holes, in which case BH_New | 175 | * system which doesn't support holes, in which case BH_New |
| 176 | * allows block_prepare_write() to zero. | 176 | * allows block_prepare_write() to zero. |
| 177 | * | ||
| 178 | * If we see this on a sparse file system, then a truncate has | ||
| 179 | * raced us and removed the cluster. In this case, we clear | ||
| 180 | * the buffers dirty and uptodate bits and let the buffer code | ||
| 181 | * ignore it as a hole. | ||
| 177 | */ | 182 | */ |
| 178 | mlog_bug_on_msg(create && p_blkno == 0 && ocfs2_sparse_alloc(osb), | 183 | if (create && p_blkno == 0 && ocfs2_sparse_alloc(osb)) { |
| 179 | "ino %lu, iblock %llu\n", inode->i_ino, | 184 | clear_buffer_dirty(bh_result); |
| 180 | (unsigned long long)iblock); | 185 | clear_buffer_uptodate(bh_result); |
| 186 | goto bail; | ||
| 187 | } | ||
| 181 | 188 | ||
| 182 | /* Treat the unwritten extent as a hole for zeroing purposes. */ | 189 | /* Treat the unwritten extent as a hole for zeroing purposes. */ |
| 183 | if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN)) | 190 | if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN)) |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index f02ccb34604d..443d108211ab 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
| @@ -1489,25 +1489,28 @@ static struct o2hb_heartbeat_group *to_o2hb_heartbeat_group(struct config_group | |||
| 1489 | : NULL; | 1489 | : NULL; |
| 1490 | } | 1490 | } |
| 1491 | 1491 | ||
| 1492 | static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *group, | 1492 | static int o2hb_heartbeat_group_make_item(struct config_group *group, |
| 1493 | const char *name) | 1493 | const char *name, |
| 1494 | struct config_item **new_item) | ||
| 1494 | { | 1495 | { |
| 1495 | struct o2hb_region *reg = NULL; | 1496 | struct o2hb_region *reg = NULL; |
| 1496 | struct config_item *ret = NULL; | 1497 | int ret = 0; |
| 1497 | 1498 | ||
| 1498 | reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL); | 1499 | reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL); |
| 1499 | if (reg == NULL) | 1500 | if (reg == NULL) { |
| 1500 | goto out; /* ENOMEM */ | 1501 | ret = -ENOMEM; |
| 1502 | goto out; | ||
| 1503 | } | ||
| 1501 | 1504 | ||
| 1502 | config_item_init_type_name(®->hr_item, name, &o2hb_region_type); | 1505 | config_item_init_type_name(®->hr_item, name, &o2hb_region_type); |
| 1503 | 1506 | ||
| 1504 | ret = ®->hr_item; | 1507 | *new_item = ®->hr_item; |
| 1505 | 1508 | ||
| 1506 | spin_lock(&o2hb_live_lock); | 1509 | spin_lock(&o2hb_live_lock); |
| 1507 | list_add_tail(®->hr_all_item, &o2hb_all_regions); | 1510 | list_add_tail(®->hr_all_item, &o2hb_all_regions); |
| 1508 | spin_unlock(&o2hb_live_lock); | 1511 | spin_unlock(&o2hb_live_lock); |
| 1509 | out: | 1512 | out: |
| 1510 | if (ret == NULL) | 1513 | if (ret) |
| 1511 | kfree(reg); | 1514 | kfree(reg); |
| 1512 | 1515 | ||
| 1513 | return ret; | 1516 | return ret; |
diff --git a/fs/ocfs2/cluster/netdebug.c b/fs/ocfs2/cluster/netdebug.c index 7bf3c0ea7bd9..d8bfa0eb41b2 100644 --- a/fs/ocfs2/cluster/netdebug.c +++ b/fs/ocfs2/cluster/netdebug.c | |||
| @@ -146,8 +146,10 @@ static int nst_seq_show(struct seq_file *seq, void *v) | |||
| 146 | nst->st_task->comm, nst->st_node, | 146 | nst->st_task->comm, nst->st_node, |
| 147 | nst->st_sc, nst->st_id, nst->st_msg_type, | 147 | nst->st_sc, nst->st_id, nst->st_msg_type, |
| 148 | nst->st_msg_key, | 148 | nst->st_msg_key, |
| 149 | nst->st_sock_time.tv_sec, nst->st_sock_time.tv_usec, | 149 | nst->st_sock_time.tv_sec, |
| 150 | nst->st_send_time.tv_sec, nst->st_send_time.tv_usec, | 150 | (unsigned long)nst->st_sock_time.tv_usec, |
| 151 | nst->st_send_time.tv_sec, | ||
| 152 | (unsigned long)nst->st_send_time.tv_usec, | ||
| 151 | nst->st_status_time.tv_sec, | 153 | nst->st_status_time.tv_sec, |
| 152 | nst->st_status_time.tv_usec); | 154 | nst->st_status_time.tv_usec); |
| 153 | } | 155 | } |
| @@ -274,7 +276,7 @@ static void *sc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
| 274 | return sc; /* unused, just needs to be null when done */ | 276 | return sc; /* unused, just needs to be null when done */ |
| 275 | } | 277 | } |
| 276 | 278 | ||
| 277 | #define TV_SEC_USEC(TV) TV.tv_sec, TV.tv_usec | 279 | #define TV_SEC_USEC(TV) TV.tv_sec, (unsigned long)TV.tv_usec |
| 278 | 280 | ||
| 279 | static int sc_seq_show(struct seq_file *seq, void *v) | 281 | static int sc_seq_show(struct seq_file *seq, void *v) |
| 280 | { | 282 | { |
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c index cfdb08b484ed..b364b7052e46 100644 --- a/fs/ocfs2/cluster/nodemanager.c +++ b/fs/ocfs2/cluster/nodemanager.c | |||
| @@ -644,27 +644,32 @@ out: | |||
| 644 | return ret; | 644 | return ret; |
| 645 | } | 645 | } |
| 646 | 646 | ||
| 647 | static struct config_item *o2nm_node_group_make_item(struct config_group *group, | 647 | static int o2nm_node_group_make_item(struct config_group *group, |
| 648 | const char *name) | 648 | const char *name, |
| 649 | struct config_item **new_item) | ||
| 649 | { | 650 | { |
| 650 | struct o2nm_node *node = NULL; | 651 | struct o2nm_node *node = NULL; |
| 651 | struct config_item *ret = NULL; | 652 | int ret = 0; |
| 652 | 653 | ||
| 653 | if (strlen(name) > O2NM_MAX_NAME_LEN) | 654 | if (strlen(name) > O2NM_MAX_NAME_LEN) { |
| 654 | goto out; /* ENAMETOOLONG */ | 655 | ret = -ENAMETOOLONG; |
| 656 | goto out; | ||
| 657 | } | ||
| 655 | 658 | ||
| 656 | node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL); | 659 | node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL); |
| 657 | if (node == NULL) | 660 | if (node == NULL) { |
| 658 | goto out; /* ENOMEM */ | 661 | ret = -ENOMEM; |
| 662 | goto out; | ||
| 663 | } | ||
| 659 | 664 | ||
| 660 | strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */ | 665 | strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */ |
| 661 | config_item_init_type_name(&node->nd_item, name, &o2nm_node_type); | 666 | config_item_init_type_name(&node->nd_item, name, &o2nm_node_type); |
| 662 | spin_lock_init(&node->nd_lock); | 667 | spin_lock_init(&node->nd_lock); |
| 663 | 668 | ||
| 664 | ret = &node->nd_item; | 669 | *new_item = &node->nd_item; |
| 665 | 670 | ||
| 666 | out: | 671 | out: |
| 667 | if (ret == NULL) | 672 | if (ret) |
| 668 | kfree(node); | 673 | kfree(node); |
| 669 | 674 | ||
| 670 | return ret; | 675 | return ret; |
| @@ -751,25 +756,31 @@ static struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *gro | |||
| 751 | } | 756 | } |
| 752 | #endif | 757 | #endif |
| 753 | 758 | ||
| 754 | static struct config_group *o2nm_cluster_group_make_group(struct config_group *group, | 759 | static int o2nm_cluster_group_make_group(struct config_group *group, |
| 755 | const char *name) | 760 | const char *name, |
| 761 | struct config_group **new_group) | ||
| 756 | { | 762 | { |
| 757 | struct o2nm_cluster *cluster = NULL; | 763 | struct o2nm_cluster *cluster = NULL; |
| 758 | struct o2nm_node_group *ns = NULL; | 764 | struct o2nm_node_group *ns = NULL; |
| 759 | struct config_group *o2hb_group = NULL, *ret = NULL; | 765 | struct config_group *o2hb_group = NULL; |
| 760 | void *defs = NULL; | 766 | void *defs = NULL; |
| 767 | int ret = 0; | ||
| 761 | 768 | ||
| 762 | /* this runs under the parent dir's i_mutex; there can be only | 769 | /* this runs under the parent dir's i_mutex; there can be only |
| 763 | * one caller in here at a time */ | 770 | * one caller in here at a time */ |
| 764 | if (o2nm_single_cluster) | 771 | if (o2nm_single_cluster) { |
| 765 | goto out; /* ENOSPC */ | 772 | ret = -ENOSPC; |
| 773 | goto out; | ||
| 774 | } | ||
| 766 | 775 | ||
| 767 | cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL); | 776 | cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL); |
| 768 | ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL); | 777 | ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL); |
| 769 | defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); | 778 | defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); |
| 770 | o2hb_group = o2hb_alloc_hb_set(); | 779 | o2hb_group = o2hb_alloc_hb_set(); |
| 771 | if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL) | 780 | if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL) { |
| 781 | ret = -ENOMEM; | ||
| 772 | goto out; | 782 | goto out; |
| 783 | } | ||
| 773 | 784 | ||
| 774 | config_group_init_type_name(&cluster->cl_group, name, | 785 | config_group_init_type_name(&cluster->cl_group, name, |
| 775 | &o2nm_cluster_type); | 786 | &o2nm_cluster_type); |
| @@ -786,11 +797,11 @@ static struct config_group *o2nm_cluster_group_make_group(struct config_group *g | |||
| 786 | cluster->cl_idle_timeout_ms = O2NET_IDLE_TIMEOUT_MS_DEFAULT; | 797 | cluster->cl_idle_timeout_ms = O2NET_IDLE_TIMEOUT_MS_DEFAULT; |
| 787 | cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT; | 798 | cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT; |
| 788 | 799 | ||
| 789 | ret = &cluster->cl_group; | 800 | *new_group = &cluster->cl_group; |
| 790 | o2nm_single_cluster = cluster; | 801 | o2nm_single_cluster = cluster; |
| 791 | 802 | ||
| 792 | out: | 803 | out: |
| 793 | if (ret == NULL) { | 804 | if (ret) { |
| 794 | kfree(cluster); | 805 | kfree(cluster); |
| 795 | kfree(ns); | 806 | kfree(ns); |
| 796 | o2hb_free_hb_set(o2hb_group); | 807 | o2hb_free_hb_set(o2hb_group); |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 80e20d9f2780..eae3d643a5e4 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/pagemap.h> | 31 | #include <linux/pagemap.h> |
| 32 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
| 33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
| 34 | #include <linux/time.h> | ||
| 34 | 35 | ||
| 35 | #define MLOG_MASK_PREFIX ML_DLM_GLUE | 36 | #define MLOG_MASK_PREFIX ML_DLM_GLUE |
| 36 | #include <cluster/masklog.h> | 37 | #include <cluster/masklog.h> |
| @@ -59,6 +60,9 @@ struct ocfs2_mask_waiter { | |||
| 59 | struct completion mw_complete; | 60 | struct completion mw_complete; |
| 60 | unsigned long mw_mask; | 61 | unsigned long mw_mask; |
| 61 | unsigned long mw_goal; | 62 | unsigned long mw_goal; |
| 63 | #ifdef CONFIG_OCFS2_FS_STATS | ||
| 64 | unsigned long long mw_lock_start; | ||
| 65 | #endif | ||
| 62 | }; | 66 | }; |
| 63 | 67 | ||
| 64 | static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); | 68 | static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres); |
| @@ -366,6 +370,75 @@ static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res) | |||
| 366 | spin_unlock(&ocfs2_dlm_tracking_lock); | 370 | spin_unlock(&ocfs2_dlm_tracking_lock); |
| 367 | } | 371 | } |
| 368 | 372 | ||
| 373 | #ifdef CONFIG_OCFS2_FS_STATS | ||
| 374 | static void ocfs2_init_lock_stats(struct ocfs2_lock_res *res) | ||
| 375 | { | ||
| 376 | res->l_lock_num_prmode = 0; | ||
| 377 | res->l_lock_num_prmode_failed = 0; | ||
| 378 | res->l_lock_total_prmode = 0; | ||
| 379 | res->l_lock_max_prmode = 0; | ||
| 380 | res->l_lock_num_exmode = 0; | ||
| 381 | res->l_lock_num_exmode_failed = 0; | ||
| 382 | res->l_lock_total_exmode = 0; | ||
| 383 | res->l_lock_max_exmode = 0; | ||
| 384 | res->l_lock_refresh = 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | static void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, int level, | ||
| 388 | struct ocfs2_mask_waiter *mw, int ret) | ||
| 389 | { | ||
| 390 | unsigned long long *num, *sum; | ||
| 391 | unsigned int *max, *failed; | ||
| 392 | struct timespec ts = current_kernel_time(); | ||
| 393 | unsigned long long time = timespec_to_ns(&ts) - mw->mw_lock_start; | ||
| 394 | |||
| 395 | if (level == LKM_PRMODE) { | ||
| 396 | num = &res->l_lock_num_prmode; | ||
| 397 | sum = &res->l_lock_total_prmode; | ||
| 398 | max = &res->l_lock_max_prmode; | ||
| 399 | failed = &res->l_lock_num_prmode_failed; | ||
| 400 | } else if (level == LKM_EXMODE) { | ||
| 401 | num = &res->l_lock_num_exmode; | ||
| 402 | sum = &res->l_lock_total_exmode; | ||
| 403 | max = &res->l_lock_max_exmode; | ||
| 404 | failed = &res->l_lock_num_exmode_failed; | ||
| 405 | } else | ||
| 406 | return; | ||
| 407 | |||
| 408 | (*num)++; | ||
| 409 | (*sum) += time; | ||
| 410 | if (time > *max) | ||
| 411 | *max = time; | ||
| 412 | if (ret) | ||
| 413 | (*failed)++; | ||
| 414 | } | ||
| 415 | |||
| 416 | static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres) | ||
| 417 | { | ||
| 418 | lockres->l_lock_refresh++; | ||
| 419 | } | ||
| 420 | |||
| 421 | static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw) | ||
| 422 | { | ||
| 423 | struct timespec ts = current_kernel_time(); | ||
| 424 | mw->mw_lock_start = timespec_to_ns(&ts); | ||
| 425 | } | ||
| 426 | #else | ||
| 427 | static inline void ocfs2_init_lock_stats(struct ocfs2_lock_res *res) | ||
| 428 | { | ||
| 429 | } | ||
| 430 | static inline void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, | ||
| 431 | int level, struct ocfs2_mask_waiter *mw, int ret) | ||
| 432 | { | ||
| 433 | } | ||
| 434 | static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres) | ||
| 435 | { | ||
| 436 | } | ||
| 437 | static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw) | ||
| 438 | { | ||
| 439 | } | ||
| 440 | #endif | ||
| 441 | |||
| 369 | static void ocfs2_lock_res_init_common(struct ocfs2_super *osb, | 442 | static void ocfs2_lock_res_init_common(struct ocfs2_super *osb, |
| 370 | struct ocfs2_lock_res *res, | 443 | struct ocfs2_lock_res *res, |
| 371 | enum ocfs2_lock_type type, | 444 | enum ocfs2_lock_type type, |
| @@ -385,6 +458,8 @@ static void ocfs2_lock_res_init_common(struct ocfs2_super *osb, | |||
| 385 | res->l_flags = OCFS2_LOCK_INITIALIZED; | 458 | res->l_flags = OCFS2_LOCK_INITIALIZED; |
| 386 | 459 | ||
| 387 | ocfs2_add_lockres_tracking(res, osb->osb_dlm_debug); | 460 | ocfs2_add_lockres_tracking(res, osb->osb_dlm_debug); |
| 461 | |||
| 462 | ocfs2_init_lock_stats(res); | ||
| 388 | } | 463 | } |
| 389 | 464 | ||
| 390 | void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res) | 465 | void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res) |
| @@ -1048,6 +1123,7 @@ static void ocfs2_init_mask_waiter(struct ocfs2_mask_waiter *mw) | |||
| 1048 | { | 1123 | { |
| 1049 | INIT_LIST_HEAD(&mw->mw_item); | 1124 | INIT_LIST_HEAD(&mw->mw_item); |
| 1050 | init_completion(&mw->mw_complete); | 1125 | init_completion(&mw->mw_complete); |
| 1126 | ocfs2_init_start_time(mw); | ||
| 1051 | } | 1127 | } |
| 1052 | 1128 | ||
| 1053 | static int ocfs2_wait_for_mask(struct ocfs2_mask_waiter *mw) | 1129 | static int ocfs2_wait_for_mask(struct ocfs2_mask_waiter *mw) |
| @@ -1254,6 +1330,7 @@ out: | |||
| 1254 | goto again; | 1330 | goto again; |
| 1255 | mlog_errno(ret); | 1331 | mlog_errno(ret); |
| 1256 | } | 1332 | } |
| 1333 | ocfs2_update_lock_stats(lockres, level, &mw, ret); | ||
| 1257 | 1334 | ||
| 1258 | mlog_exit(ret); | 1335 | mlog_exit(ret); |
| 1259 | return ret; | 1336 | return ret; |
| @@ -1983,6 +2060,7 @@ static int ocfs2_inode_lock_update(struct inode *inode, | |||
| 1983 | le32_to_cpu(fe->i_flags)); | 2060 | le32_to_cpu(fe->i_flags)); |
| 1984 | 2061 | ||
| 1985 | ocfs2_refresh_inode(inode, fe); | 2062 | ocfs2_refresh_inode(inode, fe); |
| 2063 | ocfs2_track_lock_refresh(lockres); | ||
| 1986 | } | 2064 | } |
| 1987 | 2065 | ||
| 1988 | status = 0; | 2066 | status = 0; |
| @@ -2267,6 +2345,7 @@ int ocfs2_super_lock(struct ocfs2_super *osb, | |||
| 2267 | 2345 | ||
| 2268 | if (status < 0) | 2346 | if (status < 0) |
| 2269 | mlog_errno(status); | 2347 | mlog_errno(status); |
| 2348 | ocfs2_track_lock_refresh(lockres); | ||
| 2270 | } | 2349 | } |
| 2271 | bail: | 2350 | bail: |
| 2272 | mlog_exit(status); | 2351 | mlog_exit(status); |
| @@ -2461,7 +2540,7 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 2461 | } | 2540 | } |
| 2462 | 2541 | ||
| 2463 | /* So that debugfs.ocfs2 can determine which format is being used */ | 2542 | /* So that debugfs.ocfs2 can determine which format is being used */ |
| 2464 | #define OCFS2_DLM_DEBUG_STR_VERSION 1 | 2543 | #define OCFS2_DLM_DEBUG_STR_VERSION 2 |
| 2465 | static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) | 2544 | static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) |
| 2466 | { | 2545 | { |
| 2467 | int i; | 2546 | int i; |
| @@ -2502,6 +2581,47 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) | |||
| 2502 | for(i = 0; i < DLM_LVB_LEN; i++) | 2581 | for(i = 0; i < DLM_LVB_LEN; i++) |
| 2503 | seq_printf(m, "0x%x\t", lvb[i]); | 2582 | seq_printf(m, "0x%x\t", lvb[i]); |
| 2504 | 2583 | ||
| 2584 | #ifdef CONFIG_OCFS2_FS_STATS | ||
| 2585 | # define lock_num_prmode(_l) (_l)->l_lock_num_prmode | ||
| 2586 | # define lock_num_exmode(_l) (_l)->l_lock_num_exmode | ||
| 2587 | # define lock_num_prmode_failed(_l) (_l)->l_lock_num_prmode_failed | ||
| 2588 | # define lock_num_exmode_failed(_l) (_l)->l_lock_num_exmode_failed | ||
| 2589 | # define lock_total_prmode(_l) (_l)->l_lock_total_prmode | ||
| 2590 | # define lock_total_exmode(_l) (_l)->l_lock_total_exmode | ||
| 2591 | # define lock_max_prmode(_l) (_l)->l_lock_max_prmode | ||
| 2592 | # define lock_max_exmode(_l) (_l)->l_lock_max_exmode | ||
| 2593 | # define lock_refresh(_l) (_l)->l_lock_refresh | ||
| 2594 | #else | ||
| 2595 | # define lock_num_prmode(_l) (0ULL) | ||
| 2596 | # define lock_num_exmode(_l) (0ULL) | ||
| 2597 | # define lock_num_prmode_failed(_l) (0) | ||
| 2598 | # define lock_num_exmode_failed(_l) (0) | ||
| 2599 | # define lock_total_prmode(_l) (0ULL) | ||
| 2600 | # define lock_total_exmode(_l) (0ULL) | ||
| 2601 | # define lock_max_prmode(_l) (0) | ||
| 2602 | # define lock_max_exmode(_l) (0) | ||
| 2603 | # define lock_refresh(_l) (0) | ||
| 2604 | #endif | ||
| 2605 | /* The following seq_print was added in version 2 of this output */ | ||
| 2606 | seq_printf(m, "%llu\t" | ||
| 2607 | "%llu\t" | ||
| 2608 | "%u\t" | ||
| 2609 | "%u\t" | ||
| 2610 | "%llu\t" | ||
| 2611 | "%llu\t" | ||
| 2612 | "%u\t" | ||
| 2613 | "%u\t" | ||
| 2614 | "%u\t", | ||
| 2615 | lock_num_prmode(lockres), | ||
| 2616 | lock_num_exmode(lockres), | ||
| 2617 | lock_num_prmode_failed(lockres), | ||
| 2618 | lock_num_exmode_failed(lockres), | ||
| 2619 | lock_total_prmode(lockres), | ||
| 2620 | lock_total_exmode(lockres), | ||
| 2621 | lock_max_prmode(lockres), | ||
| 2622 | lock_max_exmode(lockres), | ||
| 2623 | lock_refresh(lockres)); | ||
| 2624 | |||
| 2505 | /* End the line */ | 2625 | /* End the line */ |
| 2506 | seq_printf(m, "\n"); | 2626 | seq_printf(m, "\n"); |
| 2507 | return 0; | 2627 | return 0; |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 57e0d30cde98..e8514e8b6ce8 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -2202,7 +2202,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, | |||
| 2202 | 2202 | ||
| 2203 | ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos); | 2203 | ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos); |
| 2204 | if (ret == -EINVAL) | 2204 | if (ret == -EINVAL) |
| 2205 | mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n"); | 2205 | mlog(0, "generic_file_aio_read returned -EINVAL\n"); |
| 2206 | 2206 | ||
| 2207 | /* buffered aio wouldn't have proper lock coverage today */ | 2207 | /* buffered aio wouldn't have proper lock coverage today */ |
| 2208 | BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT)); | 2208 | BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT)); |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 9698338adc39..a8c19cb3cfdd 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
| @@ -329,7 +329,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) | |||
| 329 | 329 | ||
| 330 | mlog(0, "Trying to extend transaction by %d blocks\n", nblocks); | 330 | mlog(0, "Trying to extend transaction by %d blocks\n", nblocks); |
| 331 | 331 | ||
| 332 | #ifdef OCFS2_DEBUG_FS | 332 | #ifdef CONFIG_OCFS2_DEBUG_FS |
| 333 | status = 1; | 333 | status = 1; |
| 334 | #else | 334 | #else |
| 335 | status = journal_extend(handle, nblocks); | 335 | status = journal_extend(handle, nblocks); |
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index be774bdc8b36..28e492e4ec88 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
| @@ -498,7 +498,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, | |||
| 498 | 498 | ||
| 499 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; | 499 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; |
| 500 | 500 | ||
| 501 | #ifdef OCFS2_DEBUG_FS | 501 | #ifdef CONFIG_OCFS2_DEBUG_FS |
| 502 | if (le32_to_cpu(alloc->id1.bitmap1.i_used) != | 502 | if (le32_to_cpu(alloc->id1.bitmap1.i_used) != |
| 503 | ocfs2_local_alloc_count_bits(alloc)) { | 503 | ocfs2_local_alloc_count_bits(alloc)) { |
| 504 | ocfs2_error(osb->sb, "local alloc inode %llu says it has " | 504 | ocfs2_error(osb->sb, "local alloc inode %llu says it has " |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 31692379c170..1cb814be8ef1 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
| @@ -132,6 +132,18 @@ struct ocfs2_lock_res { | |||
| 132 | wait_queue_head_t l_event; | 132 | wait_queue_head_t l_event; |
| 133 | 133 | ||
| 134 | struct list_head l_debug_list; | 134 | struct list_head l_debug_list; |
| 135 | |||
| 136 | #ifdef CONFIG_OCFS2_FS_STATS | ||
| 137 | unsigned long long l_lock_num_prmode; /* PR acquires */ | ||
| 138 | unsigned long long l_lock_num_exmode; /* EX acquires */ | ||
| 139 | unsigned int l_lock_num_prmode_failed; /* Failed PR gets */ | ||
| 140 | unsigned int l_lock_num_exmode_failed; /* Failed EX gets */ | ||
| 141 | unsigned long long l_lock_total_prmode; /* Tot wait for PR */ | ||
| 142 | unsigned long long l_lock_total_exmode; /* Tot wait for EX */ | ||
| 143 | unsigned int l_lock_max_prmode; /* Max wait for PR */ | ||
| 144 | unsigned int l_lock_max_exmode; /* Max wait for EX */ | ||
| 145 | unsigned int l_lock_refresh; /* Disk refreshes */ | ||
| 146 | #endif | ||
| 135 | }; | 147 | }; |
| 136 | 148 | ||
| 137 | struct ocfs2_dlm_debug { | 149 | struct ocfs2_dlm_debug { |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index 52c426665154..3f1945177629 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
| @@ -901,7 +901,7 @@ static inline int ocfs2_sprintf_system_inode_name(char *buf, int len, | |||
| 901 | * list has a copy per slot. | 901 | * list has a copy per slot. |
| 902 | */ | 902 | */ |
| 903 | if (type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE) | 903 | if (type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE) |
| 904 | chars = snprintf(buf, len, | 904 | chars = snprintf(buf, len, "%s", |
| 905 | ocfs2_system_inodes[type].si_name); | 905 | ocfs2_system_inodes[type].si_name); |
| 906 | else | 906 | else |
| 907 | chars = snprintf(buf, len, | 907 | chars = snprintf(buf, len, |
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c index bd7e0f3acfc7..353fc35c6748 100644 --- a/fs/ocfs2/stack_user.c +++ b/fs/ocfs2/stack_user.c | |||
| @@ -550,26 +550,17 @@ static ssize_t ocfs2_control_read(struct file *file, | |||
| 550 | size_t count, | 550 | size_t count, |
| 551 | loff_t *ppos) | 551 | loff_t *ppos) |
| 552 | { | 552 | { |
| 553 | char *proto_string = OCFS2_CONTROL_PROTO; | 553 | ssize_t ret; |
| 554 | size_t to_write = 0; | ||
| 555 | |||
| 556 | if (*ppos >= OCFS2_CONTROL_PROTO_LEN) | ||
| 557 | return 0; | ||
| 558 | |||
| 559 | to_write = OCFS2_CONTROL_PROTO_LEN - *ppos; | ||
| 560 | if (to_write > count) | ||
| 561 | to_write = count; | ||
| 562 | if (copy_to_user(buf, proto_string + *ppos, to_write)) | ||
| 563 | return -EFAULT; | ||
| 564 | 554 | ||
| 565 | *ppos += to_write; | 555 | ret = simple_read_from_buffer(buf, count, ppos, |
| 556 | OCFS2_CONTROL_PROTO, OCFS2_CONTROL_PROTO_LEN); | ||
| 566 | 557 | ||
| 567 | /* Have we read the whole protocol list? */ | 558 | /* Have we read the whole protocol list? */ |
| 568 | if (*ppos >= OCFS2_CONTROL_PROTO_LEN) | 559 | if (ret > 0 && *ppos >= OCFS2_CONTROL_PROTO_LEN) |
| 569 | ocfs2_control_set_handshake_state(file, | 560 | ocfs2_control_set_handshake_state(file, |
| 570 | OCFS2_CONTROL_HANDSHAKE_READ); | 561 | OCFS2_CONTROL_HANDSHAKE_READ); |
| 571 | 562 | ||
| 572 | return to_write; | 563 | return ret; |
| 573 | } | 564 | } |
| 574 | 565 | ||
| 575 | static int ocfs2_control_release(struct inode *inode, struct file *file) | 566 | static int ocfs2_control_release(struct inode *inode, struct file *file) |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index df63ba20ae90..ccecfe5094fa 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
| @@ -1703,7 +1703,11 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) | |||
| 1703 | local = ocfs2_mount_local(osb); | 1703 | local = ocfs2_mount_local(osb); |
| 1704 | 1704 | ||
| 1705 | /* will play back anything left in the journal. */ | 1705 | /* will play back anything left in the journal. */ |
| 1706 | ocfs2_journal_load(osb->journal, local); | 1706 | status = ocfs2_journal_load(osb->journal, local); |
| 1707 | if (status < 0) { | ||
| 1708 | mlog(ML_ERROR, "ocfs2 journal load failed! %d\n", status); | ||
| 1709 | goto finally; | ||
| 1710 | } | ||
| 1707 | 1711 | ||
| 1708 | if (dirty) { | 1712 | if (dirty) { |
| 1709 | /* recover my local alloc if we didn't unmount cleanly. */ | 1713 | /* recover my local alloc if we didn't unmount cleanly. */ |
diff --git a/include/linux/configfs.h b/include/linux/configfs.h index 3ae65b1bf90f..0488f937634a 100644 --- a/include/linux/configfs.h +++ b/include/linux/configfs.h | |||
| @@ -165,8 +165,8 @@ struct configfs_item_operations { | |||
| 165 | }; | 165 | }; |
| 166 | 166 | ||
| 167 | struct configfs_group_operations { | 167 | struct configfs_group_operations { |
| 168 | struct config_item *(*make_item)(struct config_group *group, const char *name); | 168 | int (*make_item)(struct config_group *group, const char *name, struct config_item **new_item); |
| 169 | struct config_group *(*make_group)(struct config_group *group, const char *name); | 169 | int (*make_group)(struct config_group *group, const char *name, struct config_group **new_group); |
| 170 | int (*commit_item)(struct config_item *item); | 170 | int (*commit_item)(struct config_item *item); |
| 171 | void (*disconnect_notify)(struct config_group *group, struct config_item *item); | 171 | void (*disconnect_notify)(struct config_group *group, struct config_item *item); |
| 172 | void (*drop_item)(struct config_group *group, struct config_item *item); | 172 | void (*drop_item)(struct config_group *group, struct config_item *item); |
