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

« back to all changes in this revision

Viewing changes to fs/aufs/i_op.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2007-12-15 23:32:51 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20071215233251-2vgs2lmg8mai5d9e
Tags: 0+20071211-1ubuntu1
* Merge from debian unstable (LP: #175705), remaining changes:
  - Fix for Ubuntu Kernels (updated)
* patches/01_vserver.dpatch: Removed
* patches/06_ubuntu.dpatch: Added (update of ubuntu patch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
17
 */
18
18
 
19
 
/* $Id: i_op.c,v 1.33 2007/06/04 02:17:35 sfjro Exp $ */
 
19
/* $Id: i_op.c,v 1.51 2007/11/26 01:34:25 sfjro Exp $ */
20
20
 
21
21
//#include <linux/fs.h>
22
22
//#include <linux/namei.h>
23
23
#include <linux/security.h>
24
 
#include <asm/uaccess.h>
25
24
#include "aufs.h"
26
25
 
27
26
#ifdef CONFIG_AUFS_DLGT
38
37
        LKTRTrace("fsuid %d\n", current->fsuid);
39
38
        *a->errp = security_inode_permission(a->h_inode, a->mask, a->fake_nd);
40
39
}
41
 
#endif
 
40
#endif /* CONFIG_AUFS_DLGT */
42
41
 
43
 
static int hidden_permission(struct inode *hidden_inode, int mask,
44
 
                             struct nameidata *fake_nd, int brperm, int dlgt)
 
42
static int h_permission(struct inode *h_inode, int mask,
 
43
                        struct nameidata *fake_nd, int brperm, int dlgt)
45
44
{
46
45
        int err, submask;
47
46
        const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
48
47
 
49
48
        LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
50
 
                  hidden_inode->i_ino, mask, brperm);
 
49
                  h_inode->i_ino, mask, brperm);
51
50
 
52
51
        err = -EACCES;
53
 
        if (unlikely(write_mask && IS_IMMUTABLE(hidden_inode)))
 
52
        if (unlikely((write_mask && IS_IMMUTABLE(h_inode))
 
53
                     || ((mask & MAY_EXEC) && S_ISREG(h_inode->i_mode)
 
54
                         && fake_nd && fake_nd->mnt
 
55
                         && (fake_nd->mnt->mnt_flags & MNT_NOEXEC))
 
56
                    ))
54
57
                goto out;
55
58
 
56
59
        /* skip hidden fs test in the case of write to ro branch */
57
60
        submask = mask & ~MAY_APPEND;
58
61
        if (unlikely((write_mask && !br_writable(brperm))
59
 
                     || !hidden_inode->i_op
60
 
                     || !hidden_inode->i_op->permission)) {
 
62
                     || !h_inode->i_op
 
63
                     || !h_inode->i_op->permission)) {
61
64
                //LKTRLabel(generic_permission);
62
 
                err = generic_permission(hidden_inode, submask, NULL);
 
65
                err = generic_permission(h_inode, submask, NULL);
63
66
        } else {
64
67
                //LKTRLabel(h_inode->permission);
65
 
                err = hidden_inode->i_op->permission(hidden_inode, submask,
66
 
                                                     fake_nd);
67
 
                TraceErr(err);
 
68
                err = h_inode->i_op->permission(h_inode, submask, fake_nd);
 
69
                AuTraceErr(err);
68
70
        }
69
71
 
70
72
#if 1
71
73
        if (!err) {
72
74
#ifndef CONFIG_AUFS_DLGT
73
 
                err = security_inode_permission(hidden_inode, mask, fake_nd);
 
75
                err = security_inode_permission(h_inode, mask, fake_nd);
74
76
#else
75
77
                if (!dlgt)
76
 
                        err = security_inode_permission(hidden_inode, mask,
 
78
                        err = security_inode_permission(h_inode, mask,
77
79
                                                        fake_nd);
78
80
                else {
79
81
                        int wkq_err;
80
82
                        struct security_inode_permission_args args = {
81
83
                                .errp           = &err,
82
 
                                .h_inode        = hidden_inode,
 
84
                                .h_inode        = h_inode,
83
85
                                .mask           = mask,
84
86
                                .fake_nd        = fake_nd
85
87
                        };
88
90
                        if (unlikely(wkq_err))
89
91
                                err = wkq_err;
90
92
                }
91
 
#endif
 
93
#endif /* CONFIG_AUFS_DLGT */
92
94
        }
93
95
#endif
94
96
 
95
97
 out:
96
 
        TraceErr(err);
 
98
        AuTraceErr(err);
97
99
        return err;
98
100
}
99
101
 
105
107
        LKTRTrace("i%lu, nd %p\n", inode->i_ino, nd);
106
108
 
107
109
#ifdef CONFIG_AUFS_FAKE_DM
108
 
        si_read_lock(sb);
 
110
        si_read_lock(sb, !AuLock_FLUSH);
109
111
        ii_read_lock_child(inode);
