/* * Check whether there are new backup superblocks exist * in the last group. If there are some, mark them or clear * them in the bitmap. * * Return how many backups we find in the last group. */ static u16 ocfs2_calc_new_backup_super(struct inode *inode, struct ocfs2_group_desc *gd, int new_clusters, u32 first_new_cluster, u16 cl_cpg, int set) { int i; u16 backups = 0; u32 cluster; u64 blkno, gd_blkno, lgd_blkno = le64_to_cpu(gd->bg_blkno); for (i = 0; i < OCFS2_MAX_BACKUP_SUPERBLOCKS; i++) { blkno = ocfs2_backup_super_blkno(inode->i_sb, i); cluster = ocfs2_blocks_to_clusters(inode->i_sb, blkno); gd_blkno = ocfs2_which_cluster_group(inode, cluster); if (gd_blkno < lgd_blkno) continue; else if (gd_blkno > lgd_blkno) break; if (set) ocfs2_set_bit(cluster % cl_cpg, (unsigned long *)gd->bg_bitmap); else ocfs2_clear_bit(cluster % cl_cpg, (unsigned long *)gd->bg_bitmap); backups++; } return backups; }
/* Check whether the blkno is the super block or one of the backups. */ static void ocfs2_check_super_or_backup(struct super_block *sb, sector_t blkno) { int i; u64 backup_blkno; if (blkno == OCFS2_SUPER_BLOCK_BLKNO) return; for (i = 0; i < OCFS2_MAX_BACKUP_SUPERBLOCKS; i++) { backup_blkno = ocfs2_backup_super_blkno(sb, i); if (backup_blkno == blkno) return; } BUG(); }
static int update_backups(struct inode * inode, u32 clusters, char *data) { int i, ret = 0; u32 cluster; u64 blkno; struct buffer_head *backup = NULL; struct ocfs2_dinode *backup_di = NULL; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); /* calculate the real backups we need to update. */ for (i = 0; i < OCFS2_MAX_BACKUP_SUPERBLOCKS; i++) { blkno = ocfs2_backup_super_blkno(inode->i_sb, i); cluster = ocfs2_blocks_to_clusters(inode->i_sb, blkno); if (cluster > clusters) break; ret = ocfs2_read_blocks_sync(osb, blkno, 1, &backup); if (ret < 0) { mlog_errno(ret); break; } memcpy(backup->b_data, data, inode->i_sb->s_blocksize); backup_di = (struct ocfs2_dinode *)backup->b_data; backup_di->i_blkno = cpu_to_le64(blkno); ret = ocfs2_write_super_or_backup(osb, backup); brelse(backup); backup = NULL; if (ret < 0) { mlog_errno(ret); break; } } return ret; }
/* In case we don't have fs_blocksize, we will return * byte offsets and let the caller calculate them by itself. */ int ocfs2_get_backup_super_offsets(ocfs2_filesys *fs, uint64_t *offsets, size_t len) { size_t i; uint64_t blkno; uint32_t blocksize; memset(offsets, 0, sizeof(uint64_t) * len); len = ocfs2_min(len, (size_t)OCFS2_MAX_BACKUP_SUPERBLOCKS); if (fs) blocksize = fs->fs_blocksize; else blocksize = 1; for (i = 0; i < len; i++) { blkno = ocfs2_backup_super_blkno(blocksize, i); if (fs && fs->fs_blocks <= blkno) break; offsets[i] = blkno; } return i; }