History

Merge tag 'jfs-7.1' of github.com:kleikamp/linux-shaggy

Pull jfs updates from Dave Kleikamp: "More robust data integrity checking and some fixes" * tag 'jfs-7.1' of github.com:kleikamp/linux-shaggy: jfs: avoid -Wtautological-constant-out-of-range-compare warning again JFS: always load filesystem UUID during mount jfs: hold LOG_LOCK on umount to avoid null-ptr-deref jfs: Set the lbmDone flag at the end of lbmIODone jfs: fix corrupted list in dbUpdatePMap jfs: add dmapctl integrity check to prevent invalid operations jfs: add dtpage integrity check to prevent index/pointer overflows jfs: add dtroot integrity check to prevent index out-of-bounds

Linus Torvalds committed 7 months ago

Commit 1d51b372 parents 5414f3f dad98c510 files · +344 −30Browse files

Unified · Split

10 files
  1. fs/jfs/jfs_dmap.c +111 −3
  2. fs/jfs/jfs_dtree.c +188 −4
  3. fs/jfs/jfs_dtree.h +4 −0
  4. fs/jfs/jfs_imap.c +4 −0
  5. fs/jfs/jfs_logmgr.c +14 −20
  6. fs/jfs/jfs_logmgr.h +7 −0
  7. fs/jfs/jfs_metapage.c +2 −1
  8. fs/jfs/jfs_mount.c +2 −1
  9. fs/jfs/jfs_txnmgr.c +2 −1
  10. fs/jfs/jfs_umount.c +10 −0
