Skip to content

Commit eda4b71

Browse files
committed
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2: ocfs2: Fix system inodes cache overflow. ocfs2: Hold ip_lock when set/clear flags for indexed dir. ocfs2: Adjust masklog flag values Ocfs2: Teach 'coherency=full' O_DIRECT writes to correctly up_read i_alloc_sem. ocfs2/dlm: Migrate lockres with no locks if it has a reference
2 parents 55fb78a + 7d8f987 commit eda4b71

File tree

8 files changed

+81
-28
lines changed

8 files changed

+81
-28
lines changed

fs/ocfs2/aops.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,11 +573,14 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
573573
/* this io's submitter should not have unlocked this before we could */
574574
BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
575575

576+
if (ocfs2_iocb_is_sem_locked(iocb)) {
577+
up_read(&inode->i_alloc_sem);
578+
ocfs2_iocb_clear_sem_locked(iocb);
579+
}
580+
576581
ocfs2_iocb_clear_rw_locked(iocb);
577582

578583
level = ocfs2_iocb_rw_locked_level(iocb);
579-
if (!level)
580-
up_read(&inode->i_alloc_sem);
581584
ocfs2_rw_unlock(inode, level);
582585

583586
if (is_async)

fs/ocfs2/aops.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,27 @@ static inline void ocfs2_iocb_set_rw_locked(struct kiocb *iocb, int level)
6868
else
6969
clear_bit(1, (unsigned long *)&iocb->private);
7070
}
71+
72+
/*
73+
* Using a named enum representing lock types in terms of #N bit stored in
74+
* iocb->private, which is going to be used for communication bewteen
75+
* ocfs2_dio_end_io() and ocfs2_file_aio_write/read().
76+
*/
77+
enum ocfs2_iocb_lock_bits {
78+
OCFS2_IOCB_RW_LOCK = 0,
79+
OCFS2_IOCB_RW_LOCK_LEVEL,
80+
OCFS2_IOCB_SEM,
81+
OCFS2_IOCB_NUM_LOCKS
82+
};
83+
7184
#define ocfs2_iocb_clear_rw_locked(iocb) \
72-
clear_bit(0, (unsigned long *)&iocb->private)
85+
clear_bit(OCFS2_IOCB_RW_LOCK, (unsigned long *)&iocb->private)
7386
#define ocfs2_iocb_rw_locked_level(iocb) \
74-
test_bit(1, (unsigned long *)&iocb->private)
87+
test_bit(OCFS2_IOCB_RW_LOCK_LEVEL, (unsigned long *)&iocb->private)
88+
#define ocfs2_iocb_set_sem_locked(iocb) \
89+
set_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)
90+
#define ocfs2_iocb_clear_sem_locked(iocb) \
91+
clear_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)
92+
#define ocfs2_iocb_is_sem_locked(iocb) \
93+
test_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)
7594
#endif /* OCFS2_FILE_H */

fs/ocfs2/cluster/masklog.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,11 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
113113
define_mask(QUOTA),
114114
define_mask(REFCOUNT),
115115
define_mask(BASTS),
116+
define_mask(RESERVATIONS),
117+
define_mask(CLUSTER),
116118
define_mask(ERROR),
117119
define_mask(NOTICE),
118120
define_mask(KTHREAD),
119-
define_mask(RESERVATIONS),
120121
};
121122

122123
static struct attribute *mlog_attr_ptrs[MLOG_MAX_BITS] = {NULL, };

fs/ocfs2/cluster/masklog.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
#include <linux/sched.h>
8282

8383
/* bits that are frequently given and infrequently matched in the low word */
84-
/* NOTE: If you add a flag, you need to also update mlog.c! */
84+
/* NOTE: If you add a flag, you need to also update masklog.c! */
8585
#define ML_ENTRY 0x0000000000000001ULL /* func call entry */
8686
#define ML_EXIT 0x0000000000000002ULL /* func call exit */
8787
#define ML_TCP 0x0000000000000004ULL /* net cluster/tcp.c */
@@ -114,13 +114,14 @@
114114
#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */
115115
#define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */
116116
#define ML_REFCOUNT 0x0000000080000000ULL /* refcount tree operations */
117-
#define ML_BASTS 0x0000001000000000ULL /* dlmglue asts and basts */
117+
#define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */
118+
#define ML_RESERVATIONS 0x0000000200000000ULL /* ocfs2 alloc reservations */
119+
#define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */
120+
118121
/* bits that are infrequently given and frequently matched in the high word */
119-
#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
120-
#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
121-
#define ML_KTHREAD 0x0000000400000000ULL /* kernel thread activity */
122-
#define ML_RESERVATIONS 0x0000000800000000ULL /* ocfs2 alloc reservations */
123-
#define ML_CLUSTER 0x0000001000000000ULL /* cluster stack */
122+
#define ML_ERROR 0x1000000000000000ULL /* sent to KERN_ERR */
123+
#define ML_NOTICE 0x2000000000000000ULL /* setn to KERN_NOTICE */
124+
#define ML_KTHREAD 0x4000000000000000ULL /* kernel thread activity */
124125

