diff options
| -rw-r--r-- | fs/ocfs2/acl.c | 33 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/tcp.c | 17 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmmaster.c | 9 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmrecovery.c | 22 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmthread.c | 114 | ||||
| -rw-r--r-- | fs/ocfs2/refcounttree.c | 20 |
6 files changed, 122 insertions, 93 deletions
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index da702294d7e..a76e0aa5cd3 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c | |||
| @@ -290,12 +290,30 @@ static int ocfs2_set_acl(handle_t *handle, | |||
| 290 | 290 | ||
| 291 | int ocfs2_check_acl(struct inode *inode, int mask) | 291 | int ocfs2_check_acl(struct inode *inode, int mask) |
| 292 | { | 292 | { |
| 293 | struct posix_acl *acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS); | 293 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| 294 | struct buffer_head *di_bh = NULL; | ||
| 295 | struct posix_acl *acl; | ||
| 296 | int ret = -EAGAIN; | ||
| 294 | 297 | ||
| 295 | if (IS_ERR(acl)) | 298 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) |
| 299 | return ret; | ||
| 300 | |||
| 301 | ret = ocfs2_read_inode_block(inode, &di_bh); | ||
| 302 | if (ret < 0) { | ||
| 303 | mlog_errno(ret); | ||
| 304 | return ret; | ||
| 305 | } | ||
| 306 | |||
| 307 | acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, di_bh); | ||
| 308 | |||
| 309 | brelse(di_bh); | ||
| 310 | |||
| 311 | if (IS_ERR(acl)) { | ||
| 312 | mlog_errno(PTR_ERR(acl)); | ||
| 296 | return PTR_ERR(acl); | 313 | return PTR_ERR(acl); |
| 314 | } | ||
| 297 | if (acl) { | 315 | if (acl) { |
| 298 | int ret = posix_acl_permission(inode, acl, mask); | 316 | ret = posix_acl_permission(inode, acl, mask); |
| 299 | posix_acl_release(acl); | 317 | posix_acl_release(acl); |
| 300 | return ret; | 318 | return ret; |
| 301 | } | 319 | } |
| @@ -344,7 +362,7 @@ int ocfs2_init_acl(handle_t *handle, | |||
| 344 | { | 362 | { |
| 345 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 363 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| 346 | struct posix_acl *acl = NULL; | 364 | struct posix_acl *acl = NULL; |
| 347 | int ret = 0; | 365 | int ret = 0, ret2; |
| 348 | mode_t mode; | 366 | mode_t mode; |
| 349 | 367 | ||
| 350 | if (!S_ISLNK(inode->i_mode)) { | 368 | if (!S_ISLNK(inode->i_mode)) { |
| @@ -381,7 +399,12 @@ int ocfs2_init_acl(handle_t *handle, | |||
| 381 | mode = inode->i_mode; | 399 | mode = inode->i_mode; |
| 382 | ret = posix_acl_create_masq(clone, &mode); | 400 | ret = posix_acl_create_masq(clone, &mode); |
| 383 | if (ret >= 0) { | 401 | if (ret >= 0) { |
| 384 | ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); | 402 | ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode); |
| 403 | if (ret2) { | ||
| 404 | mlog_errno(ret2); | ||
| 405 | ret = ret2; | ||
| 406 | goto cleanup; | ||
| 407 | } | ||
| 385 | if (ret > 0) { | 408 | if (ret > 0) { |
| 386 | ret = ocfs2_set_acl(handle, inode, | 409 | ret = ocfs2_set_acl(handle, inode, |
| 387 | di_bh, ACL_TYPE_ACCESS, | 410 | di_bh, ACL_TYPE_ACCESS, |
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index aa75ca3f78d..1361997cf20 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
| @@ -1759,6 +1759,7 @@ static int o2net_accept_one(struct socket *sock) | |||
| 1759 | struct sockaddr_in sin; | 1759 | struct sockaddr_in sin; |
| 1760 | struct socket *new_sock = NULL; | 1760 | struct socket *new_sock = NULL; |
| 1761 | struct o2nm_node *node = NULL; | 1761 | struct o2nm_node *node = NULL; |
| 1762 | struct o2nm_node *local_node = NULL; | ||
| 1762 | struct o2net_sock_container *sc = NULL; | 1763 | struct o2net_sock_container *sc = NULL; |
| 1763 | struct o2net_node *nn; | 1764 | struct o2net_node *nn; |
| 1764 | 1765 | ||
| @@ -1796,11 +1797,15 @@ static int o2net_accept_one(struct socket *sock) | |||
| 1796 | goto out; | 1797 | goto out; |
| 1797 | } | 1798 | } |
| 1798 | 1799 | ||
| 1799 | if (o2nm_this_node() > node->nd_num) { | 1800 | if (o2nm_this_node() >= node->nd_num) { |
| 1800 | mlog(ML_NOTICE, "unexpected connect attempted from a lower " | 1801 | local_node = o2nm_get_node_by_num(o2nm_this_node()); |
| 1801 | "numbered node '%s' at " "%pI4:%d with num %u\n", | 1802 | mlog(ML_NOTICE, "unexpected connect attempt seen at node '%s' (" |
| 1802 | node->nd_name, &sin.sin_addr.s_addr, | 1803 | "%u, %pI4:%d) from node '%s' (%u, %pI4:%d)\n", |
| 1803 | ntohs(sin.sin_port), node->nd_num); | 1804 | local_node->nd_name, local_node->nd_num, |
| 1805 | &(local_node->nd_ipv4_address), | ||
| 1806 | ntohs(local_node->nd_ipv4_port), | ||
| 1807 | node->nd_name, node->nd_num, &sin.sin_addr.s_addr, | ||
| 1808 | ntohs(sin.sin_port)); | ||
| 1804 | ret = -EINVAL; | 1809 | ret = -EINVAL; |
| 1805 | goto out; | 1810 | goto out; |
| 1806 | } | 1811 | } |
| @@ -1857,6 +1862,8 @@ out: | |||
| 1857 | sock_release(new_sock); | 1862 | sock_release(new_sock); |
| 1858 | if (node) | 1863 | if (node) |
| 1859 | o2nm_node_put(node); | 1864 | o2nm_node_put(node); |
| 1865 | if (local_node) | ||
| 1866 | o2nm_node_put(local_node); | ||
| 1860 | if (sc) | 1867 | if (sc) |
| 1861 | sc_put(sc); | 1868 | sc_put(sc); |
| 1862 | return ret; | 1869 | return ret; |
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 94b97fc6a88..ffb4c68dafa 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
| @@ -511,8 +511,6 @@ static void dlm_lockres_release(struct kref *kref) | |||
| 511 | 511 | ||
| 512 | atomic_dec(&dlm->res_cur_count); | 512 | atomic_dec(&dlm->res_cur_count); |
| 513 | 513 | ||
| 514 | dlm_put(dlm); | ||
| 515 | |||
| 516 | if (!hlist_unhashed(&res->hash_node) || | 514 | if (!hlist_unhashed(&res->hash_node) || |
| 517 | !list_empty(&res->granted) || | 515 | !list_empty(&res->granted) || |
| 518 | !list_empty(&res->converting) || | 516 | !list_empty(&res->converting) || |
| @@ -585,8 +583,6 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm, | |||
| 585 | res->migration_pending = 0; | 583 | res->migration_pending = 0; |
| 586 | res->inflight_locks = 0; | 584 | res->inflight_locks = 0; |
| 587 | 585 | ||
| 588 | /* put in dlm_lockres_release */ | ||
| 589 | dlm_grab(dlm); | ||
| 590 | res->dlm = dlm; | 586 | res->dlm = dlm; |
| 591 | 587 | ||
| 592 | kref_init(&res->refs); | 588 | kref_init(&res->refs); |
| @@ -3050,8 +3046,6 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data, | |||
| 3050 | /* check for pre-existing lock */ | 3046 | /* check for pre-existing lock */ |
| 3051 | spin_lock(&dlm->spinlock); | 3047 | spin_lock(&dlm->spinlock); |
| 3052 | res = __dlm_lookup_lockres(dlm, name, namelen, hash); | 3048 | res = __dlm_lookup_lockres(dlm, name, namelen, hash); |
| 3053 | spin_lock(&dlm->master_lock); | ||
| 3054 | |||
| 3055 | if (res) { | 3049 | if (res) { |
| 3056 | spin_lock(&res->spinlock); | 3050 | spin_lock(&res->spinlock); |
| 3057 | if (res->state & DLM_LOCK_RES_RECOVERING) { | 3051 | if (res->state & DLM_LOCK_RES_RECOVERING) { |
| @@ -3069,14 +3063,15 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data, | |||
| 3069 | spin_unlock(&res->spinlock); | 3063 | spin_unlock(&res->spinlock); |
| 3070 | } | 3064 | } |
| 3071 | 3065 | ||
| 3066 | spin_lock(&dlm->master_lock); | ||
| 3072 | /* ignore status. only nonzero status would BUG. */ | 3067 | /* ignore status. only nonzero status would BUG. */ |
| 3073 | ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, | 3068 | ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, |
| 3074 | name, namelen, | 3069 | name, namelen, |
| 3075 | migrate->new_master, | 3070 | migrate->new_master, |
| 3076 | migrate->master); | 3071 | migrate->master); |
| 3077 | 3072 | ||
| 3078 | unlock: | ||
| 3079 | spin_unlock(&dlm->master_lock); | 3073 | spin_unlock(&dlm->master_lock); |
| 3074 | unlock: | ||
| 3080 | spin_unlock(&dlm->spinlock); | 3075 | spin_unlock(&dlm->spinlock); |
| 3081 | 3076 | ||
| 3082 | if (oldmle) { | 3077 | if (oldmle) { |
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 9dfaac73b36..aaaffbcbe91 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c | |||
| @@ -1997,6 +1997,8 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm, | |||
| 1997 | struct list_head *queue; | 1997 | struct list_head *queue; |
| 1998 | struct dlm_lock *lock, *next; | 1998 | struct dlm_lock *lock, *next; |
| 1999 | 1999 | ||
| 2000 | assert_spin_locked(&dlm->spinlock); | ||
| 2001 | assert_spin_locked(&res->spinlock); | ||
| 2000 | res->state |= DLM_LOCK_RES_RECOVERING; | 2002 | res->state |= DLM_LOCK_RES_RECOVERING; |
| 2001 | if (!list_empty(&res->recovering)) { | 2003 | if (!list_empty(&res->recovering)) { |
| 2002 | mlog(0, | 2004 | mlog(0, |
| @@ -2326,19 +2328,15 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) | |||
| 2326 | /* zero the lvb if necessary */ | 2328 | /* zero the lvb if necessary */ |
| 2327 | dlm_revalidate_lvb(dlm, res, dead_node); | 2329 | dlm_revalidate_lvb(dlm, res, dead_node); |
| 2328 | if (res->owner == dead_node) { | 2330 | if (res->owner == dead_node) { |
| 2329 | if (res->state & DLM_LOCK_RES_DROPPING_REF) | 2331 | if (res->state & DLM_LOCK_RES_DROPPING_REF) { |
| 2330 | mlog(0, "%s:%.*s: owned by " | 2332 | mlog(ML_NOTICE, "Ignore %.*s for " |
| 2331 | "dead node %u, this node was " | 2333 | "recovery as it is being freed\n", |
| 2332 | "dropping its ref when it died. " | 2334 | res->lockname.len, |
| 2333 | "continue, dropping the flag.\n", | 2335 | res->lockname.name); |
| 2334 | dlm->name, res->lockname.len, | 2336 | } else |
| 2335 | res->lockname.name, dead_node); | 2337 | dlm_move_lockres_to_recovery_list(dlm, |
| 2336 | 2338 | res); | |
| 2337 | /* the wake_up for this will happen when the | ||
| 2338 | * RECOVERING flag is dropped later */ | ||
| 2339 | res->state &= ~DLM_LOCK_RES_DROPPING_REF; | ||
| 2340 | 2339 | ||
| 2341 | dlm_move_lockres_to_recovery_list(dlm, res); | ||
| 2342 | } else if (res->owner == dlm->node_num) { | 2340 | } else if (res->owner == dlm->node_num) { |
| 2343 | dlm_free_dead_locks(dlm, res, dead_node); | 2341 | dlm_free_dead_locks(dlm, res, dead_node); |
| 2344 | __dlm_lockres_calc_usage(dlm, res); | 2342 | __dlm_lockres_calc_usage(dlm, res); |
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index d4f73ca68fe..2211acf33d9 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c | |||
| @@ -92,19 +92,27 @@ int __dlm_lockres_has_locks(struct dlm_lock_resource *res) | |||
| 92 | * truly ready to be freed. */ | 92 | * truly ready to be freed. */ |
| 93 | int __dlm_lockres_unused(struct dlm_lock_resource *res) | 93 | int __dlm_lockres_unused(struct dlm_lock_resource *res) |
| 94 | { | 94 | { |
| 95 | if (!__dlm_lockres_has_locks(res) && | 95 | int bit; |
| 96 | (list_empty(&res->dirty) && !(res->state & DLM_LOCK_RES_DIRTY))) { | 96 | |
| 97 | /* try not to scan the bitmap unless the first two | 97 | if (__dlm_lockres_has_locks(res)) |
| 98 | * conditions are already true */ | 98 | return 0; |
| 99 | int bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); | 99 | |
| 100 | if (bit >= O2NM_MAX_NODES) { | 100 | if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY) |
| 101 | /* since the bit for dlm->node_num is not | 101 | return 0; |
| 102 | * set, inflight_locks better be zero */ | 102 | |
| 103 | BUG_ON(res->inflight_locks != 0); | 103 | if (res->state & DLM_LOCK_RES_RECOVERING) |
| 104 | return 1; | 104 | return 0; |
| 105 | } | 105 | |
| 106 | } | 106 | bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0); |
| 107 | return 0; | 107 | if (bit < O2NM_MAX_NODES) |
| 108 | return 0; | ||
| 109 | |||
| 110 | /* | ||
| 111 | * since the bit for dlm->node_num is not set, inflight_locks better | ||
| 112 | * be zero | ||
| 113 | */ | ||
| 114 | BUG_ON(res->inflight_locks != 0); | ||
| 115 | return 1; | ||
| 108 | } | 116 | } |
| 109 | 117 | ||
| 110 | 118 | ||
| @@ -152,45 +160,25 @@ void dlm_lockres_calc_usage(struct dlm_ctxt *dlm, | |||
| 152 | spin_unlock(&dlm->spinlock); | 160 | spin_unlock(&dlm->spinlock); |
| 153 | } | 161 | } |
| 154 | 162 | ||
| 155 | static int dlm_purge_lockres(struct dlm_ctxt *dlm, | 163 | static void dlm_purge_lockres(struct dlm_ctxt *dlm, |
| 156 | struct dlm_lock_resource *res) | 164 | struct dlm_lock_resource *res) |
| 157 | { | 165 | { |
| 158 | int master; | 166 | int master; |
| 159 | int ret = 0; | 167 | int ret = 0; |
| 160 | 168 | ||
| 161 | spin_lock(&res->spinlock); | 169 | assert_spin_locked(&dlm->spinlock); |
| 162 | if (!__dlm_lockres_unused(res)) { | 170 | assert_spin_locked(&res->spinlock); |
| 163 | mlog(0, "%s:%.*s: tried to purge but not unused\n", | ||
| 164 | dlm->name, res->lockname.len, res->lockname.name); | ||
| 165 | __dlm_print_one_lock_resource(res); | ||
| 166 | spin_unlock(&res->spinlock); | ||
| 167 | BUG(); | ||
| 168 | } | ||
| 169 | |||
| 170 | if (res->state & DLM_LOCK_RES_MIGRATING) { | ||
| 171 | mlog(0, "%s:%.*s: Delay dropref as this lockres is " | ||
| 172 | "being remastered\n", dlm->name, res->lockname.len, | ||
| 173 | res->lockname.name); | ||
| 174 | /* Re-add the lockres to the end of the purge list */ | ||
| 175 | if (!list_empty(&res->purge)) { | ||
| 176 | list_del_init(&res->purge); | ||
| 177 | list_add_tail(&res->purge, &dlm->purge_list); | ||
| 178 | } | ||
| 179 | spin_unlock(&res->spinlock); | ||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | 171 | ||
| 183 | master = (res->owner == dlm->node_num); | 172 | master = (res->owner == dlm->node_num); |
| 184 | 173 | ||
| 185 | if (!master) | ||
| 186 | res->state |= DLM_LOCK_RES_DROPPING_REF; | ||
| 187 | spin_unlock(&res->spinlock); | ||
| 188 | 174 | ||
| 189 | mlog(0, "purging lockres %.*s, master = %d\n", res->lockname.len, | 175 | mlog(0, "purging lockres %.*s, master = %d\n", res->lockname.len, |
| 190 | res->lockname.name, master); | 176 | res->lockname.name, master); |
| 191 | 177 | ||
| 192 | if (!master) { | 178 | if (!master) { |
| 179 | res->state |= DLM_LOCK_RES_DROPPING_REF; | ||
| 193 | /* drop spinlock... retake below */ | 180 | /* drop spinlock... retake below */ |
| 181 | spin_unlock(&res->spinlock); | ||
| 194 | spin_unlock(&dlm->spinlock); | 182 | spin_unlock(&dlm->spinlock); |
| 195 | 183 | ||
| 196 | spin_lock(&res->spinlock); | 184 | spin_lock(&res->spinlock); |
| @@ -208,31 +196,35 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm, | |||
| 208 | mlog(0, "%s:%.*s: dlm_deref_lockres returned %d\n", | 196 | mlog(0, "%s:%.*s: dlm_deref_lockres returned %d\n", |
| 209 | dlm->name, res->lockname.len, res->lockname.name, ret); | 197 | dlm->name, res->lockname.len, res->lockname.name, ret); |
| 210 | spin_lock(&dlm->spinlock); | 198 | spin_lock(&dlm->spinlock); |
| 199 | spin_lock(&res->spinlock); | ||
| 211 | } | 200 | } |
| 212 | 201 | ||
| 213 | spin_lock(&res->spinlock); | ||
| 214 | if (!list_empty(&res->purge)) { | 202 | if (!list_empty(&res->purge)) { |
| 215 | mlog(0, "removing lockres %.*s:%p from purgelist, " | 203 | mlog(0, "removing lockres %.*s:%p from purgelist, " |
| 216 | "master = %d\n", res->lockname.len, res->lockname.name, | 204 | "master = %d\n", res->lockname.len, res->lockname.name, |
| 217 | res, master); | 205 | res, master); |
| 218 | list_del_init(&res->purge); | 206 | list_del_init(&res->purge); |
| 219 | spin_unlock(&res->spinlock); | ||
| 220 | dlm_lockres_put(res); | 207 | dlm_lockres_put(res); |
| 221 | dlm->purge_count--; | 208 | dlm->purge_count--; |
| 222 | } else | 209 | } |
| 223 | spin_unlock(&res->spinlock); | 210 | |
| 211 | if (!__dlm_lockres_unused(res)) { | ||
| 212 | mlog(ML_ERROR, "found lockres %s:%.*s: in use after deref\n", | ||
| 213 | dlm->name, res->lockname.len, res->lockname.name); | ||
| 214 | __dlm_print_one_lock_resource(res); | ||
| 215 | BUG(); | ||
| 216 | } | ||
| 224 | 217 | ||
| 225 | __dlm_unhash_lockres(res); | 218 | __dlm_unhash_lockres(res); |
| 226 | 219 | ||
| 227 | /* lockres is not in the hash now. drop the flag and wake up | 220 | /* lockres is not in the hash now. drop the flag and wake up |
| 228 | * any processes waiting in dlm_get_lock_resource. */ | 221 | * any processes waiting in dlm_get_lock_resource. */ |
| 229 | if (!master) { | 222 | if (!master) { |
| 230 | spin_lock(&res->spinlock); | ||
| 231 | res->state &= ~DLM_LOCK_RES_DROPPING_REF; | 223 | res->state &= ~DLM_LOCK_RES_DROPPING_REF; |
| 232 | spin_unlock(&res->spinlock); | 224 | spin_unlock(&res->spinlock); |
| 233 | wake_up(&res->wq); | 225 | wake_up(&res->wq); |
| 234 | } | 226 | } else |
| 235 | return 0; | 227 | spin_unlock(&res->spinlock); |
| 236 | } | 228 | } |
| 237 | 229 | ||
| 238 | static void dlm_run_purge_list(struct dlm_ctxt *dlm, | 230 | static void dlm_run_purge_list(struct dlm_ctxt *dlm, |
| @@ -251,17 +243,7 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm, | |||
| 251 | lockres = list_entry(dlm->purge_list.next, | 243 | lockres = list_entry(dlm->purge_list.next, |
| 252 | struct dlm_lock_resource, purge); | 244 | struct dlm_lock_resource, purge); |
| 253 | 245 | ||
| 254 | /* Status of the lockres *might* change so double | ||
| 255 | * check. If the lockres is unused, holding the dlm | ||
| 256 | * spinlock will prevent people from getting and more | ||
| 257 | * refs on it -- there's no need to keep the lockres | ||
| 258 | * spinlock. */ | ||
| 259 | spin_lock(&lockres->spinlock); | 246 | spin_lock(&lockres->spinlock); |
| 260 | unused = __dlm_lockres_unused(lockres); | ||
| 261 | spin_unlock(&lockres->spinlock); | ||
| 262 | |||
| 263 | if (!unused) | ||
| 264 | continue; | ||
| 265 | 247 | ||
| 266 | purge_jiffies = lockres->last_used + | 248 | purge_jiffies = lockres->last_used + |
| 267 | msecs_to_jiffies(DLM_PURGE_INTERVAL_MS); | 249 | msecs_to_jiffies(DLM_PURGE_INTERVAL_MS); |
| @@ -273,15 +255,29 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm, | |||
| 273 | * in tail order, we can stop at the first | 255 | * in tail order, we can stop at the first |
| 274 | * unpurgable resource -- anyone added after | 256 | * unpurgable resource -- anyone added after |
| 275 | * him will have a greater last_used value */ | 257 | * him will have a greater last_used value */ |
| 258 | spin_unlock(&lockres->spinlock); | ||
| 276 | break; | 259 | break; |
| 277 | } | 260 | } |
| 278 | 261 | ||
| 262 | /* Status of the lockres *might* change so double | ||
| 263 | * check. If the lockres is unused, holding the dlm | ||
| 264 | * spinlock will prevent people from getting and more | ||
| 265 | * refs on it. */ | ||
| 266 | unused = __dlm_lockres_unused(lockres); | ||
| 267 | if (!unused || | ||
| 268 | (lockres->state & DLM_LOCK_RES_MIGRATING)) { | ||
| 269 | mlog(0, "lockres %s:%.*s: is in use or " | ||
| 270 | "being remastered, used %d, state %d\n", | ||
| 271 | dlm->name, lockres->lockname.len, | ||
| 272 | lockres->lockname.name, !unused, lockres->state); | ||
| 273 | list_move_tail(&dlm->purge_list, &lockres->purge); | ||
| 274 | spin_unlock(&lockres->spinlock); | ||
| 275 | continue; | ||
| 276 | } | ||
| 277 | |||
| 279 | dlm_lockres_get(lockres); | 278 | dlm_lockres_get(lockres); |
| 280 | 279 | ||
| 281 | /* This may drop and reacquire the dlm spinlock if it | 280 | dlm_purge_lockres(dlm, lockres); |
| 282 | * has to do migration. */ | ||
| 283 | if (dlm_purge_lockres(dlm, lockres)) | ||
| 284 | BUG(); | ||
| 285 | 281 | ||
| 286 | dlm_lockres_put(lockres); | 282 | dlm_lockres_put(lockres); |
| 287 | 283 | ||
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 3ac5aa733e9..73a11ccfd4c 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
| @@ -2436,16 +2436,26 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, | |||
| 2436 | len = min((u64)cpos + clusters, le64_to_cpu(rec.r_cpos) + | 2436 | len = min((u64)cpos + clusters, le64_to_cpu(rec.r_cpos) + |
| 2437 | le32_to_cpu(rec.r_clusters)) - cpos; | 2437 | le32_to_cpu(rec.r_clusters)) - cpos; |
| 2438 | /* | 2438 | /* |
| 2439 | * If the refcount rec already exist, cool. We just need | ||
| 2440 | * to check whether there is a split. Otherwise we just need | ||
| 2441 | * to increase the refcount. | ||
| 2442 | * If we will insert one, increases recs_add. | ||
| 2443 | * | ||
| 2444 | * We record all the records which will be inserted to the | 2439 | * We record all the records which will be inserted to the |
| 2445 | * same refcount block, so that we can tell exactly whether | 2440 | * same refcount block, so that we can tell exactly whether |
| 2446 | * we need a new refcount block or not. | 2441 | * we need a new refcount block or not. |
| 2442 | * | ||
| 2443 | * If we will insert a new one, this is easy and only happens | ||
| 2444 | * during adding refcounted flag to the extent, so we don't | ||
| 2445 | * have a chance of spliting. We just need one record. | ||
| 2446 | * | ||
| 2447 | * If the refcount rec already exists, that would be a little | ||
| 2448 | * complicated. we may have to: | ||
| 2449 | * 1) split at the beginning if the start pos isn't aligned. | ||
| 2450 | * we need 1 more record in this case. | ||
| 2451 | * 2) split int the end if the end pos isn't aligned. | ||
| 2452 | * we need 1 more record in this case. | ||
| 2453 | * 3) split in the middle because of file system fragmentation. | ||
| 2454 | * we need 2 more records in this case(we can't detect this | ||
| 2455 | * beforehand, so always think of the worst case). | ||
| 2447 | */ | 2456 | */ |
| 2448 | if (rec.r_refcount) { | 2457 | if (rec.r_refcount) { |
| 2458 | recs_add += 2; | ||
| 2449 | /* Check whether we need a split at the beginning. */ | 2459 | /* Check whether we need a split at the beginning. */ |
| 2450 | if (cpos == start_cpos && | 2460 | if (cpos == start_cpos && |
| 2451 | cpos != le64_to_cpu(rec.r_cpos)) | 2461 | cpos != le64_to_cpu(rec.r_cpos)) |