110
112
#else
111
113
        if (!nd || !nd->dentry) {
112
 
                si_read_lock(sb);
 
114
                si_read_lock(sb, !AuLock_FLUSH);
113
115
                ii_read_lock_child(inode);
114
116
        } else if (nd->dentry->d_inode != inode) {
115
117
                locked = 1;
116
118
                /* lock child first, then parent */
117
 
                si_read_lock(sb);
 
119
                si_read_lock(sb, !AuLock_FLUSH);
118
120
                ii_read_lock_child(inode);
119
121
                di_read_lock_parent(nd->dentry, 0);
120
122
        } else {
121
123
                locked = 2;
122
 
                aufs_read_lock(nd->dentry, AUFS_I_RLOCK);
 
124
                aufs_read_lock(nd->dentry, AuLock_IR);
123
125
        }
124
 
#endif
 
126
#endif /* CONFIG_AUFS_FAKE_DM */
125
127
        return locked;
126
128
}
127
129
 
146
148
                si_read_unlock(sb);
147
149
                break;
148
150
        case 2:
149
 
                aufs_read_unlock(nd->dentry, AUFS_I_RLOCK);
 
151
                aufs_read_unlock(nd->dentry, AuLock_IR);
150
152
                break;
151
153
        default:
152
154
                BUG();
153
155
        }
154
 
#endif
 
156
#endif /* CONFIG_AUFS_FAKE_DM */
155
157
}
156
158
 
157
159
static int aufs_permission(struct inode *inode, int mask, struct nameidata *nd)
158
160
{
159
161
        int err, locked, dlgt;
160
162
        aufs_bindex_t bindex, bend;
161
 
        struct inode *hidden_inode;
 
163
        struct inode *h_inode;
162
164
        struct super_block *sb;
163
165
        struct nameidata fake_nd, *p;
164
166
        const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
165
167
        const int nondir = !S_ISDIR(inode->i_mode);
166
168
 
167
169
        LKTRTrace("ino %lu, mask 0x%x, nondir %d, write_mask %d, "
168
 
                  "nd %p{%p, %p}\n",
 
170
                  "nd %d{%d, %d}\n",
169
171
                  inode->i_ino, mask, nondir, write_mask,
170
 
                  nd, nd ? nd->dentry : NULL, nd ? nd->mnt : NULL);
 
172
                  !!nd, nd ? !!nd->dentry : 0, nd ? !!nd->mnt : 0);
171
173
 
172
174
        sb = inode->i_sb;
173
175
        locked = silly_lock(inode, nd);
174
 
        dlgt = need_dlgt(sb);
 
176
        dlgt = au_need_dlgt(sb);
175
177
 
176
178
        if (nd)
177
179
                fake_nd = *nd;
