JFS: Take logsync lock before testing mp->lsn
This fixes a race where lsn could be cleared before taking the lock Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
This commit is contained in:
parent
5b3030e390
commit
be0bf7da19
|
@ -532,10 +532,10 @@ dbUpdatePMap(struct inode *ipbmap,
|
||||||
|
|
||||||
lastlblkno = lblkno;
|
lastlblkno = lblkno;
|
||||||
|
|
||||||
|
LOGSYNC_LOCK(log, flags);
|
||||||
if (mp->lsn != 0) {
|
if (mp->lsn != 0) {
|
||||||
/* inherit older/smaller lsn */
|
/* inherit older/smaller lsn */
|
||||||
logdiff(diffp, mp->lsn, log);
|
logdiff(diffp, mp->lsn, log);
|
||||||
LOGSYNC_LOCK(log, flags);
|
|
||||||
if (difft < diffp) {
|
if (difft < diffp) {
|
||||||
mp->lsn = lsn;
|
mp->lsn = lsn;
|
||||||
|
|
||||||
|
@ -548,20 +548,17 @@ dbUpdatePMap(struct inode *ipbmap,
|
||||||
logdiff(diffp, mp->clsn, log);
|
logdiff(diffp, mp->clsn, log);
|
||||||
if (difft > diffp)
|
if (difft > diffp)
|
||||||
mp->clsn = tblk->clsn;
|
mp->clsn = tblk->clsn;
|
||||||
LOGSYNC_UNLOCK(log, flags);
|
|
||||||
} else {
|
} else {
|
||||||
mp->log = log;
|
mp->log = log;
|
||||||
mp->lsn = lsn;
|
mp->lsn = lsn;
|
||||||
|
|
||||||
/* insert bp after tblock in logsync list */
|
/* insert bp after tblock in logsync list */
|
||||||
LOGSYNC_LOCK(log, flags);
|
|
||||||
|
|
||||||
log->count++;
|
log->count++;
|
||||||
list_add(&mp->synclist, &tblk->synclist);
|
list_add(&mp->synclist, &tblk->synclist);
|
||||||
|
|
||||||
mp->clsn = tblk->clsn;
|
mp->clsn = tblk->clsn;
|
||||||
LOGSYNC_UNLOCK(log, flags);
|
|
||||||
}
|
}
|
||||||
|
LOGSYNC_UNLOCK(log, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write the last buffer. */
|
/* write the last buffer. */
|
||||||
|
|
|
@ -2844,11 +2844,11 @@ diUpdatePMap(struct inode *ipimap,
|
||||||
*/
|
*/
|
||||||
lsn = tblk->lsn;
|
lsn = tblk->lsn;
|
||||||
log = JFS_SBI(tblk->sb)->log;
|
log = JFS_SBI(tblk->sb)->log;
|
||||||
|
LOGSYNC_LOCK(log, flags);
|
||||||
if (mp->lsn != 0) {
|
if (mp->lsn != 0) {
|
||||||
/* inherit older/smaller lsn */
|
/* inherit older/smaller lsn */
|
||||||
logdiff(difft, lsn, log);
|
logdiff(difft, lsn, log);
|
||||||
logdiff(diffp, mp->lsn, log);
|
logdiff(diffp, mp->lsn, log);
|
||||||
LOGSYNC_LOCK(log, flags);
|
|
||||||
if (difft < diffp) {
|
if (difft < diffp) {
|
||||||
mp->lsn = lsn;
|
mp->lsn = lsn;
|
||||||
/* move mp after tblock in logsync list */
|
/* move mp after tblock in logsync list */
|
||||||
|
@ -2860,17 +2860,15 @@ diUpdatePMap(struct inode *ipimap,
|
||||||
logdiff(diffp, mp->clsn, log);
|
logdiff(diffp, mp->clsn, log);
|
||||||
if (difft > diffp)
|
if (difft > diffp)
|
||||||
mp->clsn = tblk->clsn;
|
mp->clsn = tblk->clsn;
|
||||||
LOGSYNC_UNLOCK(log, flags);
|
|
||||||
} else {
|
} else {
|
||||||
mp->log = log;
|
mp->log = log;
|
||||||
mp->lsn = lsn;
|
mp->lsn = lsn;
|
||||||
/* insert mp after tblock in logsync list */
|
/* insert mp after tblock in logsync list */
|
||||||
LOGSYNC_LOCK(log, flags);
|
|
||||||
log->count++;
|
log->count++;
|
||||||
list_add(&mp->synclist, &tblk->synclist);
|
list_add(&mp->synclist, &tblk->synclist);
|
||||||
mp->clsn = tblk->clsn;
|
mp->clsn = tblk->clsn;
|
||||||
LOGSYNC_UNLOCK(log, flags);
|
|
||||||
}
|
}
|
||||||
|
LOGSYNC_UNLOCK(log, flags);
|
||||||
write_metapage(mp);
|
write_metapage(mp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue