~ubuntu-branches/ubuntu/raring/linux-nexus7/raring-proposed

« back to all changes in this revision

Viewing changes to fs/overlayfs/dir.c

  • Committer: Package Import Robot
  • Author(s): Tim Gardner, Andy Whitcroft, Erez Zadok, Miklos Szeredi, Neil Brown, Paolo Pisati, Tim Gardner
  • Date: 2013-02-27 11:55:02 UTC
  • Revision ID: package-import@ubuntu.com-20130227115502-979tupqdiwnd6bob
Tags: 3.1.10-10.28
[ Andy Whitcroft ]

* ubuntu: overlayfs -- overlayfs: add statfs support
  - LP: #1076317
* ubuntu: overlayfs -- overlayfs: apply device cgroup and security
  permissions to overlay files
  - LP: #1076317, #915941, #918212
  - CVE-2012-0055
* [packaging] Rename from linaro to nexus7 -- part 2

[ Erez Zadok ]

* ubuntu: overlayfs -- overlayfs: implement show_options
  - LP: #1076317

[ Miklos Szeredi ]

* ubuntu: overlayfs -- vfs: pass struct path to __dentry_open()
  - LP: #1076317
* ubuntu: overlayfs -- vfs: add i_op->open()
  - LP: #1076317
* ubuntu: overlayfs -- vfs: export do_splice_direct() to modules
  - LP: #1076317
* ubuntu: overlayfs -- vfs: introduce clone_private_mount()
  - LP: #1076317
* ubuntu: overlayfs -- overlay filesystem
  - LP: #1076317
* ubuntu: overlayfs -- fs: limit filesystem stacking depth
  - LP: #1076317

[ Neil Brown ]

* ubuntu: overlayfs -- overlay: overlay filesystem documentation
  - LP: #1076317

[ Paolo Pisati ]

* [Config] OVERLAYFS_FS=m
  - LP: #1076317
* SAUCE: compilation fix for missing symbols
  - LP: #1076317

[ Tim Gardner ]

* Rebased against git://phablet.ubuntu.com/CyanogenMod/android_kernel_asus_grouper.git phablet-10.1
* Updated configs to be more device consistent with
  arch/arm/configs/cyanogenmod_grouper_defconfig
  https://wiki.ubuntu.com/Touch/Porting#Kernel
  http://phablet.ubuntu.com/gitweb?p=CyanogenMod/android_kernel_asus_grouper.git;a=shortlog;h=refs/heads/phablet-10.1
* Pull config changes from git://phablet.ubuntu.com/CyanogenMod/android_kernel_asus_grouper.git phablet-10.1
  CONFIG_NAMESPACES=y
  CONFIG_UTS_NS=y
  CONFIG_IPC_NS=y
  CONFIG_USER_NS=y
  CONFIG_PID_NS=y
  CONFIG_NET_NS=y
  CONFIG_DEVTMPFS=y
  CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
  CONFIG_DNOTIFY=y
  CONFIG_FANOTIFY=y
  CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
  ONFIG_ANDROID_PARANOID_NETWORK=n
  ONFIG_DEVPTS_MULTIPLE_INSTANCES=y
  CONFIG_SYSVIPC=y
* [packaging] Rename from linaro to nexus7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * Copyright (C) 2011 Novell Inc.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify it
 
6
 * under the terms of the GNU General Public License version 2 as published by
 
7
 * the Free Software Foundation.
 
8
 */
 
9
 
 
10
#include <linux/fs.h>
 
11
#include <linux/namei.h>
 
12
#include <linux/xattr.h>
 
13
#include <linux/security.h>
 
14
#include "overlayfs.h"
 
15
 
 
16
static const char *ovl_whiteout_symlink = "(overlay-whiteout)";
 
17
 
 
18
static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry)
 
19
{
 
20
        int err;
 
21
        struct dentry *newdentry;
 
22
        const struct cred *old_cred;
 
23
        struct cred *override_cred;
 
24
 
 
25
        /* FIXME: recheck lower dentry to see if whiteout is really needed */
 
26
 
 
27
        err = -ENOMEM;
 
28
        override_cred = prepare_creds();
 
29
        if (!override_cred)
 
30
                goto out;
 
31
 
 
32
        /*
 
33
         * CAP_SYS_ADMIN for setxattr
 
34
         * CAP_DAC_OVERRIDE for symlink creation
 
35
         * CAP_FOWNER for unlink in sticky directory
 
36
         */
 
37
        cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
 
38
        cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
 
39
        cap_raise(override_cred->cap_effective, CAP_FOWNER);
 
40
        override_cred->fsuid = 0;
 
41
        override_cred->fsgid = 0;
 
42
        old_cred = override_creds(override_cred);
 
43
 
 
44
        newdentry = lookup_one_len(dentry->d_name.name, upperdir,
 
45
                                   dentry->d_name.len);
 
46
        err = PTR_ERR(newdentry);
 
47
        if (IS_ERR(newdentry))
 
48
                goto out_put_cred;
 
49
 
 
50
        /* Just been removed within the same locked region */
 
51
        WARN_ON(newdentry->d_inode);
 
52
 
 
53
        err = vfs_symlink(upperdir->d_inode, newdentry, ovl_whiteout_symlink);
 
54
        if (err)
 
55
                goto out_dput;
 
56
 
 
57
        ovl_dentry_version_inc(dentry->d_parent);
 
58
 
 
59
        err = vfs_setxattr(newdentry, ovl_whiteout_xattr, "y", 1, 0);
 
60
        if (err)
 
61
                vfs_unlink(upperdir->d_inode, newdentry);
 
62
 
 
63
out_dput:
 
64
        dput(newdentry);
 
65
out_put_cred:
 
66
        revert_creds(old_cred);
 
67
        put_cred(override_cred);
 
68
out:
 
69
        if (err) {
 
70
                /*
 
71
                 * There's no way to recover from failure to whiteout.
 
72
                 * What should we do?  Log a big fat error and... ?
 
73
                 */
 
74
                printk(KERN_ERR "overlayfs: ERROR - failed to whiteout '%s'\n",
 
75
                       dentry->d_name.name);
 
76
        }
 
77
 
 
78
        return err;
 
79
}
 
80
 
 
81
static struct dentry *ovl_lookup_create(struct dentry *upperdir,
 
82
                                        struct dentry *template)
 
83
{
 
84
        int err;
 
85
        struct dentry *newdentry;
 
86
        struct qstr *name = &template->d_name;
 
87
 
 
88
        newdentry = lookup_one_len(name->name, upperdir, name->len);
 
89
        if (IS_ERR(newdentry))
 
90
                return newdentry;
 
91
 
 
92
        if (newdentry->d_inode) {
 
93
                const struct cred *old_cred;
 
94
                struct cred *override_cred;
 
95
 
 
96
                /* No need to check whiteout if lower parent is non-existent */
 
97
                err = -EEXIST;
 
98
                if (!ovl_dentry_lower(template->d_parent))
 
99
                        goto out_dput;
 
100
 
 
101
                if (!S_ISLNK(newdentry->d_inode->i_mode))
 
102
                        goto out_dput;
 
103
 
 
104
                err = -ENOMEM;
 
105
                override_cred = prepare_creds();
 
106
                if (!override_cred)
 
107
                        goto out_dput;
 
108
 
 
109
                /*
 
110
                 * CAP_SYS_ADMIN for getxattr
 
111
                 * CAP_FOWNER for unlink in sticky directory
 
112
                 */
 
113
                cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
 
114
                cap_raise(override_cred->cap_effective, CAP_FOWNER);
 
115
                old_cred = override_creds(override_cred);
 
116
 
 
117
                err = -EEXIST;
 
118
                if (ovl_is_whiteout(newdentry))
 
119
                        err = vfs_unlink(upperdir->d_inode, newdentry);
 
120
 
 
121
                revert_creds(old_cred);
 
122
                put_cred(override_cred);
 
123
                if (err)
 
124
                        goto out_dput;
 
125
 
 
126
                dput(newdentry);
 
127
                newdentry = lookup_one_len(name->name, upperdir, name->len);
 
128
                if (IS_ERR(newdentry)) {
 
129
                        ovl_whiteout(upperdir, template);
 
130
                        return newdentry;
 
131
                }
 
132
 
 
133
                /*
 
134
                 * Whiteout just been successfully removed, parent
 
135
                 * i_mutex is still held, there's no way the lookup
 
136
                 * could return positive.
 
137
                 */
 
138
                WARN_ON(newdentry->d_inode);
 
139
        }
 
140
 
 
141
        return newdentry;
 
142
 
 
143
out_dput:
 
144
        dput(newdentry);
 
145
        return ERR_PTR(err);
 
146
}
 
147
 
 
148
struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry,
 
149
                                struct kstat *stat, const char *link)
 
150
{
 
151
        int err;
 
152
        struct dentry *newdentry;
 
153
        struct inode *dir = upperdir->d_inode;
 
154
 
 
155
        newdentry = ovl_lookup_create(upperdir, dentry);
 
156
        if (IS_ERR(newdentry))
 
157
                goto out;
 
158
 
 
159
        switch (stat->mode & S_IFMT) {
 
160
        case S_IFREG:
 
161
                err = vfs_create(dir, newdentry, stat->mode, NULL);
 
162
                break;
 
163
 
 
164
        case S_IFDIR:
 
165
                err = vfs_mkdir(dir, newdentry, stat->mode);
 
166
                break;
 
167
 
 
168
        case S_IFCHR:
 
169
        case S_IFBLK:
 
170
        case S_IFIFO:
 
171
        case S_IFSOCK:
 
172
                err = vfs_mknod(dir, newdentry, stat->mode, stat->rdev);
 
173
                break;
 
174
 
 
175
        case S_IFLNK:
 
176
                err = vfs_symlink(dir, newdentry, link);
 
177
                break;
 
178
 
 
179
        default:
 
180
                err = -EPERM;
 
181
        }
 
182
        if (err) {
 
183
                if (ovl_dentry_is_opaque(dentry))
 
184
                        ovl_whiteout(upperdir, dentry);
 
185
                dput(newdentry);
 
186
                newdentry = ERR_PTR(err);
 
187
        } else if (WARN_ON(!newdentry->d_inode)) {
 
188
                /*
 
189
                 * Not quite sure if non-instantiated dentry is legal or not.
 
190
                 * VFS doesn't seem to care so check and warn here.
 
191
                 */
 
192
                dput(newdentry);
 
193
                newdentry = ERR_PTR(-ENOENT);
 
194
        }
 
195
 
 
196
out:
 
197
        return newdentry;
 
198
 
 
199
}
 
200
 
 
201
static int ovl_set_opaque(struct dentry *upperdentry)
 
202
{
 
203
        int err;
 
204
        const struct cred *old_cred;
 
205
        struct cred *override_cred;
 
206
 
 
207
        override_cred = prepare_creds();
 
208
        if (!override_cred)
 
209
                return -ENOMEM;
 
210
 
 
211
        /* CAP_SYS_ADMIN for setxattr of "trusted" namespace */
 
212
        cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
 
213
        old_cred = override_creds(override_cred);
 
214
        err = vfs_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0);
 
215
        revert_creds(old_cred);
 
216
        put_cred(override_cred);
 
217
 
 
218
        return err;
 
219
}
 
220
 
 
221
static int ovl_remove_opaque(struct dentry *upperdentry)
 
222
{
 
223
        int err;
 
224
        const struct cred *old_cred;
 
225
        struct cred *override_cred;
 
226
 
 
227
        override_cred = prepare_creds();
 
228
        if (!override_cred)
 
229
                return -ENOMEM;
 
230
 
 
231
        /* CAP_SYS_ADMIN for removexattr of "trusted" namespace */
 
232
        cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
 
233
        old_cred = override_creds(override_cred);
 
234
        err = vfs_removexattr(upperdentry, ovl_opaque_xattr);
 
235
        revert_creds(old_cred);
 
236
        put_cred(override_cred);
 
237
 
 
238
        return err;
 
239
}
 
240
 
 
241
static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
 
242
                         struct kstat *stat)
 
243
{
 
244
        int err;
 
245
        enum ovl_path_type type;
 
246
        struct path realpath;
 
247
 
 
248
        type = ovl_path_real(dentry, &realpath);
 
249
        err = vfs_getattr(realpath.mnt, realpath.dentry, stat);
 
250
        if (err)
 
251
                return err;
 
252
 
 
253
        stat->dev = dentry->d_sb->s_dev;
 
254
        stat->ino = dentry->d_inode->i_ino;
 
255
 
 
256
        /*
 
257
         * It's probably not worth it to count subdirs to get the
 
258
         * correct link count.  nlink=1 seems to pacify 'find' and
 
259
         * other utilities.
 
260
         */
 
261
        if (type == OVL_PATH_MERGE)
 
262
                stat->nlink = 1;
 
263
 
 
264
        return 0;
 
265
}
 