178
180
        if (/* unlikely */(nondir || write_mask)) {
179
 
                hidden_inode = au_h_iptr(inode);
180
 
                AuDebugOn(!hidden_inode
181
 
                          || ((hidden_inode->i_mode & S_IFMT)
 
181
                h_inode = au_h_iptr(inode);
 
182
                AuDebugOn(!h_inode
 
183
                          || ((h_inode->i_mode & S_IFMT)
182
184
                              != (inode->i_mode & S_IFMT)));
183
185
                err = 0;
184
186
                bindex = ibstart(inode);
185
 
                p = fake_dm(&fake_nd, nd, sb, bindex);
 
187
                p = au_fake_dm(&fake_nd, nd, sb, bindex);
186
188
                /* actual test will be delegated to LSM */
187
189
                if (IS_ERR(p))
188
190
                        AuDebugOn(PTR_ERR(p) != -ENOENT);
189
191
                else {
190
 
                        err = hidden_permission(hidden_inode, mask, p,
191
 
                                                sbr_perm(sb, bindex), dlgt);
192
 
                        fake_dm_release(p);
 
192
                        err = h_permission(h_inode, mask, p,
 
193
                                           sbr_perm(sb, bindex), dlgt);
 
194
                        au_fake_dm_release(p);
193
195
                }
194
196
                if (write_mask && !err) {
195
 
                        err = find_rw_br(sb, bindex);
196
 
                        if (err >= 0)
197
 
                                err = 0;
 
197
                        /* test whether the upper writable branch exists */
 
198
                        err = -EROFS;
 
199
                        for (; bindex >= 0; bindex--)
 
200
                                if (!br_rdonly(stobr(sb, bindex))) {
 
201
                                        err = 0;
 
202
                                        break;
 
203
                                }
198
204
                }
199
205
                goto out;
200
206
        }
203
209
        err = 0;
204
210
        bend = ibend(inode);
205
211
        for (bindex = ibstart(inode); !err && bindex <= bend; bindex++) {
206
 
                hidden_inode = au_h_iptr_i(inode, bindex);
207
 
                if (!hidden_inode)
 
212
                h_inode = au_h_iptr_i(inode, bindex);
 
213
                if (!h_inode)
208
214
                        continue;
209
 
                AuDebugOn(!S_ISDIR(hidden_inode->i_mode));
 
215
                AuDebugOn(!S_ISDIR(h_inode->i_mode));
210
216
 
211
 
                p = fake_dm(&fake_nd, nd, sb, bindex);
 
217
                p = au_fake_dm(&fake_nd, nd, sb, bindex);
212
218
                /* actual test will be delegated to LSM */
213
219
                if (IS_ERR(p))
214
220
                        AuDebugOn(PTR_ERR(p) != -ENOENT);
215
221
                else {
216
 
                        err = hidden_permission(hidden_inode, mask, p,
217
 
                                                sbr_perm(sb, bindex), dlgt);
218
 
                        fake_dm_release(p);
 
222
                        err = h_permission(h_inode, mask, p,
 
223
                                           sbr_perm(sb, bindex), dlgt);
 
224
                        au_fake_dm_release(p);
219
225
                }
220
226
        }
221
227
 
222
228
 out:
223
229
        silly_unlock(locked, inode, nd);
224
 
        TraceErr(err);
 
230
        AuTraceErr(err);
225
231
        return err;
226
232
}
227
233
 
233
239
        struct dentry *ret, *parent;
234
240
        int err, npositive;
235
241
        struct inode *inode;
 
242
        struct nameidata tmp_nd, *ndp;
 
243
        //todo: no more lower nameidata, only here. re-use it.
236
244
 
237
 
        LKTRTrace("dir %lu, %.*s\n", dir->i_ino, DLNPair(dentry));
 
245
        LKTRTrace("dir %lu, %.*s, nd{0x%x}\n",
 
246
                  dir->i_ino, AuDLNPair(dentry), nd ? nd->flags : 0);
238
247
        AuDebugOn(IS_ROOT(dentry));
239
248
        IMustLock(dir);
240
249
 
241
 
        // nd may be NULL
242
 
        parent = dget_parent(dentry);
243
 
        aufs_read_lock(parent, !AUFS_I_RLOCK);
 
250
        /* nd can be NULL */
 
251
        parent = dentry->d_parent; /* dir inode is locked */
 
252
        aufs_read_lock(parent, !AuLock_FLUSH);
244
253
        err = au_alloc_dinfo(dentry);
245
254
        //if (LktrCond) err = -1;
246
255
        ret = ERR_PTR(err);
247
256
        if (unlikely(err))
248
257
                goto out;
249
258
 
250
 
        err = npositive = lkup_dentry(dentry, dbstart(parent), /*type*/0);
 
259
        ndp = au_dup_nd(stosi(dir->i_sb), &tmp_nd, nd);
 
260
        npositive = au_lkup_dentry(dentry, dbstart(parent), /*type*/0, ndp);
 
261
        err = npositive;
 
262
        LKTRLabel(here);
251
263
        //err = -1;
252
264
        ret = ERR_PTR(err);
253
265
        if (unlikely(err < 0))
255
267
        inode = NULL;
256
268
        if (npositive) {
257
269
                inode = au_new_inode(dentry);
258
 
                ret = (void*)inode;
 
270
                ret = (void *)inode;
259
271
        }
260
272
        if (!IS_ERR(inode)) {
261
273
#if 1
266
278
#else
267
279
                d_add(dentry, inode);
268
280
#endif
 
281
                //AuDbgDentry(dentry);
 
282
                AuDebugOn(nd
 
283
                          && (nd->flags & LOOKUP_OPEN)
 
284
                          && nd->intent.open.file
 
285
                          && nd->intent.open.file->f_dentry);
 
286
                au_store_fmode_exec(nd, inode);
269
287
        }
270
288
 
271
289
 out_unlock:
272
290
        di_write_unlock(dentry);
273
291
 out:
274
 
        aufs_read_unlock(parent, !AUFS_I_RLOCK);
275
 
        dput(parent);
276
 
        TraceErrPtr(ret);
 
292
        aufs_read_unlock(parent, !AuLock_IR);
 
293
        AuTraceErrPtr(ret);
277
294
        return ret;
278
295
}
279
296
 
280
297
/* ---------------------------------------------------------------------- */
281
298
 
 
299
//todo: simplify
282
300
/*
283
301
 * decide the branch and the parent dir where we will create a new entry.
284
302
 * returns new bindex or an error.
285
303
 * copyup the parent dir if needed.
286
304
 */
287
 
int wr_dir(struct dentry *dentry, int add_entry, struct dentry *src_dentry,
288
 
           aufs_bindex_t force_btgt, int do_lock_srcdir)
 
305
int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
 
306
              struct au_wr_dir_args *args)
289
307
{
290
308
        int err;
291
309
        aufs_bindex_t bcpup, bstart, src_bstart;
292
 
        struct dentry *hidden_parent;
293
310
        struct super_block *sb;
294
 
        struct dentry *parent, *src_parent = NULL;
 
311
        struct dentry *parent, *src_parent = NULL, *h_parent;
295
312
        struct inode *dir, *src_dir = NULL;
 
313
        struct aufs_sbinfo *sbinfo;
296
314
 
297
 
        LKTRTrace("%.*s, add %d, src %p, force %d, lock_srcdir %d\n",
298
 
                  DLNPair(dentry), add_entry, src_dentry, force_btgt,
299
 
                  do_lock_srcdir);
 
315
        LKTRTrace("%.*s, src %p, {%d, %d, %d, %d}\n",
 
316
                  AuDLNPair(dentry), src_dentry, args->force_btgt,
 
317
                  args->add_entry, args->do_lock_srcdir, args->isdir);
 
318
        //AuDbgDentry(dentry);
300
319
 
301
320
        sb = dentry->d_sb;
 
321
        sbinfo = stosi(sb);
302
322
        parent = dget_parent(dentry);
303
 
        bcpup = bstart = dbstart(dentry);
304
 
        if (force_btgt < 0) {
 
323
        bstart = dbstart(dentry);
 
324
        bcpup = bstart;
 
325
        if (args->force_btgt < 0) {
305
326
                if (src_dentry) {
306
327
                        src_bstart = dbstart(src_dentry);
307
328
                        if (src_bstart < bstart)
308
329
                                bcpup = src_bstart;
 
330
                } else if (args->add_entry) {
 
331
                        err = AuWbrCreate(sbinfo, dentry, args->isdir);
 
332
                        bcpup = err;
309
333
                }
310
 
                if (test_ro(sb, bcpup, dentry->d_inode)) {
311
 
                        if (!add_entry)
312
 
                                di_read_lock_parent(parent, !AUFS_I_RLOCK);
313
 
                        bcpup = err = find_rw_parent_br(dentry, bcpup);
314
 
                        //bcpup = err = find_rw_br(sb, bcpup);
315
 
                        if (!add_entry)
316
 
                                di_read_unlock(parent, !AUFS_I_RLOCK);
 
334
 
 
335
                if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
 
336
                        if (args->add_entry)
 
337
                                err = AuWbrCopyup(sbinfo, dentry);
 
338
                        else {
 
339
                                di_read_lock_parent(parent, !AuLock_IR);
 
340
                                err = AuWbrCopyup(sbinfo, dentry);
 
341
                                di_read_unlock(parent, !AuLock_IR);
 
342
                        }
317
343
                        //err = -1;
 
344
                        bcpup = err;
318
345
                        if (unlikely(err < 0))
319
346
                                goto out;
320
347
                }
321
348
        } else {
322
 
                AuDebugOn(bstart <= force_btgt
323
 
                          || test_ro(sb, force_btgt, dentry->d_inode));
324
 
                bcpup = force_btgt;
 
349
                bcpup = args->force_btgt;
 
350
                AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
325
351
        }
326
352
        LKTRTrace("bstart %d, bcpup %d\n", bstart, bcpup);
 
353
        if (bstart < bcpup)
 
354
                au_update_dbrange(dentry, /*do_put_zero*/1);
327
355
 
328
356
        err = bcpup;
329
357
        if (bcpup == bstart)
330
358
                goto out; /* success */
331
359
 
332
360
        /* copyup the new parent into the branch we process */
333
 
        hidden_parent = dget_parent(au_h_dptr(dentry));
334
361
        if (src_dentry) {
335
362
                src_parent = dget_parent(src_dentry);
336
363
                src_dir = src_parent->d_inode;
337
 
                if (do_lock_srcdir)
 
364
                if (args->do_lock_srcdir)
338
365
                        di_write_lock_parent2(src_parent);
339
366
        }
340
367
 
341
368
        dir = parent->d_inode;
342
 
        if (add_entry) {
 
369
        if (args->add_entry) {
343
370
                au_update_dbstart(dentry);
344
371
                IMustLock(dir);
345
372
                DiMustWriteLock(parent);
348
375
                di_write_lock_parent(parent);
349
376
 
350
377
        err = 0;
351
 
        if (!au_h_dptr_i(parent, bcpup))
352
 
                err = cpup_dirs(dentry, bcpup, src_parent);
 
378
        if (!au_h_dptr_i(parent, bcpup)) {
 
379
                if (bstart < bcpup)
 
380
                        err = au_cpdown_dirs(dentry, bcpup, src_parent);
 
381
                else
 
382
                        err = au_cpup_dirs(dentry, bcpup, src_parent);
 
383
        }
353
384
        //err = -1;
354
 
        if (!err && add_entry) {
355
 
                dput(hidden_parent);
356
 
                hidden_parent = dget(au_h_dptr_i(parent, bcpup));
357
 
                AuDebugOn(!hidden_parent || !hidden_parent->d_inode);
358
 
                hi_lock_parent(hidden_parent->d_inode);
359
 
                err = lkup_neg(dentry, bcpup);
 
385
        if (!err && args->add_entry) {
 
386
                h_parent = au_h_dptr_i(parent, bcpup);
 
387
                AuDebugOn(!h_parent || !h_parent->d_inode);
 
388
                vfsub_i_lock_nested(h_parent->d_inode, AuLsc_I_PARENT);
 
389
                err = au_lkup_neg(dentry, bcpup);
360
390
                //err = -1;
361
 
                i_unlock(hidden_parent->d_inode);
 
391
                vfsub_i_unlock(h_parent->d_inode);
 
392
                if (bstart < bcpup && dbstart(dentry) < 0) {
 
393
                        set_dbstart(dentry, 0);
 
394
                        au_update_dbrange(dentry, /*do_put_zero*/0);
 
395
                }
362
396
        }
363
 
        dput(hidden_parent);
364
397
 
365
 
        if (!add_entry)
 
398
        if (!args->add_entry)
366
399
                di_write_unlock(parent);
367
 
        if (do_lock_srcdir)
 
400
        if (args->do_lock_srcdir)
368
401
                di_write_unlock(src_parent);
369
402
        dput(src_parent);
370
403
        if (!err)
372
405
        //err = -EPERM;
373
406
 out:
374
407
        dput(parent);
375
 
        TraceErr(err);
 
408
        LKTRTrace("err %d\n", err);
 
409
        AuTraceErr(err);
376
410
        return err;
377
411
}
378
412
 
380
414
 
381
415
static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
382
416
{
383
 
        int err, isdir;
 
417
        int err;
384
418
        aufs_bindex_t bstart, bcpup;
385
 
        struct inode *hidden_inode, *inode, *dir, *h_dir, *gh_dir, *gdir;
386
 
        struct dentry *hidden_dentry, *parent;
 
419
        struct inode *h_inode, *inode, *dir, *h_dir, *gdir;
 
420
        struct dentry *h_dentry, *parent, *hi_wh, *gparent;
387
421
        unsigned int udba;
 
422
        struct aufs_hin_ignore ign;
 
423
        struct vfsub_args vargs;
 
424
        struct super_block *sb;
 
425
        __u32 events;
 
426
        struct au_cpup_flags cflags;
 
427
        struct au_wr_dir_args wr_dir_args = {
 
428
                .force_btgt     = -1,
 
429
                .add_entry      = 0,
 
430
                .do_lock_srcdir = 0,
 
431
                .isdir          = S_ISDIR(dentry->d_inode->i_mode)
 
432
        };
388
433
 
389
 
        LKTRTrace("%.*s, ia_valid 0x%x\n", DLNPair(dentry), ia->ia_valid);
 
434
        LKTRTrace("%.*s, ia_valid 0x%x\n", AuDLNPair(dentry), ia->ia_valid);
390
435
        inode = dentry->d_inode;
391
436
        IMustLock(inode);
392
437
 
393
 
        aufs_read_lock(dentry, AUFS_D_WLOCK);
 
438
        aufs_read_lock(dentry, AuLock_DW);
394
439
        bstart = dbstart(dentry);
395
 
        bcpup = err = wr_dir(dentry, /*add*/0, /*src_dentry*/NULL,
396
 
                             /*force_btgt*/-1, /*do_lock_srcdir*/0);
 
440
        err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
 
441
        bcpup = err;
397
442
        //err = -1;
398
443
        if (unlikely(err < 0))
399
444
                goto out;
400
445
 
401
446
        /* crazy udba locks */
402
 
        udba = au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY);
 
447
        sb = dentry->d_sb;
 
448
        udba = au_flag_test_udba_inotify(sb);
403
449
        parent = NULL;
404
 
        gdir = gh_dir = dir = h_dir = NULL;
405
 
        if ((udba || bstart != bcpup) && !IS_ROOT(dentry)) {
406
 
                parent = dentry->d_parent; // dget_parent()
 
450
        dir = NULL;
 
451
        if (!IS_ROOT(dentry)) {
 
452
                parent = dget_parent(dentry);
407
453
                dir = parent->d_inode;
408
 
                di_read_lock_parent(parent, AUFS_I_RLOCK);
409
 
                h_dir = au_h_iptr_i(dir, bcpup);
410
 
        }
411
 
        if (parent) {
412
 
                if (unlikely(udba && !IS_ROOT(parent))) {
413
 
                        gdir = parent->d_parent->d_inode;  // dget_parent()
414
 
                        ii_read_lock_parent2(gdir);
415
 
                        gh_dir = au_h_iptr_i(gdir, bcpup);
416
 
                        hgdir_lock(gh_dir, gdir, bcpup);
417
 
                }
418
 
                hdir_lock(h_dir, dir, bcpup);
419
 
        }
420
 
 
421
 
        isdir = S_ISDIR(inode->i_mode);
422
 
        hidden_dentry = au_h_dptr(dentry);
423
 
        hidden_inode = hidden_dentry->d_inode;
424
 
        AuDebugOn(!hidden_inode);
425
 
 
426
 
#define HiLock(bindex) do {\
427
 
        if (!isdir) \
428
 
                hi_lock_child(hidden_inode); \
429
 
        else \
430
 
                hdir2_lock(hidden_inode, inode, bindex); \
 
454
                di_read_lock_parent(parent, AuLock_IR);
 
455
        }
 
456
        gparent = NULL;
 
457
        gdir = NULL;
 
458
        if (unlikely(udba && parent && !IS_ROOT(parent))) {
 
459
                gparent = dget_parent(parent);
 
460
                gdir = gparent->d_inode;
 
461
                ii_read_lock_parent2(gdir);
 
462
        }
 
463
 
 
464
        h_dentry = au_h_dptr(dentry);
 
465
        h_inode = h_dentry->d_inode;
 
466
        AuDebugOn(!h_inode);
 
467
 
 
468
#define HiLock(bindex) \
 
469
        do { \
 
470
                if (!wr_dir_args.isdir) \
 
471
                        vfsub_i_lock_nested(h_inode, AuLsc_I_CHILD); \
 
472
                else \
 
473
                        hdir2_lock(h_inode, inode, bindex); \
431
474
        } while (0)
432
 
#define HiUnlock(bindex) do {\
433
 
        if (!isdir) \
434
 
                i_unlock(hidden_inode); \
435
 
        else \
436
 
                hdir_unlock(hidden_inode, inode, bindex); \
 
475
#define HiUnlock(bindex) \
 
476
        do { \
 
477
                if (!wr_dir_args.isdir) \
 
478
                        vfsub_i_unlock(h_inode); \
 
479
                else \
 
480
                        hdir_unlock(h_inode, inode, bindex); \
437
481
        } while (0)
438
482
 
439
483
        if (bstart != bcpup) {
444
488
                        size = ia->ia_size;
445
489
                        ia->ia_valid &= ~ATTR_SIZE;
446
490
                }
 
491
                hi_wh = NULL;
 
492
                h_dir = au_h_iptr_i(dir, bcpup);
 
493
                hdir_lock(h_dir, dir, bcpup);
447
494
                HiLock(bstart);
448
 
                err = sio_cpup_simple(dentry, bcpup, size,
449
 
                                      au_flags_cpup(CPUP_DTIME, parent));
 
495
                if (!d_unhashed(dentry)) {
 
496
                        cflags.dtime = 1;
 
497
                        err = au_sio_cpup_simple(dentry, bcpup, size, &cflags);
 
498
                } else {
 
499
                        hi_wh = au_hi_wh(inode, bcpup);
 
500
                        if (!hi_wh) {
 
501
                                err = au_sio_cpup_wh(dentry, bcpup, size,
 
502
                                                     /*file*/NULL);
 
503
                                if (!err)
 
504
                                        hi_wh = au_hi_wh(inode, bcpup);
 
505
                        }
 
506
                }
 
507
 
450
508
                //err = -1;
451
509
                HiUnlock(bstart);
 
510
                hdir_unlock(h_dir, dir, bcpup);
452
511
                if (unlikely(err || !ia->ia_valid))
453
512
                        goto out_unlock;
454
513
 
455
 
                hidden_dentry = au_h_dptr(dentry);
456
 
                hidden_inode = hidden_dentry->d_inode;
457
 
                AuDebugOn(!hidden_inode);
458
 
        }
459
 
 
 
514
                if (!hi_wh)
 
515
                        h_dentry = au_h_dptr(dentry);
 
516
                else
 
517
                        h_dentry = hi_wh; /* do not dget here */
 
518
                h_inode = h_dentry->d_inode;
 
519
                AuDebugOn(!h_inode);
 
520
        }
 
521
 
 
522
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 
523
        if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
 
524
                ia->ia_valid &= ~ATTR_MODE;
 
525
#endif
 
526
 
 
527
        vfsub_args_init(&vargs, &ign, au_need_dlgt(sb), 0);
 
528
        if (unlikely(udba && dir)) {
 
529
                events = vfsub_events_notify_change(ia);
 
530
                if (events)
 
531
                        vfsub_ign_hinode(&vargs, events, itohi(dir, bcpup));
 
532
        }
460
533
        HiLock(bcpup);
461
 
        err = vfsub_notify_change(hidden_dentry, ia, need_dlgt(dentry->d_sb));
 
534
        err = vfsub_notify_change(h_dentry, ia, &vargs);
462
535
        //err = -1;
463
536
        if (!err)
464
 
                au_cpup_attr_changable(inode);
 
537
                au_cpup_attr_changeable(inode);
465
538
        HiUnlock(bcpup);
466
539
#undef HiLock
467
540
#undef HiUnlock
468
541
 
469
542
 out_unlock:
470
543
        if (parent) {
471
 
                hdir_unlock(h_dir, dir, bcpup);
472
 
                di_read_unlock(parent, AUFS_I_RLOCK);
 
544
                di_read_unlock(parent, AuLock_IR);
 
545
                dput(parent);
473
546
        }
474
547
        if (unlikely(gdir)) {
475
 
                hdir_unlock(gh_dir, gdir, bcpup);
476
548
                ii_read_unlock(gdir);
 
549
                dput(gparent);
477
550
        }
478
551
 out:
479
 
        aufs_read_unlock(dentry, AUFS_D_WLOCK);
480
 
        TraceErr(err);
481
 
        return err;
482
 
}
 
552
        aufs_read_unlock(dentry, AuLock_DW);
 
553
        AuTraceErr(err);
 
554
        return err;
 
555
}
 
556
 
 
557
/* currently, for fuse only */
 
558
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
 
559
static int aufs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 
560
                        struct kstat *st)
 
561
{
 
562
        int err;
 
563
        struct inode *inode, *h_inode;
 
564
        struct dentry *h_dentry;
 
565
 
 
566
        LKTRTrace("%.*s\n", AuDLNPair(dentry));
 
567
 
 
568
        err = 0;
 
569
        aufs_read_lock(dentry, AuLock_IR);
 
570
        inode = dentry->d_inode;
 
571
        h_inode = au_h_iptr(inode);
 
572
        if (unlikely(au_test_fuse(h_inode->i_sb))) {
 
573
                h_dentry = d_find_alias(h_inode);
 
574
                /* simply gave up updating fuse inode */
 
575
                if (h_dentry) {
 
576
                        /*ignore*/
 
577
                        if (!au_update_fuse_h_inode(NULL, h_dentry))
 
578
                                au_cpup_attr_all(inode);
 
579
                        dput(h_dentry);
 
580
                }
 
581
        }
 
582
        generic_fillattr(inode, st);
 
583
 
 
584
        aufs_read_unlock(dentry, AuLock_IR);
 
585
        return err;
 
586
}
 
587
#endif /* CONFIG_AUFS_WORKAROUND_FUSE */
483
588
 
484
589
/* ---------------------------------------------------------------------- */
485
590
 
486
 
static int hidden_readlink(struct dentry *dentry, int bindex,
487
 
                           char __user * buf, int bufsiz)
 
591
static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
 
592
                      int bufsiz)
488
593
{
489
594
        struct super_block *sb;
490
 
        struct dentry *hidden_dentry;
491
 
 
492
 
        hidden_dentry = au_h_dptr_i(dentry, bindex);
493
 
        if (unlikely(!hidden_dentry->d_inode->i_op
494
 
                     || !hidden_dentry->d_inode->i_op->readlink))
 
595
        struct dentry *h_dentry;
 
596
 
 
597
        LKTRTrace("%.*s, b%d, %d\n", AuDLNPair(dentry), bindex, bufsiz);
 
598
 
 
599
        h_dentry = au_h_dptr_i(dentry, bindex);
 
600
        if (unlikely(!h_dentry->d_inode->i_op
 
601
                     || !h_dentry->d_inode->i_op->readlink))
495
602
                return -EINVAL;
496
603
 
497
604
        sb = dentry->d_sb;
498
 
        if (!test_ro(sb, bindex, dentry->d_inode)) {
499
 
                touch_atime(sbr_mnt(sb, bindex), hidden_dentry);
500
 
                dentry->d_inode->i_atime = hidden_dentry->d_inode->i_atime;
 
605
        if (!au_test_ro(sb, bindex, dentry->d_inode)) {
 
606
                touch_atime(sbr_mnt(sb, bindex), h_dentry);
 
607
                au_update_fuse_h_inode(NULL, h_dentry); /*ignore*/
 
608
                dentry->d_inode->i_atime = h_dentry->d_inode->i_atime;
501
609
        }
502
 
        return hidden_dentry->d_inode->i_op->readlink
503
 
                (hidden_dentry, buf, bufsiz);
 
610
        return h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
504
611
}
505
612
 
506
 
static int aufs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
 
613
static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
507
614
{
508
615
        int err;
509
616
 
510
 
        LKTRTrace("%.*s, %d\n", DLNPair(dentry), bufsiz);
 
617
        LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), bufsiz);
511
618
 
512
 
        aufs_read_lock(dentry, AUFS_I_RLOCK);
513
 
        err = hidden_readlink(dentry, dbstart(dentry), buf, bufsiz);
 
619
        aufs_read_lock(dentry, AuLock_IR);
 
620
        err = h_readlink(dentry, dbstart(dentry), buf, bufsiz);
514
621
        //err = -1;
515
 
        aufs_read_unlock(dentry, AUFS_I_RLOCK);
516
 
        TraceErr(err);
 
622
        aufs_read_unlock(dentry, AuLock_IR);
 
623
        AuTraceErr(err);
517
624
        return err;
518
625
}
519
626
 
523
630
        char *buf;
524
631
        mm_segment_t old_fs;
525
632
 
526
 
        LKTRTrace("%.*s, nd %.*s\n", DLNPair(dentry), DLNPair(nd->dentry));
 
633
        LKTRTrace("%.*s, nd %.*s\n", AuDLNPair(dentry), AuDLNPair(nd->dentry));
527
634
 
528
635
        err = -ENOMEM;
529
636
        buf = __getname();
531
638
        if (unlikely(!buf))
532
639
                goto out;
533
640
 
534
 
        aufs_read_lock(dentry, AUFS_I_RLOCK);
 
641
        aufs_read_lock(dentry, AuLock_IR);
535
642
        old_fs = get_fs();
536
643
        set_fs(KERNEL_DS);
