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
133133 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1
134134 };
135135
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+ */
142+static 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+
136223 /*
137224 * NAME: dbMount()
138225 *
@@ -1372,7 +1459,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) · 1233 unmodified lines
13721459 dcp = (struct dmapctl *) mp->data;
13731460 budmin = dcp->budmin;
13741461
1375− if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {
1462+ if (unlikely(!check_dmapctl(dcp))) {
13761463 jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");
13771464 release_metapage(mp);
13781465 return -EIO;
@@ -1702,7 +1789,7 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno) · 323 unmodified lines
17021789 dcp = (struct dmapctl *) mp->data;
17031790 budmin = dcp->budmin;
17041791
1705− if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {
1792+ if (unlikely(!check_dmapctl(dcp))) {
17061793 jfs_error(bmp->db_ipbmap->i_sb,
17071794 "Corrupt dmapctl page\n");
17081795 release_metapage(mp);
@@ -2485,7 +2572,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) · 776 unmodified lines
24852572 return -EIO;
24862573 dcp = (struct dmapctl *) mp->data;
24872574
2488− if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {
2575+ if (unlikely(!check_dmapctl(dcp))) {
24892576 jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");
24902577 release_metapage(mp);
24912578 return -EIO;
@@ -3454,6 +3541,11 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 962 unmodified lines
34543541 return -EIO;
34553542 }
34563543 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+ }
34573549
34583550 /* compute start L1 */
34593551 k = blkno >> L2MAXL1SIZE;
@@ -3471,6 +3563,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 11 unmodified lines
34713563 if (l1mp == NULL)
34723564 goto errout;
34733565 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+ }
34743570
34753571 /* compute start L0 */
34763572 j = (blkno & (MAXL1SIZE - 1)) >> L2MAXL0SIZE;
@@ -3484,6 +3580,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 7 unmodified lines
34843580 goto errout;
34853581
34863582 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+ }
34873587
34883588 /* compute start L0 */
34893589 j = 0;
@@ -3503,6 +3603,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 13 unmodified lines
35033603 if (l0mp == NULL)
35043604 goto errout;
35053605 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+ }
35063610
35073611 /* compute start dmap */
35083612 i = (blkno & (MAXL0SIZE - 1)) >>
@@ -3518,6 +3622,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) · 9 unmodified lines
35183622 goto errout;
35193623
35203624 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+ }
35213629
35223630 /* compute start dmap */
35233631 i = 0;
fs/jfs/jfs_dtree.c+188−4
@@ -115,10 +115,7 @@ struct dtsplit { · 114 unmodified lines
115115 do { \
116116 BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \
117117 if (!(RC)) { \
118− if (((P)->header.nextindex > \
119− (((BN) == 0) ? DTROOTMAXSLOT : (P)->header.maxslot)) || \
120− ((BN) && (((P)->header.maxslot > DTPAGEMAXSLOT) || \
121− ((P)->header.stblindex >= DTPAGEMAXSLOT)))) { \
118+ if ((BN) && !check_dtpage(P)) { \
122119 BT_PUTPAGE(MP); \
123120 jfs_error((IP)->i_sb, \
124121 "DT_GETPAGE: dtree page corrupt\n"); \
@@ -4297,3 +4294,190 @@ int dtModify(tid_t tid, struct inode *ip, · 4172 unmodified lines
42974294
42984295 return 0;
42994296 }
4297+
4298+bool 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+
4384+bool 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
253253 ino_t * orig_ino, ino_t new_ino, int flag);
254254
255255 extern int jfs_readdir(struct file *file, struct dir_context *ctx);
256+
257+extern bool check_dtroot(dtroot_t *p);
258+
259+extern bool check_dtpage(dtpage_t *p);
256260 #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
31023102
31033103 if (S_ISDIR(ip->i_mode)) {
31043104 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+ }
31053109 } else if (S_ISREG(ip->i_mode) || S_ISLNK(ip->i_mode)) {
31063110 memcpy(&jfs_ip->i_xtroot, &dip->di_xtroot, 288);
31073111 } else
fs/jfs/jfs_logmgr.c+14−20
@@ -74,12 +74,6 @@ static struct lbuf *log_redrive_list; · 73 unmodified lines
7474 static DEFINE_SPINLOCK(log_redrive_lock);
7575
7676
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))
8377
8478
8579 /*
@@ -204,9 +198,13 @@ static void write_special_inodes(struct jfs_log *log, · 118 unmodified lines
204198 struct jfs_sb_info *sbi;
205199
206200 list_for_each_entry(sbi, &log->sb_list, log_list) {
207− writer(sbi->ipbmap->i_mapping);
208− writer(sbi->ipimap->i_mapping);
209− writer(sbi->direct_inode->i_mapping);
201+ /* These pointers can be NULL before list_del during umount */
202+ if (sbi->ipbmap)
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);
210208 }
211209 }
212210
@@ -2180,8 +2178,6 @@ static void lbmIODone(struct bio *bio) · 1967 unmodified lines
21802178
21812179 LCACHE_LOCK(flags); /* disable+lock */
21822180
2183− bp->l_flag |= lbmDONE;
2184−
21852181 if (bio->bi_status) {
21862182 bp->l_flag |= lbmERROR;
21872183
@@ -2196,12 +2192,10 @@ static void lbmIODone(struct bio *bio) · 8 unmodified lines
21962192 if (bp->l_flag & lbmREAD) {
21972193 bp->l_flag &= ~lbmREAD;
21982194
2199− LCACHE_UNLOCK(flags); /* unlock+enable */
2200−
22012195 /* wakeup I/O initiator */
22022196 LCACHE_WAKEUP(&bp->l_ioevent);
22032197
2204− return;
2198+ goto out;
22052199 }
22062200
22072201 /*
@@ -2225,8 +2219,7 @@ static void lbmIODone(struct bio *bio) · 17 unmodified lines
22252219
22262220 if (bp->l_flag & lbmDIRECT) {
22272221 LCACHE_WAKEUP(&bp->l_ioevent);
2228− LCACHE_UNLOCK(flags);
2229− return;
2222+ goto out;
22302223 }
22312224
22322225 tail = log->wqueue;
@@ -2278,8 +2271,6 @@ static void lbmIODone(struct bio *bio) · 45 unmodified lines
22782271 * leave buffer for i/o initiator to dispose
22792272 */
22802273 if (bp->l_flag & lbmSYNC) {
2281− LCACHE_UNLOCK(flags); /* unlock+enable */
2282−
22832274 /* wakeup I/O initiator */
22842275 LCACHE_WAKEUP(&bp->l_ioevent);
22852276 }
@@ -2290,6 +2281,7 @@ static void lbmIODone(struct bio *bio) · 4 unmodified lines
22902281 else if (bp->l_flag & lbmGC) {
22912282 LCACHE_UNLOCK(flags);
22922283 lmPostGC(bp);
2284+ LCACHE_LOCK(flags); /* disable+lock */
22932285 }
22942286
22952287 /*
@@ -2302,9 +2294,11 @@ static void lbmIODone(struct bio *bio) · 6 unmodified lines
23022294 assert(bp->l_flag & lbmRELEASE);
23032295 assert(bp->l_flag & lbmFREE);
23042296 lbmfree(bp);
2305−
2306− LCACHE_UNLOCK(flags); /* unlock+enable */
23072297 }
2298+
2299+out:
2300+ bp->l_flag |= lbmDONE;
2301+ LCACHE_UNLOCK(flags);
23082302 }
23092303
23102304 int jfsIOWait(void *arg)
fs/jfs/jfs_logmgr.h+7−0
@@ -402,6 +402,13 @@ struct jfs_log { · 401 unmodified lines
402402 int no_integrity; /* 3: flag to disable journaling to disk */
403403 };
404404
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+
405412 /*
406413 * Log flag
407414 */
fs/jfs/jfs_metapage.c+2−1
@@ -270,6 +270,7 @@ static inline struct metapage *alloc_metapage(gfp_t gfp_mask) · 269 unmodified lines
270270 mp->clsn = 0;
271271 mp->log = NULL;
272272 init_waitqueue_head(&mp->wait);
273+ INIT_LIST_HEAD(&mp->synclist);
273274 }
274275 return mp;
275276 }
@@ -379,7 +380,7 @@ static void remove_from_logsync(struct metapage *mp) · 103 unmodified lines
379380 mp->lsn = 0;
380381 mp->clsn = 0;
381382 log->count--;
382− list_del(&mp->synclist);
383+ list_del_init(&mp->synclist);
383384 }
384385 LOGSYNC_UNLOCK(log, flags);
385386 }
fs/jfs/jfs_mount.c+2−1
@@ -378,11 +378,12 @@ static int chkSuper(struct super_block *sb) · 377 unmodified lines
378378 sbi->nbperpage = PSIZE >> sbi->l2bsize;
379379 sbi->l2nbperpage = L2PSIZE - sbi->l2bsize;
380380 sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
381+ uuid_copy(&sbi->uuid, &j_sb->s_uuid);
382+
381383 if (sbi->mntflag & JFS_INLINELOG)
382384 sbi->logpxd = j_sb->s_logpxd;
383385 else {
384386 sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev));
385− uuid_copy(&sbi->uuid, &j_sb->s_uuid);
386387 uuid_copy(&sbi->loguuid, &j_sb->s_loguuid);
387388 }
388389 sbi->fsckpxd = j_sb->s_fsckpxd;
fs/jfs/jfs_txnmgr.c+2−1
@@ -275,6 +275,7 @@ int txInit(void) · 274 unmodified lines
275275 for (k = 0; k < nTxBlock; k++) {
276276 init_waitqueue_head(&TxBlock[k].gcwait);
277277 init_waitqueue_head(&TxBlock[k].waitor);
278+ INIT_LIST_HEAD(&TxBlock[k].synclist);
278279 }
279280
280281 for (k = 1; k < nTxBlock - 1; k++) {
@@ -974,7 +975,7 @@ static void txUnlock(struct tblock * tblk) · 693 unmodified lines
974975 if (tblk->lsn) {
975976 LOGSYNC_LOCK(log, flags);
976977 log->count--;
977− list_del(&tblk->synclist);
978+ list_del_init(&tblk->synclist);
978979 LOGSYNC_UNLOCK(log, flags);
979980 }
980981 }
fs/jfs/jfs_umount.c+10−0
@@ -20,6 +20,7 @@ · 19 unmodified lines
2020 #include "jfs_superblock.h"
2121 #include "jfs_dmap.h"
2222 #include "jfs_imap.h"
23+#include "jfs_logmgr.h"
2324 #include "jfs_metapage.h"
2425 #include "jfs_debug.h"
2526
@@ -57,6 +58,12 @@ int jfs_umount(struct super_block *sb) · 31 unmodified lines
5758 */
5859 jfs_flush_journal(log, 2);
5960
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);
6067 /*
6168 * close fileset inode allocation map (aka fileset inode)
6269 */
@@ -95,6 +102,9 @@ int jfs_umount(struct super_block *sb) · 32 unmodified lines
95102 */
96103 filemap_write_and_wait(sbi->direct_inode->i_mapping);
97104
105+ if (log)
106+ LOG_UNLOCK(log);
107+
98108 /*
99109 * ensure all file system file pages are propagated to their
100110 * 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