266
 
 
267
static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
 
268
                             const char *link)
 
269
{
 
270
        int err;
 
271
        struct dentry *newdentry;
 
272
        struct dentry *upperdir;
 
273
        struct inode *inode;
 
274
        struct kstat stat = {
 
275
                .mode = mode,
 
276
                .rdev = rdev,
 
277
        };
 
278
 
 
279
        err = -ENOMEM;
 
280
        inode = ovl_new_inode(dentry->d_sb, mode, dentry->d_fsdata);
 
281
        if (!inode)
 
282
                goto out;
 
283
 
 
284
        err = ovl_copy_up(dentry->d_parent);
 
285
        if (err)
 
286
                goto out_iput;
 
287
 
 
288
        upperdir = ovl_dentry_upper(dentry->d_parent);
 
289
        mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT);
 
290
 
 
291
        newdentry = ovl_upper_create(upperdir, dentry, &stat, link);
 
292
        err = PTR_ERR(newdentry);
 
293
        if (IS_ERR(newdentry))
 
294
                goto out_unlock;
 
295
 
 
296
        ovl_dentry_version_inc(dentry->d_parent);
 
297
        if (ovl_dentry_is_opaque(dentry) && S_ISDIR(mode)) {
 
298
                err = ovl_set_opaque(newdentry);
 
299
                if (err) {
 
300
                        vfs_rmdir(upperdir->d_inode, newdentry);
 
301
                        ovl_whiteout(upperdir, dentry);
 
302
                        goto out_dput;
 
303
                }
 
304
        }
 
305
        ovl_dentry_update(dentry, newdentry);
 
306
        d_instantiate(dentry, inode);
 
307
        inode = NULL;
 
308
        newdentry = NULL;
 
309
        err = 0;
 
310
 
 
311
out_dput:
 
312
        dput(newdentry);
 
313
out_unlock:
 
314
        mutex_unlock(&upperdir->d_inode->i_mutex);
 
315
out_iput:
 
316
        iput(inode);
 
317
out:
 
318
        return err;
 
319
}
 
320
 
 
321
static int ovl_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 
322
                        struct nameidata *nd)
 
323
{
 
324
        return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL);
 
325
}
 
326
 
 
327
static int ovl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
328
{
 
329
        return ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL);
 
330
}
 
331
 
 
332
static int ovl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
 
333
                     dev_t rdev)
 
334
{
 
335
        return ovl_create_object(dentry, mode, rdev, NULL);
 
336
}
 
337
 
 
338
static int ovl_symlink(struct inode *dir, struct dentry *dentry,
 
339
                         const char *link)
 
340
{
 
341
        return ovl_create_object(dentry, S_IFLNK, 0, link);
 
342
}
 
343
 
 
344
static int ovl_do_remove(struct dentry *dentry, bool is_dir)
 
345
{
 
346
        int err;
 
347
        enum ovl_path_type type;
 
348
        struct path realpath;
 
349
        struct dentry *upperdir;
 
350
 
 
351
        err = ovl_copy_up(dentry->d_parent);
 
352
        if (err)
 
353
                return err;
 
354
 
 
355
        upperdir = ovl_dentry_upper(dentry->d_parent);
 
356
        mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT);
 
357
        type = ovl_path_real(dentry, &realpath);
 
358
        if (type != OVL_PATH_LOWER) {
 
359
                err = -ESTALE;
 
360
                if (realpath.dentry->d_parent != upperdir)
 
361
                        goto out_d_drop;
 
362
 
 
363
                /* FIXME: create whiteout up front and rename to target */
 
364
 
 
365
                if (is_dir)
 
366
                        err = vfs_rmdir(upperdir->d_inode, realpath.dentry);
 
367
                else
 
368
                        err = vfs_unlink(upperdir->d_inode, realpath.dentry);
 
369
                if (err)
 
370
                        goto out_d_drop;
 
371
 
 
372
                ovl_dentry_version_inc(dentry->d_parent);
 
373
        }
 
374
 
 
375
        if (type != OVL_PATH_UPPER || ovl_dentry_is_opaque(dentry))
 
376
                err = ovl_whiteout(upperdir, dentry);
 
377
 
 
378
        /*
 
379
         * Keeping this dentry hashed would mean having to release
 
380
         * upperpath/lowerpath, which could only be done if we are the
 
381
         * sole user of this dentry.  Too tricky...  Just unhash for
 
382
         * now.
 
383
         */
 
384
out_d_drop:
 
385
        d_drop(dentry);
 
386
        mutex_unlock(&upperdir->d_inode->i_mutex);
 
387
 
 
388
        return err;
 
389
}
 
390
 
 
391
static int ovl_unlink(struct inode *dir, struct dentry *dentry)
 
392
{
 
393
        return ovl_do_remove(dentry, false);
 
394
}
 
395
 
 
396
 
 
397
static int ovl_rmdir(struct inode *dir, struct dentry *dentry)
 
398
{
 
399
        int err;
 
400
        enum ovl_path_type type;
 
401
 
 
402
        type = ovl_path_type(dentry);
 
403
        if (type != OVL_PATH_UPPER) {
 
404
                err = ovl_check_empty_and_clear(dentry, type);
 
405
                if (err)
 
406
                        return err;
 
407
        }
 
408
 
 
409
        return ovl_do_remove(dentry, true);
 
410
}
 
411
 
 
412
static int ovl_link(struct dentry *old, struct inode *newdir,
 
413
                    struct dentry *new)
 
414
{
 
415
        int err;
 
416
        struct dentry *olddentry;
 
417
        struct dentry *newdentry;
 
418
        struct dentry *upperdir;
 
419
 
 
420
        err = ovl_copy_up(old);
 
421
        if (err)
 
422
                goto out;
 
423
 
 
424
        err = ovl_copy_up(new->d_parent);
 
425
        if (err)
 
426
                goto out;
 
427
 
 
428
        upperdir = ovl_dentry_upper(new->d_parent);
 
429
        mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT);
 
430
        newdentry = ovl_lookup_create(upperdir, new);
 
431
        err = PTR_ERR(newdentry);
 
432
        if (IS_ERR(newdentry))
 
433
                goto out_unlock;
 
434
 
 
435
        olddentry = ovl_dentry_upper(old);
 
436
        err = vfs_link(olddentry, upperdir->d_inode, newdentry);
 
437
        if (!err) {
 
438
                if (WARN_ON(!newdentry->d_inode)) {
 
439
                        dput(newdentry);
 
440
                        err = -ENOENT;
 
441
                        goto out_unlock;
 
442
                }
 
443
 
 
444
                ovl_dentry_version_inc(new->d_parent);
 
445
                ovl_dentry_update(new, newdentry);
 
446
 
 
447
                ihold(old->d_inode);
 
448
                d_instantiate(new, old->d_inode);
 
449
        } else {
 
450
                if (ovl_dentry_is_opaque(new))
 
451
                        ovl_whiteout(upperdir, new);
 
452
                dput(newdentry);
 
453
        }
 
454
out_unlock:
 
455
        mutex_unlock(&upperdir->d_inode->i_mutex);
 
456
out:
 
457
        return err;
 
458
 
 
459
}
 
460
 
 
461
static int ovl_rename(struct inode *olddir, struct dentry *old,
 
462
                        struct inode *newdir, struct dentry *new)
 
463
{
 
464
        int err;
 
465
        enum ovl_path_type old_type;
 
466
        enum ovl_path_type new_type;
 
467
        struct dentry *old_upperdir;
 
468
        struct dentry *new_upperdir;
 
469
        struct dentry *olddentry;
 
470
        struct dentry *newdentry;
 
471
        struct dentry *trap;
 
472
        bool old_opaque;
 
473
        bool new_opaque;
 
474
        bool new_create = false;
 
475
        bool is_dir = S_ISDIR(old->d_inode->i_mode);
 
476
 
 
477
        /* Don't copy up directory trees */
 
478
        old_type = ovl_path_type(old);
 
479
        if (old_type != OVL_PATH_UPPER && is_dir)
 
480
                return -EXDEV;
 
481
 
 
482
        if (new->d_inode) {
 
483
                new_type = ovl_path_type(new);
 
484
 
 
485
                if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) {
 
486
                        if (ovl_dentry_lower(old)->d_inode ==
 
487
                            ovl_dentry_lower(new)->d_inode)
 
488
                                return 0;
 
489
                }
 
490
                if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) {
 
491
                        if (ovl_dentry_upper(old)->d_inode ==
 
492
                            ovl_dentry_upper(new)->d_inode)
 
493
                                return 0;
 
494
                }
 
