sbinfo.c 3.72 KB
Newer Older
J. R. Okajima's avatar
J. R. Okajima committed
1
2
3
4
5
6
7
8
9
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2005-2019 Junjiro R. Okajima
 */

/*
 * superblock private data
 */

J. R. Okajima's avatar
J. R. Okajima committed
10
#include <linux/iversion.h>
J. R. Okajima's avatar
J. R. Okajima committed
11
12
13
14
15
16
17
#include "aufs.h"

/*
 * they are necessary regardless sysfs is disabled.
 */
void au_si_free(struct kobject *kobj)
{
18
	int i;
J. R. Okajima's avatar
J. R. Okajima committed
19
	struct au_sbinfo *sbinfo;
20
	char *locked __maybe_unused; /* debug only */
J. R. Okajima's avatar
J. R. Okajima committed
21
22

	sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
23
24
	for (i = 0; i < AuPlink_NHASH; i++)
		AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i));
J. R. Okajima's avatar
J. R. Okajima committed
25
	AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
26
27
28
29
30

	au_rw_write_lock(&sbinfo->si_rwsem);
	au_br_free(sbinfo);
	au_rw_write_unlock(&sbinfo->si_rwsem);

J. R. Okajima's avatar
J. R. Okajima committed
31
	au_kfree_try_rcu(sbinfo->si_branch);
J. R. Okajima's avatar
J. R. Okajima committed
32
	mutex_destroy(&sbinfo->si_xib_mtx);
J. R. Okajima's avatar
J. R. Okajima committed
33
34
35
36
37
38
39
	AuRwDestroy(&sbinfo->si_rwsem);

	au_kfree_rcu(sbinfo);
}

int au_si_alloc(struct super_block *sb)
{
40
	int err, i;
J. R. Okajima's avatar
J. R. Okajima committed
41
42
43
44
45
46
47
48
49
50
51
52
	struct au_sbinfo *sbinfo;

	err = -ENOMEM;
	sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
	if (unlikely(!sbinfo))
		goto out;

	/* will be reallocated separately */
	sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
	if (unlikely(!sbinfo->si_branch))
		goto out_sbinfo;

J. R. Okajima's avatar
J. R. Okajima committed
53
54
55
56
	err = sysaufs_si_init(sbinfo);
	if (unlikely(err))
		goto out_br;

J. R. Okajima's avatar
J. R. Okajima committed
57
	au_nwt_init(&sbinfo->si_nowait);
J. R. Okajima's avatar
J. R. Okajima committed
58
59
60
	au_rw_init_wlock(&sbinfo->si_rwsem);

	sbinfo->si_bbot = -1;
61
	sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2;
J. R. Okajima's avatar
J. R. Okajima committed
62

63
	sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
J. R. Okajima's avatar
J. R. Okajima committed
64

J. R. Okajima's avatar
J. R. Okajima committed
65
66
67
	sbinfo->si_xino_jiffy = jiffies;
	sbinfo->si_xino_expire
		= msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC);
J. R. Okajima's avatar
J. R. Okajima committed
68
69
70
	mutex_init(&sbinfo->si_xib_mtx);
	/* leave si_xib_last_pindex and si_xib_next_bit */

71
72
73
74
75
	for (i = 0; i < AuPlink_NHASH; i++)
		INIT_HLIST_BL_HEAD(sbinfo->si_plink + i);
	init_waitqueue_head(&sbinfo->si_plink_wq);
	spin_lock_init(&sbinfo->si_plink_maint_lock);

J. R. Okajima's avatar
J. R. Okajima committed
76
	/* leave other members for sysaufs and si_mnt. */
J. R. Okajima's avatar
J. R. Okajima committed
77
	sbinfo->si_sb = sb;
J. R. Okajima's avatar
J. R. Okajima committed
78
	sb->s_fs_info = sbinfo;
79
	si_pid_set(sb);
J. R. Okajima's avatar
J. R. Okajima committed
80
81
	return 0; /* success */

J. R. Okajima's avatar
J. R. Okajima committed
82
out_br:
J. R. Okajima's avatar
J. R. Okajima committed
83
84
85
86
87
88
	au_kfree_try_rcu(sbinfo->si_branch);
out_sbinfo:
	au_kfree_rcu(sbinfo);
out:
	return err;
}
J. R. Okajima's avatar
J. R. Okajima committed
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink)
{
	int err, sz;
	struct au_branch **brp;

	AuRwMustWriteLock(&sbinfo->si_rwsem);

	err = -ENOMEM;
	sz = sizeof(*brp) * (sbinfo->si_bbot + 1);
	if (unlikely(!sz))
		sz = sizeof(*brp);
	brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS,
			   may_shrink);
	if (brp) {
		sbinfo->si_branch = brp;
		err = 0;
	}

	return err;
}

J. R. Okajima's avatar
J. R. Okajima committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* ---------------------------------------------------------------------- */

unsigned int au_sigen_inc(struct super_block *sb)
{
	unsigned int gen;
	struct inode *inode;

	SiMustWriteLock(sb);

	gen = ++au_sbi(sb)->si_generation;
	au_update_digen(sb->s_root);
	inode = d_inode(sb->s_root);
	au_update_iigen(inode, /*half*/0);
	inode_inc_iversion(inode);
	return gen;
}
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

aufs_bindex_t au_new_br_id(struct super_block *sb)
{
	aufs_bindex_t br_id;
	int i;
	struct au_sbinfo *sbinfo;

	SiMustWriteLock(sb);

	sbinfo = au_sbi(sb);
	for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
		br_id = ++sbinfo->si_last_br_id;
		AuDebugOn(br_id < 0);
		if (br_id && au_br_index(sb, br_id) < 0)
			return br_id;
	}

	return -1;
}
J. R. Okajima's avatar
J. R. Okajima committed
146
147
148
149
150
151

/* ---------------------------------------------------------------------- */

/* it is ok that new 'nwt' tasks are appended while we are sleeping */
int si_read_lock(struct super_block *sb, int flags)
{
152
153
154
	int err;

	err = 0;
J. R. Okajima's avatar
J. R. Okajima committed
155
156
157
158
	if (au_ftest_lock(flags, FLUSH))
		au_nwt_flush(&au_sbi(sb)->si_nowait);

	si_noflush_read_lock(sb);
159
160
161
	err = au_plink_maint(sb, flags);
	if (unlikely(err))
		si_read_unlock(sb);
J. R. Okajima's avatar
J. R. Okajima committed
162

163
	return err;
J. R. Okajima's avatar
J. R. Okajima committed
164
165
166
167
}

int si_write_lock(struct super_block *sb, int flags)
{
168
169
	int err;

J. R. Okajima's avatar
J. R. Okajima committed
170
171
172
173
	if (au_ftest_lock(flags, FLUSH))
		au_nwt_flush(&au_sbi(sb)->si_nowait);

	si_noflush_write_lock(sb);
174
175
176
	err = au_plink_maint(sb, flags);
	if (unlikely(err))
		si_write_unlock(sb);
J. R. Okajima's avatar
J. R. Okajima committed
177

178
	return err;
J. R. Okajima's avatar
J. R. Okajima committed
179
}