return 0;
 }
 
+static pg_data_t *hotadd_new_pgdat(int nid, u64 start)
+{
+       struct pglist_data *pgdat;
+       unsigned long zones_size[MAX_NR_ZONES] = {0};
+       unsigned long zholes_size[MAX_NR_ZONES] = {0};
+       unsigned long start_pfn = start >> PAGE_SHIFT;
+
+       pgdat = arch_alloc_nodedata(nid);
+       if (!pgdat)
+               return NULL;
+
+       arch_refresh_nodedata(nid, pgdat);
+
+       /* we can use NODE_DATA(nid) from here */
+
+       /* init node's zones as empty zones, we don't have any present pages.*/
+       free_area_init_node(nid, pgdat, zones_size, start_pfn, zholes_size);
+
+       return pgdat;
+}
+
+static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
+{
+       arch_refresh_nodedata(nid, NULL);
+       arch_free_nodedata(pgdat);
+       return;
+}
+
 int add_memory(int nid, u64 start, u64 size)
 {
+       pg_data_t *pgdat = NULL;
+       int new_pgdat = 0;
        int ret;
 
+       if (!node_online(nid)) {
+               pgdat = hotadd_new_pgdat(nid, start);
+               if (!pgdat)
+                       return -ENOMEM;
+               new_pgdat = 1;
+               ret = kswapd_run(nid);
+               if (ret)
+                       goto error;
+       }
+
        /* call arch's memory hotadd */
        ret = arch_add_memory(nid, start, size);
 
+       if (ret < 0)
+               goto error;
+
+       /* we online node here. we have no error path from here. */
+       node_set_online(nid);
+
+       return ret;
+error:
+       /* rollback pgdat allocation and others */
+       if (new_pgdat)
+               rollback_node_hotadd(nid, pgdat);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(add_memory);