495
 
 
496
                if (new_type != OVL_PATH_UPPER &&
 
497
                    S_ISDIR(new->d_inode->i_mode)) {
 
498
                        err = ovl_check_empty_and_clear(new, new_type);
 
499
                        if (err)
 
500
                                return err;
 
501
                }
 
502
        } else {
 
503
                new_type = OVL_PATH_UPPER;
 
504
        }
 
505
 
 
506
        err = ovl_copy_up(old);
 
507
        if (err)
 
508
                return err;
 
509
 
 
510
        err = ovl_copy_up(new->d_parent);
 
511
        if (err)
 
512
                return err;
 
513
 
 
514
        old_upperdir = ovl_dentry_upper(old->d_parent);
 
515
        new_upperdir = ovl_dentry_upper(new->d_parent);
 
516
 
 
517
        trap = lock_rename(new_upperdir, old_upperdir);
 
518
 
 
519
        olddentry = ovl_dentry_upper(old);
 
520
        newdentry = ovl_dentry_upper(new);
 
521
        if (newdentry) {
 
522
                dget(newdentry);
 
523
        } else {
 
524
                new_create = true;
 
525
                newdentry = ovl_lookup_create(new_upperdir, new);
 
526
                err = PTR_ERR(newdentry);
 
527
                if (IS_ERR(newdentry))
 
528
                        goto out_unlock;
 
529
        }
 
530
 
 
531
        err = -ESTALE;
 
532
        if (olddentry->d_parent != old_upperdir)
 
533
                goto out_dput;
 
534
        if (newdentry->d_parent != new_upperdir)
 
535
                goto out_dput;
 
536
        if (olddentry == trap)
 
537
                goto out_dput;
 
538
        if (newdentry == trap)
 
539
                goto out_dput;
 
540
 
 
541
        old_opaque = ovl_dentry_is_opaque(old);
 
542
        new_opaque = ovl_dentry_is_opaque(new) || new_type != OVL_PATH_UPPER;
 
543
 
 
544
        if (is_dir && !old_opaque && new_opaque) {
 
545
                err = ovl_set_opaque(olddentry);
 
546
                if (err)
 
547
                        goto out_dput;
 
548
        }
 
549
 
 
550
        err = vfs_rename(old_upperdir->d_inode, olddentry,
 
551
                         new_upperdir->d_inode, newdentry);
 
552
 
 
553
        if (err) {
 
554
                if (new_create && ovl_dentry_is_opaque(new))
 
555
                        ovl_whiteout(new_upperdir, new);
 
556
                if (is_dir && !old_opaque && new_opaque)
 
557
                        ovl_remove_opaque(olddentry);
 
558
                goto out_dput;
 
559
        }
 
560
 
 
561
        if (old_type != OVL_PATH_UPPER || old_opaque)
 
562
                err = ovl_whiteout(old_upperdir, old);
 
563
        if (is_dir && old_opaque && !new_opaque)
 
564
                ovl_remove_opaque(olddentry);
 
565
 
 
566
        if (old_opaque != new_opaque)
 
567
                ovl_dentry_set_opaque(old, new_opaque);
 
568
 
 
569
        ovl_dentry_version_inc(old->d_parent);
 
570
        ovl_dentry_version_inc(new->d_parent);
 
571
 
 
572
out_dput:
 
573
        dput(newdentry);
 
574
out_unlock:
 
575
        unlock_rename(new_upperdir, old_upperdir);
 
576
        return err;
 
577
}
 
578
 
 
579
const struct inode_operations ovl_dir_inode_operations = {
 
580
        .lookup         = ovl_lookup,
 
581
        .mkdir          = ovl_mkdir,
 
582
        .symlink        = ovl_symlink,
 
583
        .unlink         = ovl_unlink,
 
584
        .rmdir          = ovl_rmdir,
 
585
        .rename         = ovl_rename,
 
586
        .link           = ovl_link,
 
587
        .setattr        = ovl_setattr,
 
588
        .create         = ovl_create,
 
589
        .mknod          = ovl_mknod,
 
590
        .permission     = ovl_permission,
 
591
        .getattr        = ovl_dir_getattr,
 
592
        .setxattr       = ovl_setxattr,
 
593
        .getxattr       = ovl_getxattr,
 
594
        .listxattr      = ovl_listxattr,
 
595
        .removexattr    = ovl_removexattr,
 
596
};