hc
2024-05-10 ee930fffee469d076998274a2ca55e13dc1efb67
kernel/fs/nilfs2/super.c
....@@ -373,10 +373,31 @@
373373 goto out;
374374 }
375375 nsbp = (void *)nsbh->b_data + offset;
376
- memset(nsbp, 0, nilfs->ns_blocksize);
376
+
377
+ lock_buffer(nsbh);
378
+ if (sb2i >= 0) {
379
+ /*
380
+ * The position of the second superblock only changes by 4KiB,
381
+ * which is larger than the maximum superblock data size
382
+ * (= 1KiB), so there is no need to use memmove() to allow
383
+ * overlap between source and destination.
384
+ */
385
+ memcpy(nsbp, nilfs->ns_sbp[sb2i], nilfs->ns_sbsize);
386
+
387
+ /*
388
+ * Zero fill after copy to avoid overwriting in case of move
389
+ * within the same block.
390
+ */
391
+ memset(nsbh->b_data, 0, offset);
392
+ memset((void *)nsbp + nilfs->ns_sbsize, 0,
393
+ nsbh->b_size - offset - nilfs->ns_sbsize);
394
+ } else {
395
+ memset(nsbh->b_data, 0, nsbh->b_size);
396
+ }
397
+ set_buffer_uptodate(nsbh);
398
+ unlock_buffer(nsbh);
377399
378400 if (sb2i >= 0) {
379
- memcpy(nsbp, nilfs->ns_sbp[sb2i], nilfs->ns_sbsize);
380401 brelse(nilfs->ns_sbh[sb2i]);
381402 nilfs->ns_sbh[sb2i] = nsbh;
382403 nilfs->ns_sbp[sb2i] = nsbp;
....@@ -408,6 +429,15 @@
408429 devsize = i_size_read(sb->s_bdev->bd_inode);
409430 if (newsize > devsize)
410431 goto out;
432
+
433
+ /*
434
+ * Prevent underflow in second superblock position calculation.
435
+ * The exact minimum size check is done in nilfs_sufile_resize().
436
+ */
437
+ if (newsize < 4096) {
438
+ ret = -ENOSPC;
439
+ goto out;
440
+ }
411441
412442 /*
413443 * Write lock is required to protect some functions depending
....@@ -474,6 +504,7 @@
474504 up_write(&nilfs->ns_sem);
475505 }
476506
507
+ nilfs_sysfs_delete_device_group(nilfs);
477508 iput(nilfs->ns_sufile);
478509 iput(nilfs->ns_cpfile);
479510 iput(nilfs->ns_dat);
....@@ -1097,6 +1128,7 @@
10971128 nilfs_put_root(fsroot);
10981129
10991130 failed_unload:
1131
+ nilfs_sysfs_delete_device_group(nilfs);
11001132 iput(nilfs->ns_sufile);
11011133 iput(nilfs->ns_cpfile);
11021134 iput(nilfs->ns_dat);