125126
#define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE)
126127
#define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT)

fs/ocfs2/dir.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2461,8 +2461,10 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
24612461

24622462
di->i_dx_root = cpu_to_le64(dr_blkno);
24632463

2464+
spin_lock(&OCFS2_I(dir)->ip_lock);
24642465
OCFS2_I(dir)->ip_dyn_features |= OCFS2_INDEXED_DIR_FL;
24652466
di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
2467+
spin_unlock(&OCFS2_I(dir)->ip_lock);
24662468

24672469
ocfs2_journal_dirty(handle, di_bh);
24682470

@@ -4466,8 +4468,10 @@ static int ocfs2_dx_dir_remove_index(struct inode *dir,
44664468
goto out_commit;
44674469
}
44684470

4471+
spin_lock(&OCFS2_I(dir)->ip_lock);
44694472
OCFS2_I(dir)->ip_dyn_features &= ~OCFS2_INDEXED_DIR_FL;
44704473
di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
4474+
spin_unlock(&OCFS2_I(dir)->ip_lock);
44714475
di->i_dx_root = cpu_to_le64(0ULL);
44724476

44734477
ocfs2_journal_dirty(handle, di_bh);

fs/ocfs2/dlm/dlmmaster.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,7 +2346,8 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
23462346
*/
23472347
static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
23482348
struct dlm_lock_resource *res,
2349-
int *numlocks)
2349+
int *numlocks,
2350+
int *hasrefs)
23502351
{
23512352
int ret;
23522353
int i;
@@ -2356,6 +2357,9 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
23562357

23572358
assert_spin_locked(&res->spinlock);
23582359

2360+
*numlocks = 0;
2361+
*hasrefs = 0;
2362+
23592363
ret = -EINVAL;
23602364
if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
23612365
mlog(0, "cannot migrate lockres with unknown owner!\n");
@@ -2386,7 +2390,13 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
23862390
}
23872391

23882392
*numlocks = count;
2389-
mlog(0, "migrateable lockres having %d locks\n", *numlocks);
2393+
2394+
count = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
2395+
if (count < O2NM_MAX_NODES)
2396+
*hasrefs = 1;
2397+
2398+
mlog(0, "%s: res %.*s, Migrateable, locks %d, refs %d\n", dlm->name,
2399+
res->lockname.len, res->lockname.name, *numlocks, *hasrefs);
23902400

23912401
leave:
23922402
return ret;
@@ -2408,7 +2418,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
24082418
const char *name;
24092419
unsigned int namelen;
24102420
int mle_added = 0;
2411-
int numlocks;
2421+
int numlocks, hasrefs;
24122422
int wake = 0;
24132423

24142424
if (!dlm_grab(dlm))
@@ -2417,24 +2427,22 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
24172427
name = res->lockname.name;
24182428
namelen = res->lockname.len;
24192429

2420-
mlog(0, "migrating %.*s to %u\n", namelen, name, target);
2430+
mlog(0, "%s: Migrating %.*s to %u\n", dlm->name, namelen, name, target);
24212431

24222432
/*
24232433
* ensure this lockres is a proper candidate for migration
24242434
*/
24252435
spin_lock(&res->spinlock);
2426-
ret = dlm_is_lockres_migrateable(dlm, res, &numlocks);
2436+
ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs);
24272437
if (ret < 0) {
24282438
spin_unlock(&res->spinlock);
24292439
goto leave;
24302440
}
24312441
spin_unlock(&res->spinlock);
24322442

24332443
/* no work to do */
2434-
if (numlocks == 0) {
2435-
mlog(0, "no locks were found on this lockres! done!\n");
2444+
if (numlocks == 0 && !hasrefs)
24362445
goto leave;
2437-
}
24382446

24392447
/*
24402448
* preallocate up front
@@ -2459,14 +2467,14 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
24592467
* find a node to migrate the lockres to
24602468
*/
24612469

