aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs/super.c
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-06-25 10:28:56 -0400
committerAnton Altaparmakov <aia21@cantab.net>2005-06-25 10:28:56 -0400
commit3f2faef00c6af17542ea8672ed7d09367222b2d0 (patch)
tree8b5cf2d76f2af684988d79b04e21ae92aaea8711 /fs/ntfs/super.c
parent38b22b6e9f46ab8f73ef5734f0e0a000766a9258 (diff)
NTFS: Stamp the transaction log ($UsnJrnl), aka user space journal, if it
is active on the volume and we are mounting read-write or remounting from read-only to read-write. Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs/ntfs/super.c')
-rw-r--r--fs/ntfs/super.c254
1 files changed, 251 insertions, 3 deletions
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 455cbe0a6296..92e1d28219b3 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -34,6 +34,7 @@
34#include "sysctl.h" 34#include "sysctl.h"
35#include "logfile.h" 35#include "logfile.h"
36#include "quota.h" 36#include "quota.h"
37#include "usnjrnl.h"
37#include "dir.h" 38#include "dir.h"
38#include "debug.h" 39#include "debug.h"
39#include "index.h" 40#include "index.h"
@@ -497,6 +498,12 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
497 NVolSetErrors(vol); 498 NVolSetErrors(vol);
498 return -EROFS; 499 return -EROFS;
499 } 500 }
501 if (!ntfs_stamp_usnjrnl(vol)) {
502 ntfs_error(sb, "Failed to stamp transation log "
503 "($UsnJrnl)%s", es);
504 NVolSetErrors(vol);
505 return -EROFS;
506 }
500 } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { 507 } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
501 /* Remounting read-only. */ 508 /* Remounting read-only. */
502 if (!NVolErrors(vol)) { 509 if (!NVolErrors(vol)) {
@@ -1219,6 +1226,167 @@ static BOOL load_and_init_quota(ntfs_volume *vol)
1219} 1226}
1220 1227
1221/** 1228/**
1229 * load_and_init_usnjrnl - load and setup the transaction log if present
1230 * @vol: ntfs super block describing device whose usnjrnl file to load
1231 *
1232 * Return TRUE on success or FALSE on error.
1233 *
1234 * If $UsnJrnl is not present or in the process of being disabled, we set
1235 * NVolUsnJrnlStamped() and return success.
1236 *
1237 * If the $UsnJrnl $DATA/$J attribute has a size equal to the lowest valid usn,
1238 * i.e. transaction logging has only just been enabled or the journal has been
1239 * stamped and nothing has been logged since, we also set NVolUsnJrnlStamped()
1240 * and return success.
1241 */
1242static BOOL load_and_init_usnjrnl(ntfs_volume *vol)
1243{
1244 MFT_REF mref;
1245 struct inode *tmp_ino;
1246 ntfs_inode *tmp_ni;
1247 struct page *page;
1248 ntfs_name *name = NULL;
1249 USN_HEADER *uh;
1250 static const ntfschar UsnJrnl[9] = { const_cpu_to_le16('$'),
1251 const_cpu_to_le16('U'), const_cpu_to_le16('s'),
1252 const_cpu_to_le16('n'), const_cpu_to_le16('J'),
1253 const_cpu_to_le16('r'), const_cpu_to_le16('n'),
1254 const_cpu_to_le16('l'), 0 };
1255 static ntfschar Max[5] = { const_cpu_to_le16('$'),
1256 const_cpu_to_le16('M'), const_cpu_to_le16('a'),
1257 const_cpu_to_le16('x'), 0 };
1258 static ntfschar J[3] = { const_cpu_to_le16('$'),
1259 const_cpu_to_le16('J'), 0 };
1260
1261 ntfs_debug("Entering.");
1262 /*
1263 * Find the inode number for the transaction log file by looking up the
1264 * filename $UsnJrnl in the extended system files directory $Extend.
1265 */
1266 down(&vol->extend_ino->i_sem);
1267 mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), UsnJrnl, 8,
1268 &name);
1269 up(&vol->extend_ino->i_sem);
1270 if (IS_ERR_MREF(mref)) {
1271 /*
1272 * If the file does not exist, transaction logging is disabled,
1273 * just return success.
1274 */
1275 if (MREF_ERR(mref) == -ENOENT) {
1276 ntfs_debug("$UsnJrnl not present. Volume does not "
1277 "have transaction logging enabled.");
1278not_enabled:
1279 /*
1280 * No need to try to stamp the transaction log if
1281 * transaction logging is not enabled.
1282 */
1283 NVolSetUsnJrnlStamped(vol);
1284 return TRUE;
1285 }
1286 /* A real error occured. */
1287 ntfs_error(vol->sb, "Failed to find inode number for "
1288 "$UsnJrnl.");
1289 return FALSE;
1290 }
1291 /* We do not care for the type of match that was found. */
1292 kfree(name);
1293 /* Get the inode. */
1294 tmp_ino = ntfs_iget(vol->sb, MREF(mref));
1295 if (unlikely(IS_ERR(tmp_ino) || is_bad_inode(tmp_ino))) {
1296 if (!IS_ERR(tmp_ino))
1297 iput(tmp_ino);
1298 ntfs_error(vol->sb, "Failed to load $UsnJrnl.");
1299 return FALSE;
1300 }
1301 vol->usnjrnl_ino = tmp_ino;
1302 /*
1303 * If the transaction log is in the process of being deleted, we can
1304 * ignore it.
1305 */
1306 if (unlikely(vol->vol_flags & VOLUME_DELETE_USN_UNDERWAY)) {
1307 ntfs_debug("$UsnJrnl in the process of being disabled. "
1308 "Volume does not have transaction logging "
1309 "enabled.");
1310 goto not_enabled;
1311 }
1312 /* Get the $DATA/$Max attribute. */
1313 tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, Max, 4);
1314 if (IS_ERR(tmp_ino)) {
1315 ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$Max "
1316 "attribute.");
1317 return FALSE;
1318 }
1319 vol->usnjrnl_max_ino = tmp_ino;
1320 if (unlikely(i_size_read(tmp_ino) < sizeof(USN_HEADER))) {
1321 ntfs_error(vol->sb, "Found corrupt $UsnJrnl/$DATA/$Max "
1322 "attribute (size is 0x%llx but should be at "
1323 "least 0x%x bytes).", i_size_read(tmp_ino),
1324 sizeof(USN_HEADER));
1325 return FALSE;
1326 }
1327 /* Get the $DATA/$J attribute. */
1328 tmp_ino = ntfs_attr_iget(vol->usnjrnl_ino, AT_DATA, J, 2);
1329 if (IS_ERR(tmp_ino)) {
1330 ntfs_error(vol->sb, "Failed to load $UsnJrnl/$DATA/$J "
1331 "attribute.");
1332 return FALSE;
1333 }
1334 vol->usnjrnl_j_ino = tmp_ino;
1335 /* Verify $J is non-resident and sparse. */
1336 tmp_ni = NTFS_I(vol->usnjrnl_j_ino);
1337 if (unlikely(!NInoNonResident(tmp_ni) || !NInoSparse(tmp_ni))) {
1338 ntfs_error(vol->sb, "$UsnJrnl/$DATA/$J attribute is resident "
1339 "and/or not sparse.");
1340 return FALSE;
1341 }
1342 /* Read the USN_HEADER from $DATA/$Max. */
1343 page = ntfs_map_page(vol->usnjrnl_max_ino->i_mapping, 0);
1344 if (IS_ERR(page)) {
1345 ntfs_error(vol->sb, "Failed to read from $UsnJrnl/$DATA/$Max "
1346 "attribute.");
1347 return FALSE;
1348 }
1349 uh = (USN_HEADER*)page_address(page);
1350 /* Sanity check the $Max. */
1351 if (unlikely(sle64_to_cpu(uh->allocation_delta) >
1352 sle64_to_cpu(uh->maximum_size))) {
1353 ntfs_error(vol->sb, "Allocation delta (0x%llx) exceeds "
1354 "maximum size (0x%llx). $UsnJrnl is corrupt.",
1355 (long long)sle64_to_cpu(uh->allocation_delta),
1356 (long long)sle64_to_cpu(uh->maximum_size));
1357 ntfs_unmap_page(page);
1358 return FALSE;
1359 }
1360 /*
1361 * If the transaction log has been stamped and nothing has been written
1362 * to it since, we do not need to stamp it.
1363 */
1364 if (unlikely(sle64_to_cpu(uh->lowest_valid_usn) >=
1365 i_size_read(vol->usnjrnl_j_ino))) {
1366 if (likely(sle64_to_cpu(uh->lowest_valid_usn) ==
1367 i_size_read(vol->usnjrnl_j_ino))) {
1368 ntfs_unmap_page(page);
1369 ntfs_debug("$UsnJrnl is enabled but nothing has been "
1370 "logged since it was last stamped. "
1371 "Treating this as if the volume does "
1372 "not have transaction logging "
1373 "enabled.");
1374 goto not_enabled;
1375 }
1376 ntfs_error(vol->sb, "$UsnJrnl has lowest valid usn (0x%llx) "
1377 "which is out of bounds (0x%llx). $UsnJrnl "
1378 "is corrupt.",
1379 (long long)sle64_to_cpu(uh->lowest_valid_usn),
1380 i_size_read(vol->usnjrnl_j_ino));
1381 ntfs_unmap_page(page);
1382 return FALSE;
1383 }
1384 ntfs_unmap_page(page);
1385 ntfs_debug("Done.");
1386 return TRUE;
1387}
1388
1389/**
1222 * load_and_init_attrdef - load the attribute definitions table for a volume 1390 * load_and_init_attrdef - load the attribute definitions table for a volume
1223 * @vol: ntfs super block describing device whose attrdef to load 1391 * @vol: ntfs super block describing device whose attrdef to load
1224 * 1392 *
@@ -1653,7 +1821,7 @@ get_ctx_vol_failed:
1653 goto iput_logfile_err_out; 1821 goto iput_logfile_err_out;
1654 } 1822 }
1655 /* If on NTFS versions before 3.0, we are done. */ 1823 /* If on NTFS versions before 3.0, we are done. */
1656 if (vol->major_ver < 3) 1824 if (unlikely(vol->major_ver < 3))
1657 return TRUE; 1825 return TRUE;
1658 /* NTFS 3.0+ specific initialization. */ 1826 /* NTFS 3.0+ specific initialization. */
1659 /* Get the security descriptors inode. */ 1827 /* Get the security descriptors inode. */
@@ -1664,7 +1832,7 @@ get_ctx_vol_failed:
1664 ntfs_error(sb, "Failed to load $Secure."); 1832 ntfs_error(sb, "Failed to load $Secure.");
1665 goto iput_root_err_out; 1833 goto iput_root_err_out;
1666 } 1834 }
1667 // FIXME: Initialize security. 1835 // TODO: Initialize security.
1668 /* Get the extended system files' directory inode. */ 1836 /* Get the extended system files' directory inode. */
1669 vol->extend_ino = ntfs_iget(sb, FILE_Extend); 1837 vol->extend_ino = ntfs_iget(sb, FILE_Extend);
1670 if (IS_ERR(vol->extend_ino) || is_bad_inode(vol->extend_ino)) { 1838 if (IS_ERR(vol->extend_ino) || is_bad_inode(vol->extend_ino)) {
@@ -1715,10 +1883,60 @@ get_ctx_vol_failed:
1715 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME; 1883 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
1716 NVolSetErrors(vol); 1884 NVolSetErrors(vol);
1717 } 1885 }
1718 // TODO: Delete or checkpoint the $UsnJrnl if it exists. 1886 /*
1887 * Find the transaction log file ($UsnJrnl), load it if present, check
1888 * it, and set it up.
1889 */
1890 if (!load_and_init_usnjrnl(vol)) {
1891 static const char *es1 = "Failed to load $UsnJrnl";
1892 static const char *es2 = ". Run chkdsk.";
1893
1894 /* If a read-write mount, convert it to a read-only mount. */
1895 if (!(sb->s_flags & MS_RDONLY)) {
1896 if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO |
1897 ON_ERRORS_CONTINUE))) {
1898 ntfs_error(sb, "%s and neither on_errors="
1899 "continue nor on_errors="
1900 "remount-ro was specified%s",
1901 es1, es2);
1902 goto iput_usnjrnl_err_out;
1903 }
1904 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
1905 ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
1906 } else
1907 ntfs_warning(sb, "%s. Will not be able to remount "
1908 "read-write%s", es1, es2);
1909 /* This will prevent a read-write remount. */
1910 NVolSetErrors(vol);
1911 }
1912 /* If (still) a read-write mount, stamp the transaction log. */
1913 if (!(sb->s_flags & MS_RDONLY) && !ntfs_stamp_usnjrnl(vol)) {
1914 static const char *es1 = "Failed to stamp transaction log "
1915 "($UsnJrnl)";
1916 static const char *es2 = ". Run chkdsk.";
1917
1918 /* Convert to a read-only mount. */
1919 if (!(vol->on_errors & (ON_ERRORS_REMOUNT_RO |
1920 ON_ERRORS_CONTINUE))) {
1921 ntfs_error(sb, "%s and neither on_errors=continue nor "
1922 "on_errors=remount-ro was specified%s",
1923 es1, es2);
1924 goto iput_usnjrnl_err_out;
1925 }
1926 ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
1927 sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
1928 NVolSetErrors(vol);
1929 }
1719#endif /* NTFS_RW */ 1930#endif /* NTFS_RW */
1720 return TRUE; 1931 return TRUE;
1721#ifdef NTFS_RW 1932#ifdef NTFS_RW
1933iput_usnjrnl_err_out:
1934 if (vol->usnjrnl_j_ino)
1935 iput(vol->usnjrnl_j_ino);
1936 if (vol->usnjrnl_max_ino)
1937 iput(vol->usnjrnl_max_ino);
1938 if (vol->usnjrnl_ino)
1939 iput(vol->usnjrnl_ino);
1722iput_quota_err_out: 1940iput_quota_err_out:
1723 if (vol->quota_q_ino) 1941 if (vol->quota_q_ino)
1724 iput(vol->quota_q_ino); 1942 iput(vol->quota_q_ino);
@@ -1792,6 +2010,12 @@ static void ntfs_put_super(struct super_block *sb)
1792 2010
1793 /* NTFS 3.0+ specific. */ 2011 /* NTFS 3.0+ specific. */
1794 if (vol->major_ver >= 3) { 2012 if (vol->major_ver >= 3) {
2013 if (vol->usnjrnl_j_ino)
2014 ntfs_commit_inode(vol->usnjrnl_j_ino);
2015 if (vol->usnjrnl_max_ino)
2016 ntfs_commit_inode(vol->usnjrnl_max_ino);
2017 if (vol->usnjrnl_ino)
2018 ntfs_commit_inode(vol->usnjrnl_ino);
1795 if (vol->quota_q_ino) 2019 if (vol->quota_q_ino)
1796 ntfs_commit_inode(vol->quota_q_ino); 2020 ntfs_commit_inode(vol->quota_q_ino);
1797 if (vol->quota_ino) 2021 if (vol->quota_ino)
@@ -1847,6 +2071,18 @@ static void ntfs_put_super(struct super_block *sb)
1847 /* NTFS 3.0+ specific clean up. */ 2071 /* NTFS 3.0+ specific clean up. */
1848 if (vol->major_ver >= 3) { 2072 if (vol->major_ver >= 3) {
1849#ifdef NTFS_RW 2073#ifdef NTFS_RW
2074 if (vol->usnjrnl_j_ino) {
2075 iput(vol->usnjrnl_j_ino);
2076 vol->usnjrnl_j_ino = NULL;
2077 }
2078 if (vol->usnjrnl_max_ino) {
2079 iput(vol->usnjrnl_max_ino);
2080 vol->usnjrnl_max_ino = NULL;
2081 }
2082 if (vol->usnjrnl_ino) {
2083 iput(vol->usnjrnl_ino);
2084 vol->usnjrnl_ino = NULL;
2085 }
1850 if (vol->quota_q_ino) { 2086 if (vol->quota_q_ino) {
1851 iput(vol->quota_q_ino); 2087 iput(vol->quota_q_ino);
1852 vol->quota_q_ino = NULL; 2088 vol->quota_q_ino = NULL;
@@ -2463,6 +2699,18 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
2463 /* NTFS 3.0+ specific clean up. */ 2699 /* NTFS 3.0+ specific clean up. */
2464 if (vol->major_ver >= 3) { 2700 if (vol->major_ver >= 3) {
2465#ifdef NTFS_RW 2701#ifdef NTFS_RW
2702 if (vol->usnjrnl_j_ino) {
2703 iput(vol->usnjrnl_j_ino);
2704 vol->usnjrnl_j_ino = NULL;
2705 }
2706 if (vol->usnjrnl_max_ino) {
2707 iput(vol->usnjrnl_max_ino);
2708 vol->usnjrnl_max_ino = NULL;
2709 }
2710 if (vol->usnjrnl_ino) {
2711 iput(vol->usnjrnl_ino);
2712 vol->usnjrnl_ino = NULL;
2713 }
2466 if (vol->quota_q_ino) { 2714 if (vol->quota_q_ino) {
2467 iput(vol->quota_q_ino); 2715 iput(vol->quota_q_ino);
2468 vol->quota_q_ino = NULL; 2716 vol->quota_q_ino = NULL;