cookbooks/fb_storage/resources/format_devices.rb (124 lines of code) (raw):

# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2 # # Copyright (c) 2016-present, Facebook, Inc. # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. property :do_reprobe, [true, false] action_class do include FB::Storage::FormatDevicesProvider end action :run do fb_storage_format_devices 'go again' do action :nothing do_reprobe false notifies :reload, 'ohai[filesystem]', :immediately end storage = FB::Storage.new(node) to_do = filesystems_to_format(storage) if to_do[:devices].empty? && to_do[:partitions].empty? && to_do[:arrays].empty? && to_do[:fill_arrays].empty? Chef::Log.info( 'fb_storage: No storage to converge, or no permission to do so', ) # if the user asked us to converge everything we could and there was nothing # to do, clean up that file file FB::Storage::CONVERGE_ALL_FILE do action :delete end else Chef::Log.debug( "fb_storage: filesystems_to_format to do is #{to_do}", ) if !to_do[:devices].empty? && new_resource.do_reprobe devices_to_reprobe = to_do[:devices].join(' ') Chef::Log.info("fb_storage: reprobing #{devices_to_reprobe} as requested") execute "reprobe #{devices_to_reprobe}" do command "partprobe #{devices_to_reprobe} && sleep 5" notifies :reload, 'ohai[filesystem]', :immediately notifies :run, 'fb_storage_format_devices[go again]', :immediately end else msg = [] unless to_do[:devices].empty? msg << "Partitioning #{to_do[:devices]}" end unless to_do[:partitions].empty? msg << "Formatting #{to_do[:partitions]}" end converge_by msg.join(', ') do converge_storage(to_do, storage) end end end # No matter what, we pass the data onto fb_fstab - this isn't a change # fb_fstab will report any changes it makes when it runs. # # unless we're in firstboot_os, since we don't converge storage until we're in # firstboot_tier unless node.firstboot_os? storage.gen_fb_fstab(node).each do |name, data| node.default['fb_fstab']['mounts'][name] = data end end # Determine if the kernel has multi-queue support enabled kernel_ver = FB::Version.new(node['kernel']['release']) kernel_mq_ver = FB::Version.new('4.11') kernel_has_mq = kernel_ver >= kernel_mq_ver # Finally, set any tunables storage.config.each_key do |device| dev = FB::Storage.device_name_from_path(device) if node['fb_storage']['tuning']['scheduler'] # ~FC023 fb_sysfs "/sys/block/#{dev}/queue/scheduler" do # Kernels prior to 4.11 do not have multi-queue support - t19377518 not_if { dev.start_with?('nvme') && !kernel_has_mq } type :list value node['fb_storage']['tuning']['scheduler'] end end if node['fb_storage']['tuning']['queue_depth'] # ~FC023 fb_sysfs "/sys/block/#{dev}/device/queue_depth" do type :int value node['fb_storage']['tuning']['queue_depth'] end end if node['fb_storage']['tuning']['discard_max_bytes'] # ~FC023 fname = "/sys/block/#{dev}/device/discard_max_bytes" fb_sysfs fname do only_if do # Only enables this setting when file exists and # file has root write permission bit set # This is due to older kernels don't support any # change to this file, we can tell if this is supported # by checking if root write permission bit is set # We're using the bitwise operation because internally ruby uses # eaccess which seems to consider root able to write anything # regardless of mode bits. ::File.exist?(fname) && ::File.stat(fname).mode & 0200 == 128 end type :int value node['fb_storage']['tuning']['discard_max_bytes'] end end # put a hard maximum on max_sectors_kb for nvme devices by default # (see T22006954) ignore_failure = FB::Fstab.get_in_maint_disks.include?(dev) nvme_max_sectors = 8192 max_sectors_kb = node['fb_storage']['tuning']['max_sectors_kb'] begin max_hw_sectors_kb = ::File.read("/sys/block/#{dev}/queue/max_hw_sectors_kb").to_i rescue StandardError if ignore_failure next else raise end end if dev.start_with?('nvme') if !max_sectors_kb Chef::Log.warn( 'fb_storage: max_sectors_kb unspecified for ' + "#{dev}, setting to #{nvme_max_sectors}.", ) max_sectors_kb = nvme_max_sectors elsif max_sectors_kb > nvme_max_sectors Chef::Log.warn( "fb_storage: max_sectors_kb #{max_sectors_kb} exceeds " + "allowed nvme limit for #{dev}, setting to #{nvme_max_sectors}.", ) max_sectors_kb = nvme_max_sectors end end if max_sectors_kb # set to the smaller of max_hw_sectors_kb and user chosen value if max_sectors_kb > max_hw_sectors_kb Chef::Log.warn( 'fb_storage: max_sectors_kb is limited by ' + "max_hw_sectors_kb, using #{max_hw_sectors_kb} instead " + "of #{max_sectors_kb}", ) max_sectors_kb = max_hw_sectors_kb end fb_sysfs "/sys/block/#{dev}/queue/max_sectors_kb" do type :int value max_sectors_kb ignore_failure ignore_failure end end end end