]>
Commit | Line | Data |
---|---|---|
c088e31d SF |
1 | /* |
2 | * Copyright (C) 2005-2017 Junjiro R. Okajima | |
3 | * | |
4 | * This program, aufs is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | ||
18 | /* | |
19 | * file private data | |
20 | */ | |
21 | ||
22 | #include "aufs.h" | |
23 | ||
24 | void au_hfput(struct au_hfile *hf, int execed) | |
25 | { | |
26 | if (execed) | |
27 | allow_write_access(hf->hf_file); | |
28 | fput(hf->hf_file); | |
29 | hf->hf_file = NULL; | |
30 | au_br_put(hf->hf_br); | |
31 | hf->hf_br = NULL; | |
32 | } | |
33 | ||
34 | void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val) | |
35 | { | |
36 | struct au_finfo *finfo = au_fi(file); | |
37 | struct au_hfile *hf; | |
38 | struct au_fidir *fidir; | |
39 | ||
40 | fidir = finfo->fi_hdir; | |
41 | if (!fidir) { | |
42 | AuDebugOn(finfo->fi_btop != bindex); | |
43 | hf = &finfo->fi_htop; | |
44 | } else | |
45 | hf = fidir->fd_hfile + bindex; | |
46 | ||
47 | if (hf && hf->hf_file) | |
48 | au_hfput(hf, vfsub_file_execed(file)); | |
49 | if (val) { | |
50 | FiMustWriteLock(file); | |
51 | AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry)); | |
52 | hf->hf_file = val; | |
53 | hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex); | |
54 | } | |
55 | } | |
56 | ||
57 | void au_update_figen(struct file *file) | |
58 | { | |
59 | atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry)); | |
60 | /* smp_mb(); */ /* atomic_set */ | |
61 | } | |
62 | ||
63 | /* ---------------------------------------------------------------------- */ | |
64 | ||
65 | struct au_fidir *au_fidir_alloc(struct super_block *sb) | |
66 | { | |
67 | struct au_fidir *fidir; | |
68 | int nbr; | |
69 | ||
70 | nbr = au_sbbot(sb) + 1; | |
71 | if (nbr < 2) | |
72 | nbr = 2; /* initial allocate for 2 branches */ | |
73 | fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS); | |
74 | if (fidir) { | |
75 | fidir->fd_bbot = -1; | |
76 | fidir->fd_nent = nbr; | |
77 | } | |
78 | ||
79 | return fidir; | |
80 | } | |
81 | ||
82 | int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink) | |
83 | { | |
84 | int err; | |
85 | struct au_fidir *fidir, *p; | |
86 | ||
87 | AuRwMustWriteLock(&finfo->fi_rwsem); | |
88 | fidir = finfo->fi_hdir; | |
89 | AuDebugOn(!fidir); | |
90 | ||
91 | err = -ENOMEM; | |
92 | p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr), | |
93 | GFP_NOFS, may_shrink); | |
94 | if (p) { | |
95 | p->fd_nent = nbr; | |
96 | finfo->fi_hdir = p; | |
97 | err = 0; | |
98 | } | |
99 | ||
100 | return err; | |
101 | } | |
102 | ||
103 | /* ---------------------------------------------------------------------- */ | |
104 | ||
105 | void au_finfo_fin(struct file *file) | |
106 | { | |
107 | struct au_finfo *finfo; | |
108 | ||
109 | au_nfiles_dec(file->f_path.dentry->d_sb); | |
110 | ||
111 | finfo = au_fi(file); | |
112 | AuDebugOn(finfo->fi_hdir); | |
113 | AuRwDestroy(&finfo->fi_rwsem); | |
114 | au_cache_free_finfo(finfo); | |
115 | } | |
116 | ||
117 | void au_fi_init_once(void *_finfo) | |
118 | { | |
119 | struct au_finfo *finfo = _finfo; | |
120 | ||
121 | au_rw_init(&finfo->fi_rwsem); | |
122 | } | |
123 | ||
124 | int au_finfo_init(struct file *file, struct au_fidir *fidir) | |
125 | { | |
126 | int err; | |
127 | struct au_finfo *finfo; | |
128 | struct dentry *dentry; | |
129 | ||
130 | err = -ENOMEM; | |
131 | dentry = file->f_path.dentry; | |
132 | finfo = au_cache_alloc_finfo(); | |
133 | if (unlikely(!finfo)) | |
134 | goto out; | |
135 | ||
136 | err = 0; | |
137 | au_nfiles_inc(dentry->d_sb); | |
138 | au_rw_write_lock(&finfo->fi_rwsem); | |
139 | finfo->fi_btop = -1; | |
140 | finfo->fi_hdir = fidir; | |
141 | atomic_set(&finfo->fi_generation, au_digen(dentry)); | |
142 | /* smp_mb(); */ /* atomic_set */ | |
143 | ||
144 | file->private_data = finfo; | |
145 | ||
146 | out: | |
147 | return err; | |
148 | } |