]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/aufs/finfo.c
UBUNTU: ubuntu: vbox -- update to 5.2.6-dfsg-5
[mirror_ubuntu-bionic-kernel.git] / fs / aufs / finfo.c
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 }