aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs/super.c
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-06-25 11:31:27 -0400
committerAnton Altaparmakov <aia21@cantab.net>2005-06-25 11:31:27 -0400
commitca8fd7a0c6aa835e8014830b290cb965e85ac88e (patch)
tree504929d2a4beacb86fbc420c85f5c102f2a27fed /fs/ntfs/super.c
parent9f993fe4634b39ca4404ba278053b03f360ec08a (diff)
NTFS: Detect the case when Windows has been suspended to disk on the volume
to be mounted and if this is the case do not allow (re)mounting read-write. This is done by parsing hiberfil.sys if present. Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs/ntfs/super.c')
-rw-r--r--fs/ntfs/super.c179
1 files changed, 168 insertions, 11 deletions
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 92e1d28219b3..41aa8eb6755b 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -1156,6 +1156,124 @@ static BOOL load_and_check_logfile(ntfs_volume *vol)
1156 return TRUE; 1156 return TRUE;
1157} 1157}
1158 1158
1159#define NTFS_HIBERFIL_HEADER_SIZE 4096
1160
1161/**
1162 * check_windows_hibernation_status - check if Windows is suspended on a volume
1163 * @vol: ntfs super block of device to check
1164 *
1165 * Check if Windows is hibernated on the ntfs volume @vol. This is done by
1166 * looking for the file hiberfil.sys in the root directory of the volume. If
1167 * the file is not present Windows is definitely not suspended.
1168 *
1169 * If hiberfil.sys exists and is less than 4kiB in size it means Windows is
1170 * definitely suspended (this volume is not the system volume). Caveat: on a
1171 * system with many volumes it is possible that the < 4kiB check is bogus but
1172 * for now this should do fine.
1173 *
1174 * If hiberfil.sys exists and is larger than 4kiB in size, we need to read the
1175 * hiberfil header (which is the first 4kiB). If this begins with "hibr",
1176 * Windows is definitely suspended. If it is completely full of zeroes,
1177 * Windows is definitely not hibernated. Any other case is treated as if
1178 * Windows is suspended. This caters for the above mentioned caveat of a
1179 * system with many volumes where no "hibr" magic would be present and there is
1180 * no zero header.
1181 *
1182 * Return 0 if Windows is not hibernated on the volume, >0 if Windows is
1183 * hibernated on the volume, and -errno on error.
1184 */
1185static int check_windows_hibernation_status(ntfs_volume *vol)
1186{
1187 MFT_REF mref;
1188 struct inode *vi;
1189 ntfs_inode *ni;
1190 struct page *page;
1191 u32 *kaddr, *kend;
1192 ntfs_name *name = NULL;
1193 int ret = 1;
1194 static const ntfschar hiberfil[13] = { const_cpu_to_le16('h'),
1195 const_cpu_to_le16('i'), const_cpu_to_le16('b'),
1196 const_cpu_to_le16('e'), const_cpu_to_le16('r'),
1197 const_cpu_to_le16('f'), const_cpu_to_le16('i'),
1198 const_cpu_to_le16('l'), const_cpu_to_le16('.'),
1199 const_cpu_to_le16('s'), const_cpu_to_le16('y'),
1200 const_cpu_to_le16('s'), 0 };
1201
1202 ntfs_debug("Entering.");
1203 /*
1204 * Find the inode number for the hibernation file by looking up the
1205 * filename hiberfil.sys in the root directory.
1206 */
1207 down(&vol->root_ino->i_sem);
1208 mref = ntfs_lookup_inode_by_name(NTFS_I(vol->root_ino), hiberfil, 12,
1209 &name);
1210 up(&vol->root_ino->i_sem);
1211 if (IS_ERR_MREF(mref)) {
1212 ret = MREF_ERR(mref);
1213 /* If the file does not exist, Windows is not hibernated. */
1214 if (ret == -ENOENT) {
1215 ntfs_debug("hiberfil.sys not present. Windows is not "
1216 "hibernated on the volume.");
1217 return 0;
1218 }
1219 /* A real error occured. */
1220 ntfs_error(vol->sb, "Failed to find inode number for "
1221 "hiberfil.sys.");
1222 return ret;
1223 }
1224 /* We do not care for the type of match that was found. */
1225 kfree(name);
1226 /* Get the inode. */
1227 vi = ntfs_iget(vol->sb, MREF(mref));
1228 if (IS_ERR(vi) || is_bad_inode(vi)) {
1229 if (!IS_ERR(vi))
1230 iput(vi);
1231 ntfs_error(vol->sb, "Failed to load hiberfil.sys.");
1232 return IS_ERR(vi) ? PTR_ERR(vi) : -EIO;
1233 }
1234 if (unlikely(i_size_read(vi) < NTFS_HIBERFIL_HEADER_SIZE)) {
1235 ntfs_debug("hiberfil.sys is smaller than 4kiB (0x%llx). "
1236 "Windows is hibernated on the volume. This "
1237 "is not the system volume.", i_size_read(vi));
1238 goto iput_out;
1239 }
1240 ni = NTFS_I(vi);
1241 page = ntfs_map_page(vi->i_mapping, 0);
1242 if (IS_ERR(page)) {
1243 ntfs_error(vol->sb, "Failed to read from hiberfil.sys.");
1244 ret = PTR_ERR(page);
1245 goto iput_out;
1246 }
1247 kaddr = (u32*)page_address(page);
1248 if (*(le32*)kaddr == const_cpu_to_le32(0x72626968)/*'hibr'*/) {
1249 ntfs_debug("Magic \"hibr\" found in hiberfil.sys. Windows is "
1250 "hibernated on the volume. This is the "
1251 "system volume.");
1252 goto unm_iput_out;
1253 }
1254 kend = kaddr + NTFS_HIBERFIL_HEADER_SIZE/sizeof(*kaddr);
1255 do {
1256 if (unlikely(*kaddr)) {
1257 ntfs_debug("hiberfil.sys is larger than 4kiB "
1258 "(0x%llx), does not contain the "
1259 "\"hibr\" magic, and does not have a "
1260 "zero header. Windows is hibernated "
1261 "on the volume. This is not the "
1262 "system volume.", i_size_read(vi));
1263 goto unm_iput_out;
1264 }
1265 } while (++kaddr < kend);
1266 ntfs_debug("hiberfil.sys contains a zero header. Windows is not "
1267 "hibernated on the volume. This is the system "
1268 "volume.");
1269 ret = 0;
1270unm_iput_out:
1271 ntfs_unmap_page(page);
1272iput_out:
1273 iput(vi);
1274 return ret;
1275}
1276
1159/** 1277/**
1160 * load_and_init_quota - load and setup the quota file for a volume if present 1278 * load_and_init_quota - load and setup the quota file for a volume if present
1161 * @vol: ntfs super block describing device whose quota file to load 1279 * @vol: ntfs super block describing device whose quota file to load
@@ -1570,6 +1688,9 @@ static BOOL load_system_files(ntfs_volume *vol)
1570 MFT_RECORD *m; 1688 MFT_RECORD *m;
1571 VOLUME_INFORMATION *vi; 1689 VOLUME_INFORMATION *vi;
1572 ntfs_attr_search_ctx *ctx; 1690 ntfs_attr_search_ctx *ctx;
1691#ifdef NTFS_RW
1692 int err;
1693#endif /* NTFS_RW */
1573 1694
1574 ntfs_debug("Entering."); 1695 ntfs_debug("Entering.");
1575#ifdef NTFS_RW 1696#ifdef NTFS_RW
@@ -1746,6 +1867,50 @@ get_ctx_vol_failed:
1746 /* This will prevent a read-write remount. */ 1867 /* This will prevent a read-write remount. */
1747 NVolSetErrors(vol); 1868 NVolSetErrors(vol);
1748 } 1869 }
1870#endif /* NTFS_RW */
1871 /* Get the root directory inode so we can do path lookups. */
1872 vol->root_ino = ntfs_iget(sb, FILE_root);
1873 if (IS_ERR(vol->root_ino) || is_bad_inode(vol->root_ino)) {
1874 if (!IS_ERR(vol->root_ino))
1875 iput(vol->root_ino);
1876 ntfs_error(sb, "Failed to load root directory.");
1877 goto iput_logfile_err_out;
1878 }
1879#ifdef NTFS_RW
1880 /*
1881 * Check if Windows is suspended to disk on the target volume. If it
1882 * is hibernated, we must not write *anything* to the disk so set
1883 * NVolErrors() without setting the dirty volume flag and mount
1884 * read-only. This will prevent read-write remounting and it will also
1885 * prevent all writes.
1886 */
1887 err = check_windows_hibernation_status(vol);
1888 if (unlikely(err)) {
1889 static const char *es1a = "Failed to determine if Windows is "
1890 "hibernated";
1891 static const char *es1b = "Windows is hibernated";
1892 static const char *es2 = ". Run chkdsk.";
1893 const char *es1;
1894
1895 es1 = err < 0 ? es1a : es1b;
1896 /* If a read-write mount, convert it to a read-only mount. */
1897 if (!(sb->s_flags & MS_RDONLY)) {
1898 if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO |
1899 ON_ERRORS_CONTINUE))) {
1900 ntfs_error(sb, "%s and neither on_errors="
1901 "continue nor on_errors="
1902 "remount-ro was specified%s",
1903 es1, es2);
1904 goto iput_root_err_out;
1905 }
1906 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
1907 ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
1908 } else
1909 ntfs_warning(sb, "%s. Will not be able to remount "
1910 "read-write%s", es1, es2);
1911 /* This will prevent a read-write remount. */
1912 NVolSetErrors(vol);
1913 }
1749 /* If (still) a read-write mount, mark the volume dirty. */ 1914 /* If (still) a read-write mount, mark the volume dirty. */
1750 if (!(sb->s_flags & MS_RDONLY) && 1915 if (!(sb->s_flags & MS_RDONLY) &&
1751 ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) { 1916 ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) {
@@ -1759,7 +1924,7 @@ get_ctx_vol_failed:
1759 ntfs_error(sb, "%s and neither on_errors=continue nor " 1924 ntfs_error(sb, "%s and neither on_errors=continue nor "
1760 "on_errors=remount-ro was specified%s", 1925 "on_errors=remount-ro was specified%s",
1761 es1, es2); 1926 es1, es2);
1762 goto iput_logfile_err_out; 1927 goto iput_root_err_out;
1763 } 1928 }
1764 ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 1929 ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
1765 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; 1930 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
@@ -1786,7 +1951,7 @@ get_ctx_vol_failed:
1786 ntfs_error(sb, "%s and neither on_errors=continue nor " 1951 ntfs_error(sb, "%s and neither on_errors=continue nor "
1787 "on_errors=remount-ro was specified%s", 1952 "on_errors=remount-ro was specified%s",
1788 es1, es2); 1953 es1, es2);
1789 goto iput_logfile_err_out; 1954 goto iput_root_err_out;
1790 } 1955 }
1791 ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 1956 ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
1792 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; 1957 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
@@ -1805,21 +1970,13 @@ get_ctx_vol_failed:
1805 ntfs_error(sb, "%s and neither on_errors=continue nor " 1970 ntfs_error(sb, "%s and neither on_errors=continue nor "
1806 "on_errors=remount-ro was specified%s", 1971 "on_errors=remount-ro was specified%s",
1807 es1, es2); 1972 es1, es2);
1808 goto iput_logfile_err_out; 1973 goto iput_root_err_out;
1809 } 1974 }
1810 ntfs_error(sb, "%s. Mounting read-only%s", es1, es2); 1975 ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
1811 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; 1976 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
1812 NVolSetErrors(vol); 1977 NVolSetErrors(vol);
1813 } 1978 }
1814#endif /* NTFS_RW */ 1979#endif /* NTFS_RW */
1815 /* Get the root directory inode. */
1816 vol->root_ino = ntfs_iget(sb, FILE_root);
1817 if (IS_ERR(vol->root_ino) || is_bad_inode(vol->root_ino)) {
1818 if (!IS_ERR(vol->root_ino))
1819 iput(vol->root_ino);
1820 ntfs_error(sb, "Failed to load root directory.");
1821 goto iput_logfile_err_out;
1822 }
1823 /* If on NTFS versions before 3.0, we are done. */ 1980 /* If on NTFS versions before 3.0, we are done. */
1824 if (unlikely(vol->major_ver < 3)) 1981 if (unlikely(vol->major_ver < 3))
1825 return TRUE; 1982 return TRUE;