[PATCH 06/16] fs/ntfs3: Reduce stack usage

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Signed-off-by: Konstantin Komarov <almaz.alexandrovich@xxxxxxxxxxxxxxxxxxxx>
---
 fs/ntfs3/fslog.c | 218 +++++++++++++++++++++--------------------------
 1 file changed, 98 insertions(+), 120 deletions(-)

diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c
index 98ccb6650858..7dbb000fc691 100644
--- a/fs/ntfs3/fslog.c
+++ b/fs/ntfs3/fslog.c
@@ -974,6 +974,16 @@ static inline void *alloc_rsttbl_from_idx(struct RESTART_TABLE **tbl, u32 vbo)
     return e;
 }

+struct restart_info {
+    u64 last_lsn;
+    struct RESTART_HDR *r_page;
+    u32 vbo;
+    bool chkdsk_was_run;
+    bool valid_page;
+    bool initialized;
+    bool restart;
+};
+
 #define RESTART_SINGLE_PAGE_IO cpu_to_le16(0x0001)

 #define NTFSLOG_WRAPPED 0x00000001
@@ -987,6 +997,7 @@ struct ntfs_log {
     struct ntfs_inode *ni;

     u32 l_size;
+    u32 orig_file_size;
     u32 sys_page_size;
     u32 sys_page_mask;
     u32 page_size;
@@ -1040,6 +1051,8 @@ struct ntfs_log {

     struct CLIENT_ID client_id;
     u32 client_undo_commit;
+
+    struct restart_info rst_info, rst_info2;
 };

 static inline u32 lsn_to_vbo(struct ntfs_log *log, const u64 lsn)
@@ -1105,16 +1118,6 @@ static inline bool verify_client_lsn(struct ntfs_log *log,
            lsn <= le64_to_cpu(log->ra->current_lsn) && lsn;
 }

-struct restart_info {
-    u64 last_lsn;
-    struct RESTART_HDR *r_page;
-    u32 vbo;
-    bool chkdsk_was_run;
-    bool valid_page;
-    bool initialized;
-    bool restart;
-};
-
 static int read_log_page(struct ntfs_log *log, u32 vbo,
              struct RECORD_PAGE_HDR **buffer, bool *usa_error)
 {
@@ -1176,7 +1179,7 @@ static int read_log_page(struct ntfs_log *log, u32 vbo,
  * restart page header. It will stop the first time we find a
  * valid page header.
  */
-static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first,
+static int log_read_rst(struct ntfs_log *log, bool first,
             struct restart_info *info)
 {
     u32 skip, vbo;
@@ -1192,7 +1195,7 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first,
     }

     /* Loop continuously until we succeed. */
-    for (; vbo < l_size; vbo = 2 * vbo + skip, skip = 0) {
+    for (; vbo < log->l_size; vbo = 2 * vbo + skip, skip = 0) {
         bool usa_error;
         bool brst, bchk;
         struct RESTART_AREA *ra;
@@ -1285,22 +1288,17 @@ static int log_read_rst(struct ntfs_log *log, u32 l_size, bool first,
 /*
  * Ilog_init_pg_hdr - Init @log from restart page header.
  */
-static void log_init_pg_hdr(struct ntfs_log *log, u32 sys_page_size,
-                u32 page_size, u16 major_ver, u16 minor_ver)
+static void log_init_pg_hdr(struct ntfs_log *log, u16 major_ver, u16 minor_ver)
 {
-    log->sys_page_size = sys_page_size;
-    log->sys_page_mask = sys_page_size - 1;
-    log->page_size = page_size;
-    log->page_mask = page_size - 1;
-    log->page_bits = blksize_bits(page_size);
+    log->sys_page_size = log->page_size;
+    log->sys_page_mask = log->page_mask;

     log->clst_per_page = log->page_size >> log->ni->mi.sbi->cluster_bits;
     if (!log->clst_per_page)
         log->clst_per_page = 1;

-    log->first_page = major_ver >= 2 ?
-                  0x22 * page_size :
-                  ((sys_page_size << 1) + (page_size << 1));
+    log->first_page = major_ver >= 2 ? 0x22 * log->page_size :
+                       4 * log->page_size;
     log->major_ver = major_ver;
     log->minor_ver = minor_ver;
 }
@@ -1308,12 +1306,11 @@ static void log_init_pg_hdr(struct ntfs_log *log, u32 sys_page_size,
 /*
  * log_create - Init @log in cases when we don't have a restart area to use.
  */
-static void log_create(struct ntfs_log *log, u32 l_size, const u64 last_lsn,
+static void log_create(struct ntfs_log *log, const u64 last_lsn,
                u32 open_log_count, bool wrapped, bool use_multi_page)
 {
-    log->l_size = l_size;
     /* All file offsets must be quadword aligned. */
-    log->file_data_bits = blksize_bits(l_size) - 3;
+    log->file_data_bits = blksize_bits(log->l_size) - 3;
     log->seq_num_mask = (8 << log->file_data_bits) - 1;
     log->seq_num_bits = sizeof(u64) * 8 - log->file_data_bits;
     log->seq_num = (last_lsn >> log->file_data_bits) + 2;
@@ -3720,10 +3717,8 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
     struct ntfs_sb_info *sbi = ni->mi.sbi;
     struct ntfs_log *log;

-    struct restart_info rst_info, rst_info2;
-    u64 rec_lsn, ra_lsn, checkpt_lsn = 0, rlsn = 0;
+    u64 rec_lsn, checkpt_lsn = 0, rlsn = 0;
     struct ATTR_NAME_ENTRY *attr_names = NULL;
-    struct ATTR_NAME_ENTRY *ane;
     struct RESTART_TABLE *dptbl = NULL;
     struct RESTART_TABLE *trtbl = NULL;
     const struct RESTART_TABLE *rt;
@@ -3741,9 +3736,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
     struct TRANSACTION_ENTRY *tr;
     struct DIR_PAGE_ENTRY *dp;
     u32 i, bytes_per_attr_entry;
-    u32 l_size = ni->vfs_inode.i_size;
-    u32 orig_file_size = l_size;
-    u32 page_size, vbo, tail, off, dlen;
+    u32 vbo, tail, off, dlen;
     u32 saved_len, rec_len, transact_id;
     bool use_second_page;
     struct RESTART_AREA *ra2, *ra = NULL;
@@ -3758,52 +3751,50 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
     u16 t16;
     u32 t32;

-    /* Get the size of page. NOTE: To replay we can use default page. */
-#if PAGE_SIZE >= DefaultLogPageSize && PAGE_SIZE <= DefaultLogPageSize * 2
-    page_size = norm_file_page(PAGE_SIZE, &l_size, true);
-#else
-    page_size = norm_file_page(PAGE_SIZE, &l_size, false);
-#endif
-    if (!page_size)
-        return -EINVAL;
-
     log = kzalloc(sizeof(struct ntfs_log), GFP_NOFS);
     if (!log)
         return -ENOMEM;

     log->ni = ni;
-    log->l_size = l_size;
-    log->one_page_buf = kmalloc(page_size, GFP_NOFS);
+    log->l_size = log->orig_file_size = ni->vfs_inode.i_size;
+
+    /* Get the size of page. NOTE: To replay we can use default page. */
+#if PAGE_SIZE >= DefaultLogPageSize && PAGE_SIZE <= DefaultLogPageSize * 2
+    log->page_size = norm_file_page(PAGE_SIZE, &log->l_size, true);
+#else
+    log->page_size = norm_file_page(PAGE_SIZE, &log->l_size, false);
+#endif
+    if (!log->page_size) {
+        err = -EINVAL;
+        goto out;
+    }

+    log->one_page_buf = kmalloc(log->page_size, GFP_NOFS);
     if (!log->one_page_buf) {
         err = -ENOMEM;
         goto out;
     }

-    log->page_size = page_size;
-    log->page_mask = page_size - 1;
-    log->page_bits = blksize_bits(page_size);
+    log->page_mask = log->page_size - 1;
+    log->page_bits = blksize_bits(log->page_size);

     /* Look for a restart area on the disk. */
-    memset(&rst_info, 0, sizeof(struct restart_info));
-    err = log_read_rst(log, l_size, true, &rst_info);
+    err = log_read_rst(log, true, &log->rst_info);
     if (err)
         goto out;

     /* remember 'initialized' */
-    *initialized = rst_info.initialized;
+    *initialized = log->rst_info.initialized;

-    if (!rst_info.restart) {
-        if (rst_info.initialized) {
+    if (!log->rst_info.restart) {
+        if (log->rst_info.initialized) {
             /* No restart area but the file is not initialized. */
             err = -EINVAL;
             goto out;
         }

-        log_init_pg_hdr(log, page_size, page_size, 1, 1);
-        log_create(log, l_size, 0, get_random_u32(), false, false);
-
-        log->ra = ra;
+        log_init_pg_hdr(log, 1, 1);
+        log_create(log, 0, get_random_u32(), false, false);

         ra = log_create_ra(log);
         if (!ra) {
@@ -3820,25 +3811,26 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
      * If the restart offset above wasn't zero then we won't
      * look for a second restart.
      */
-    if (rst_info.vbo)
+    if (log->rst_info.vbo)
         goto check_restart_area;

-    memset(&rst_info2, 0, sizeof(struct restart_info));
-    err = log_read_rst(log, l_size, false, &rst_info2);
+    err = log_read_rst(log, false, &log->rst_info2);
     if (err)
         goto out;

     /* Determine which restart area to use. */
-    if (!rst_info2.restart || rst_info2.last_lsn <= rst_info.last_lsn)
+    if (!log->rst_info2.restart ||
+        log->rst_info2.last_lsn <= log->rst_info.last_lsn)
         goto use_first_page;

     use_second_page = true;

-    if (rst_info.chkdsk_was_run && page_size != rst_info.vbo) {
+    if (log->rst_info.chkdsk_was_run &&
+        log->page_size != log->rst_info.vbo) {
         struct RECORD_PAGE_HDR *sp = NULL;
         bool usa_error;

-        if (!read_log_page(log, page_size, &sp, &usa_error) &&
+        if (!read_log_page(log, log->page_size, &sp, &usa_error) &&
             sp->rhdr.sign == NTFS_CHKD_SIGNATURE) {
             use_second_page = false;
         }
@@ -3846,52 +3838,43 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
     }

     if (use_second_page) {
-        kfree(rst_info.r_page);
-        memcpy(&rst_info, &rst_info2, sizeof(struct restart_info));
-        rst_info2.r_page = NULL;
+        kfree(log->rst_info.r_page);
+        memcpy(&log->rst_info, &log->rst_info2,
+               sizeof(struct restart_info));
+        log->rst_info2.r_page = NULL;
     }

 use_first_page:
-    kfree(rst_info2.r_page);
+    kfree(log->rst_info2.r_page);

 check_restart_area:
     /*
      * If the restart area is at offset 0, we want
      * to write the second restart area first.
      */
-    log->init_ra = !!rst_info.vbo;
+    log->init_ra = !!log->rst_info.vbo;

     /* If we have a valid page then grab a pointer to the restart area. */
-    ra2 = rst_info.valid_page ?
-              Add2Ptr(rst_info.r_page,
-                  le16_to_cpu(rst_info.r_page->ra_off)) :
+    ra2 = log->rst_info.valid_page ?
+              Add2Ptr(log->rst_info.r_page,
+                  le16_to_cpu(log->rst_info.r_page->ra_off)) :
               NULL;

-    if (rst_info.chkdsk_was_run ||
+    if (log->rst_info.chkdsk_was_run ||
         (ra2 && ra2->client_idx[1] == LFS_NO_CLIENT_LE)) {
         bool wrapped = false;
         bool use_multi_page = false;
         u32 open_log_count;

         /* Do some checks based on whether we have a valid log page. */
-        if (!rst_info.valid_page) {
-            open_log_count = get_random_u32();
-            goto init_log_instance;
-        }
-        open_log_count = le32_to_cpu(ra2->open_log_count);
-
-        /*
-         * If the restart page size isn't changing then we want to
-         * check how much work we need to do.
-         */
-        if (page_size != le32_to_cpu(rst_info.r_page->sys_page_size))
-            goto init_log_instance;
+        open_log_count = log->rst_info.valid_page ?
+                     le32_to_cpu(ra2->open_log_count) :
+                     get_random_u32();

-init_log_instance:
-        log_init_pg_hdr(log, page_size, page_size, 1, 1);
+        log_init_pg_hdr(log, 1, 1);

-        log_create(log, l_size, rst_info.last_lsn, open_log_count,
-               wrapped, use_multi_page);
+        log_create(log, log->rst_info.last_lsn, open_log_count, wrapped,
+               use_multi_page);

         ra = log_create_ra(log);
         if (!ra) {
@@ -3916,28 +3899,27 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
      * use the log file. We must use the system page size instead of the
      * default size if there is not a clean shutdown.
      */
-    t32 = le32_to_cpu(rst_info.r_page->sys_page_size);
-    if (page_size != t32) {
-        l_size = orig_file_size;
-        page_size =
-            norm_file_page(t32, &l_size, t32 == DefaultLogPageSize);
+    t32 = le32_to_cpu(log->rst_info.r_page->sys_page_size);
+    if (log->page_size != t32) {
+        log->l_size = log->orig_file_size;
+        log->page_size = norm_file_page(t32, &log->l_size,
+                        t32 == DefaultLogPageSize);
     }

-    if (page_size != t32 ||
-        page_size != le32_to_cpu(rst_info.r_page->page_size)) {
+    if (log->page_size != t32 ||
+        log->page_size != le32_to_cpu(log->rst_info.r_page->page_size)) {
         err = -EINVAL;
         goto out;
     }

     /* If the file size has shrunk then we won't mount it. */
-    if (l_size < le64_to_cpu(ra2->l_size)) {
+    if (log->l_size < le64_to_cpu(ra2->l_size)) {
         err = -EINVAL;
         goto out;
     }

-    log_init_pg_hdr(log, page_size, page_size,
-            le16_to_cpu(rst_info.r_page->major_ver),
-            le16_to_cpu(rst_info.r_page->minor_ver));
+    log_init_pg_hdr(log, le16_to_cpu(log->rst_info.r_page->major_ver),
+            le16_to_cpu(log->rst_info.r_page->minor_ver));

     log->l_size = le64_to_cpu(ra2->l_size);
     log->seq_num_bits = le32_to_cpu(ra2->seq_num_bits);
@@ -3945,7 +3927,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
     log->seq_num_mask = (8 << log->file_data_bits) - 1;
     log->last_lsn = le64_to_cpu(ra2->current_lsn);
     log->seq_num = log->last_lsn >> log->file_data_bits;
-    log->ra_off = le16_to_cpu(rst_info.r_page->ra_off);
+    log->ra_off = le16_to_cpu(log->rst_info.r_page->ra_off);
     log->restart_size = log->sys_page_size - log->ra_off;
     log->record_header_len = le16_to_cpu(ra2->rec_hdr_len);
     log->ra_size = le16_to_cpu(ra2->ra_len);
@@ -4045,7 +4027,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
     log->current_avail = current_log_avail(log);

     /* Remember which restart area to write first. */
-    log->init_ra = rst_info.vbo;
+    log->init_ra = log->rst_info.vbo;

 process_log:
     /* 1.0, 1.1, 2.0 log->major_ver/minor_ver - short values. */
@@ -4105,7 +4087,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
     log->client_id.seq_num = cr->seq_num;
     log->client_id.client_idx = client;

-    err = read_rst_area(log, &rst, &ra_lsn);
+    err = read_rst_area(log, &rst, &checkpt_lsn);
     if (err)
         goto out;

@@ -4114,9 +4096,8 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)

     bytes_per_attr_entry = !rst->major_ver ? 0x2C : 0x28;

-    checkpt_lsn = le64_to_cpu(rst->check_point_start);
-    if (!checkpt_lsn)
-        checkpt_lsn = ra_lsn;
+    if (rst->check_point_start)
+        checkpt_lsn = le64_to_cpu(rst->check_point_start);

     /* Allocate and Read the Transaction Table. */
     if (!rst->transact_table_len)
@@ -4330,23 +4311,20 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
     lcb = NULL;

 check_attribute_names2:
-    if (!rst->attr_names_len)
-        goto trace_attribute_table;
-
-    ane = attr_names;
-    if (!oatbl)
-        goto trace_attribute_table;
-    while (ane->off) {
-        /* TODO: Clear table on exit! */
-        oe = Add2Ptr(oatbl, le16_to_cpu(ane->off));
-        t16 = le16_to_cpu(ane->name_bytes);
-        oe->name_len = t16 / sizeof(short);
-        oe->ptr = ane->name;
-        oe->is_attr_name = 2;
-        ane = Add2Ptr(ane, sizeof(struct ATTR_NAME_ENTRY) + t16);
-    }
-
-trace_attribute_table:
+    if (rst->attr_names_len && oatbl) {
+        struct ATTR_NAME_ENTRY *ane = attr_names;
+        while (ane->off) {
+            /* TODO: Clear table on exit! */
+            oe = Add2Ptr(oatbl, le16_to_cpu(ane->off));
+            t16 = le16_to_cpu(ane->name_bytes);
+            oe->name_len = t16 / sizeof(short);
+            oe->ptr = ane->name;
+            oe->is_attr_name = 2;
+            ane = Add2Ptr(ane,
+                      sizeof(struct ATTR_NAME_ENTRY) + t16);
+        }
+    }
+
     /*
      * If the checkpt_lsn is zero, then this is a freshly
      * formatted disk and we have no work to do.
@@ -5189,7 +5167,7 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
     kfree(oatbl);
     kfree(dptbl);
     kfree(attr_names);
-    kfree(rst_info.r_page);
+    kfree(log->rst_info.r_page);

     kfree(ra);
     kfree(log->one_page_buf);
--
2.34.1





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux