~ubuntu-branches/ubuntu/vivid/aufs/vivid

« back to all changes in this revision

Viewing changes to fs/aufs25/iinfo.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2008-05-06 18:35:50 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080506183550-0b6c974kkgc46oeh
Tags: 0+20080506-1
* New upstream release, supports Kernel 2.6.25 (Closes: #479717)
* Fix building with older Kernels (Closes: #475042)
* Update the patches 01, 04 and 07 to also patch fs/aufs25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005-2008 Junjiro 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, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 */
 
18
 
 
19
/*
 
20
 * inode private data
 
21
 *
 
22
 * $Id: iinfo.c,v 1.2 2008/04/21 01:32:05 sfjro Exp $
 
23
 */
 
24
 
 
25
#include "aufs.h"
 
26
 
 
27
struct au_iinfo *au_ii(struct inode *inode)
 
28
{
 
29
        struct au_iinfo *iinfo;
 
30
 
 
31
        iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
 
32
        /* bad_inode case */
 
33
        if (unlikely(!iinfo->ii_hinode))
 
34
                return NULL;
 
35
        AuDebugOn(!iinfo->ii_hinode
 
36
                  /* || au_sbi(inode->i_sb)->si_bend < iinfo->ii_bend */
 
37
                  || iinfo->ii_bend < iinfo->ii_bstart);
 
38
        return iinfo;
 
39
}
 
40
 
 
41
struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
 
42
{
 
43
        struct inode *hidden_inode;
 
44
 
 
45
        IiMustAnyLock(inode);
 
46
        AuDebugOn(bindex < 0 || au_ibend(inode) < bindex);
 
47
        hidden_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
 
48
        AuDebugOn(hidden_inode && atomic_read(&hidden_inode->i_count) <= 0);
 
49
        return hidden_inode;
 
50
}
 
51
 
 
52
aufs_bindex_t au_ii_br_id(struct inode *inode, aufs_bindex_t bindex)
 
53
{
 
54
        IiMustAnyLock(inode);
 
55
        AuDebugOn(bindex < 0
 
56
                  || au_ibend(inode) < bindex
 
57
                  || !au_ii(inode)->ii_hinode[0 + bindex].hi_inode);
 
58
        return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
 
59
}
 
60
 
 
61
// hard/soft set
 
62
void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
 
63
{
 
64
        struct au_iinfo *iinfo = au_ii(inode);
 
65
        struct inode *h_inode;
 
66
 
 
67
        IiMustWriteLock(inode);
 
68
        AuDebugOn(au_sbend(inode->i_sb) < bindex);
 
69
        iinfo->ii_bstart = bindex;
 
70
        h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
 
71
        if (h_inode)
 
72
                au_cpup_igen(inode, h_inode);
 
73
}
 
74
 
 
75
unsigned int au_hi_flags(struct inode *inode, int isdir)
 
76
{
 
77
        unsigned int flags;
 
78
        const unsigned int mnt_flags = au_mntflags(inode->i_sb);
 
79
 
 
80
        flags = 0;
 
81
        if (au_opt_test(mnt_flags, XINO))
 
82
                au_fset_hi(flags, XINO);
 
83
        if (unlikely(isdir && au_opt_test(mnt_flags, UDBA_INOTIFY)))
 
84
                au_fset_hi(flags, NOTIFY);
 
85
        return flags;
 
86
}
 
87
 
 
88
void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
 
89
                   struct inode *h_inode, unsigned int flags)
 
90
{
 
91
        struct au_hinode *hinode;
 
92
        struct inode *hi;
 
93
        struct au_iinfo *iinfo = au_ii(inode);
 
94
 
 
95
        LKTRTrace("i%lu, b%d, hi%lu, flags 0x%x\n",
 
96
                  inode->i_ino, bindex, h_inode ? h_inode->i_ino : 0, flags);
 
97
        IiMustWriteLock(inode);
 
98
        hinode = iinfo->ii_hinode + bindex;
 
99
        hi = hinode->hi_inode;
 
100
        AuDebugOn(bindex < au_ibstart(inode) || au_ibend(inode) < bindex
 
101
                  || (h_inode && atomic_read(&h_inode->i_count) <= 0)
 
102
                  || (h_inode && hi));
 
103
 
 
104
        if (hi) {
 
105
#if 0 // remove this
 
106
                if (!hi->i_nlink && au_ftest_hi(flags, XINO)) {
 
107
                        AuDebugOn(au_sbr_id(sb, bindex) != hinode->hi_id);
 
108
                        au_xino_write0(inode->i_sb, bindex, hi->i_ino, 0);
 
109
                        /* ignore this error */
 
110
                        /* bad action? */
 
111
                }
 
112
#endif
 
113
                au_hiput(hinode);
 
114
        }
 
115
        hinode->hi_inode = h_inode;
 
116
        if (h_inode) {
 
117
                int err;
 
118
                struct super_block *sb = inode->i_sb;
 
119
 
 
120
                if (bindex == iinfo->ii_bstart)
 
121
                        au_cpup_igen(inode, h_inode);
 
122
                hinode->hi_id = au_sbr_id(sb, bindex);
 
123
                if (au_ftest_hi(flags, XINO)) {
 
124
                        struct au_xino_entry xinoe = {
 
125
                                .ino    = inode->i_ino,
 
126
                                //.h_gen        = h_inode->i_generation
 
127
                        };
 
128
                        err = au_xino_write(sb, bindex, h_inode->i_ino, &xinoe);
 
129
                        if (unlikely(err))
 
130
                                AuIOErr1("failed au_xino_write() %d\n", err);
 
131
                }
 
132
 
 
133
                if (unlikely(au_ftest_hi(flags, NOTIFY)
 
134
                             && au_br_hinotifyable(au_sbr_perm(sb, bindex)))) {
 
135
                        err = au_hin_alloc(hinode, inode, h_inode);
 
136
                        if (unlikely(err))
 
137
                                AuIOErr1("au_hin_alloc() %d\n", err);
 
138
                }
 
139
        }
 
140
}
 
141
 
 
142
void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
 
143
                  struct dentry *h_wh)
 
144
{
 
145
        struct au_hinode *hinode;
 
146
 
 
147
        IiMustWriteLock(inode);
 
148
        hinode = au_ii(inode)->ii_hinode + bindex;
 
149
        AuDebugOn(hinode->hi_whdentry);
 
150
        hinode->hi_whdentry = h_wh;
 
151
}
 
152
 
 
153
void au_update_iigen(struct inode *inode)
 
154
{
 
155
        //IiMustWriteLock(inode);
 
156
        AuDebugOn(!inode->i_sb);
 
157
        atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
 
158
        //smp_mb(); /* atomic_set */
 
159
}
 
160
 
 
161
/* it may be called at remount time, too */
 
162
void au_update_brange(struct inode *inode, int do_put_zero)
 
163
{
 
164
        struct au_iinfo *iinfo;
 
165
 
 
166
        LKTRTrace("i%lu, %d\n", inode->i_ino, do_put_zero);
 
167
        IiMustWriteLock(inode);
 
168
 
 
169
        iinfo = au_ii(inode);
 
170
        if (unlikely(!iinfo) || iinfo->ii_bstart < 0)
 
171
                return;
 
172
 
 
173
        if (do_put_zero) {
 
174
                aufs_bindex_t bindex;
 
175
                for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
 
176
                     bindex++) {
 
177
                        struct inode *h_i;
 
178
                        h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
 
179
                        if (h_i && !h_i->i_nlink)
 
180
                                au_set_h_iptr(inode, bindex, NULL, 0);
 
181
                }
 
182
        }
 
183
 
 
184
        iinfo->ii_bstart = -1;
 
185
        while (++iinfo->ii_bstart <= iinfo->ii_bend)
 
186
                if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
 
187
                        break;
 
188
        if (iinfo->ii_bstart > iinfo->ii_bend) {
 
189
                iinfo->ii_bstart = -1;
 
190
                iinfo->ii_bend = -1;
 
191
                return;
 
192
        }
 
193
 
 
194
        iinfo->ii_bend++;
 
195
        while (0 <= --iinfo->ii_bend)
 
196
                if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
 
197
                        break;
 
198
        AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
 
199
}
 
200
 
 
201
/* ---------------------------------------------------------------------- */
 
202
 
 
203
int au_iinfo_init(struct inode *inode)
 
204
{
 
205
        struct au_iinfo *iinfo;
 
206
        struct super_block *sb;
 
207
        int nbr, i;
 
208
 
 
209
        sb = inode->i_sb;
 
210
        AuDebugOn(!sb);
 
211
        iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
 
212
        AuDebugOn(iinfo->ii_hinode);
 
213
        nbr = au_sbend(sb) + 1;
 
214
        if (unlikely(nbr <= 0))
 
215
                nbr = 1;
 
216
        iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_KERNEL);
 
217
        //iinfo->ii_hinode = NULL;
 
218
        if (iinfo->ii_hinode) {
 
219
                for (i = 0; i < nbr; i++)
 
220
                        iinfo->ii_hinode[i].hi_id = -1;
 
221
                atomic_set(&iinfo->ii_generation, au_sigen(sb));
 
222
                //smp_mb(); /* atomic_set */
 
223
                au_rw_init_nolock(&iinfo->ii_rwsem);
 
224
                iinfo->ii_bstart = -1;
 
225
                iinfo->ii_bend = -1;
 
226
                iinfo->ii_vdir = NULL;
 
227
                return 0;
 
228
        }
 
229
        return -ENOMEM;
 
230
}
 
231
 
 
232
static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
 
233
                           ino_t ino)
 
234
{
 
235
        int err, locked;
 
236
        aufs_bindex_t bindex;
 
237
 
 
238
        err = 0;
 
239
        locked = si_read_trylock(sb, !AuLock_FLUSH); // crucio!
 
240
        bindex = au_br_index(sb, hinode->hi_id);
 
241
        if (bindex >= 0)
 
242
                err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
 
243
        /* error action? */
 
244
        if (locked)
 
245
                si_read_unlock(sb);
 
246
        return err;
 
247
}
 
248
 
 
249
void au_iinfo_fin(struct inode *inode)
 
250
{
 
251
        struct au_iinfo *iinfo;
 
252
        aufs_bindex_t bend;
 
253
        struct au_hinode *hi;
 
254
        struct super_block *sb;
 
255
        int unlinked;
 
256
        ino_t ino;
 
257
 
 
258
        iinfo = au_ii(inode);
 
259
        /* bad_inode case */
 
260
        if (unlikely(!iinfo))
 
261
                return;
 
262
 
 
263
        if (unlikely(iinfo->ii_vdir))
 
264
                au_vdir_free(iinfo->ii_vdir);
 
265
 
 
266
        if (iinfo->ii_bstart >= 0) {
 
267
                sb = inode->i_sb;
 
268
                unlinked = !inode->i_nlink;
 
269
                ino = 0;
 
270
                if (unlinked)
 
271
                        ino = inode->i_ino;
 
272
                hi = iinfo->ii_hinode + iinfo->ii_bstart;
 
273
                bend = iinfo->ii_bend;
 
274
                while (iinfo->ii_bstart++ <= bend) {
 
275
                        if (hi->hi_inode) {
 
276
                                if (unlinked || !hi->hi_inode->i_nlink) {
 
277
                                        au_iinfo_write0(sb, hi, ino);
 
278
                                        /* ignore this error */
 
279
                                        ino = 0;
 
280
                                }
 
281
                                au_hiput(hi);
 
282
                        }
 
283
                        hi++;
 
284
                }
 
285
                //iinfo->ii_bstart = iinfo->ii_bend = -1;
 
286
        }
 
287
 
 
288
        kfree(iinfo->ii_hinode);
 
289
        //iinfo->ii_hinode = NULL;
 
290
}