@@ -60,6 +60,7 @@ const (
6060 volumeLimitBig int64 = 127
6161 defaultLinuxFsType = "ext4"
6262 defaultWindowsFsType = "ntfs"
63+ fsTypeExt3 = "ext3"
6364)
6465
6566func getDefaultFsType () string {
@@ -311,8 +312,29 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
311312 return & csi.NodeStageVolumeResponse {}, nil
312313 }
313314
315+ readonly , _ := getReadOnlyFromCapability (volumeCapability )
316+ if readonly {
317+ options = append (options , "ro" )
318+ klog .V (4 ).Infof ("CSI volume is read-only, mounting with extra option ro" )
319+ }
320+
314321 err = formatAndMount (devicePath , stagingTargetPath , fstype , options , ns .Mounter )
315322 if err != nil {
323+ // If a volume is created from a content source like snapshot or cloning, the filesystem might get marked
324+ // as "dirty" even if it is otherwise consistent and ext3/4 will try to restore to a consistent state by replaying
325+ // the journal which is not possible in read-only mode. So we'll try again with noload option to skip it. This may
326+ // allow mounting of an actually inconsistent filesystem, but because the mount is read-only no further damage should
327+ // be caused.
328+ if readonly && (fstype == defaultLinuxFsType || fstype == fsTypeExt3 ) {
329+ klog .V (4 ).Infof ("Failed to mount CSI volume read-only, retry mounting with extra option noload" )
330+
331+ options = append (options , "noload" )
332+ err = formatAndMount (devicePath , stagingTargetPath , fstype , options , ns .Mounter )
333+ if err == nil {
334+ klog .V (4 ).Infof ("NodeStageVolume succeeded with \" noload\" option on %v to %s" , volumeID , stagingTargetPath )
335+ return & csi.NodeStageVolumeResponse {}, nil
336+ }
337+ }
316338 return nil , status .Error (codes .Internal ,
317339 fmt .Sprintf ("Failed to format and mount device from (%q) to (%q) with fstype (%q) and options (%q): %v" ,
318340 devicePath , stagingTargetPath , fstype , options , err ))
0 commit comments