fs/jfs/jfs_dmap.c+111−3
@@ -133,6 +133,93 @@ static const s8 budtab[256] = { · 132 unmodified lines
133 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1133 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1
134};134};
135 135
136/*
137 * check_dmapctl - Validate integrity of a dmapctl structure
138 * @dcp: Pointer to the dmapctl structure to check
139 *
140 * Return: true if valid, false if corrupted
141 */
142static bool check_dmapctl(struct dmapctl *dcp)
143{
144 s8 budmin = dcp->budmin;
145 u32 nleafs, l2nleafs, leafidx, height;
146 int i;
147
148 nleafs = le32_to_cpu(dcp->nleafs);
149 /* Check basic field ranges */
150 if (unlikely(nleafs > LPERCTL)) {
151 jfs_err("dmapctl: invalid nleafs %u (max %u)",
152 nleafs, LPERCTL);
153 return false;
154 }
155
156 l2nleafs = le32_to_cpu(dcp->l2nleafs);
157 if (unlikely(l2nleafs > L2LPERCTL)) {
158 jfs_err("dmapctl: invalid l2nleafs %u (max %u)",
159 l2nleafs, L2LPERCTL);
160 return false;
161 }
162
163 /* Verify nleafs matches l2nleafs (must be power of two) */
164 if (unlikely((1U << l2nleafs) != nleafs)) {
165 jfs_err("dmapctl: nleafs %u != 2^%u",
166 nleafs, l2nleafs);
167 return false;
168 }
169
170 leafidx = le32_to_cpu(dcp->leafidx);
171 /* Check leaf index matches expected position */
172 if (unlikely(leafidx != CTLLEAFIND)) {
173 jfs_err("dmapctl: invalid leafidx %u (expected %u)",
174 leafidx, CTLLEAFIND);
175 return false;
176 }
177
178 height = le32_to_cpu(dcp->height);
179 /* Check tree height is within valid range */
180 if (unlikely(height > (L2LPERCTL >> 1))) {
181 jfs_err("dmapctl: invalid height %u (max %u)",
182 height, L2LPERCTL >> 1);
183 return false;
184 }
185
186 /* Check budmin is valid (cannot be NOFREE for non-empty tree) */
187 if (budmin == NOFREE) {
188 if (unlikely(nleafs > 0)) {
189 jfs_err("dmapctl: budmin is NOFREE but nleafs %u",
190 nleafs);
191 return false;
192 }
193 } else if (unlikely(budmin < BUDMIN)) {
194 jfs_err("dmapctl: invalid budmin %d (min %d)",
195 budmin, BUDMIN);
196 return false;
197 }
198
199 /* Check leaf nodes fit within stree array */
200 if (unlikely(leafidx + nleafs > CTLTREESIZE)) {
201 jfs_err("dmapctl: leaf range exceeds stree size (end %u > %u)",
202 leafidx + nleafs, CTLTREESIZE);
203 return false;
204 }
205
206 /* Check leaf nodes have valid values */
207 for (i = leafidx; i < leafidx + nleafs; i++) {
208 s8 val = dcp->stree[i];
209
210 if (unlikely(val < NOFREE)) {
211 jfs_err("dmapctl: invalid leaf value %d at index %d",
212 val, i);
213 return false;
214 } else if (unlikely(val > 31)) {
215 jfs_err("dmapctl: leaf value %d too large at index %d", val, i);
216 return false;
217 }
218 }
219
220 return true;
221}
222
136/*223/*
137 * NAME: dbMount()224 * NAME: dbMount()
138 *225 *
@@ -1372,7 +1459,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) · 1233 unmodified lines
1372 dcp = (struct dmapctl *) mp->data;1459 dcp = (struct dmapctl *) mp->data;
1373 budmin = dcp->budmin;1460 budmin = dcp->budmin;
1374 1461
1375 if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {1462 if (unlikely(!check_dmapctl(dcp))) {
1376 jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");1463 jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");
1377 release_metapage(mp);1464 release_metapage(mp);
1378 return -EIO;1465 return -EIO;
@@ -1702,7 +1789,7 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno) · 323 unmodified lines
1702 dcp = (struct dmapctl *) mp->data;1789 dcp = (struct dmapctl *) mp->data;
1703 budmin = dcp->budmin;1790 budmin = dcp->budmin;
1704 1791
1705 if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {1792 if (unlikely(!check_dmapctl(dcp))) {
1706 jfs_error(bmp->db_ipbmap->i_sb,1793 jfs_error(bmp->db_ipbmap->i_sb,
1707 "Corrupt dmapctl page\n");1794 "Corrupt dmapctl page\n");
1708 release_metapage(mp);1795 release_metapage(mp);
@@ -2485,7 +2572,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) · 776 unmodified lines
2485 return -EIO;2572 return -EIO;
2486 dcp = (struct dmapctl *) mp->data;2573 dcp = (struct dmapctl *) mp->data;
2487 2574
2488 if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {2575 if (unlikely(!check_dmapctl(dcp))) {
2489 jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");2576 jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");
2490 release_metapage(mp);2577 release_metapage(mp);
2491 return -EIO;2578 return -EIO;
@@ -3454,6 +3541,11 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 962 unmodified lines
3454 return -EIO;3541 return -EIO;
3455 }3542 }
3456 l2dcp = (struct dmapctl *) l2mp->data;3543 l2dcp = (struct dmapctl *) l2mp->data;
3544 if (unlikely(!check_dmapctl(l2dcp))) {
3545 jfs_error(ipbmap->i_sb, "Corrupt dmapctl page\n");
3546 release_metapage(l2mp);
3547 return -EIO;
3548 }
3457 3549
3458 /* compute start L1 */3550 /* compute start L1 */
3459 k = blkno >> L2MAXL1SIZE;3551 k = blkno >> L2MAXL1SIZE;
@@ -3471,6 +3563,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 11 unmodified lines
3471 if (l1mp == NULL)3563 if (l1mp == NULL)
3472 goto errout;3564 goto errout;
3473 l1dcp = (struct dmapctl *) l1mp->data;3565 l1dcp = (struct dmapctl *) l1mp->data;
3566 if (unlikely(!check_dmapctl(l1dcp))) {
3567 jfs_error(ipbmap->i_sb, "Corrupt dmapctl page\n");
3568 goto errout;
3569 }
3474 3570
3475 /* compute start L0 */3571 /* compute start L0 */
3476 j = (blkno & (MAXL1SIZE - 1)) >> L2MAXL0SIZE;3572 j = (blkno & (MAXL1SIZE - 1)) >> L2MAXL0SIZE;
@@ -3484,6 +3580,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 7 unmodified lines
3484 goto errout;3580 goto errout;
3485 3581
3486 l1dcp = (struct dmapctl *) l1mp->data;3582 l1dcp = (struct dmapctl *) l1mp->data;
3583 if (unlikely(!check_dmapctl(l1dcp))) {
3584 jfs_error(ipbmap->i_sb, "Corrupt dmapctl page\n");
3585 goto errout;
3586 }
3487 3587
3488 /* compute start L0 */3588 /* compute start L0 */
3489 j = 0;3589 j = 0;
@@ -3503,6 +3603,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 13 unmodified lines
3503 if (l0mp == NULL)3603 if (l0mp == NULL)
3504 goto errout;3604 goto errout;
3505 l0dcp = (struct dmapctl *) l0mp->data;3605 l0dcp = (struct dmapctl *) l0mp->data;
3606 if (unlikely(!check_dmapctl(l0dcp))) {
3607 jfs_error(ipbmap->i_sb, "Corrupt dmapctl page\n");
3608 goto errout;
3609 }
3506 3610
3507 /* compute start dmap */3611 /* compute start dmap */
3508 i = (blkno & (MAXL0SIZE - 1)) >>3612 i = (blkno & (MAXL0SIZE - 1)) >>
@@ -3518,6 +3622,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 9 unmodified lines
3518 goto errout;3622 goto errout;
3519 3623
3520 l0dcp = (struct dmapctl *) l0mp->data;3624 l0dcp = (struct dmapctl *) l0mp->data;
3625 if (unlikely(!check_dmapctl(l0dcp))) {
3626 jfs_error(ipbmap->i_sb, "Corrupt dmapctl page\n");
3627 goto errout;
3628 }
3521 3629
3522 /* compute start dmap */3630 /* compute start dmap */
3523 i = 0;3631 i = 0;
fs/jfs/jfs_dtree.c+188−4
@@ -115,10 +115,7 @@ struct dtsplit { · 114 unmodified lines
115do { \115do { \
116 BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \116 BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \
117 if (!(RC)) { \117 if (!(RC)) { \
118 if (((P)->header.nextindex > \118 if ((BN) && !check_dtpage(P)) { \
119 (((BN) == 0) ? DTROOTMAXSLOT : (P)->header.maxslot)) || \
120 ((BN) && (((P)->header.maxslot > DTPAGEMAXSLOT) || \
121 ((P)->header.stblindex >= DTPAGEMAXSLOT)))) { \
122 BT_PUTPAGE(MP); \119 BT_PUTPAGE(MP); \
123 jfs_error((IP)->i_sb, \120 jfs_error((IP)->i_sb, \
124 "DT_GETPAGE: dtree page corrupt\n"); \121 "DT_GETPAGE: dtree page corrupt\n"); \
@@ -4297,3 +4294,190 @@ int dtModify(tid_t tid, struct inode *ip, · 4172 unmodified lines
4297 4294
4298 return 0;4295 return 0;
4299}4296}
4297
4298bool check_dtroot(dtroot_t *p)
4299{
4300 DECLARE_BITMAP(bitmap, DTROOTMAXSLOT) = {0};
4301 int i;
4302
4303 /* freecnt cannot be negative or exceed DTROOTMAXSLOT-1
4304 * (since slot[0] is occupied by the header).
4305 */
4306 if (unlikely(p->header.freecnt < 0 ||
4307 p->header.freecnt > DTROOTMAXSLOT - 1)) {
4308 jfs_err("Bad freecnt:%d in dtroot\n", p->header.freecnt);
4309 return false;
4310 } else if (p->header.freecnt == 0) {
4311 /* No free slots: freelist must be -1 */
4312 if (unlikely(p->header.freelist != -1)) {
4313 jfs_err("freecnt=0, but freelist=%d in dtroot\n",
4314 p->header.freelist);
4315 return false;
4316 }
4317 } else {
4318 int fsi, i;
4319 /* When there are free slots, freelist must be a valid slot index in
4320 * 1~DTROOTMAXSLOT-1(since slot[0] is occupied by the header).
4321 */
4322 if (unlikely(p->header.freelist < 1 ||
4323 p->header.freelist >= DTROOTMAXSLOT)) {
4324 jfs_err("Bad freelist:%d in dtroot\n", p->header.freelist);
4325 return false;
4326 }
4327
4328 /* Traverse the free list to check validity of all node indices */
4329 fsi = p->header.freelist;
4330 for (i = 0; i < p->header.freecnt - 1; i++) {
4331 /* Check for duplicate indices in the free list */
4332 if (unlikely(__test_and_set_bit(fsi, bitmap))) {
4333 jfs_err("duplicate index%d in slot in dtroot\n", fsi);
4334 return false;
4335 }
4336 fsi = p->slot[fsi].next;
4337
4338 /* Ensure the next slot index in the free list is valid */
4339 if (unlikely(fsi < 1 || fsi >= DTROOTMAXSLOT)) {
4340 jfs_err("Bad index:%d in slot in dtroot\n", fsi);
4341 return false;
4342 }
4343 }
4344
4345 /* The last node in the free list must terminate with next = -1 */
4346 if (unlikely(p->slot[fsi].next != -1)) {
4347 jfs_err("Bad next:%d of the last slot in dtroot\n",
4348 p->slot[fsi].next);
4349 return false;
4350 }
4351 }
4352
4353 /* Validate nextindex (next free entry index in stbl)
4354 * stbl array has size 8 (indices 0~7).
4355 * It may get set to 8 when the last free slot has been filled.
4356 */
4357 if (unlikely(p->header.nextindex > ARRAY_SIZE(p->header.stbl))) {
4358 jfs_err("Bad nextindex:%d in dtroot\n", p->header.nextindex);
4359 return false;
4360 }
4361
4362 /* Validate index validity of stbl array (8 elements)
4363 * Each entry in stbl is a slot index, with valid range: -1 (invalid)
4364 * or 0~8 (slot[0]~slot[8])
4365 */
4366 for (i = 0; i < p->header.nextindex; i++) {
4367 int idx = p->header.stbl[i];
4368
4369 if (unlikely(idx < 0 || idx >= 9)) {
4370 jfs_err("Bad index:%d of stbl[%d] in dtroot\n", idx, i);
4371 return false; /* stbl entry points out of slot array range */
4372 }
4373
4374 /* Check for duplicate valid indices (skip check for idx=0) */
4375 if (unlikely(idx && __test_and_set_bit(idx, bitmap))) {
4376 jfs_err("Duplicate index:%d in stbl in dtroot\n", idx);
4377 return false;
4378 }
4379 }
4380
4381 return true;
4382}
4383
4384bool check_dtpage(dtpage_t *p)
4385{
4386 DECLARE_BITMAP(bitmap, DTPAGEMAXSLOT) = {0};
4387 const int stblsize = ((PSIZE >> L2DTSLOTSIZE) + 31) >> L2DTSLOTSIZE;
4388 int i;
4389
4390 /* Validate maxslot (maximum number of slots in the page)
4391 * dtpage_t slot array is defined to hold up to DTPAGEMAXSLOT (128) slots
4392 */
4393 if (unlikely(p->header.maxslot != DTPAGEMAXSLOT)) {
4394 jfs_err("Bad maxslot:%d in dtpage (expected %d)\n",
4395 p->header.maxslot, DTPAGEMAXSLOT);
4396 return false;
4397 }
4398
4399 /* freecnt cannot be negative or exceed DTPAGEMAXSLOT-1
4400 * (since slot[0] is occupied by the header).
4401 */
4402 if (unlikely(p->header.freecnt < 0 ||
4403 p->header.freecnt > DTPAGEMAXSLOT - 1)) {
4404 jfs_err("Bad freecnt:%d in dtpage\n", p->header.freecnt);
4405 return false;
4406 } else if (p->header.freecnt == 0) {
4407 /* No free slots: freelist must be -1 */
4408 if (unlikely(p->header.freelist != -1)) {
4409 jfs_err("freecnt=0 but freelist=%d in dtpage\n",
4410 p->header.freelist);
4411 return false;
4412 }
4413 } else {
4414 int fsi;
4415
4416 if (unlikely(p->header.freelist < 1)) {
4417 jfs_err("Bad freelist:%d in dtpage\n", p->header.freelist);
4418 return false;
4419 }
4420
4421 /* Traverse the free list to check validity of all node indices */
4422 fsi = p->header.freelist;
4423 for (i = 0; i < p->header.freecnt - 1; i++) {
4424 /* Check for duplicate indices in the free list */
4425 if (unlikely(__test_and_set_bit(fsi, bitmap))) {
4426 jfs_err("duplicate index%d in slot in dtpage\n", fsi);
4427 return false;
4428 }
4429 fsi = p->slot[fsi].next;
4430
4431 /* Ensure the next slot index in the free list is valid */
4432 if (unlikely(fsi < 1 || fsi >= DTPAGEMAXSLOT)) {
4433 jfs_err("Bad index:%d in slot in dtpage\n", fsi);
4434 return false;
4435 }
4436 }
4437
4438 /* The last node in the free list must terminate with next = -1 */
4439 if (unlikely(p->slot[fsi].next != -1)) {
4440 jfs_err("Bad next:%d of the last slot in dtpage\n",
4441 p->slot[fsi].next);
4442 return false;
4443 }
4444 }
4445
4446 /* stbl must be little then DTPAGEMAXSLOT */
4447 if (unlikely(p->header.stblindex >= DTPAGEMAXSLOT - stblsize)) {
4448 jfs_err("Bad stblindex:%d in dtpage (stbl size %d)\n",
4449 p->header.stblindex, stblsize);
4450 return false;
4451 }
4452
4453 /* nextindex must be little then stblsize*32 */
4454 if (unlikely(p->header.nextindex > (stblsize << L2DTSLOTSIZE))) {
4455 jfs_err("Bad nextindex:%d in dtpage (stbl size %d)\n",
4456 p->header.nextindex, stblsize);
4457 return false;
4458 }
4459
4460 /* Validate stbl entries
4461 * Each entry is a slot index, valid range: -1 (invalid) or
4462 * [0, nextindex-1] (valid data slots)
4463 * (stblindex and higher slots are reserved for stbl itself)
4464 */
4465 for (i = 0; i < p->header.nextindex; i++) {
4466 int idx = DT_GETSTBL(p)[i];
4467
4468 /* Check if index is out of valid data slot range */
4469 if (unlikely(idx < 1 || idx >= DTPAGEMAXSLOT)) {
4470 jfs_err("Bad stbl[%d] index:%d (stblindex %d) in dtpage\n",
4471 i, idx, p->header.stblindex);
4472 return false;
4473 }
4474
4475 /* Check for duplicate valid indices (skip -1) */
4476 if (unlikely(__test_and_set_bit(idx, bitmap))) {
4477 jfs_err("Duplicate index:%d in stbl of dtpage\n", idx);
4478 return false;
4479 }
4480 }
4481
4482 return true;
4483}
fs/jfs/jfs_dtree.h+4−0
@@ -253,4 +253,8 @@ extern int dtModify(tid_t tid, struct inode *ip, struct component_name * key, · 252 unmodified lines
253 ino_t * orig_ino, ino_t new_ino, int flag);253 ino_t * orig_ino, ino_t new_ino, int flag);
254 254
255extern int jfs_readdir(struct file *file, struct dir_context *ctx);255extern int jfs_readdir(struct file *file, struct dir_context *ctx);
256
257extern bool check_dtroot(dtroot_t *p);
258
259extern bool check_dtpage(dtpage_t *p);
256#endif /* !_H_JFS_DTREE */260#endif /* !_H_JFS_DTREE */
fs/jfs/jfs_imap.c+4−0
@@ -3102,6 +3102,10 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip) · 3101 unmodified lines
3102 3102
3103 if (S_ISDIR(ip->i_mode)) {3103 if (S_ISDIR(ip->i_mode)) {
3104 memcpy(&jfs_ip->u.dir, &dip->u._dir, 384);3104 memcpy(&jfs_ip->u.dir, &dip->u._dir, 384);
3105 if (!check_dtroot(&jfs_ip->i_dtroot)) {
3106 jfs_error(ip->i_sb, "Corrupt dtroot\n");
3107 return -EIO;
3108 }
3105 } else if (S_ISREG(ip->i_mode) || S_ISLNK(ip->i_mode)) {3109 } else if (S_ISREG(ip->i_mode) || S_ISLNK(ip->i_mode)) {
3106 memcpy(&jfs_ip->i_xtroot, &dip->di_xtroot, 288);3110 memcpy(&jfs_ip->i_xtroot, &dip->di_xtroot, 288);
3107 } else3111 } else
fs/jfs/jfs_logmgr.c+14−20
@@ -74,12 +74,6 @@ static struct lbuf *log_redrive_list; · 73 unmodified lines
74static DEFINE_SPINLOCK(log_redrive_lock);74static DEFINE_SPINLOCK(log_redrive_lock);
75 75
76 76
77/*
78 * log read/write serialization (per log)
79 */
80#define LOG_LOCK_INIT(log) mutex_init(&(log)->loglock)
81#define LOG_LOCK(log) mutex_lock(&((log)->loglock))
82#define LOG_UNLOCK(log) mutex_unlock(&((log)->loglock))
83 77
84 78
85/*79/*
@@ -204,9 +198,13 @@ static void write_special_inodes(struct jfs_log *log, · 118 unmodified lines
204 struct jfs_sb_info *sbi;198 struct jfs_sb_info *sbi;
205 199
206 list_for_each_entry(sbi, &log->sb_list, log_list) {200 list_for_each_entry(sbi, &log->sb_list, log_list) {
207 writer(sbi->ipbmap->i_mapping);201 /* These pointers can be NULL before list_del during umount */
208 writer(sbi->ipimap->i_mapping);202 if (sbi->ipbmap)
209 writer(sbi->direct_inode->i_mapping);203 writer(sbi->ipbmap->i_mapping);
204 if (sbi->ipimap)
205 writer(sbi->ipimap->i_mapping);
206 if (sbi->direct_inode)
207 writer(sbi->direct_inode->i_mapping);
210 }208 }
211}209}
212 210
@@ -2180,8 +2178,6 @@ static void lbmIODone(struct bio *bio) · 1967 unmodified lines
2180 2178
2181 LCACHE_LOCK(flags); /* disable+lock */2179 LCACHE_LOCK(flags); /* disable+lock */
2182 2180
2183 bp->l_flag |= lbmDONE;
2184
2185 if (bio->bi_status) {2181 if (bio->bi_status) {
2186 bp->l_flag |= lbmERROR;2182 bp->l_flag |= lbmERROR;
2187 2183
@@ -2196,12 +2192,10 @@ static void lbmIODone(struct bio *bio) · 8 unmodified lines
2196 if (bp->l_flag & lbmREAD) {2192 if (bp->l_flag & lbmREAD) {
2197 bp->l_flag &= ~lbmREAD;2193 bp->l_flag &= ~lbmREAD;
2198 2194
2199 LCACHE_UNLOCK(flags); /* unlock+enable */
2200
2201 /* wakeup I/O initiator */2195 /* wakeup I/O initiator */
2202 LCACHE_WAKEUP(&bp->l_ioevent);2196 LCACHE_WAKEUP(&bp->l_ioevent);
2203 2197
2204 return;2198 goto out;
2205 }2199 }
2206 2200
2207 /*2201 /*
@@ -2225,8 +2219,7 @@ static void lbmIODone(struct bio *bio) · 17 unmodified lines
2225 2219
2226 if (bp->l_flag & lbmDIRECT) {2220 if (bp->l_flag & lbmDIRECT) {
2227 LCACHE_WAKEUP(&bp->l_ioevent);2221 LCACHE_WAKEUP(&bp->l_ioevent);
2228 LCACHE_UNLOCK(flags);2222 goto out;
2229 return;
2230 }2223 }
2231 2224
2232 tail = log->wqueue;2225 tail = log->wqueue;
@@ -2278,8 +2271,6 @@ static void lbmIODone(struct bio *bio) · 45 unmodified lines
2278 * leave buffer for i/o initiator to dispose2271 * leave buffer for i/o initiator to dispose
2279 */2272 */
2280 if (bp->l_flag & lbmSYNC) {2273 if (bp->l_flag & lbmSYNC) {
2281 LCACHE_UNLOCK(flags); /* unlock+enable */
2282
2283 /* wakeup I/O initiator */2274 /* wakeup I/O initiator */
2284 LCACHE_WAKEUP(&bp->l_ioevent);2275 LCACHE_WAKEUP(&bp->l_ioevent);
2285 }2276 }
@@ -2290,6 +2281,7 @@ static void lbmIODone(struct bio *bio) · 4 unmodified lines
2290 else if (bp->l_flag & lbmGC) {2281 else if (bp->l_flag & lbmGC) {
2291 LCACHE_UNLOCK(flags);2282 LCACHE_UNLOCK(flags);
2292 lmPostGC(bp);2283 lmPostGC(bp);
2284 LCACHE_LOCK(flags); /* disable+lock */
2293 }2285 }
2294 2286
2295 /*2287 /*
@@ -2302,9 +2294,11 @@ static void lbmIODone(struct bio *bio) · 6 unmodified lines
2302 assert(bp->l_flag & lbmRELEASE);2294 assert(bp->l_flag & lbmRELEASE);
2303 assert(bp->l_flag & lbmFREE);2295 assert(bp->l_flag & lbmFREE);
2304 lbmfree(bp);2296 lbmfree(bp);
2305
2306 LCACHE_UNLOCK(flags); /* unlock+enable */
2307 }2297 }
2298
2299out:
2300 bp->l_flag |= lbmDONE;
2301 LCACHE_UNLOCK(flags);
2308}2302}
2309 2303
2310int jfsIOWait(void *arg)2304int jfsIOWait(void *arg)
fs/jfs/jfs_logmgr.h+7−0
@@ -402,6 +402,13 @@ struct jfs_log { · 401 unmodified lines
402 int no_integrity; /* 3: flag to disable journaling to disk */402 int no_integrity; /* 3: flag to disable journaling to disk */
403};403};
404 404
405/*
406 * log read/write serialization (per log)
407 */
408#define LOG_LOCK_INIT(log) mutex_init(&(log)->loglock)
409#define LOG_LOCK(log) mutex_lock(&((log)->loglock))
410#define LOG_UNLOCK(log) mutex_unlock(&((log)->loglock))
411
405/*412/*
406 * Log flag413 * Log flag
407 */414 */
fs/jfs/jfs_metapage.c+2−1
@@ -270,6 +270,7 @@ static inline struct metapage *alloc_metapage(gfp_t gfp_mask) · 269 unmodified lines
270 mp->clsn = 0;270 mp->clsn = 0;
271 mp->log = NULL;271 mp->log = NULL;
272 init_waitqueue_head(&mp->wait);272 init_waitqueue_head(&mp->wait);
273 INIT_LIST_HEAD(&mp->synclist);
273 }274 }
274 return mp;275 return mp;
275}276}
@@ -379,7 +380,7 @@ static void remove_from_logsync(struct metapage *mp) · 103 unmodified lines
379 mp->lsn = 0;380 mp->lsn = 0;
380 mp->clsn = 0;381 mp->clsn = 0;
381 log->count--;382 log->count--;
382 list_del(&mp->synclist);383 list_del_init(&mp->synclist);
383 }384 }
384 LOGSYNC_UNLOCK(log, flags);385 LOGSYNC_UNLOCK(log, flags);
385}386}
fs/jfs/jfs_mount.c+2−1
@@ -378,11 +378,12 @@ static int chkSuper(struct super_block *sb) · 377 unmodified lines
378 sbi->nbperpage = PSIZE >> sbi->l2bsize;378 sbi->nbperpage = PSIZE >> sbi->l2bsize;
379 sbi->l2nbperpage = L2PSIZE - sbi->l2bsize;379 sbi->l2nbperpage = L2PSIZE - sbi->l2bsize;
380 sbi->l2niperblk = sbi->l2bsize - L2DISIZE;380 sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
381 uuid_copy(&sbi->uuid, &j_sb->s_uuid);
382
381 if (sbi->mntflag & JFS_INLINELOG)383 if (sbi->mntflag & JFS_INLINELOG)
382 sbi->logpxd = j_sb->s_logpxd;384 sbi->logpxd = j_sb->s_logpxd;
383 else {385 else {
384 sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev));386 sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev));
385 uuid_copy(&sbi->uuid, &j_sb->s_uuid);
386 uuid_copy(&sbi->loguuid, &j_sb->s_loguuid);387 uuid_copy(&sbi->loguuid, &j_sb->s_loguuid);
387 }388 }
388 sbi->fsckpxd = j_sb->s_fsckpxd;389 sbi->fsckpxd = j_sb->s_fsckpxd;
fs/jfs/jfs_txnmgr.c+2−1
@@ -275,6 +275,7 @@ int txInit(void) · 274 unmodified lines
275 for (k = 0; k < nTxBlock; k++) {275 for (k = 0; k < nTxBlock; k++) {
276 init_waitqueue_head(&TxBlock[k].gcwait);276 init_waitqueue_head(&TxBlock[k].gcwait);
277 init_waitqueue_head(&TxBlock[k].waitor);277 init_waitqueue_head(&TxBlock[k].waitor);
278 INIT_LIST_HEAD(&TxBlock[k].synclist);
278 }279 }
279 280
280 for (k = 1; k < nTxBlock - 1; k++) {281 for (k = 1; k < nTxBlock - 1; k++) {
@@ -974,7 +975,7 @@ static void txUnlock(struct tblock * tblk) · 693 unmodified lines
974 if (tblk->lsn) {975 if (tblk->lsn) {
975 LOGSYNC_LOCK(log, flags);976 LOGSYNC_LOCK(log, flags);
976 log->count--;977 log->count--;
977 list_del(&tblk->synclist);978 list_del_init(&tblk->synclist);
978 LOGSYNC_UNLOCK(log, flags);979 LOGSYNC_UNLOCK(log, flags);
979 }980 }
980}981}
fs/jfs/jfs_umount.c+10−0
@@ -20,6 +20,7 @@ · 19 unmodified lines
20#include "jfs_superblock.h"20#include "jfs_superblock.h"
21#include "jfs_dmap.h"21#include "jfs_dmap.h"
22#include "jfs_imap.h"22#include "jfs_imap.h"
23#include "jfs_logmgr.h"
23#include "jfs_metapage.h"24#include "jfs_metapage.h"
24#include "jfs_debug.h"25#include "jfs_debug.h"
25 26
@@ -57,6 +58,12 @@ int jfs_umount(struct super_block *sb) · 31 unmodified lines
57 */58 */
58 jfs_flush_journal(log, 2);59 jfs_flush_journal(log, 2);
59 60
61 /*
62 * Hold log lock so write_special_inodes (lmLogSync) cannot see
63 * this sbi with a NULL inode pointer while iterating log->sb_list.
64 */
65 if (log)
66 LOG_LOCK(log);
60 /*67 /*
61 * close fileset inode allocation map (aka fileset inode)68 * close fileset inode allocation map (aka fileset inode)
62 */69 */
@@ -95,6 +102,9 @@ int jfs_umount(struct super_block *sb) · 32 unmodified lines
95 */102 */
96 filemap_write_and_wait(sbi->direct_inode->i_mapping);103 filemap_write_and_wait(sbi->direct_inode->i_mapping);
97 104
105 if (log)
106 LOG_UNLOCK(log);
107
98 /*108 /*
99 * ensure all file system file pages are propagated to their109 * ensure all file system file pages are propagated to their
100 * home blocks on disk (and their in-memory buffer pages are110 * home blocks on disk (and their in-memory buffer pages are

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t