Index: lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java	(revision 1348794)
+++ lucene/core/src/java/org/apache/lucene/index/SegmentInfos.java	(working copy)
@@ -339,7 +339,7 @@
 
   private void write(Directory directory) throws IOException {
 
-    String segmentFileName = getNextSegmentFileName();
+    String segmentsFileName = getNextSegmentFileName();
     
     // Always advance the generation on write:
     if (generation == -1) {
@@ -354,7 +354,7 @@
     final Set<String> upgradedSIFiles = new HashSet<String>();
 
     try {
-      segnOutput = new ChecksumIndexOutput(directory.createOutput(segmentFileName, IOContext.DEFAULT));
+      segnOutput = new ChecksumIndexOutput(directory.createOutput(segmentsFileName, IOContext.DEFAULT));
       CodecUtil.writeHeader(segnOutput, "segments", VERSION_40);
       segnOutput.writeLong(version); 
       segnOutput.writeInt(counter); // write counter
@@ -373,9 +373,32 @@
         // "ugprade" to write the .si file for it:
         String version = si.getVersion();
         if (version == null || StringHelper.getVersionComparator().compare(version, "4.0") < 0) {
-          String fileName = IndexFileNames.segmentFileName(si.name, "", Lucene3xSegmentInfoFormat.UPGRADED_SI_EXTENSION);
-          if (!directory.fileExists(fileName)) {
-            upgradedSIFiles.add(write3xInfo(directory, si, IOContext.DEFAULT));
+
+          // Check marker file:
+          String markerFileName = IndexFileNames.segmentFileName(si.name, "upgraded", Lucene3xSegmentInfoFormat.UPGRADED_SI_EXTENSION);
+          if (!directory.fileExists(markerFileName)) {
+
+            // If there was a JVM kill/crash, OS crash, power loss,
+            // etc. last time, there could now be a partially
+            // upgraded file without the corresponding marker file:
+            if (directory.fileExists(fileName)) {
+              directory.deleteFile(fileName);
+            }
+
+            final String segmentFileName = write3xInfo(directory, si, IOContext.DEFAULT);
+            upgradedSIFiles.add(segmentFileName);
+            directory.sync(Collections.singletonList(segmentFileName));
+
+            // Write separate marker file indicating upgrade is completed
+            si.addFile(markerFileName);
+            IndexOutput out = directory.createOutput(markerFileName, IOContext.DEFAULT);
+            try {
+              CodecUtil.writeHeader(out, "SegmentInfo3xUpgrade", 0);
+            } finally {
+              out.close();
+            }
+            upgradedSIFiles.add(markerFileName);
+            directory.sync(Collections.singletonList(markerFileName));
           }
         }
       }
@@ -399,7 +422,7 @@
         try {
           // Try not to leave a truncated segments_N file in
           // the index:
-          directory.deleteFile(segmentFileName);
+          directory.deleteFile(segmentsFileName);
         } catch (Throwable t) {
           // Suppress so we keep throwing the original exception
         }
