Comment 4 for bug 1685899

Revision history for this message
bugproxy (bugproxy) wrote : Comment bridged from LTC Bugzilla

------- Comment From <email address hidden> 2017-04-24 17:11 EDT-------
In jfs_mount_rw() we have the following:

249 if (remount) {
250 if (chkSuper(sb) || (sbi->state != FM_CLEAN))
251 return -EINVAL;
252
253 truncate_inode_pages(sbi->ipimap->i_mapping, 0);
254 truncate_inode_pages(sbi->ipbmap->i_mapping, 0);
255 diUnmount(sbi->ipimap, 1);
256 if ((rc = diMount(sbi->ipimap))) {

and so the two truncate_inode_pages()

diUnmount() also does the following which to me seems like it should invalidate it a second time:

191 int diUnmount(struct inode *ipimap, int mounterror)
192 {
193 struct inomap *imap = JFS_IP(ipimap)->i_imap;
194
195 /*
196 * update the on-disk inode map control structure
197 */
198
199 if (!(mounterror || isReadOnly(ipimap)))
200 diSync(ipimap);
201
202 /*
203 * Invalidate the page cache buffers
204 */
205 truncate_inode_pages(ipimap->i_mapping, 0);
206
207 /*
208 * free in-memory control structure
209 */
210 kfree(imap);

but the interesting part is that it does a kfree() of the same struct inomap *imap that the diRead() routine references when it does the diIAGRead() call

319 jfs_info("diRead: ino = %ld", ip->i_ino);
320
321 ipimap = sbi->ipimap;
322 JFS_IP(ip)->ipimap = ipimap;
323
324 /* determine the iag number for this inode (number) */
325 iagno = INOTOIAG(ip->i_ino);
326
327 /* read the iag */
328 imap = JFS_IP(ipimap)->i_imap;
329 IREAD_LOCK(ipimap, RDWRLOCK_IMAP);
330 rc = diIAGRead(imap, iagno, &mp);

and dilAGRead() does:

2674 static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
2675 {
2676 struct inode *ipimap = imap->im_ipimap;
2677 s64 blkno;
2678
2679 /* compute the logical block number of the iag. */
2680 blkno = IAGTOLBLK(iagno, JFS_SBI(ipimap->i_sb)->l2nbperpage);
2681
2682 /* read the iag. */
2683 *mpp = read_metapage(ipimap, blkno, PSIZE, 0);

where read_metapage() is essentially:

66 #define read_metapage(inode, lblock, size, absolute)\
67 __get_metapage(inode, lblock, size, absolute, false)

I have to wonder if we have a window between the time that jfs_mount_rw() frees some of these structures hanging of parts of the sbi between the time it does the diUnmount() and the diMount() kmallocs a new struct inomap that something else reuses that freed structure while a parallel systemd operation is still running trying to read from something on /

255 diUnmount(sbi->ipimap, 1);
256 if ((rc = diMount(sbi->ipimap))) {

I am trying see if there is anything that prevents an attempt to diRead() between the above window but don't offhand see anything.