2462-
mlog(0, "picking a migration node\n");
24632470
spin_lock(&dlm->spinlock);
24642471
/* pick a new node */
24652472
if (!test_bit(target, dlm->domain_map) ||
24662473
target >= O2NM_MAX_NODES) {
24672474
target = dlm_pick_migration_target(dlm, res);
24682475
}
2469-
mlog(0, "node %u chosen for migration\n", target);
2476+
mlog(0, "%s: res %.*s, Node %u chosen for migration\n", dlm->name,
2477+
namelen, name, target);
24702478

24712479
if (target >= O2NM_MAX_NODES ||
24722480
!test_bit(target, dlm->domain_map)) {
@@ -2667,7 +2675,7 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
26672675
{
26682676
int ret;
26692677
int lock_dropped = 0;
2670-
int numlocks;
2678+
int numlocks, hasrefs;
26712679

26722680
spin_lock(&res->spinlock);
26732681
if (res->owner != dlm->node_num) {
@@ -2681,8 +2689,8 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
26812689
}
26822690

26832691
/* No need to migrate a lockres having no locks */
2684-
ret = dlm_is_lockres_migrateable(dlm, res, &numlocks);
2685-
if (ret >= 0 && numlocks == 0) {
2692+
ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs);
2693+
if (ret >= 0 && numlocks == 0 && !hasrefs) {
26862694
spin_unlock(&res->spinlock);
26872695
goto leave;
26882696
}
@@ -2915,6 +2923,12 @@ static u8 dlm_pick_migration_target(struct dlm_ctxt *dlm,
29152923
}
29162924
queue++;
29172925
}
2926+
2927+
nodenum = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
2928+
if (nodenum < O2NM_MAX_NODES) {
2929+
spin_unlock(&res->spinlock);
2930+
return nodenum;
2931+
}
29182932
spin_unlock(&res->spinlock);
29192933
mlog(0, "have not found a suitable target yet! checking domain map\n");
29202934

fs/ocfs2/file.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,11 +2241,15 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
22412241

22422242
mutex_lock(&inode->i_mutex);
22432243

2244+
ocfs2_iocb_clear_sem_locked(iocb);
2245+
22442246
relock:
22452247
/* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */
22462248
if (direct_io) {
22472249
down_read(&inode->i_alloc_sem);
22482250
have_alloc_sem = 1;
2251+
/* communicate with ocfs2_dio_end_io */
2252+
ocfs2_iocb_set_sem_locked(iocb);
22492253
}
22502254

22512255
/*
@@ -2382,8 +2386,10 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
23822386
ocfs2_rw_unlock(inode, rw_level);
23832387

23842388
out_sems:
2385-
if (have_alloc_sem)
2389+
if (have_alloc_sem) {
23862390
up_read(&inode->i_alloc_sem);
2391+
ocfs2_iocb_clear_sem_locked(iocb);
2392+
}
23872393

23882394
mutex_unlock(&inode->i_mutex);
23892395

@@ -2527,13 +2533,16 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
25272533
goto bail;
25282534
}
25292535

2536+
ocfs2_iocb_clear_sem_locked(iocb);
2537+
25302538
/*
25312539
* buffered reads protect themselves in ->readpage(). O_DIRECT reads
25322540
* need locks to protect pending reads from racing with truncate.
25332541
*/
25342542
if (filp->f_flags & O_DIRECT) {
25352543
down_read(&inode->i_alloc_sem);
25362544
have_alloc_sem = 1;
2545+
ocfs2_iocb_set_sem_locked(iocb);
25372546

25382547
ret = ocfs2_rw_lock(inode, 0);
25392548
if (ret < 0) {
@@ -2575,8 +2584,10 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
25752584
}
25762585

25772586
bail:
2578-
if (have_alloc_sem)
2587+
if (have_alloc_sem) {
25792588
up_read(&inode->i_alloc_sem);
2589+
ocfs2_iocb_clear_sem_locked(iocb);
2590+
}
25802591
if (rw_level != -1)
25812592
ocfs2_rw_unlock(inode, rw_level);
25822593
mlog_exit(ret);

fs/ocfs2/ocfs2_fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ enum {
350350
#define OCFS2_LAST_LOCAL_SYSTEM_INODE LOCAL_GROUP_QUOTA_SYSTEM_INODE
351351
NUM_SYSTEM_INODES
352352
};
353-
#define NUM_GLOBAL_SYSTEM_INODES OCFS2_LAST_GLOBAL_SYSTEM_INODE
353+
#define NUM_GLOBAL_SYSTEM_INODES OCFS2_FIRST_LOCAL_SYSTEM_INODE
354354
#define NUM_LOCAL_SYSTEM_INODES \
355355
(NUM_SYSTEM_INODES - OCFS2_FIRST_LOCAL_SYSTEM_INODE)
356356

0 commit comments

Comments
 (0)