537
 
        err = hidden_readlink(dentry, dbstart(dentry), (char __user *)buf,
538
 
                              PATH_MAX);
 
644
        err = h_readlink(dentry, dbstart(dentry), (char __user *)buf, PATH_MAX);
539
645
        //err = -1;
540
646
        set_fs(old_fs);
541
 
        aufs_read_unlock(dentry, AUFS_I_RLOCK);
 
647
        aufs_read_unlock(dentry, AuLock_IR);
542
648
 
543
649
        if (err >= 0) {
544
650
                buf[err] = 0;
550
656
 
551
657
 out:
552
658
        path_release(nd);
553
 
        TraceErr(err);
 
659
        AuTraceErr(err);
554
660
        return ERR_PTR(err);
555
661
}
556
662
 
557
663
static void aufs_put_link(struct dentry *dentry, struct nameidata *nd,
558
664
                          void *cookie)
559
665
{
560
 
        LKTRTrace("%.*s\n", DLNPair(dentry));
 
666
        LKTRTrace("%.*s\n", AuDLNPair(dentry));
561
667
        __putname(nd_get_link(nd));
562
668
}
563
669
 
564
670
/* ---------------------------------------------------------------------- */
565
 
#if 0 // comment
566
 
struct inode_operations {
567
 
        int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
568
 
        struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
569
 
        int (*link) (struct dentry *,struct inode *,struct dentry *);
570
 
        int (*unlink) (struct inode *,struct dentry *);
571
 
        int (*symlink) (struct inode *,struct dentry *,const char *);
572
 
        int (*mkdir) (struct inode *,struct dentry *,int);
573
 
        int (*rmdir) (struct inode *,struct dentry *);
574
 
        int (*mknod) (struct inode *,struct dentry *,int,dev_t);
575
 
        int (*rename) (struct inode *, struct dentry *,
576
 
                        struct inode *, struct dentry *);
577
 
        int (*readlink) (struct dentry *, char __user *,int);
578
 
        void * (*follow_link) (struct dentry *, struct nameidata *);
579
 
        void (*put_link) (struct dentry *, struct nameidata *, void *);
580
 
        void (*truncate) (struct inode *);
581
 
        int (*permission) (struct inode *, int, struct nameidata *);
582
 
        int (*setattr) (struct dentry *, struct iattr *);
583
 
        int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
584
 
        int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
585
 
        ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
586
 
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
587
 
        int (*removexattr) (struct dentry *, const char *);
588
 
        void (*truncate_range)(struct inode *, loff_t, loff_t);
589
 
};
590
 
#endif
 
671
 
 
672
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
 
673
static void aufs_truncate_range(struct inode *inode, loff_t start, loff_t end)
 
674
{
 
675
        AuUnsupport();
 
676
}
 
677
#endif
 
678
 
 
679
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
 
680
static long aufs_fallocate(struct inode *inode, int mode, loff_t offset,
 
681
                           loff_t len)
 
682
{
 
683
        AuUnsupport();
 
684
        return -ENOSYS;
 
685
}
 
686
#endif
 
687
 
 
688
/* ---------------------------------------------------------------------- */
591
689
 
592
690
struct inode_operations aufs_symlink_iop = {
593
691
        .permission     = aufs_permission,
594
692
        .setattr        = aufs_setattr,
 
693
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
 
694
        .getattr        = aufs_getattr,
 
695
#endif
595
696
 
596
697
        .readlink       = aufs_readlink,
597
698
        .follow_link    = aufs_follow_link,
611
712
 
612
713
        .permission     = aufs_permission,
613
714
        .setattr        = aufs_setattr,
 
715
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
 
716
        .getattr        = aufs_getattr,
 
717
#endif
614
718
 
615
719
#if 0 // xattr
616
720
        .setxattr       = aufs_setxattr,
617
721
        .getxattr       = aufs_getxattr,
618
722
        .listxattr      = aufs_listxattr,
619
 
        .removexattr    = aufs_removexattr
 
723
        .removexattr    = aufs_removexattr,
 
724
#endif
 
725
 
 
726
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
 
727
        .fallocate      = aufs_fallocate
620
728
#endif
621
729
};
622
730
 
623
731
struct inode_operations aufs_iop = {
624
732
        .permission     = aufs_permission,
625
733
        .setattr        = aufs_setattr,
 
734
#ifdef CONFIG_AUFS_WORKAROUND_FUSE
 
735
        .getattr        = aufs_getattr,
 
736
#endif
626
737
 
627
738
#if 0 // xattr
628
739
        .setxattr       = aufs_setxattr,
629
740
        .getxattr       = aufs_getxattr,
630
741
        .listxattr      = aufs_listxattr,
631
 
        .removexattr    = aufs_removexattr
 
742
        .removexattr    = aufs_removexattr,
 
743
#endif
 
744
 
 
745
        //void (*truncate) (struct inode *);
 
746
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
 
747
        .truncate_range = aufs_truncate_range,
 
748
#endif
 
749
 
 
750
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
 
751
        .fallocate      = aufs_fallocate
632
752
#endif
633
753
};