diff options
-rw-r--r-- | Documentation/filesystems/overlayfs.txt | 26 | ||||
-rw-r--r-- | fs/ioctl.c | 6 | ||||
-rw-r--r-- | fs/namei.c | 6 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 3 | ||||
-rw-r--r-- | fs/overlayfs/Kconfig | 14 | ||||
-rw-r--r-- | fs/overlayfs/Makefile | 2 | ||||
-rw-r--r-- | fs/overlayfs/copy_up.c | 61 | ||||
-rw-r--r-- | fs/overlayfs/dir.c | 375 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 78 | ||||
-rw-r--r-- | fs/overlayfs/namei.c | 401 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 62 | ||||
-rw-r--r-- | fs/overlayfs/ovl_entry.h | 53 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 557 | ||||
-rw-r--r-- | fs/overlayfs/util.c | 265 | ||||
-rw-r--r-- | fs/read_write.c | 23 | ||||
-rw-r--r-- | include/linux/fs.h | 13 | ||||
-rw-r--r-- | net/unix/af_unix.c | 6 |
17 files changed, 1139 insertions, 812 deletions
diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt index bcbf9710e4af..634d03e20c2d 100644 --- a/Documentation/filesystems/overlayfs.txt +++ b/Documentation/filesystems/overlayfs.txt | |||
@@ -66,7 +66,7 @@ At mount time, the two directories given as mount options "lowerdir" and | |||
66 | "upperdir" are combined into a merged directory: | 66 | "upperdir" are combined into a merged directory: |
67 | 67 | ||
68 | mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,\ | 68 | mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,\ |
69 | workdir=/work /merged | 69 | workdir=/work /merged |
70 | 70 | ||
71 | The "workdir" needs to be an empty directory on the same filesystem | 71 | The "workdir" needs to be an empty directory on the same filesystem |
72 | as upperdir. | 72 | as upperdir. |
@@ -118,6 +118,7 @@ programs. | |||
118 | 118 | ||
119 | seek offsets are assigned sequentially when the directories are read. | 119 | seek offsets are assigned sequentially when the directories are read. |
120 | Thus if | 120 | Thus if |
121 | |||
121 | - read part of a directory | 122 | - read part of a directory |
122 | - remember an offset, and close the directory | 123 | - remember an offset, and close the directory |
123 | - re-open the directory some time later | 124 | - re-open the directory some time later |
@@ -130,6 +131,23 @@ directory. | |||
130 | Readdir on directories that are not merged is simply handled by the | 131 | Readdir on directories that are not merged is simply handled by the |
131 | underlying directory (upper or lower). | 132 | underlying directory (upper or lower). |
132 | 133 | ||
134 | renaming directories | ||
135 | -------------------- | ||
136 | |||
137 | When renaming a directory that is on the lower layer or merged (i.e. the | ||
138 | directory was not created on the upper layer to start with) overlayfs can | ||
139 | handle it in two different ways: | ||
140 | |||
141 | 1. return EXDEV error: this error is returned by rename(2) when trying to | ||
142 | move a file or directory across filesystem boundaries. Hence | ||
143 | applications are usually prepared to hande this error (mv(1) for example | ||
144 | recursively copies the directory tree). This is the default behavior. | ||
145 | |||
146 | 2. If the "redirect_dir" feature is enabled, then the directory will be | ||
147 | copied up (but not the contents). Then the "trusted.overlay.redirect" | ||
148 | extended attribute is set to the path of the original location from the | ||
149 | root of the overlay. Finally the directory is moved to the new | ||
150 | location. | ||
133 | 151 | ||
134 | Non-directories | 152 | Non-directories |
135 | --------------- | 153 | --------------- |
@@ -185,13 +203,13 @@ filesystem, so both st_dev and st_ino of the file may change. | |||
185 | 203 | ||
186 | Any open files referring to this inode will access the old data. | 204 | Any open files referring to this inode will access the old data. |
187 | 205 | ||
188 | Any file locks (and leases) obtained before copy_up will not apply | ||
189 | to the copied up file. | ||
190 | |||
191 | If a file with multiple hard links is copied up, then this will | 206 | If a file with multiple hard links is copied up, then this will |
192 | "break" the link. Changes will not be propagated to other names | 207 | "break" the link. Changes will not be propagated to other names |
193 | referring to the same inode. | 208 | referring to the same inode. |
194 | 209 | ||
210 | Unless "redirect_dir" feature is enabled, rename(2) on a lower or merged | ||
211 | directory will fail with EXDEV. | ||
212 | |||
195 | Changes to underlying filesystems | 213 | Changes to underlying filesystems |
196 | --------------------------------- | 214 | --------------------------------- |
197 | 215 | ||
diff --git a/fs/ioctl.c b/fs/ioctl.c index c415668c86d4..cb9b02940805 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -223,7 +223,11 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd, | |||
223 | 223 | ||
224 | if (!src_file.file) | 224 | if (!src_file.file) |
225 | return -EBADF; | 225 | return -EBADF; |
226 | ret = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen); | 226 | ret = -EXDEV; |
227 | if (src_file.file->f_path.mnt != dst_file->f_path.mnt) | ||
228 | goto fdput; | ||
229 | ret = do_clone_file_range(src_file.file, off, dst_file, destoff, olen); | ||
230 | fdput: | ||
227 | fdput(src_file); | 231 | fdput(src_file); |
228 | return ret; | 232 | return ret; |
229 | } | 233 | } |
diff --git a/fs/namei.c b/fs/namei.c index 092ac5667ec7..2b55ea142273 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -4306,11 +4306,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4306 | bool new_is_dir = false; | 4306 | bool new_is_dir = false; |
4307 | unsigned max_links = new_dir->i_sb->s_max_links; | 4307 | unsigned max_links = new_dir->i_sb->s_max_links; |
4308 | 4308 | ||
4309 | /* | 4309 | if (source == target) |
4310 | * Check source == target. | ||
4311 | * On overlayfs need to look at underlying inodes. | ||
4312 | */ | ||
4313 | if (d_real_inode(old_dentry) == d_real_inode(new_dentry)) | ||
4314 | return 0; | 4310 | return 0; |
4315 | 4311 | ||
4316 | error = may_delete(old_dir, old_dentry, is_dir); | 4312 | error = may_delete(old_dir, old_dentry, is_dir); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 8ca642fe9b21..357e844aee84 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -509,8 +509,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
509 | __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, | 509 | __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, |
510 | u64 dst_pos, u64 count) | 510 | u64 dst_pos, u64 count) |
511 | { | 511 | { |
512 | return nfserrno(vfs_clone_file_range(src, src_pos, dst, dst_pos, | 512 | return nfserrno(do_clone_file_range(src, src_pos, dst, dst_pos, count)); |
513 | count)); | ||
514 | } | 513 | } |
515 | 514 | ||
516 | ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst, | 515 | ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst, |
diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig index 34355818a2e0..0daac5112f7a 100644 --- a/fs/overlayfs/Kconfig +++ b/fs/overlayfs/Kconfig | |||
@@ -8,3 +8,17 @@ config OVERLAY_FS | |||
8 | merged with the 'upper' object. | 8 | merged with the 'upper' object. |
9 | 9 | ||
10 | For more information see Documentation/filesystems/overlayfs.txt | 10 | For more information see Documentation/filesystems/overlayfs.txt |
11 | |||
12 | config OVERLAY_FS_REDIRECT_DIR | ||
13 | bool "Overlayfs: turn on redirect dir feature by default" | ||
14 | depends on OVERLAY_FS | ||
15 | help | ||
16 | If this config option is enabled then overlay filesystems will use | ||
17 | redirects when renaming directories by default. In this case it is | ||
18 | still possible to turn off redirects globally with the | ||
19 | "redirect_dir=off" module option or on a filesystem instance basis | ||
20 | with the "redirect_dir=off" mount option. | ||
21 | |||
22 | Note, that redirects are not backward compatible. That is, mounting | ||
23 | an overlay which has redirects on a kernel that doesn't support this | ||
24 | feature will have unexpected results. | ||
diff --git a/fs/overlayfs/Makefile b/fs/overlayfs/Makefile index 900daed3e91d..99373bbc1478 100644 --- a/fs/overlayfs/Makefile +++ b/fs/overlayfs/Makefile | |||
@@ -4,4 +4,4 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_OVERLAY_FS) += overlay.o | 5 | obj-$(CONFIG_OVERLAY_FS) += overlay.o |
6 | 6 | ||
7 | overlay-objs := super.o inode.o dir.o readdir.o copy_up.o | 7 | overlay-objs := super.o namei.o util.o inode.o dir.o readdir.o copy_up.o |
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 2838bddb1f91..f57043dace62 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
@@ -153,6 +153,13 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) | |||
153 | goto out_fput; | 153 | goto out_fput; |
154 | } | 154 | } |
155 | 155 | ||
156 | /* Try to use clone_file_range to clone up within the same fs */ | ||
157 | error = vfs_clone_file_range(old_file, 0, new_file, 0, len); | ||
158 | if (!error) | ||
159 | goto out; | ||
160 | /* Couldn't clone, so now we try to copy the data */ | ||
161 | error = 0; | ||
162 | |||
156 | /* FIXME: copy up sparse files efficiently */ | 163 | /* FIXME: copy up sparse files efficiently */ |
157 | while (len) { | 164 | while (len) { |
158 | size_t this_len = OVL_COPY_UP_CHUNK_SIZE; | 165 | size_t this_len = OVL_COPY_UP_CHUNK_SIZE; |
@@ -177,7 +184,7 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) | |||
177 | 184 | ||
178 | len -= bytes; | 185 | len -= bytes; |
179 | } | 186 | } |
180 | 187 | out: | |
181 | if (!error) | 188 | if (!error) |
182 | error = vfs_fsync(new_file, 0); | 189 | error = vfs_fsync(new_file, 0); |
183 | fput(new_file); | 190 | fput(new_file); |
@@ -231,10 +238,15 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, | |||
231 | struct inode *udir = upperdir->d_inode; | 238 | struct inode *udir = upperdir->d_inode; |
232 | struct dentry *newdentry = NULL; | 239 | struct dentry *newdentry = NULL; |
233 | struct dentry *upper = NULL; | 240 | struct dentry *upper = NULL; |
234 | umode_t mode = stat->mode; | ||
235 | int err; | 241 | int err; |
236 | const struct cred *old_creds = NULL; | 242 | const struct cred *old_creds = NULL; |
237 | struct cred *new_creds = NULL; | 243 | struct cred *new_creds = NULL; |
244 | struct cattr cattr = { | ||
245 | /* Can't properly set mode on creation because of the umask */ | ||
246 | .mode = stat->mode & S_IFMT, | ||
247 | .rdev = stat->rdev, | ||
248 | .link = link | ||
249 | }; | ||
238 | 250 | ||
239 | newdentry = ovl_lookup_temp(workdir, dentry); | 251 | newdentry = ovl_lookup_temp(workdir, dentry); |
240 | err = PTR_ERR(newdentry); | 252 | err = PTR_ERR(newdentry); |
@@ -254,10 +266,7 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, | |||
254 | if (new_creds) | 266 | if (new_creds) |
255 | old_creds = override_creds(new_creds); | 267 | old_creds = override_creds(new_creds); |
256 | 268 | ||
257 | /* Can't properly set mode on creation because of the umask */ | 269 | err = ovl_create_real(wdir, newdentry, &cattr, NULL, true); |
258 | stat->mode &= S_IFMT; | ||
259 | err = ovl_create_real(wdir, newdentry, stat, link, NULL, true); | ||
260 | stat->mode = mode; | ||
261 | 270 | ||
262 | if (new_creds) { | 271 | if (new_creds) { |
263 | revert_creds(old_creds); | 272 | revert_creds(old_creds); |
@@ -296,12 +305,6 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, | |||
296 | ovl_dentry_update(dentry, newdentry); | 305 | ovl_dentry_update(dentry, newdentry); |
297 | ovl_inode_update(d_inode(dentry), d_inode(newdentry)); | 306 | ovl_inode_update(d_inode(dentry), d_inode(newdentry)); |
298 | newdentry = NULL; | 307 | newdentry = NULL; |
299 | |||
300 | /* | ||
301 | * Non-directores become opaque when copied up. | ||
302 | */ | ||
303 | if (!S_ISDIR(stat->mode)) | ||
304 | ovl_dentry_set_opaque(dentry, true); | ||
305 | out2: | 308 | out2: |
306 | dput(upper); | 309 | dput(upper); |
307 | out1: | 310 | out1: |
@@ -317,20 +320,14 @@ out_cleanup: | |||
317 | /* | 320 | /* |
318 | * Copy up a single dentry | 321 | * Copy up a single dentry |
319 | * | 322 | * |
320 | * Directory renames only allowed on "pure upper" (already created on | 323 | * All renames start with copy up of source if necessary. The actual |
321 | * upper filesystem, never copied up). Directories which are on lower or | 324 | * rename will only proceed once the copy up was successful. Copy up uses |
322 | * are merged may not be renamed. For these -EXDEV is returned and | 325 | * upper parent i_mutex for exclusion. Since rename can change d_parent it |
323 | * userspace has to deal with it. This means, when copying up a | 326 | * is possible that the copy up will lock the old parent. At that point |
324 | * directory we can rely on it and ancestors being stable. | 327 | * the file will have already been copied up anyway. |
325 | * | ||
326 | * Non-directory renames start with copy up of source if necessary. The | ||
327 | * actual rename will only proceed once the copy up was successful. Copy | ||
328 | * up uses upper parent i_mutex for exclusion. Since rename can change | ||
329 | * d_parent it is possible that the copy up will lock the old parent. At | ||
330 | * that point the file will have already been copied up anyway. | ||
331 | */ | 328 | */ |
332 | int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | 329 | static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, |
333 | struct path *lowerpath, struct kstat *stat) | 330 | struct path *lowerpath, struct kstat *stat) |
334 | { | 331 | { |
335 | DEFINE_DELAYED_CALL(done); | 332 | DEFINE_DELAYED_CALL(done); |
336 | struct dentry *workdir = ovl_workdir(dentry); | 333 | struct dentry *workdir = ovl_workdir(dentry); |
@@ -339,7 +336,6 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | |||
339 | struct path parentpath; | 336 | struct path parentpath; |
340 | struct dentry *lowerdentry = lowerpath->dentry; | 337 | struct dentry *lowerdentry = lowerpath->dentry; |
341 | struct dentry *upperdir; | 338 | struct dentry *upperdir; |
342 | struct dentry *upperdentry; | ||
343 | const char *link = NULL; | 339 | const char *link = NULL; |
344 | 340 | ||
345 | if (WARN_ON(!workdir)) | 341 | if (WARN_ON(!workdir)) |
@@ -365,8 +361,7 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | |||
365 | pr_err("overlayfs: failed to lock workdir+upperdir\n"); | 361 | pr_err("overlayfs: failed to lock workdir+upperdir\n"); |
366 | goto out_unlock; | 362 | goto out_unlock; |
367 | } | 363 | } |
368 | upperdentry = ovl_dentry_upper(dentry); | 364 | if (ovl_dentry_upper(dentry)) { |
369 | if (upperdentry) { | ||
370 | /* Raced with another copy-up? Nothing to do, then... */ | 365 | /* Raced with another copy-up? Nothing to do, then... */ |
371 | err = 0; | 366 | err = 0; |
372 | goto out_unlock; | 367 | goto out_unlock; |
@@ -385,7 +380,7 @@ out_unlock: | |||
385 | return err; | 380 | return err; |
386 | } | 381 | } |
387 | 382 | ||
388 | int ovl_copy_up(struct dentry *dentry) | 383 | int ovl_copy_up_flags(struct dentry *dentry, int flags) |
389 | { | 384 | { |
390 | int err = 0; | 385 | int err = 0; |
391 | const struct cred *old_cred = ovl_override_creds(dentry->d_sb); | 386 | const struct cred *old_cred = ovl_override_creds(dentry->d_sb); |
@@ -415,6 +410,9 @@ int ovl_copy_up(struct dentry *dentry) | |||
415 | 410 | ||
416 | ovl_path_lower(next, &lowerpath); | 411 | ovl_path_lower(next, &lowerpath); |
417 | err = vfs_getattr(&lowerpath, &stat); | 412 | err = vfs_getattr(&lowerpath, &stat); |
413 | /* maybe truncate regular file. this has no effect on dirs */ | ||
414 | if (flags & O_TRUNC) | ||
415 | stat.size = 0; | ||
418 | if (!err) | 416 | if (!err) |
419 | err = ovl_copy_up_one(parent, next, &lowerpath, &stat); | 417 | err = ovl_copy_up_one(parent, next, &lowerpath, &stat); |
420 | 418 | ||
@@ -425,3 +423,8 @@ int ovl_copy_up(struct dentry *dentry) | |||
425 | 423 | ||
426 | return err; | 424 | return err; |
427 | } | 425 | } |
426 | |||
427 | int ovl_copy_up(struct dentry *dentry) | ||
428 | { | ||
429 | return ovl_copy_up_flags(dentry, 0); | ||
430 | } | ||
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 306b6c161840..16e06dd89457 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c | |||
@@ -12,11 +12,18 @@ | |||
12 | #include <linux/xattr.h> | 12 | #include <linux/xattr.h> |
13 | #include <linux/security.h> | 13 | #include <linux/security.h> |
14 | #include <linux/cred.h> | 14 | #include <linux/cred.h> |
15 | #include <linux/module.h> | ||
15 | #include <linux/posix_acl.h> | 16 | #include <linux/posix_acl.h> |
16 | #include <linux/posix_acl_xattr.h> | 17 | #include <linux/posix_acl_xattr.h> |
17 | #include <linux/atomic.h> | 18 | #include <linux/atomic.h> |
19 | #include <linux/ratelimit.h> | ||
18 | #include "overlayfs.h" | 20 | #include "overlayfs.h" |
19 | 21 | ||
22 | static unsigned short ovl_redirect_max = 256; | ||
23 | module_param_named(redirect_max, ovl_redirect_max, ushort, 0644); | ||
24 | MODULE_PARM_DESC(ovl_redirect_max, | ||
25 | "Maximum length of absolute redirect xattr value"); | ||
26 | |||
20 | void ovl_cleanup(struct inode *wdir, struct dentry *wdentry) | 27 | void ovl_cleanup(struct inode *wdir, struct dentry *wdentry) |
21 | { | 28 | { |
22 | int err; | 29 | int err; |
@@ -75,8 +82,7 @@ static struct dentry *ovl_whiteout(struct dentry *workdir, | |||
75 | } | 82 | } |
76 | 83 | ||
77 | int ovl_create_real(struct inode *dir, struct dentry *newdentry, | 84 | int ovl_create_real(struct inode *dir, struct dentry *newdentry, |
78 | struct kstat *stat, const char *link, | 85 | struct cattr *attr, struct dentry *hardlink, bool debug) |
79 | struct dentry *hardlink, bool debug) | ||
80 | { | 86 | { |
81 | int err; | 87 | int err; |
82 | 88 | ||
@@ -86,13 +92,13 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry, | |||
86 | if (hardlink) { | 92 | if (hardlink) { |
87 | err = ovl_do_link(hardlink, dir, newdentry, debug); | 93 | err = ovl_do_link(hardlink, dir, newdentry, debug); |
88 | } else { | 94 | } else { |
89 | switch (stat->mode & S_IFMT) { | 95 | switch (attr->mode & S_IFMT) { |
90 | case S_IFREG: | 96 | case S_IFREG: |
91 | err = ovl_do_create(dir, newdentry, stat->mode, debug); | 97 | err = ovl_do_create(dir, newdentry, attr->mode, debug); |
92 | break; | 98 | break; |
93 | 99 | ||
94 | case S_IFDIR: | 100 | case S_IFDIR: |
95 | err = ovl_do_mkdir(dir, newdentry, stat->mode, debug); | 101 | err = ovl_do_mkdir(dir, newdentry, attr->mode, debug); |
96 | break; | 102 | break; |
97 | 103 | ||
98 | case S_IFCHR: | 104 | case S_IFCHR: |
@@ -100,11 +106,11 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry, | |||
100 | case S_IFIFO: | 106 | case S_IFIFO: |
101 | case S_IFSOCK: | 107 | case S_IFSOCK: |
102 | err = ovl_do_mknod(dir, newdentry, | 108 | err = ovl_do_mknod(dir, newdentry, |
103 | stat->mode, stat->rdev, debug); | 109 | attr->mode, attr->rdev, debug); |
104 | break; | 110 | break; |
105 | 111 | ||
106 | case S_IFLNK: | 112 | case S_IFLNK: |
107 | err = ovl_do_symlink(dir, newdentry, link, debug); | 113 | err = ovl_do_symlink(dir, newdentry, attr->link, debug); |
108 | break; | 114 | break; |
109 | 115 | ||
110 | default: | 116 | default: |
@@ -121,20 +127,15 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry, | |||
121 | return err; | 127 | return err; |
122 | } | 128 | } |
123 | 129 | ||
124 | static int ovl_set_opaque(struct dentry *upperdentry) | 130 | static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry) |
125 | { | ||
126 | return ovl_do_setxattr(upperdentry, OVL_XATTR_OPAQUE, "y", 1, 0); | ||
127 | } | ||
128 | |||
129 | static void ovl_remove_opaque(struct dentry *upperdentry) | ||
130 | { | 131 | { |
131 | int err; | 132 | int err; |
132 | 133 | ||
133 | err = ovl_do_removexattr(upperdentry, OVL_XATTR_OPAQUE); | 134 | err = ovl_do_setxattr(upperdentry, OVL_XATTR_OPAQUE, "y", 1, 0); |
134 | if (err) { | 135 | if (!err) |
135 | pr_warn("overlayfs: failed to remove opaque from '%s' (%i)\n", | 136 | ovl_dentry_set_opaque(dentry); |
136 | upperdentry->d_name.name, err); | 137 | |
137 | } | 138 | return err; |
138 | } | 139 | } |
139 | 140 | ||
140 | static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, | 141 | static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, |
@@ -182,9 +183,13 @@ static void ovl_instantiate(struct dentry *dentry, struct inode *inode, | |||
182 | d_instantiate(dentry, inode); | 183 | d_instantiate(dentry, inode); |
183 | } | 184 | } |
184 | 185 | ||
186 | static bool ovl_type_merge(struct dentry *dentry) | ||
187 | { | ||
188 | return OVL_TYPE_MERGE(ovl_path_type(dentry)); | ||
189 | } | ||
190 | |||
185 | static int ovl_create_upper(struct dentry *dentry, struct inode *inode, | 191 | static int ovl_create_upper(struct dentry *dentry, struct inode *inode, |
186 | struct kstat *stat, const char *link, | 192 | struct cattr *attr, struct dentry *hardlink) |
187 | struct dentry *hardlink) | ||
188 | { | 193 | { |
189 | struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); | 194 | struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); |
190 | struct inode *udir = upperdir->d_inode; | 195 | struct inode *udir = upperdir->d_inode; |
@@ -192,7 +197,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, | |||
192 | int err; | 197 | int err; |
193 | 198 | ||
194 | if (!hardlink && !IS_POSIXACL(udir)) | 199 | if (!hardlink && !IS_POSIXACL(udir)) |
195 | stat->mode &= ~current_umask(); | 200 | attr->mode &= ~current_umask(); |
196 | 201 | ||
197 | inode_lock_nested(udir, I_MUTEX_PARENT); | 202 | inode_lock_nested(udir, I_MUTEX_PARENT); |
198 | newdentry = lookup_one_len(dentry->d_name.name, upperdir, | 203 | newdentry = lookup_one_len(dentry->d_name.name, upperdir, |
@@ -200,10 +205,15 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, | |||
200 | err = PTR_ERR(newdentry); | 205 | err = PTR_ERR(newdentry); |
201 | if (IS_ERR(newdentry)) | 206 | if (IS_ERR(newdentry)) |
202 | goto out_unlock; | 207 | goto out_unlock; |
203 | err = ovl_create_real(udir, newdentry, stat, link, hardlink, false); | 208 | err = ovl_create_real(udir, newdentry, attr, hardlink, false); |
204 | if (err) | 209 | if (err) |
205 | goto out_dput; | 210 | goto out_dput; |
206 | 211 | ||
212 | if (ovl_type_merge(dentry->d_parent)) { | ||
213 | /* Setting opaque here is just an optimization, allow to fail */ | ||
214 | ovl_set_opaque(dentry, newdentry); | ||
215 | } | ||
216 | |||
207 | ovl_instantiate(dentry, inode, newdentry, !!hardlink); | 217 | ovl_instantiate(dentry, inode, newdentry, !!hardlink); |
208 | newdentry = NULL; | 218 | newdentry = NULL; |
209 | out_dput: | 219 | out_dput: |
@@ -270,7 +280,8 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, | |||
270 | if (IS_ERR(opaquedir)) | 280 | if (IS_ERR(opaquedir)) |
271 | goto out_unlock; | 281 | goto out_unlock; |
272 | 282 | ||
273 | err = ovl_create_real(wdir, opaquedir, &stat, NULL, NULL, true); | 283 | err = ovl_create_real(wdir, opaquedir, |
284 | &(struct cattr){.mode = stat.mode}, NULL, true); | ||
274 | if (err) | 285 | if (err) |
275 | goto out_dput; | 286 | goto out_dput; |
276 | 287 | ||
@@ -278,7 +289,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, | |||
278 | if (err) | 289 | if (err) |
279 | goto out_cleanup; | 290 | goto out_cleanup; |
280 | 291 | ||
281 | err = ovl_set_opaque(opaquedir); | 292 | err = ovl_set_opaque(dentry, opaquedir); |
282 | if (err) | 293 | if (err) |
283 | goto out_cleanup; | 294 | goto out_cleanup; |
284 | 295 | ||
@@ -370,7 +381,7 @@ out_free: | |||
370 | } | 381 | } |
371 | 382 | ||
372 | static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, | 383 | static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, |
373 | struct kstat *stat, const char *link, | 384 | struct cattr *cattr, |
374 | struct dentry *hardlink) | 385 | struct dentry *hardlink) |
375 | { | 386 | { |
376 | struct dentry *workdir = ovl_workdir(dentry); | 387 | struct dentry *workdir = ovl_workdir(dentry); |
@@ -387,7 +398,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, | |||
387 | 398 | ||
388 | if (!hardlink) { | 399 | if (!hardlink) { |
389 | err = posix_acl_create(dentry->d_parent->d_inode, | 400 | err = posix_acl_create(dentry->d_parent->d_inode, |
390 | &stat->mode, &default_acl, &acl); | 401 | &cattr->mode, &default_acl, &acl); |
391 | if (err) | 402 | if (err) |
392 | return err; | 403 | return err; |
393 | } | 404 | } |
@@ -407,7 +418,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, | |||
407 | if (IS_ERR(upper)) | 418 | if (IS_ERR(upper)) |
408 | goto out_dput; | 419 | goto out_dput; |
409 | 420 | ||
410 | err = ovl_create_real(wdir, newdentry, stat, link, hardlink, true); | 421 | err = ovl_create_real(wdir, newdentry, cattr, hardlink, true); |
411 | if (err) | 422 | if (err) |
412 | goto out_dput2; | 423 | goto out_dput2; |
413 | 424 | ||
@@ -415,10 +426,11 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, | |||
415 | * mode could have been mutilated due to umask (e.g. sgid directory) | 426 | * mode could have been mutilated due to umask (e.g. sgid directory) |
416 | */ | 427 | */ |
417 | if (!hardlink && | 428 | if (!hardlink && |
418 | !S_ISLNK(stat->mode) && newdentry->d_inode->i_mode != stat->mode) { | 429 | !S_ISLNK(cattr->mode) && |
430 | newdentry->d_inode->i_mode != cattr->mode) { | ||
419 | struct iattr attr = { | 431 | struct iattr attr = { |
420 | .ia_valid = ATTR_MODE, | 432 | .ia_valid = ATTR_MODE, |
421 | .ia_mode = stat->mode, | 433 | .ia_mode = cattr->mode, |
422 | }; | 434 | }; |
423 | inode_lock(newdentry->d_inode); | 435 | inode_lock(newdentry->d_inode); |
424 | err = notify_change(newdentry, &attr, NULL); | 436 | err = notify_change(newdentry, &attr, NULL); |
@@ -438,8 +450,8 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, | |||
438 | goto out_cleanup; | 450 | goto out_cleanup; |
439 | } | 451 | } |
440 | 452 | ||
441 | if (!hardlink && S_ISDIR(stat->mode)) { | 453 | if (!hardlink && S_ISDIR(cattr->mode)) { |
442 | err = ovl_set_opaque(newdentry); | 454 | err = ovl_set_opaque(dentry, newdentry); |
443 | if (err) | 455 | if (err) |
444 | goto out_cleanup; | 456 | goto out_cleanup; |
445 | 457 | ||
@@ -475,8 +487,7 @@ out_cleanup: | |||
475 | } | 487 | } |
476 | 488 | ||
477 | static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, | 489 | static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, |
478 | struct kstat *stat, const char *link, | 490 | struct cattr *attr, struct dentry *hardlink) |
479 | struct dentry *hardlink) | ||
480 | { | 491 | { |
481 | int err; | 492 | int err; |
482 | const struct cred *old_cred; | 493 | const struct cred *old_cred; |
@@ -494,7 +505,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, | |||
494 | override_cred->fsgid = inode->i_gid; | 505 | override_cred->fsgid = inode->i_gid; |
495 | if (!hardlink) { | 506 | if (!hardlink) { |
496 | err = security_dentry_create_files_as(dentry, | 507 | err = security_dentry_create_files_as(dentry, |
497 | stat->mode, &dentry->d_name, old_cred, | 508 | attr->mode, &dentry->d_name, old_cred, |
498 | override_cred); | 509 | override_cred); |
499 | if (err) { | 510 | if (err) { |
500 | put_cred(override_cred); | 511 | put_cred(override_cred); |
@@ -504,12 +515,12 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, | |||
504 | put_cred(override_creds(override_cred)); | 515 | put_cred(override_creds(override_cred)); |
505 | put_cred(override_cred); | 516 | put_cred(override_cred); |
506 | 517 | ||
507 | if (!ovl_dentry_is_opaque(dentry)) | 518 | if (!ovl_dentry_is_whiteout(dentry)) |
508 | err = ovl_create_upper(dentry, inode, stat, link, | 519 | err = ovl_create_upper(dentry, inode, attr, |
509 | hardlink); | 520 | hardlink); |
510 | else | 521 | else |
511 | err = ovl_create_over_whiteout(dentry, inode, stat, | 522 | err = ovl_create_over_whiteout(dentry, inode, attr, |
512 | link, hardlink); | 523 | hardlink); |
513 | } | 524 | } |
514 | out_revert_creds: | 525 | out_revert_creds: |
515 | revert_creds(old_cred); | 526 | revert_creds(old_cred); |
@@ -528,8 +539,9 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev, | |||
528 | { | 539 | { |
529 | int err; | 540 | int err; |
530 | struct inode *inode; | 541 | struct inode *inode; |
531 | struct kstat stat = { | 542 | struct cattr attr = { |
532 | .rdev = rdev, | 543 | .rdev = rdev, |
544 | .link = link, | ||
533 | }; | 545 | }; |
534 | 546 | ||
535 | err = ovl_want_write(dentry); | 547 | err = ovl_want_write(dentry); |
@@ -537,14 +549,14 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev, | |||
537 | goto out; | 549 | goto out; |
538 | 550 | ||
539 | err = -ENOMEM; | 551 | err = -ENOMEM; |
540 | inode = ovl_new_inode(dentry->d_sb, mode); | 552 | inode = ovl_new_inode(dentry->d_sb, mode, rdev); |
541 | if (!inode) | 553 | if (!inode) |
542 | goto out_drop_write; | 554 | goto out_drop_write; |
543 | 555 | ||
544 | inode_init_owner(inode, dentry->d_parent->d_inode, mode); | 556 | inode_init_owner(inode, dentry->d_parent->d_inode, mode); |
545 | stat.mode = inode->i_mode; | 557 | attr.mode = inode->i_mode; |
546 | 558 | ||
547 | err = ovl_create_or_link(dentry, inode, &stat, link, NULL); | 559 | err = ovl_create_or_link(dentry, inode, &attr, NULL); |
548 | if (err) | 560 | if (err) |
549 | iput(inode); | 561 | iput(inode); |
550 | 562 | ||
@@ -598,7 +610,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir, | |||
598 | inode = d_inode(old); | 610 | inode = d_inode(old); |
599 | ihold(inode); | 611 | ihold(inode); |
600 | 612 | ||
601 | err = ovl_create_or_link(new, inode, NULL, NULL, ovl_dentry_upper(old)); | 613 | err = ovl_create_or_link(new, inode, NULL, ovl_dentry_upper(old)); |
602 | if (err) | 614 | if (err) |
603 | iput(inode); | 615 | iput(inode); |
604 | 616 | ||
@@ -684,8 +696,17 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir) | |||
684 | struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); | 696 | struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); |
685 | struct inode *dir = upperdir->d_inode; | 697 | struct inode *dir = upperdir->d_inode; |
686 | struct dentry *upper; | 698 | struct dentry *upper; |
699 | struct dentry *opaquedir = NULL; | ||
687 | int err; | 700 | int err; |
688 | 701 | ||
702 | /* Redirect dir can be !ovl_lower_positive && OVL_TYPE_MERGE */ | ||
703 | if (is_dir && ovl_dentry_get_redirect(dentry)) { | ||
704 | opaquedir = ovl_check_empty_and_clear(dentry); | ||
705 | err = PTR_ERR(opaquedir); | ||
706 | if (IS_ERR(opaquedir)) | ||
707 | goto out; | ||
708 | } | ||
709 | |||
689 | inode_lock_nested(dir, I_MUTEX_PARENT); | 710 | inode_lock_nested(dir, I_MUTEX_PARENT); |
690 | upper = lookup_one_len(dentry->d_name.name, upperdir, | 711 | upper = lookup_one_len(dentry->d_name.name, upperdir, |
691 | dentry->d_name.len); | 712 | dentry->d_name.len); |
@@ -694,14 +715,15 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir) | |||
694 | goto out_unlock; | 715 | goto out_unlock; |
695 | 716 | ||
696 | err = -ESTALE; | 717 | err = -ESTALE; |
697 | if (upper == ovl_dentry_upper(dentry)) { | 718 | if ((opaquedir && upper != opaquedir) || |
698 | if (is_dir) | 719 | (!opaquedir && upper != ovl_dentry_upper(dentry))) |
699 | err = vfs_rmdir(dir, upper); | 720 | goto out_dput_upper; |
700 | else | 721 | |
701 | err = vfs_unlink(dir, upper, NULL); | 722 | if (is_dir) |
702 | ovl_dentry_version_inc(dentry->d_parent); | 723 | err = vfs_rmdir(dir, upper); |
703 | } | 724 | else |
704 | dput(upper); | 725 | err = vfs_unlink(dir, upper, NULL); |
726 | ovl_dentry_version_inc(dentry->d_parent); | ||
705 | 727 | ||
706 | /* | 728 | /* |
707 | * Keeping this dentry hashed would mean having to release | 729 | * Keeping this dentry hashed would mean having to release |
@@ -711,34 +733,21 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir) | |||
711 | */ | 733 | */ |
712 | if (!err) | 734 | if (!err) |
713 | d_drop(dentry); | 735 | d_drop(dentry); |
736 | out_dput_upper: | ||
737 | dput(upper); | ||
714 | out_unlock: | 738 | out_unlock: |
715 | inode_unlock(dir); | 739 | inode_unlock(dir); |
716 | 740 | dput(opaquedir); | |
741 | out: | ||
717 | return err; | 742 | return err; |
718 | } | 743 | } |
719 | 744 | ||
720 | static inline int ovl_check_sticky(struct dentry *dentry) | ||
721 | { | ||
722 | struct inode *dir = ovl_dentry_real(dentry->d_parent)->d_inode; | ||
723 | struct inode *inode = ovl_dentry_real(dentry)->d_inode; | ||
724 | |||
725 | if (check_sticky(dir, inode)) | ||
726 | return -EPERM; | ||
727 | |||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | static int ovl_do_remove(struct dentry *dentry, bool is_dir) | 745 | static int ovl_do_remove(struct dentry *dentry, bool is_dir) |
732 | { | 746 | { |
733 | enum ovl_path_type type; | 747 | enum ovl_path_type type; |
734 | int err; | 748 | int err; |
735 | const struct cred *old_cred; | 749 | const struct cred *old_cred; |
736 | 750 | ||
737 | |||
738 | err = ovl_check_sticky(dentry); | ||
739 | if (err) | ||
740 | goto out; | ||
741 | |||
742 | err = ovl_want_write(dentry); | 751 | err = ovl_want_write(dentry); |
743 | if (err) | 752 | if (err) |
744 | goto out; | 753 | goto out; |
@@ -750,7 +759,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) | |||
750 | type = ovl_path_type(dentry); | 759 | type = ovl_path_type(dentry); |
751 | 760 | ||
752 | old_cred = ovl_override_creds(dentry->d_sb); | 761 | old_cred = ovl_override_creds(dentry->d_sb); |
753 | if (OVL_TYPE_PURE_UPPER(type)) | 762 | if (!ovl_lower_positive(dentry)) |
754 | err = ovl_remove_upper(dentry, is_dir); | 763 | err = ovl_remove_upper(dentry, is_dir); |
755 | else | 764 | else |
756 | err = ovl_remove_and_whiteout(dentry, is_dir); | 765 | err = ovl_remove_and_whiteout(dentry, is_dir); |
@@ -777,13 +786,114 @@ static int ovl_rmdir(struct inode *dir, struct dentry *dentry) | |||
777 | return ovl_do_remove(dentry, true); | 786 | return ovl_do_remove(dentry, true); |
778 | } | 787 | } |
779 | 788 | ||
780 | static int ovl_rename2(struct inode *olddir, struct dentry *old, | 789 | static bool ovl_type_merge_or_lower(struct dentry *dentry) |
781 | struct inode *newdir, struct dentry *new, | 790 | { |
782 | unsigned int flags) | 791 | enum ovl_path_type type = ovl_path_type(dentry); |
792 | |||
793 | return OVL_TYPE_MERGE(type) || !OVL_TYPE_UPPER(type); | ||
794 | } | ||
795 | |||
796 | static bool ovl_can_move(struct dentry *dentry) | ||
797 | { | ||
798 | return ovl_redirect_dir(dentry->d_sb) || | ||
799 | !d_is_dir(dentry) || !ovl_type_merge_or_lower(dentry); | ||
800 | } | ||
801 | |||
802 | static char *ovl_get_redirect(struct dentry *dentry, bool samedir) | ||
803 | { | ||
804 | char *buf, *ret; | ||
805 | struct dentry *d, *tmp; | ||
806 | int buflen = ovl_redirect_max + 1; | ||
807 | |||
808 | if (samedir) { | ||
809 | ret = kstrndup(dentry->d_name.name, dentry->d_name.len, | ||
810 | GFP_KERNEL); | ||
811 | goto out; | ||
812 | } | ||
813 | |||
814 | buf = ret = kmalloc(buflen, GFP_TEMPORARY); | ||
815 | if (!buf) | ||
816 | goto out; | ||
817 | |||
818 | buflen--; | ||
819 | buf[buflen] = '\0'; | ||
820 | for (d = dget(dentry); !IS_ROOT(d);) { | ||
821 | const char *name; | ||
822 | int thislen; | ||
823 | |||
824 | spin_lock(&d->d_lock); | ||
825 | name = ovl_dentry_get_redirect(d); | ||
826 | if (name) { | ||
827 | thislen = strlen(name); | ||
828 | } else { | ||
829 | name = d->d_name.name; | ||
830 | thislen = d->d_name.len; | ||
831 | } | ||
832 | |||
833 | /* If path is too long, fall back to userspace move */ | ||
834 | if (thislen + (name[0] != '/') > buflen) { | ||
835 | ret = ERR_PTR(-EXDEV); | ||
836 | spin_unlock(&d->d_lock); | ||
837 | goto out_put; | ||
838 | } | ||
839 | |||
840 | buflen -= thislen; | ||
841 | memcpy(&buf[buflen], name, thislen); | ||
842 | tmp = dget_dlock(d->d_parent); | ||
843 | spin_unlock(&d->d_lock); | ||
844 | |||
845 | dput(d); | ||
846 | d = tmp; | ||
847 | |||
848 | /* Absolute redirect: finished */ | ||
849 | if (buf[buflen] == '/') | ||
850 | break; | ||
851 | buflen--; | ||
852 | buf[buflen] = '/'; | ||
853 | } | ||
854 | ret = kstrdup(&buf[buflen], GFP_KERNEL); | ||
855 | out_put: | ||
856 | dput(d); | ||
857 | kfree(buf); | ||
858 | out: | ||
859 | return ret ? ret : ERR_PTR(-ENOMEM); | ||
860 | } | ||
861 | |||
862 | static int ovl_set_redirect(struct dentry *dentry, bool samedir) | ||
863 | { | ||
864 | int err; | ||
865 | const char *redirect = ovl_dentry_get_redirect(dentry); | ||
866 | |||
867 | if (redirect && (samedir || redirect[0] == '/')) | ||
868 | return 0; | ||
869 | |||
870 | redirect = ovl_get_redirect(dentry, samedir); | ||
871 | if (IS_ERR(redirect)) | ||
872 | return PTR_ERR(redirect); | ||
873 | |||
874 | err = ovl_do_setxattr(ovl_dentry_upper(dentry), OVL_XATTR_REDIRECT, | ||
875 | redirect, strlen(redirect), 0); | ||
876 | if (!err) { | ||
877 | spin_lock(&dentry->d_lock); | ||
878 | ovl_dentry_set_redirect(dentry, redirect); | ||
879 | spin_unlock(&dentry->d_lock); | ||
880 | } else { | ||
881 | kfree(redirect); | ||
882 | if (err == -EOPNOTSUPP) | ||
883 | ovl_clear_redirect_dir(dentry->d_sb); | ||
884 | else | ||
885 | pr_warn_ratelimited("overlay: failed to set redirect (%i)\n", err); | ||
886 | /* Fall back to userspace copy-up */ | ||
887 | err = -EXDEV; | ||
888 | } | ||
889 | return err; | ||
890 | } | ||
891 | |||
892 | static int ovl_rename(struct inode *olddir, struct dentry *old, | ||
893 | struct inode *newdir, struct dentry *new, | ||
894 | unsigned int flags) | ||
783 | { | 895 | { |
784 | int err; | 896 | int err; |
785 | enum ovl_path_type old_type; | ||
786 | enum ovl_path_type new_type; | ||
787 | struct dentry *old_upperdir; | 897 | struct dentry *old_upperdir; |
788 | struct dentry *new_upperdir; | 898 | struct dentry *new_upperdir; |
789 | struct dentry *olddentry; | 899 | struct dentry *olddentry; |
@@ -794,7 +904,8 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
794 | bool cleanup_whiteout = false; | 904 | bool cleanup_whiteout = false; |
795 | bool overwrite = !(flags & RENAME_EXCHANGE); | 905 | bool overwrite = !(flags & RENAME_EXCHANGE); |
796 | bool is_dir = d_is_dir(old); | 906 | bool is_dir = d_is_dir(old); |
797 | bool new_is_dir = false; | 907 | bool new_is_dir = d_is_dir(new); |
908 | bool samedir = olddir == newdir; | ||
798 | struct dentry *opaquedir = NULL; | 909 | struct dentry *opaquedir = NULL; |
799 | const struct cred *old_cred = NULL; | 910 | const struct cred *old_cred = NULL; |
800 | 911 | ||
@@ -804,46 +915,12 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
804 | 915 | ||
805 | flags &= ~RENAME_NOREPLACE; | 916 | flags &= ~RENAME_NOREPLACE; |
806 | 917 | ||
807 | err = ovl_check_sticky(old); | ||
808 | if (err) | ||
809 | goto out; | ||
810 | |||
811 | /* Don't copy up directory trees */ | 918 | /* Don't copy up directory trees */ |
812 | old_type = ovl_path_type(old); | ||
813 | err = -EXDEV; | 919 | err = -EXDEV; |
814 | if (OVL_TYPE_MERGE_OR_LOWER(old_type) && is_dir) | 920 | if (!ovl_can_move(old)) |
921 | goto out; | ||
922 | if (!overwrite && !ovl_can_move(new)) | ||
815 | goto out; | 923 | goto out; |
816 | |||
817 | if (new->d_inode) { | ||
818 | err = ovl_check_sticky(new); | ||
819 | if (err) | ||
820 | goto out; | ||
821 | |||
822 | if (d_is_dir(new)) | ||
823 | new_is_dir = true; | ||
824 | |||
825 | new_type = ovl_path_type(new); | ||
826 | err = -EXDEV; | ||
827 | if (!overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) | ||
828 | goto out; | ||
829 | |||
830 | err = 0; | ||
831 | if (!OVL_TYPE_UPPER(new_type) && !OVL_TYPE_UPPER(old_type)) { | ||
832 | if (ovl_dentry_lower(old)->d_inode == | ||
833 | ovl_dentry_lower(new)->d_inode) | ||
834 | goto out; | ||
835 | } | ||
836 | if (OVL_TYPE_UPPER(new_type) && OVL_TYPE_UPPER(old_type)) { | ||
837 | if (ovl_dentry_upper(old)->d_inode == | ||
838 | ovl_dentry_upper(new)->d_inode) | ||
839 | goto out; | ||
840 | } | ||
841 | } else { | ||
842 | if (ovl_dentry_is_opaque(new)) | ||
843 | new_type = __OVL_PATH_UPPER; | ||
844 | else | ||
845 | new_type = __OVL_PATH_UPPER | __OVL_PATH_PURE; | ||
846 | } | ||
847 | 924 | ||
848 | err = ovl_want_write(old); | 925 | err = ovl_want_write(old); |
849 | if (err) | 926 | if (err) |
@@ -862,12 +939,9 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
862 | goto out_drop_write; | 939 | goto out_drop_write; |
863 | } | 940 | } |
864 | 941 | ||
865 | old_opaque = !OVL_TYPE_PURE_UPPER(old_type); | ||
866 | new_opaque = !OVL_TYPE_PURE_UPPER(new_type); | ||
867 | |||
868 | old_cred = ovl_override_creds(old->d_sb); | 942 | old_cred = ovl_override_creds(old->d_sb); |
869 | 943 | ||
870 | if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) { | 944 | if (overwrite && new_is_dir && ovl_type_merge_or_lower(new)) { |
871 | opaquedir = ovl_check_empty_and_clear(new); | 945 | opaquedir = ovl_check_empty_and_clear(new); |
872 | err = PTR_ERR(opaquedir); | 946 | err = PTR_ERR(opaquedir); |
873 | if (IS_ERR(opaquedir)) { | 947 | if (IS_ERR(opaquedir)) { |
@@ -877,15 +951,15 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
877 | } | 951 | } |
878 | 952 | ||
879 | if (overwrite) { | 953 | if (overwrite) { |
880 | if (old_opaque) { | 954 | if (ovl_lower_positive(old)) { |
881 | if (new->d_inode || !new_opaque) { | 955 | if (!ovl_dentry_is_whiteout(new)) { |
882 | /* Whiteout source */ | 956 | /* Whiteout source */ |
883 | flags |= RENAME_WHITEOUT; | 957 | flags |= RENAME_WHITEOUT; |
884 | } else { | 958 | } else { |
885 | /* Switch whiteouts */ | 959 | /* Switch whiteouts */ |
886 | flags |= RENAME_EXCHANGE; | 960 | flags |= RENAME_EXCHANGE; |
887 | } | 961 | } |
888 | } else if (is_dir && !new->d_inode && new_opaque) { | 962 | } else if (is_dir && ovl_dentry_is_whiteout(new)) { |
889 | flags |= RENAME_EXCHANGE; | 963 | flags |= RENAME_EXCHANGE; |
890 | cleanup_whiteout = true; | 964 | cleanup_whiteout = true; |
891 | } | 965 | } |
@@ -896,7 +970,6 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
896 | 970 | ||
897 | trap = lock_rename(new_upperdir, old_upperdir); | 971 | trap = lock_rename(new_upperdir, old_upperdir); |
898 | 972 | ||
899 | |||
900 | olddentry = lookup_one_len(old->d_name.name, old_upperdir, | 973 | olddentry = lookup_one_len(old->d_name.name, old_upperdir, |
901 | old->d_name.len); | 974 | old->d_name.len); |
902 | err = PTR_ERR(olddentry); | 975 | err = PTR_ERR(olddentry); |
@@ -913,6 +986,9 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
913 | if (IS_ERR(newdentry)) | 986 | if (IS_ERR(newdentry)) |
914 | goto out_dput_old; | 987 | goto out_dput_old; |
915 | 988 | ||
989 | old_opaque = ovl_dentry_is_opaque(old); | ||
990 | new_opaque = ovl_dentry_is_opaque(new); | ||
991 | |||
916 | err = -ESTALE; | 992 | err = -ESTALE; |
917 | if (ovl_dentry_upper(new)) { | 993 | if (ovl_dentry_upper(new)) { |
918 | if (opaquedir) { | 994 | if (opaquedir) { |
@@ -933,54 +1009,31 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
933 | if (newdentry == trap) | 1009 | if (newdentry == trap) |
934 | goto out_dput; | 1010 | goto out_dput; |
935 | 1011 | ||
936 | if (is_dir && !old_opaque && new_opaque) { | 1012 | if (WARN_ON(olddentry->d_inode == newdentry->d_inode)) |
937 | err = ovl_set_opaque(olddentry); | 1013 | goto out_dput; |
1014 | |||
1015 | err = 0; | ||
1016 | if (is_dir) { | ||
1017 | if (ovl_type_merge_or_lower(old)) | ||
1018 | err = ovl_set_redirect(old, samedir); | ||
1019 | else if (!old_opaque && ovl_type_merge(new->d_parent)) | ||
1020 | err = ovl_set_opaque(old, olddentry); | ||
938 | if (err) | 1021 | if (err) |
939 | goto out_dput; | 1022 | goto out_dput; |
940 | } | 1023 | } |
941 | if (!overwrite && new_is_dir && old_opaque && !new_opaque) { | 1024 | if (!overwrite && new_is_dir) { |
942 | err = ovl_set_opaque(newdentry); | 1025 | if (ovl_type_merge_or_lower(new)) |
1026 | err = ovl_set_redirect(new, samedir); | ||
1027 | else if (!new_opaque && ovl_type_merge(old->d_parent)) | ||
1028 | err = ovl_set_opaque(new, newdentry); | ||
943 | if (err) | 1029 | if (err) |
944 | goto out_dput; | 1030 | goto out_dput; |
945 | } | 1031 | } |
946 | 1032 | ||
947 | if (old_opaque || new_opaque) { | 1033 | err = ovl_do_rename(old_upperdir->d_inode, olddentry, |
948 | err = ovl_do_rename(old_upperdir->d_inode, olddentry, | 1034 | new_upperdir->d_inode, newdentry, flags); |
949 | new_upperdir->d_inode, newdentry, | 1035 | if (err) |
950 | flags); | ||
951 | } else { | ||
952 | /* No debug for the plain case */ | ||
953 | BUG_ON(flags & ~RENAME_EXCHANGE); | ||
954 | err = vfs_rename(old_upperdir->d_inode, olddentry, | ||
955 | new_upperdir->d_inode, newdentry, | ||
956 | NULL, flags); | ||
957 | } | ||
958 | |||
959 | if (err) { | ||
960 | if (is_dir && !old_opaque && new_opaque) | ||
961 | ovl_remove_opaque(olddentry); | ||
962 | if (!overwrite && new_is_dir && old_opaque && !new_opaque) | ||
963 | ovl_remove_opaque(newdentry); | ||
964 | goto out_dput; | 1036 | goto out_dput; |
965 | } | ||
966 | |||
967 | if (is_dir && old_opaque && !new_opaque) | ||
968 | ovl_remove_opaque(olddentry); | ||
969 | if (!overwrite && new_is_dir && !old_opaque && new_opaque) | ||
970 | ovl_remove_opaque(newdentry); | ||
971 | |||
972 | /* | ||
973 | * Old dentry now lives in different location. Dentries in | ||
974 | * lowerstack are stale. We cannot drop them here because | ||
975 | * access to them is lockless. This could be only pure upper | ||
976 | * or opaque directory - numlower is zero. Or upper non-dir | ||
977 | * entry - its pureness is tracked by flag opaque. | ||
978 | */ | ||
979 | if (old_opaque != new_opaque) { | ||
980 | ovl_dentry_set_opaque(old, new_opaque); | ||
981 | if (!overwrite) | ||
982 | ovl_dentry_set_opaque(new, old_opaque); | ||
983 | } | ||
984 | 1037 | ||
985 | if (cleanup_whiteout) | 1038 | if (cleanup_whiteout) |
986 | ovl_cleanup(old_upperdir->d_inode, newdentry); | 1039 | ovl_cleanup(old_upperdir->d_inode, newdentry); |
@@ -1009,7 +1062,7 @@ const struct inode_operations ovl_dir_inode_operations = { | |||
1009 | .symlink = ovl_symlink, | 1062 | .symlink = ovl_symlink, |
1010 | .unlink = ovl_unlink, | 1063 | .unlink = ovl_unlink, |
1011 | .rmdir = ovl_rmdir, | 1064 | .rmdir = ovl_rmdir, |
1012 | .rename = ovl_rename2, | 1065 | .rename = ovl_rename, |
1013 | .link = ovl_link, | 1066 | .link = ovl_link, |
1014 | .setattr = ovl_setattr, | 1067 | .setattr = ovl_setattr, |
1015 | .create = ovl_create, | 1068 | .create = ovl_create, |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 7fb53d055537..1ab8b0dbc237 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -13,34 +13,6 @@ | |||
13 | #include <linux/posix_acl.h> | 13 | #include <linux/posix_acl.h> |
14 | #include "overlayfs.h" | 14 | #include "overlayfs.h" |
15 | 15 | ||
16 | static int ovl_copy_up_truncate(struct dentry *dentry) | ||
17 | { | ||
18 | int err; | ||
19 | struct dentry *parent; | ||
20 | struct kstat stat; | ||
21 | struct path lowerpath; | ||
22 | const struct cred *old_cred; | ||
23 | |||
24 | parent = dget_parent(dentry); | ||
25 | err = ovl_copy_up(parent); | ||
26 | if (err) | ||
27 | goto out_dput_parent; | ||
28 | |||
29 | ovl_path_lower(dentry, &lowerpath); | ||
30 | |||
31 | old_cred = ovl_override_creds(dentry->d_sb); | ||
32 | err = vfs_getattr(&lowerpath, &stat); | ||
33 | if (!err) { | ||
34 | stat.size = 0; | ||
35 | err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); | ||
36 | } | ||
37 | revert_creds(old_cred); | ||
38 | |||
39 | out_dput_parent: | ||
40 | dput(parent); | ||
41 | return err; | ||
42 | } | ||
43 | |||
44 | int ovl_setattr(struct dentry *dentry, struct iattr *attr) | 16 | int ovl_setattr(struct dentry *dentry, struct iattr *attr) |
45 | { | 17 | { |
46 | int err; | 18 | int err; |
@@ -64,27 +36,10 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) | |||
64 | if (err) | 36 | if (err) |
65 | goto out; | 37 | goto out; |
66 | 38 | ||
67 | if (attr->ia_valid & ATTR_SIZE) { | ||
68 | struct inode *realinode = d_inode(ovl_dentry_real(dentry)); | ||
69 | |||
70 | err = -ETXTBSY; | ||
71 | if (atomic_read(&realinode->i_writecount) < 0) | ||
72 | goto out_drop_write; | ||
73 | } | ||
74 | |||
75 | err = ovl_copy_up(dentry); | 39 | err = ovl_copy_up(dentry); |
76 | if (!err) { | 40 | if (!err) { |
77 | struct inode *winode = NULL; | ||
78 | |||
79 | upperdentry = ovl_dentry_upper(dentry); | 41 | upperdentry = ovl_dentry_upper(dentry); |
80 | 42 | ||
81 | if (attr->ia_valid & ATTR_SIZE) { | ||
82 | winode = d_inode(upperdentry); | ||
83 | err = get_write_access(winode); | ||
84 | if (err) | ||
85 | goto out_drop_write; | ||
86 | } | ||
87 | |||
88 | if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) | 43 | if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) |
89 | attr->ia_valid &= ~ATTR_MODE; | 44 | attr->ia_valid &= ~ATTR_MODE; |
90 | 45 | ||
@@ -95,11 +50,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) | |||
95 | if (!err) | 50 | if (!err) |
96 | ovl_copyattr(upperdentry->d_inode, dentry->d_inode); | 51 | ovl_copyattr(upperdentry->d_inode, dentry->d_inode); |
97 | inode_unlock(upperdentry->d_inode); | 52 | inode_unlock(upperdentry->d_inode); |
98 | |||
99 | if (winode) | ||
100 | put_write_access(winode); | ||
101 | } | 53 | } |
102 | out_drop_write: | ||
103 | ovl_drop_write(dentry); | 54 | ovl_drop_write(dentry); |
104 | out: | 55 | out: |
105 | return err; | 56 | return err; |
@@ -302,10 +253,7 @@ int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags) | |||
302 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { | 253 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { |
303 | err = ovl_want_write(dentry); | 254 | err = ovl_want_write(dentry); |
304 | if (!err) { | 255 | if (!err) { |
305 | if (file_flags & O_TRUNC) | 256 | err = ovl_copy_up_flags(dentry, file_flags); |
306 | err = ovl_copy_up_truncate(dentry); | ||
307 | else | ||
308 | err = ovl_copy_up(dentry); | ||
309 | ovl_drop_write(dentry); | 257 | ovl_drop_write(dentry); |
310 | } | 258 | } |
311 | } | 259 | } |
@@ -354,7 +302,7 @@ static const struct inode_operations ovl_symlink_inode_operations = { | |||
354 | .update_time = ovl_update_time, | 302 | .update_time = ovl_update_time, |
355 | }; | 303 | }; |
356 | 304 | ||
357 | static void ovl_fill_inode(struct inode *inode, umode_t mode) | 305 | static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev) |
358 | { | 306 | { |
359 | inode->i_ino = get_next_ino(); | 307 | inode->i_ino = get_next_ino(); |
360 | inode->i_mode = mode; | 308 | inode->i_mode = mode; |
@@ -363,8 +311,11 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode) | |||
363 | inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE; | 311 | inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE; |
364 | #endif | 312 | #endif |
365 | 313 | ||
366 | mode &= S_IFMT; | 314 | switch (mode & S_IFMT) { |
367 | switch (mode) { | 315 | case S_IFREG: |
316 | inode->i_op = &ovl_file_inode_operations; | ||
317 | break; | ||
318 | |||
368 | case S_IFDIR: | 319 | case S_IFDIR: |
369 | inode->i_op = &ovl_dir_inode_operations; | 320 | inode->i_op = &ovl_dir_inode_operations; |
370 | inode->i_fop = &ovl_dir_operations; | 321 | inode->i_fop = &ovl_dir_operations; |
@@ -375,26 +326,19 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode) | |||
375 | break; | 326 | break; |
376 | 327 | ||
377 | default: | 328 | default: |
378 | WARN(1, "illegal file type: %i\n", mode); | ||
379 | /* Fall through */ | ||
380 | |||
381 | case S_IFREG: | ||
382 | case S_IFSOCK: | ||
383 | case S_IFBLK: | ||
384 | case S_IFCHR: | ||
385 | case S_IFIFO: | ||
386 | inode->i_op = &ovl_file_inode_operations; | 329 | inode->i_op = &ovl_file_inode_operations; |
330 | init_special_inode(inode, mode, rdev); | ||
387 | break; | 331 | break; |
388 | } | 332 | } |
389 | } | 333 | } |
390 | 334 | ||
391 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode) | 335 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev) |
392 | { | 336 | { |
393 | struct inode *inode; | 337 | struct inode *inode; |
394 | 338 | ||
395 | inode = new_inode(sb); | 339 | inode = new_inode(sb); |
396 | if (inode) | 340 | if (inode) |
397 | ovl_fill_inode(inode, mode); | 341 | ovl_fill_inode(inode, mode, rdev); |
398 | 342 | ||
399 | return inode; | 343 | return inode; |
400 | } | 344 | } |
@@ -418,7 +362,7 @@ struct inode *ovl_get_inode(struct super_block *sb, struct inode *realinode) | |||
418 | inode = iget5_locked(sb, (unsigned long) realinode, | 362 | inode = iget5_locked(sb, (unsigned long) realinode, |
419 | ovl_inode_test, ovl_inode_set, realinode); | 363 | ovl_inode_test, ovl_inode_set, realinode); |
420 | if (inode && inode->i_state & I_NEW) { | 364 | if (inode && inode->i_state & I_NEW) { |
421 | ovl_fill_inode(inode, realinode->i_mode); | 365 | ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev); |
422 | set_nlink(inode, realinode->i_nlink); | 366 | set_nlink(inode, realinode->i_nlink); |
423 | unlock_new_inode(inode); | 367 | unlock_new_inode(inode); |
424 | } | 368 | } |
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c new file mode 100644 index 000000000000..9ad48d9202a9 --- /dev/null +++ b/fs/overlayfs/namei.c | |||
@@ -0,0 +1,401 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Novell Inc. | ||
3 | * Copyright (C) 2016 Red Hat, 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/ratelimit.h> | ||
14 | #include "overlayfs.h" | ||
15 | #include "ovl_entry.h" | ||
16 | |||
17 | struct ovl_lookup_data { | ||
18 | struct qstr name; | ||
19 | bool is_dir; | ||
20 | bool opaque; | ||
21 | bool stop; | ||
22 | bool last; | ||
23 | char *redirect; | ||
24 | }; | ||
25 | |||
26 | static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, | ||
27 | size_t prelen, const char *post) | ||
28 | { | ||
29 | int res; | ||
30 | char *s, *next, *buf = NULL; | ||
31 | |||
32 | res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0); | ||
33 | if (res < 0) { | ||
34 | if (res == -ENODATA || res == -EOPNOTSUPP) | ||
35 | return 0; | ||
36 | goto fail; | ||
37 | } | ||
38 | buf = kzalloc(prelen + res + strlen(post) + 1, GFP_TEMPORARY); | ||
39 | if (!buf) | ||
40 | return -ENOMEM; | ||
41 | |||
42 | if (res == 0) | ||
43 | goto invalid; | ||
44 | |||
45 | res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res); | ||
46 | if (res < 0) | ||
47 | goto fail; | ||
48 | if (res == 0) | ||
49 | goto invalid; | ||
50 | if (buf[0] == '/') { | ||
51 | for (s = buf; *s++ == '/'; s = next) { | ||
52 | next = strchrnul(s, '/'); | ||
53 | if (s == next) | ||
54 | goto invalid; | ||
55 | } | ||
56 | } else { | ||
57 | if (strchr(buf, '/') != NULL) | ||
58 | goto invalid; | ||
59 | |||
60 | memmove(buf + prelen, buf, res); | ||
61 | memcpy(buf, d->name.name, prelen); | ||
62 | } | ||
63 | |||
64 | strcat(buf, post); | ||
65 | kfree(d->redirect); | ||
66 | d->redirect = buf; | ||
67 | d->name.name = d->redirect; | ||
68 | d->name.len = strlen(d->redirect); | ||
69 | |||
70 | return 0; | ||
71 | |||
72 | err_free: | ||
73 | kfree(buf); | ||
74 | return 0; | ||
75 | fail: | ||
76 | pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res); | ||
77 | goto err_free; | ||
78 | invalid: | ||
79 | pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf); | ||
80 | goto err_free; | ||
81 | } | ||
82 | |||
83 | static bool ovl_is_opaquedir(struct dentry *dentry) | ||
84 | { | ||
85 | int res; | ||
86 | char val; | ||
87 | |||
88 | if (!d_is_dir(dentry)) | ||
89 | return false; | ||
90 | |||
91 | res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1); | ||
92 | if (res == 1 && val == 'y') | ||
93 | return true; | ||
94 | |||
95 | return false; | ||
96 | } | ||
97 | |||
98 | static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d, | ||
99 | const char *name, unsigned int namelen, | ||
100 | size_t prelen, const char *post, | ||
101 | struct dentry **ret) | ||
102 | { | ||
103 | struct dentry *this; | ||
104 | int err; | ||
105 | |||
106 | this = lookup_one_len_unlocked(name, base, namelen); | ||
107 | if (IS_ERR(this)) { | ||
108 | err = PTR_ERR(this); | ||
109 | this = NULL; | ||
110 | if (err == -ENOENT || err == -ENAMETOOLONG) | ||
111 | goto out; | ||
112 | goto out_err; | ||
113 | } | ||
114 | if (!this->d_inode) | ||
115 | goto put_and_out; | ||
116 | |||
117 | if (ovl_dentry_weird(this)) { | ||
118 | /* Don't support traversing automounts and other weirdness */ | ||
119 | err = -EREMOTE; | ||
120 | goto out_err; | ||
121 | } | ||
122 | if (ovl_is_whiteout(this)) { | ||
123 | d->stop = d->opaque = true; | ||
124 | goto put_and_out; | ||
125 | } | ||
126 | if (!d_can_lookup(this)) { | ||
127 | d->stop = true; | ||
128 | if (d->is_dir) | ||
129 | goto put_and_out; | ||
130 | goto out; | ||
131 | } | ||
132 | d->is_dir = true; | ||
133 | if (!d->last && ovl_is_opaquedir(this)) { | ||
134 | d->stop = d->opaque = true; | ||
135 | goto out; | ||
136 | } | ||
137 | err = ovl_check_redirect(this, d, prelen, post); | ||
138 | if (err) | ||
139 | goto out_err; | ||
140 | out: | ||
141 | *ret = this; | ||
142 | return 0; | ||
143 | |||
144 | put_and_out: | ||
145 | dput(this); | ||
146 | this = NULL; | ||
147 | goto out; | ||
148 | |||
149 | out_err: | ||
150 | dput(this); | ||
151 | return err; | ||
152 | } | ||
153 | |||
154 | static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d, | ||
155 | struct dentry **ret) | ||
156 | { | ||
157 | const char *s = d->name.name; | ||
158 | struct dentry *dentry = NULL; | ||
159 | int err; | ||
160 | |||
161 | if (*s != '/') | ||
162 | return ovl_lookup_single(base, d, d->name.name, d->name.len, | ||
163 | 0, "", ret); | ||
164 | |||
165 | while (*s++ == '/' && !IS_ERR_OR_NULL(base) && d_can_lookup(base)) { | ||
166 | const char *next = strchrnul(s, '/'); | ||
167 | size_t slen = strlen(s); | ||
168 | |||
169 | if (WARN_ON(slen > d->name.len) || | ||
170 | WARN_ON(strcmp(d->name.name + d->name.len - slen, s))) | ||
171 | return -EIO; | ||
172 | |||
173 | err = ovl_lookup_single(base, d, s, next - s, | ||
174 | d->name.len - slen, next, &base); | ||
175 | dput(dentry); | ||
176 | if (err) | ||
177 | return err; | ||
178 | dentry = base; | ||
179 | s = next; | ||
180 | } | ||
181 | *ret = dentry; | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Returns next layer in stack starting from top. | ||
187 | * Returns -1 if this is the last layer. | ||
188 | */ | ||
189 | int ovl_path_next(int idx, struct dentry *dentry, struct path *path) | ||
190 | { | ||
191 | struct ovl_entry *oe = dentry->d_fsdata; | ||
192 | |||
193 | BUG_ON(idx < 0); | ||
194 | if (idx == 0) { | ||
195 | ovl_path_upper(dentry, path); | ||
196 | if (path->dentry) | ||
197 | return oe->numlower ? 1 : -1; | ||
198 | idx++; | ||
199 | } | ||
200 | BUG_ON(idx > oe->numlower); | ||
201 | *path = oe->lowerstack[idx - 1]; | ||
202 | |||
203 | return (idx < oe->numlower) ? idx + 1 : -1; | ||
204 | } | ||
205 | |||
206 | struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | ||
207 | unsigned int flags) | ||
208 | { | ||
209 | struct ovl_entry *oe; | ||
210 | const struct cred *old_cred; | ||
211 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
212 | struct ovl_entry *poe = dentry->d_parent->d_fsdata; | ||
213 | struct path *stack = NULL; | ||
214 | struct dentry *upperdir, *upperdentry = NULL; | ||
215 | unsigned int ctr = 0; | ||
216 | struct inode *inode = NULL; | ||
217 | bool upperopaque = false; | ||
218 | char *upperredirect = NULL; | ||
219 | struct dentry *this; | ||
220 | unsigned int i; | ||
221 | int err; | ||
222 | struct ovl_lookup_data d = { | ||
223 | .name = dentry->d_name, | ||
224 | .is_dir = false, | ||
225 | .opaque = false, | ||
226 | .stop = false, | ||
227 | .last = !poe->numlower, | ||
228 | .redirect = NULL, | ||
229 | }; | ||
230 | |||
231 | if (dentry->d_name.len > ofs->namelen) | ||
232 | return ERR_PTR(-ENAMETOOLONG); | ||
233 | |||
234 | old_cred = ovl_override_creds(dentry->d_sb); | ||
235 | upperdir = ovl_upperdentry_dereference(poe); | ||
236 | if (upperdir) { | ||
237 | err = ovl_lookup_layer(upperdir, &d, &upperdentry); | ||
238 | if (err) | ||
239 | goto out; | ||
240 | |||
241 | if (upperdentry && unlikely(ovl_dentry_remote(upperdentry))) { | ||
242 | dput(upperdentry); | ||
243 | err = -EREMOTE; | ||
244 | goto out; | ||
245 | } | ||
246 | |||
247 | if (d.redirect) { | ||
248 | upperredirect = kstrdup(d.redirect, GFP_KERNEL); | ||
249 | if (!upperredirect) | ||
250 | goto out_put_upper; | ||
251 | if (d.redirect[0] == '/') | ||
252 | poe = dentry->d_sb->s_root->d_fsdata; | ||
253 | } | ||
254 | upperopaque = d.opaque; | ||
255 | } | ||
256 | |||
257 | if (!d.stop && poe->numlower) { | ||
258 | err = -ENOMEM; | ||
259 | stack = kcalloc(ofs->numlower, sizeof(struct path), | ||
260 | GFP_TEMPORARY); | ||
261 | if (!stack) | ||
262 | goto out_put_upper; | ||
263 | } | ||
264 | |||
265 | for (i = 0; !d.stop && i < poe->numlower; i++) { | ||
266 | struct path lowerpath = poe->lowerstack[i]; | ||
267 | |||
268 | d.last = i == poe->numlower - 1; | ||
269 | err = ovl_lookup_layer(lowerpath.dentry, &d, &this); | ||
270 | if (err) | ||
271 | goto out_put; | ||
272 | |||
273 | if (!this) | ||
274 | continue; | ||
275 | |||
276 | stack[ctr].dentry = this; | ||
277 | stack[ctr].mnt = lowerpath.mnt; | ||
278 | ctr++; | ||
279 | |||
280 | if (d.stop) | ||
281 | break; | ||
282 | |||
283 | if (d.redirect && | ||
284 | d.redirect[0] == '/' && | ||
285 | poe != dentry->d_sb->s_root->d_fsdata) { | ||
286 | poe = dentry->d_sb->s_root->d_fsdata; | ||
287 | |||
288 | /* Find the current layer on the root dentry */ | ||
289 | for (i = 0; i < poe->numlower; i++) | ||
290 | if (poe->lowerstack[i].mnt == lowerpath.mnt) | ||
291 | break; | ||
292 | if (WARN_ON(i == poe->numlower)) | ||
293 | break; | ||
294 | } | ||
295 | } | ||
296 | |||
297 | oe = ovl_alloc_entry(ctr); | ||
298 | err = -ENOMEM; | ||
299 | if (!oe) | ||
300 | goto out_put; | ||
301 | |||
302 | if (upperdentry || ctr) { | ||
303 | struct dentry *realdentry; | ||
304 | struct inode *realinode; | ||
305 | |||
306 | realdentry = upperdentry ? upperdentry : stack[0].dentry; | ||
307 | realinode = d_inode(realdentry); | ||
308 | |||
309 | err = -ENOMEM; | ||
310 | if (upperdentry && !d_is_dir(upperdentry)) { | ||
311 | inode = ovl_get_inode(dentry->d_sb, realinode); | ||
312 | } else { | ||
313 | inode = ovl_new_inode(dentry->d_sb, realinode->i_mode, | ||
314 | realinode->i_rdev); | ||
315 | if (inode) | ||
316 | ovl_inode_init(inode, realinode, !!upperdentry); | ||
317 | } | ||
318 | if (!inode) | ||
319 | goto out_free_oe; | ||
320 | ovl_copyattr(realdentry->d_inode, inode); | ||
321 | } | ||
322 | |||
323 | revert_creds(old_cred); | ||
324 | oe->opaque = upperopaque; | ||
325 | oe->redirect = upperredirect; | ||
326 | oe->__upperdentry = upperdentry; | ||
327 | memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); | ||
328 | kfree(stack); | ||
329 | kfree(d.redirect); | ||
330 | dentry->d_fsdata = oe; | ||
331 | d_add(dentry, inode); | ||
332 | |||
333 | return NULL; | ||
334 | |||
335 | out_free_oe: | ||
336 | kfree(oe); | ||
337 | out_put: | ||
338 | for (i = 0; i < ctr; i++) | ||
339 | dput(stack[i].dentry); | ||
340 | kfree(stack); | ||
341 | out_put_upper: | ||
342 | dput(upperdentry); | ||
343 | kfree(upperredirect); | ||
344 | out: | ||
345 | kfree(d.redirect); | ||
346 | revert_creds(old_cred); | ||
347 | return ERR_PTR(err); | ||
348 | } | ||
349 | |||
350 | bool ovl_lower_positive(struct dentry *dentry) | ||
351 | { | ||
352 | struct ovl_entry *oe = dentry->d_fsdata; | ||
353 | struct ovl_entry *poe = dentry->d_parent->d_fsdata; | ||
354 | const struct qstr *name = &dentry->d_name; | ||
355 | unsigned int i; | ||
356 | bool positive = false; | ||
357 | bool done = false; | ||
358 | |||
359 | /* | ||
360 | * If dentry is negative, then lower is positive iff this is a | ||
361 | * whiteout. | ||
362 | */ | ||
363 | if (!dentry->d_inode) | ||
364 | return oe->opaque; | ||
365 | |||
366 | /* Negative upper -> positive lower */ | ||
367 | if (!oe->__upperdentry) | ||
368 | return true; | ||
369 | |||
370 | /* Positive upper -> have to look up lower to see whether it exists */ | ||
371 | for (i = 0; !done && !positive && i < poe->numlower; i++) { | ||
372 | struct dentry *this; | ||
373 | struct dentry *lowerdir = poe->lowerstack[i].dentry; | ||
374 | |||
375 | this = lookup_one_len_unlocked(name->name, lowerdir, | ||
376 | name->len); | ||
377 | if (IS_ERR(this)) { | ||
378 | switch (PTR_ERR(this)) { | ||
379 | case -ENOENT: | ||
380 | case -ENAMETOOLONG: | ||
381 | break; | ||
382 | |||
383 | default: | ||
384 | /* | ||
385 | * Assume something is there, we just couldn't | ||
386 | * access it. | ||
387 | */ | ||
388 | positive = true; | ||
389 | break; | ||
390 | } | ||
391 | } else { | ||
392 | if (this->d_inode) { | ||
393 | positive = !ovl_is_whiteout(this); | ||
394 | done = true; | ||
395 | } | ||
396 | dput(this); | ||
397 | } | ||
398 | } | ||
399 | |||
400 | return positive; | ||
401 | } | ||
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index e218e741cb99..8af450b0e57a 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
@@ -9,23 +9,17 @@ | |||
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | 11 | ||
12 | struct ovl_entry; | ||
13 | |||
14 | enum ovl_path_type { | 12 | enum ovl_path_type { |
15 | __OVL_PATH_PURE = (1 << 0), | 13 | __OVL_PATH_UPPER = (1 << 0), |
16 | __OVL_PATH_UPPER = (1 << 1), | 14 | __OVL_PATH_MERGE = (1 << 1), |
17 | __OVL_PATH_MERGE = (1 << 2), | ||
18 | }; | 15 | }; |
19 | 16 | ||
20 | #define OVL_TYPE_UPPER(type) ((type) & __OVL_PATH_UPPER) | 17 | #define OVL_TYPE_UPPER(type) ((type) & __OVL_PATH_UPPER) |
21 | #define OVL_TYPE_MERGE(type) ((type) & __OVL_PATH_MERGE) | 18 | #define OVL_TYPE_MERGE(type) ((type) & __OVL_PATH_MERGE) |
22 | #define OVL_TYPE_PURE_UPPER(type) ((type) & __OVL_PATH_PURE) | ||
23 | #define OVL_TYPE_MERGE_OR_LOWER(type) \ | ||
24 | (OVL_TYPE_MERGE(type) || !OVL_TYPE_UPPER(type)) | ||
25 | |||
26 | 19 | ||
27 | #define OVL_XATTR_PREFIX XATTR_TRUSTED_PREFIX "overlay." | 20 | #define OVL_XATTR_PREFIX XATTR_TRUSTED_PREFIX "overlay." |
28 | #define OVL_XATTR_OPAQUE OVL_XATTR_PREFIX "opaque" | 21 | #define OVL_XATTR_OPAQUE OVL_XATTR_PREFIX "opaque" |
22 | #define OVL_XATTR_REDIRECT OVL_XATTR_PREFIX "redirect" | ||
29 | 23 | ||
30 | #define OVL_ISUPPER_MASK 1UL | 24 | #define OVL_ISUPPER_MASK 1UL |
31 | 25 | ||
@@ -143,35 +137,43 @@ static inline struct inode *ovl_inode_real(struct inode *inode, bool *is_upper) | |||
143 | return (struct inode *) (x & ~OVL_ISUPPER_MASK); | 137 | return (struct inode *) (x & ~OVL_ISUPPER_MASK); |
144 | } | 138 | } |
145 | 139 | ||
140 | /* util.c */ | ||
141 | int ovl_want_write(struct dentry *dentry); | ||
142 | void ovl_drop_write(struct dentry *dentry); | ||
143 | struct dentry *ovl_workdir(struct dentry *dentry); | ||
144 | const struct cred *ovl_override_creds(struct super_block *sb); | ||
145 | struct ovl_entry *ovl_alloc_entry(unsigned int numlower); | ||
146 | bool ovl_dentry_remote(struct dentry *dentry); | ||
147 | bool ovl_dentry_weird(struct dentry *dentry); | ||
146 | enum ovl_path_type ovl_path_type(struct dentry *dentry); | 148 | enum ovl_path_type ovl_path_type(struct dentry *dentry); |
147 | u64 ovl_dentry_version_get(struct dentry *dentry); | ||
148 | void ovl_dentry_version_inc(struct dentry *dentry); | ||
149 | void ovl_path_upper(struct dentry *dentry, struct path *path); | 149 | void ovl_path_upper(struct dentry *dentry, struct path *path); |
150 | void ovl_path_lower(struct dentry *dentry, struct path *path); | 150 | void ovl_path_lower(struct dentry *dentry, struct path *path); |
151 | enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); | 151 | enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); |
152 | int ovl_path_next(int idx, struct dentry *dentry, struct path *path); | ||
153 | struct dentry *ovl_dentry_upper(struct dentry *dentry); | 152 | struct dentry *ovl_dentry_upper(struct dentry *dentry); |
154 | struct dentry *ovl_dentry_lower(struct dentry *dentry); | 153 | struct dentry *ovl_dentry_lower(struct dentry *dentry); |
155 | struct dentry *ovl_dentry_real(struct dentry *dentry); | 154 | struct dentry *ovl_dentry_real(struct dentry *dentry); |
156 | struct vfsmount *ovl_entry_mnt_real(struct ovl_entry *oe, struct inode *inode, | ||
157 | bool is_upper); | ||
158 | struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry); | 155 | struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry); |
159 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache); | 156 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache); |
160 | struct dentry *ovl_workdir(struct dentry *dentry); | ||
161 | int ovl_want_write(struct dentry *dentry); | ||
162 | void ovl_drop_write(struct dentry *dentry); | ||
163 | bool ovl_dentry_is_opaque(struct dentry *dentry); | 157 | bool ovl_dentry_is_opaque(struct dentry *dentry); |
164 | void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque); | 158 | bool ovl_dentry_is_whiteout(struct dentry *dentry); |
165 | bool ovl_is_whiteout(struct dentry *dentry); | 159 | void ovl_dentry_set_opaque(struct dentry *dentry); |
166 | const struct cred *ovl_override_creds(struct super_block *sb); | 160 | bool ovl_redirect_dir(struct super_block *sb); |
161 | void ovl_clear_redirect_dir(struct super_block *sb); | ||
162 | const char *ovl_dentry_get_redirect(struct dentry *dentry); | ||
163 | void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect); | ||
167 | void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry); | 164 | void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry); |
165 | void ovl_inode_init(struct inode *inode, struct inode *realinode, | ||
166 | bool is_upper); | ||
168 | void ovl_inode_update(struct inode *inode, struct inode *upperinode); | 167 | void ovl_inode_update(struct inode *inode, struct inode *upperinode); |
169 | struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | 168 | void ovl_dentry_version_inc(struct dentry *dentry); |
170 | unsigned int flags); | 169 | u64 ovl_dentry_version_get(struct dentry *dentry); |
170 | bool ovl_is_whiteout(struct dentry *dentry); | ||
171 | struct file *ovl_path_open(struct path *path, int flags); | 171 | struct file *ovl_path_open(struct path *path, int flags); |
172 | 172 | ||
173 | struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry, | 173 | /* namei.c */ |
174 | struct kstat *stat, const char *link); | 174 | int ovl_path_next(int idx, struct dentry *dentry, struct path *path); |
175 | struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags); | ||
176 | bool ovl_lower_positive(struct dentry *dentry); | ||
175 | 177 | ||
176 | /* readdir.c */ | 178 | /* readdir.c */ |
177 | extern const struct file_operations ovl_dir_operations; | 179 | extern const struct file_operations ovl_dir_operations; |
@@ -195,7 +197,7 @@ int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags); | |||
195 | int ovl_update_time(struct inode *inode, struct timespec *ts, int flags); | 197 | int ovl_update_time(struct inode *inode, struct timespec *ts, int flags); |
196 | bool ovl_is_private_xattr(const char *name); | 198 | bool ovl_is_private_xattr(const char *name); |
197 | 199 | ||
198 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode); | 200 | struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev); |
199 | struct inode *ovl_get_inode(struct super_block *sb, struct inode *realinode); | 201 | struct inode *ovl_get_inode(struct super_block *sb, struct inode *realinode); |
200 | static inline void ovl_copyattr(struct inode *from, struct inode *to) | 202 | static inline void ovl_copyattr(struct inode *from, struct inode *to) |
201 | { | 203 | { |
@@ -210,14 +212,18 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to) | |||
210 | /* dir.c */ | 212 | /* dir.c */ |
211 | extern const struct inode_operations ovl_dir_inode_operations; | 213 | extern const struct inode_operations ovl_dir_inode_operations; |
212 | struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry); | 214 | struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry); |
215 | struct cattr { | ||
216 | dev_t rdev; | ||
217 | umode_t mode; | ||
218 | const char *link; | ||
219 | }; | ||
213 | int ovl_create_real(struct inode *dir, struct dentry *newdentry, | 220 | int ovl_create_real(struct inode *dir, struct dentry *newdentry, |
214 | struct kstat *stat, const char *link, | 221 | struct cattr *attr, |
215 | struct dentry *hardlink, bool debug); | 222 | struct dentry *hardlink, bool debug); |
216 | void ovl_cleanup(struct inode *dir, struct dentry *dentry); | 223 | void ovl_cleanup(struct inode *dir, struct dentry *dentry); |
217 | 224 | ||
218 | /* copy_up.c */ | 225 | /* copy_up.c */ |
219 | int ovl_copy_up(struct dentry *dentry); | 226 | int ovl_copy_up(struct dentry *dentry); |
220 | int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | 227 | int ovl_copy_up_flags(struct dentry *dentry, int flags); |
221 | struct path *lowerpath, struct kstat *stat); | ||
222 | int ovl_copy_xattr(struct dentry *old, struct dentry *new); | 228 | int ovl_copy_xattr(struct dentry *old, struct dentry *new); |
223 | int ovl_set_attr(struct dentry *upper, struct kstat *stat); | 229 | int ovl_set_attr(struct dentry *upper, struct kstat *stat); |
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h new file mode 100644 index 000000000000..d14bca1850d9 --- /dev/null +++ b/fs/overlayfs/ovl_entry.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (C) 2011 Novell Inc. | ||
4 | * Copyright (C) 2016 Red Hat, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | struct ovl_config { | ||
12 | char *lowerdir; | ||
13 | char *upperdir; | ||
14 | char *workdir; | ||
15 | bool default_permissions; | ||
16 | bool redirect_dir; | ||
17 | }; | ||
18 | |||
19 | /* private information held for overlayfs's superblock */ | ||
20 | struct ovl_fs { | ||
21 | struct vfsmount *upper_mnt; | ||
22 | unsigned numlower; | ||
23 | struct vfsmount **lower_mnt; | ||
24 | struct dentry *workdir; | ||
25 | long namelen; | ||
26 | /* pathnames of lower and upper dirs, for show_options */ | ||
27 | struct ovl_config config; | ||
28 | /* creds of process who forced instantiation of super block */ | ||
29 | const struct cred *creator_cred; | ||
30 | }; | ||
31 | |||
32 | /* private information held for every overlayfs dentry */ | ||
33 | struct ovl_entry { | ||
34 | struct dentry *__upperdentry; | ||
35 | struct ovl_dir_cache *cache; | ||
36 | union { | ||
37 | struct { | ||
38 | u64 version; | ||
39 | const char *redirect; | ||
40 | bool opaque; | ||
41 | }; | ||
42 | struct rcu_head rcu; | ||
43 | }; | ||
44 | unsigned numlower; | ||
45 | struct path lowerstack[]; | ||
46 | }; | ||
47 | |||
48 | struct ovl_entry *ovl_alloc_entry(unsigned int numlower); | ||
49 | |||
50 | static inline struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) | ||
51 | { | ||
52 | return lockless_dereference(oe->__upperdentry); | ||
53 | } | ||
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 0e100856c7b8..20f48abbb82f 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -9,280 +9,29 @@ | |||
9 | 9 | ||
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include <linux/namei.h> | 11 | #include <linux/namei.h> |
12 | #include <linux/pagemap.h> | ||
13 | #include <linux/xattr.h> | 12 | #include <linux/xattr.h> |
14 | #include <linux/security.h> | ||
15 | #include <linux/mount.h> | 13 | #include <linux/mount.h> |
16 | #include <linux/slab.h> | ||
17 | #include <linux/parser.h> | 14 | #include <linux/parser.h> |
18 | #include <linux/module.h> | 15 | #include <linux/module.h> |
19 | #include <linux/sched.h> | ||
20 | #include <linux/statfs.h> | 16 | #include <linux/statfs.h> |
21 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
22 | #include <linux/posix_acl_xattr.h> | 18 | #include <linux/posix_acl_xattr.h> |
23 | #include "overlayfs.h" | 19 | #include "overlayfs.h" |
20 | #include "ovl_entry.h" | ||
24 | 21 | ||
25 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); | 22 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); |
26 | MODULE_DESCRIPTION("Overlay filesystem"); | 23 | MODULE_DESCRIPTION("Overlay filesystem"); |
27 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
28 | 25 | ||
29 | struct ovl_config { | ||
30 | char *lowerdir; | ||
31 | char *upperdir; | ||
32 | char *workdir; | ||
33 | bool default_permissions; | ||
34 | }; | ||
35 | |||
36 | /* private information held for overlayfs's superblock */ | ||
37 | struct ovl_fs { | ||
38 | struct vfsmount *upper_mnt; | ||
39 | unsigned numlower; | ||
40 | struct vfsmount **lower_mnt; | ||
41 | struct dentry *workdir; | ||
42 | long lower_namelen; | ||
43 | /* pathnames of lower and upper dirs, for show_options */ | ||
44 | struct ovl_config config; | ||
45 | /* creds of process who forced instantiation of super block */ | ||
46 | const struct cred *creator_cred; | ||
47 | }; | ||
48 | 26 | ||
49 | struct ovl_dir_cache; | 27 | struct ovl_dir_cache; |
50 | 28 | ||
51 | /* private information held for every overlayfs dentry */ | ||
52 | struct ovl_entry { | ||
53 | struct dentry *__upperdentry; | ||
54 | struct ovl_dir_cache *cache; | ||
55 | union { | ||
56 | struct { | ||
57 | u64 version; | ||
58 | bool opaque; | ||
59 | }; | ||
60 | struct rcu_head rcu; | ||
61 | }; | ||
62 | unsigned numlower; | ||
63 | struct path lowerstack[]; | ||
64 | }; | ||
65 | |||
66 | #define OVL_MAX_STACK 500 | 29 | #define OVL_MAX_STACK 500 |
67 | 30 | ||
68 | static struct dentry *__ovl_dentry_lower(struct ovl_entry *oe) | 31 | static bool ovl_redirect_dir_def = IS_ENABLED(CONFIG_OVERLAY_FS_REDIRECT_DIR); |
69 | { | 32 | module_param_named(redirect_dir, ovl_redirect_dir_def, bool, 0644); |
70 | return oe->numlower ? oe->lowerstack[0].dentry : NULL; | 33 | MODULE_PARM_DESC(ovl_redirect_dir_def, |
71 | } | 34 | "Default to on or off for the redirect_dir feature"); |
72 | |||
73 | enum ovl_path_type ovl_path_type(struct dentry *dentry) | ||
74 | { | ||
75 | struct ovl_entry *oe = dentry->d_fsdata; | ||
76 | enum ovl_path_type type = 0; | ||
77 | |||
78 | if (oe->__upperdentry) { | ||
79 | type = __OVL_PATH_UPPER; | ||
80 | |||
81 | /* | ||
82 | * Non-dir dentry can hold lower dentry from previous | ||
83 | * location. Its purity depends only on opaque flag. | ||
84 | */ | ||
85 | if (oe->numlower && S_ISDIR(dentry->d_inode->i_mode)) | ||
86 | type |= __OVL_PATH_MERGE; | ||
87 | else if (!oe->opaque) | ||
88 | type |= __OVL_PATH_PURE; | ||
89 | } else { | ||
90 | if (oe->numlower > 1) | ||
91 | type |= __OVL_PATH_MERGE; | ||
92 | } | ||
93 | return type; | ||
94 | } | ||
95 | |||
96 | static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) | ||
97 | { | ||
98 | return lockless_dereference(oe->__upperdentry); | ||
99 | } | ||
100 | |||
101 | void ovl_path_upper(struct dentry *dentry, struct path *path) | ||
102 | { | ||
103 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
104 | struct ovl_entry *oe = dentry->d_fsdata; | ||
105 | |||
106 | path->mnt = ofs->upper_mnt; | ||
107 | path->dentry = ovl_upperdentry_dereference(oe); | ||
108 | } | ||
109 | |||
110 | enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path) | ||
111 | { | ||
112 | enum ovl_path_type type = ovl_path_type(dentry); | ||
113 | |||
114 | if (!OVL_TYPE_UPPER(type)) | ||
115 | ovl_path_lower(dentry, path); | ||
116 | else | ||
117 | ovl_path_upper(dentry, path); | ||
118 | |||
119 | return type; | ||
120 | } | ||
121 | |||
122 | struct dentry *ovl_dentry_upper(struct dentry *dentry) | ||
123 | { | ||
124 | struct ovl_entry *oe = dentry->d_fsdata; | ||
125 | |||
126 | return ovl_upperdentry_dereference(oe); | ||
127 | } | ||
128 | |||
129 | struct dentry *ovl_dentry_lower(struct dentry *dentry) | ||
130 | { | ||
131 | struct ovl_entry *oe = dentry->d_fsdata; | ||
132 | |||
133 | return __ovl_dentry_lower(oe); | ||
134 | } | ||
135 | |||
136 | struct dentry *ovl_dentry_real(struct dentry *dentry) | ||
137 | { | ||
138 | struct ovl_entry *oe = dentry->d_fsdata; | ||
139 | struct dentry *realdentry; | ||
140 | |||
141 | realdentry = ovl_upperdentry_dereference(oe); | ||
142 | if (!realdentry) | ||
143 | realdentry = __ovl_dentry_lower(oe); | ||
144 | |||
145 | return realdentry; | ||
146 | } | ||
147 | |||
148 | static void ovl_inode_init(struct inode *inode, struct inode *realinode, | ||
149 | bool is_upper) | ||
150 | { | ||
151 | WRITE_ONCE(inode->i_private, (unsigned long) realinode | | ||
152 | (is_upper ? OVL_ISUPPER_MASK : 0)); | ||
153 | } | ||
154 | |||
155 | struct vfsmount *ovl_entry_mnt_real(struct ovl_entry *oe, struct inode *inode, | ||
156 | bool is_upper) | ||
157 | { | ||
158 | if (is_upper) { | ||
159 | struct ovl_fs *ofs = inode->i_sb->s_fs_info; | ||
160 | |||
161 | return ofs->upper_mnt; | ||
162 | } else { | ||
163 | return oe->numlower ? oe->lowerstack[0].mnt : NULL; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry) | ||
168 | { | ||
169 | struct ovl_entry *oe = dentry->d_fsdata; | ||
170 | |||
171 | return oe->cache; | ||
172 | } | ||
173 | |||
174 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache) | ||
175 | { | ||
176 | struct ovl_entry *oe = dentry->d_fsdata; | ||
177 | |||
178 | oe->cache = cache; | ||
179 | } | ||
180 | |||
181 | void ovl_path_lower(struct dentry *dentry, struct path *path) | ||
182 | { | ||
183 | struct ovl_entry *oe = dentry->d_fsdata; | ||
184 | |||
185 | *path = oe->numlower ? oe->lowerstack[0] : (struct path) { NULL, NULL }; | ||
186 | } | ||
187 | |||
188 | int ovl_want_write(struct dentry *dentry) | ||
189 | { | ||
190 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
191 | return mnt_want_write(ofs->upper_mnt); | ||
192 | } | ||
193 | |||
194 | void ovl_drop_write(struct dentry *dentry) | ||
195 | { | ||
196 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
197 | mnt_drop_write(ofs->upper_mnt); | ||
198 | } | ||
199 | |||
200 | struct dentry *ovl_workdir(struct dentry *dentry) | ||
201 | { | ||
202 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
203 | return ofs->workdir; | ||
204 | } | ||
205 | |||
206 | bool ovl_dentry_is_opaque(struct dentry *dentry) | ||
207 | { | ||
208 | struct ovl_entry *oe = dentry->d_fsdata; | ||
209 | return oe->opaque; | ||
210 | } | ||
211 | |||
212 | void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque) | ||
213 | { | ||
214 | struct ovl_entry *oe = dentry->d_fsdata; | ||
215 | oe->opaque = opaque; | ||
216 | } | ||
217 | |||
218 | void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry) | ||
219 | { | ||
220 | struct ovl_entry *oe = dentry->d_fsdata; | ||
221 | |||
222 | WARN_ON(!inode_is_locked(upperdentry->d_parent->d_inode)); | ||
223 | WARN_ON(oe->__upperdentry); | ||
224 | /* | ||
225 | * Make sure upperdentry is consistent before making it visible to | ||
226 | * ovl_upperdentry_dereference(). | ||
227 | */ | ||
228 | smp_wmb(); | ||
229 | oe->__upperdentry = upperdentry; | ||
230 | } | ||
231 | |||
232 | void ovl_inode_update(struct inode *inode, struct inode *upperinode) | ||
233 | { | ||
234 | WARN_ON(!upperinode); | ||
235 | WARN_ON(!inode_unhashed(inode)); | ||
236 | WRITE_ONCE(inode->i_private, | ||
237 | (unsigned long) upperinode | OVL_ISUPPER_MASK); | ||
238 | if (!S_ISDIR(upperinode->i_mode)) | ||
239 | __insert_inode_hash(inode, (unsigned long) upperinode); | ||
240 | } | ||
241 | |||
242 | void ovl_dentry_version_inc(struct dentry *dentry) | ||
243 | { | ||
244 | struct ovl_entry *oe = dentry->d_fsdata; | ||
245 | |||
246 | WARN_ON(!inode_is_locked(dentry->d_inode)); | ||
247 | oe->version++; | ||
248 | } | ||
249 | |||
250 | u64 ovl_dentry_version_get(struct dentry *dentry) | ||
251 | { | ||
252 | struct ovl_entry *oe = dentry->d_fsdata; | ||
253 | |||
254 | WARN_ON(!inode_is_locked(dentry->d_inode)); | ||
255 | return oe->version; | ||
256 | } | ||
257 | |||
258 | bool ovl_is_whiteout(struct dentry *dentry) | ||
259 | { | ||
260 | struct inode *inode = dentry->d_inode; | ||
261 | |||
262 | return inode && IS_WHITEOUT(inode); | ||
263 | } | ||
264 | |||
265 | const struct cred *ovl_override_creds(struct super_block *sb) | ||
266 | { | ||
267 | struct ovl_fs *ofs = sb->s_fs_info; | ||
268 | |||
269 | return override_creds(ofs->creator_cred); | ||
270 | } | ||
271 | |||
272 | static bool ovl_is_opaquedir(struct dentry *dentry) | ||
273 | { | ||
274 | int res; | ||
275 | char val; | ||
276 | |||
277 | if (!d_is_dir(dentry)) | ||
278 | return false; | ||
279 | |||
280 | res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1); | ||
281 | if (res == 1 && val == 'y') | ||
282 | return true; | ||
283 | |||
284 | return false; | ||
285 | } | ||
286 | 35 | ||
287 | static void ovl_dentry_release(struct dentry *dentry) | 36 | static void ovl_dentry_release(struct dentry *dentry) |
288 | { | 37 | { |
@@ -292,6 +41,7 @@ static void ovl_dentry_release(struct dentry *dentry) | |||
292 | unsigned int i; | 41 | unsigned int i; |
293 | 42 | ||
294 | dput(oe->__upperdentry); | 43 | dput(oe->__upperdentry); |
44 | kfree(oe->redirect); | ||
295 | for (i = 0; i < oe->numlower; i++) | 45 | for (i = 0; i < oe->numlower; i++) |
296 | dput(oe->lowerstack[i].dentry); | 46 | dput(oe->lowerstack[i].dentry); |
297 | kfree_rcu(oe, rcu); | 47 | kfree_rcu(oe, rcu); |
@@ -304,7 +54,7 @@ static struct dentry *ovl_d_real(struct dentry *dentry, | |||
304 | { | 54 | { |
305 | struct dentry *real; | 55 | struct dentry *real; |
306 | 56 | ||
307 | if (d_is_dir(dentry)) { | 57 | if (!d_is_reg(dentry)) { |
308 | if (!inode || inode == d_inode(dentry)) | 58 | if (!inode || inode == d_inode(dentry)) |
309 | return dentry; | 59 | return dentry; |
310 | goto bug; | 60 | goto bug; |
@@ -392,226 +142,6 @@ static const struct dentry_operations ovl_reval_dentry_operations = { | |||
392 | .d_weak_revalidate = ovl_dentry_weak_revalidate, | 142 | .d_weak_revalidate = ovl_dentry_weak_revalidate, |
393 | }; | 143 | }; |
394 | 144 | ||
395 | static struct ovl_entry *ovl_alloc_entry(unsigned int numlower) | ||
396 | { | ||
397 | size_t size = offsetof(struct ovl_entry, lowerstack[numlower]); | ||
398 | struct ovl_entry *oe = kzalloc(size, GFP_KERNEL); | ||
399 | |||
400 | if (oe) | ||
401 | oe->numlower = numlower; | ||
402 | |||
403 | return oe; | ||
404 | } | ||
405 | |||
406 | static bool ovl_dentry_remote(struct dentry *dentry) | ||
407 | { | ||
408 | return dentry->d_flags & | ||
409 | (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE | | ||
410 | DCACHE_OP_REAL); | ||
411 | } | ||
412 | |||
413 | static bool ovl_dentry_weird(struct dentry *dentry) | ||
414 | { | ||
415 | return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT | | ||
416 | DCACHE_MANAGE_TRANSIT | | ||
417 | DCACHE_OP_HASH | | ||
418 | DCACHE_OP_COMPARE); | ||
419 | } | ||
420 | |||
421 | static inline struct dentry *ovl_lookup_real(struct dentry *dir, | ||
422 | const struct qstr *name) | ||
423 | { | ||
424 | struct dentry *dentry; | ||
425 | |||
426 | dentry = lookup_one_len_unlocked(name->name, dir, name->len); | ||
427 | |||
428 | if (IS_ERR(dentry)) { | ||
429 | if (PTR_ERR(dentry) == -ENOENT) | ||
430 | dentry = NULL; | ||
431 | } else if (!dentry->d_inode) { | ||
432 | dput(dentry); | ||
433 | dentry = NULL; | ||
434 | } else if (ovl_dentry_weird(dentry)) { | ||
435 | dput(dentry); | ||
436 | /* Don't support traversing automounts and other weirdness */ | ||
437 | dentry = ERR_PTR(-EREMOTE); | ||
438 | } | ||
439 | return dentry; | ||
440 | } | ||
441 | |||
442 | /* | ||
443 | * Returns next layer in stack starting from top. | ||
444 | * Returns -1 if this is the last layer. | ||
445 | */ | ||
446 | int ovl_path_next(int idx, struct dentry *dentry, struct path *path) | ||
447 | { | ||
448 | struct ovl_entry *oe = dentry->d_fsdata; | ||
449 | |||
450 | BUG_ON(idx < 0); | ||
451 | if (idx == 0) { | ||
452 | ovl_path_upper(dentry, path); | ||
453 | if (path->dentry) | ||
454 | return oe->numlower ? 1 : -1; | ||
455 | idx++; | ||
456 | } | ||
457 | BUG_ON(idx > oe->numlower); | ||
458 | *path = oe->lowerstack[idx - 1]; | ||
459 | |||
460 | return (idx < oe->numlower) ? idx + 1 : -1; | ||
461 | } | ||
462 | |||
463 | struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | ||
464 | unsigned int flags) | ||
465 | { | ||
466 | struct ovl_entry *oe; | ||
467 | const struct cred *old_cred; | ||
468 | struct ovl_entry *poe = dentry->d_parent->d_fsdata; | ||
469 | struct path *stack = NULL; | ||
470 | struct dentry *upperdir, *upperdentry = NULL; | ||
471 | unsigned int ctr = 0; | ||
472 | struct inode *inode = NULL; | ||
473 | bool upperopaque = false; | ||
474 | struct dentry *this, *prev = NULL; | ||
475 | unsigned int i; | ||
476 | int err; | ||
477 | |||
478 | old_cred = ovl_override_creds(dentry->d_sb); | ||
479 | upperdir = ovl_upperdentry_dereference(poe); | ||
480 | if (upperdir) { | ||
481 | this = ovl_lookup_real(upperdir, &dentry->d_name); | ||
482 | err = PTR_ERR(this); | ||
483 | if (IS_ERR(this)) | ||
484 | goto out; | ||
485 | |||
486 | if (this) { | ||
487 | if (unlikely(ovl_dentry_remote(this))) { | ||
488 | dput(this); | ||
489 | err = -EREMOTE; | ||
490 | goto out; | ||
491 | } | ||
492 | if (ovl_is_whiteout(this)) { | ||
493 | dput(this); | ||
494 | this = NULL; | ||
495 | upperopaque = true; | ||
496 | } else if (poe->numlower && ovl_is_opaquedir(this)) { | ||
497 | upperopaque = true; | ||
498 | } | ||
499 | } | ||
500 | upperdentry = prev = this; | ||
501 | } | ||
502 | |||
503 | if (!upperopaque && poe->numlower) { | ||
504 | err = -ENOMEM; | ||
505 | stack = kcalloc(poe->numlower, sizeof(struct path), GFP_KERNEL); | ||
506 | if (!stack) | ||
507 | goto out_put_upper; | ||
508 | } | ||
509 | |||
510 | for (i = 0; !upperopaque && i < poe->numlower; i++) { | ||
511 | bool opaque = false; | ||
512 | struct path lowerpath = poe->lowerstack[i]; | ||
513 | |||
514 | this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name); | ||
515 | err = PTR_ERR(this); | ||
516 | if (IS_ERR(this)) { | ||
517 | /* | ||
518 | * If it's positive, then treat ENAMETOOLONG as ENOENT. | ||
519 | */ | ||
520 | if (err == -ENAMETOOLONG && (upperdentry || ctr)) | ||
521 | continue; | ||
522 | goto out_put; | ||
523 | } | ||
524 | if (!this) | ||
525 | continue; | ||
526 | if (ovl_is_whiteout(this)) { | ||
527 | dput(this); | ||
528 | break; | ||
529 | } | ||
530 | /* | ||
531 | * Only makes sense to check opaque dir if this is not the | ||
532 | * lowermost layer. | ||
533 | */ | ||
534 | if (i < poe->numlower - 1 && ovl_is_opaquedir(this)) | ||
535 | opaque = true; | ||
536 | |||
537 | if (prev && (!S_ISDIR(prev->d_inode->i_mode) || | ||
538 | !S_ISDIR(this->d_inode->i_mode))) { | ||
539 | /* | ||
540 | * FIXME: check for upper-opaqueness maybe better done | ||
541 | * in remove code. | ||
542 | */ | ||
543 | if (prev == upperdentry) | ||
544 | upperopaque = true; | ||
545 | dput(this); | ||
546 | break; | ||
547 | } | ||
548 | /* | ||
549 | * If this is a non-directory then stop here. | ||
550 | */ | ||
551 | if (!S_ISDIR(this->d_inode->i_mode)) | ||
552 | opaque = true; | ||
553 | |||
554 | stack[ctr].dentry = this; | ||
555 | stack[ctr].mnt = lowerpath.mnt; | ||
556 | ctr++; | ||
557 | prev = this; | ||
558 | if (opaque) | ||
559 | break; | ||
560 | } | ||
561 | |||
562 | oe = ovl_alloc_entry(ctr); | ||
563 | err = -ENOMEM; | ||
564 | if (!oe) | ||
565 | goto out_put; | ||
566 | |||
567 | if (upperdentry || ctr) { | ||
568 | struct dentry *realdentry; | ||
569 | struct inode *realinode; | ||
570 | |||
571 | realdentry = upperdentry ? upperdentry : stack[0].dentry; | ||
572 | realinode = d_inode(realdentry); | ||
573 | |||
574 | err = -ENOMEM; | ||
575 | if (upperdentry && !d_is_dir(upperdentry)) { | ||
576 | inode = ovl_get_inode(dentry->d_sb, realinode); | ||
577 | } else { | ||
578 | inode = ovl_new_inode(dentry->d_sb, realinode->i_mode); | ||
579 | if (inode) | ||
580 | ovl_inode_init(inode, realinode, !!upperdentry); | ||
581 | } | ||
582 | if (!inode) | ||
583 | goto out_free_oe; | ||
584 | ovl_copyattr(realdentry->d_inode, inode); | ||
585 | } | ||
586 | |||
587 | revert_creds(old_cred); | ||
588 | oe->opaque = upperopaque; | ||
589 | oe->__upperdentry = upperdentry; | ||
590 | memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); | ||
591 | kfree(stack); | ||
592 | dentry->d_fsdata = oe; | ||
593 | d_add(dentry, inode); | ||
594 | |||
595 | return NULL; | ||
596 | |||
597 | out_free_oe: | ||
598 | kfree(oe); | ||
599 | out_put: | ||
600 | for (i = 0; i < ctr; i++) | ||
601 | dput(stack[i].dentry); | ||
602 | kfree(stack); | ||
603 | out_put_upper: | ||
604 | dput(upperdentry); | ||
605 | out: | ||
606 | revert_creds(old_cred); | ||
607 | return ERR_PTR(err); | ||
608 | } | ||
609 | |||
610 | struct file *ovl_path_open(struct path *path, int flags) | ||
611 | { | ||
612 | return dentry_open(path, flags | O_NOATIME, current_cred()); | ||
613 | } | ||
614 | |||
615 | static void ovl_put_super(struct super_block *sb) | 145 | static void ovl_put_super(struct super_block *sb) |
616 | { | 146 | { |
617 | struct ovl_fs *ufs = sb->s_fs_info; | 147 | struct ovl_fs *ufs = sb->s_fs_info; |
@@ -649,7 +179,7 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
649 | 179 | ||
650 | err = vfs_statfs(&path, buf); | 180 | err = vfs_statfs(&path, buf); |
651 | if (!err) { | 181 | if (!err) { |
652 | buf->f_namelen = max(buf->f_namelen, ofs->lower_namelen); | 182 | buf->f_namelen = ofs->namelen; |
653 | buf->f_type = OVERLAYFS_SUPER_MAGIC; | 183 | buf->f_type = OVERLAYFS_SUPER_MAGIC; |
654 | } | 184 | } |
655 | 185 | ||
@@ -674,6 +204,9 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry) | |||
674 | } | 204 | } |
675 | if (ufs->config.default_permissions) | 205 | if (ufs->config.default_permissions) |
676 | seq_puts(m, ",default_permissions"); | 206 | seq_puts(m, ",default_permissions"); |
207 | if (ufs->config.redirect_dir != ovl_redirect_dir_def) | ||
208 | seq_printf(m, ",redirect_dir=%s", | ||
209 | ufs->config.redirect_dir ? "on" : "off"); | ||
677 | return 0; | 210 | return 0; |
678 | } | 211 | } |
679 | 212 | ||
@@ -700,6 +233,8 @@ enum { | |||
700 | OPT_UPPERDIR, | 233 | OPT_UPPERDIR, |
701 | OPT_WORKDIR, | 234 | OPT_WORKDIR, |
702 | OPT_DEFAULT_PERMISSIONS, | 235 | OPT_DEFAULT_PERMISSIONS, |
236 | OPT_REDIRECT_DIR_ON, | ||
237 | OPT_REDIRECT_DIR_OFF, | ||
703 | OPT_ERR, | 238 | OPT_ERR, |
704 | }; | 239 | }; |
705 | 240 | ||
@@ -708,6 +243,8 @@ static const match_table_t ovl_tokens = { | |||
708 | {OPT_UPPERDIR, "upperdir=%s"}, | 243 | {OPT_UPPERDIR, "upperdir=%s"}, |
709 | {OPT_WORKDIR, "workdir=%s"}, | 244 | {OPT_WORKDIR, "workdir=%s"}, |
710 | {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, | 245 | {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, |
246 | {OPT_REDIRECT_DIR_ON, "redirect_dir=on"}, | ||
247 | {OPT_REDIRECT_DIR_OFF, "redirect_dir=off"}, | ||
711 | {OPT_ERR, NULL} | 248 | {OPT_ERR, NULL} |
712 | }; | 249 | }; |
713 | 250 | ||
@@ -772,6 +309,14 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) | |||
772 | config->default_permissions = true; | 309 | config->default_permissions = true; |
773 | break; | 310 | break; |
774 | 311 | ||
312 | case OPT_REDIRECT_DIR_ON: | ||
313 | config->redirect_dir = true; | ||
314 | break; | ||
315 | |||
316 | case OPT_REDIRECT_DIR_OFF: | ||
317 | config->redirect_dir = false; | ||
318 | break; | ||
319 | |||
775 | default: | 320 | default: |
776 | pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p); | 321 | pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p); |
777 | return -EINVAL; | 322 | return -EINVAL; |
@@ -809,12 +354,9 @@ retry: | |||
809 | strlen(OVL_WORKDIR_NAME)); | 354 | strlen(OVL_WORKDIR_NAME)); |
810 | 355 | ||
811 | if (!IS_ERR(work)) { | 356 | if (!IS_ERR(work)) { |
812 | struct kstat stat = { | ||
813 | .mode = S_IFDIR | 0, | ||
814 | }; | ||
815 | struct iattr attr = { | 357 | struct iattr attr = { |
816 | .ia_valid = ATTR_MODE, | 358 | .ia_valid = ATTR_MODE, |
817 | .ia_mode = stat.mode, | 359 | .ia_mode = S_IFDIR | 0, |
818 | }; | 360 | }; |
819 | 361 | ||
820 | if (work->d_inode) { | 362 | if (work->d_inode) { |
@@ -828,7 +370,9 @@ retry: | |||
828 | goto retry; | 370 | goto retry; |
829 | } | 371 | } |
830 | 372 | ||
831 | err = ovl_create_real(dir, work, &stat, NULL, NULL, true); | 373 | err = ovl_create_real(dir, work, |
374 | &(struct cattr){.mode = S_IFDIR | 0}, | ||
375 | NULL, true); | ||
832 | if (err) | 376 | if (err) |
833 | goto out_dput; | 377 | goto out_dput; |
834 | 378 | ||
@@ -903,7 +447,7 @@ static int ovl_mount_dir_noesc(const char *name, struct path *path) | |||
903 | pr_err("overlayfs: filesystem on '%s' not supported\n", name); | 447 | pr_err("overlayfs: filesystem on '%s' not supported\n", name); |
904 | goto out_put; | 448 | goto out_put; |
905 | } | 449 | } |
906 | if (!S_ISDIR(path->dentry->d_inode->i_mode)) { | 450 | if (!d_is_dir(path->dentry)) { |
907 | pr_err("overlayfs: '%s' not a directory\n", name); | 451 | pr_err("overlayfs: '%s' not a directory\n", name); |
908 | goto out_put; | 452 | goto out_put; |
909 | } | 453 | } |
@@ -936,22 +480,33 @@ static int ovl_mount_dir(const char *name, struct path *path) | |||
936 | return err; | 480 | return err; |
937 | } | 481 | } |
938 | 482 | ||
939 | static int ovl_lower_dir(const char *name, struct path *path, long *namelen, | 483 | static int ovl_check_namelen(struct path *path, struct ovl_fs *ofs, |
940 | int *stack_depth, bool *remote) | 484 | const char *name) |
941 | { | 485 | { |
942 | int err; | ||
943 | struct kstatfs statfs; | 486 | struct kstatfs statfs; |
487 | int err = vfs_statfs(path, &statfs); | ||
488 | |||
489 | if (err) | ||
490 | pr_err("overlayfs: statfs failed on '%s'\n", name); | ||
491 | else | ||
492 | ofs->namelen = max(ofs->namelen, statfs.f_namelen); | ||
493 | |||
494 | return err; | ||
495 | } | ||
496 | |||
497 | static int ovl_lower_dir(const char *name, struct path *path, | ||
498 | struct ovl_fs *ofs, int *stack_depth, bool *remote) | ||
499 | { | ||
500 | int err; | ||
944 | 501 | ||
945 | err = ovl_mount_dir_noesc(name, path); | 502 | err = ovl_mount_dir_noesc(name, path); |
946 | if (err) | 503 | if (err) |
947 | goto out; | 504 | goto out; |
948 | 505 | ||
949 | err = vfs_statfs(path, &statfs); | 506 | err = ovl_check_namelen(path, ofs, name); |
950 | if (err) { | 507 | if (err) |
951 | pr_err("overlayfs: statfs failed on '%s'\n", name); | ||
952 | goto out_put; | 508 | goto out_put; |
953 | } | 509 | |
954 | *namelen = max(*namelen, statfs.f_namelen); | ||
955 | *stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth); | 510 | *stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth); |
956 | 511 | ||
957 | if (ovl_dentry_remote(path->dentry)) | 512 | if (ovl_dentry_remote(path->dentry)) |
@@ -1067,7 +622,7 @@ static int ovl_own_xattr_get(const struct xattr_handler *handler, | |||
1067 | struct dentry *dentry, struct inode *inode, | 622 | struct dentry *dentry, struct inode *inode, |
1068 | const char *name, void *buffer, size_t size) | 623 | const char *name, void *buffer, size_t size) |
1069 | { | 624 | { |
1070 | return -EPERM; | 625 | return -EOPNOTSUPP; |
1071 | } | 626 | } |
1072 | 627 | ||
1073 | static int ovl_own_xattr_set(const struct xattr_handler *handler, | 628 | static int ovl_own_xattr_set(const struct xattr_handler *handler, |
@@ -1075,7 +630,7 @@ static int ovl_own_xattr_set(const struct xattr_handler *handler, | |||
1075 | const char *name, const void *value, | 630 | const char *name, const void *value, |
1076 | size_t size, int flags) | 631 | size_t size, int flags) |
1077 | { | 632 | { |
1078 | return -EPERM; | 633 | return -EOPNOTSUPP; |
1079 | } | 634 | } |
1080 | 635 | ||
1081 | static int ovl_other_xattr_get(const struct xattr_handler *handler, | 636 | static int ovl_other_xattr_get(const struct xattr_handler *handler, |
@@ -1153,6 +708,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
1153 | if (!ufs) | 708 | if (!ufs) |
1154 | goto out; | 709 | goto out; |
1155 | 710 | ||
711 | ufs->config.redirect_dir = ovl_redirect_dir_def; | ||
1156 | err = ovl_parse_opt((char *) data, &ufs->config); | 712 | err = ovl_parse_opt((char *) data, &ufs->config); |
1157 | if (err) | 713 | if (err) |
1158 | goto out_free_config; | 714 | goto out_free_config; |
@@ -1183,6 +739,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
1183 | goto out_put_upperpath; | 739 | goto out_put_upperpath; |
1184 | } | 740 | } |
1185 | 741 | ||
742 | err = ovl_check_namelen(&upperpath, ufs, ufs->config.upperdir); | ||
743 | if (err) | ||
744 | goto out_put_upperpath; | ||
745 | |||
1186 | err = ovl_mount_dir(ufs->config.workdir, &workpath); | 746 | err = ovl_mount_dir(ufs->config.workdir, &workpath); |
1187 | if (err) | 747 | if (err) |
1188 | goto out_put_upperpath; | 748 | goto out_put_upperpath; |
@@ -1214,15 +774,16 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
1214 | goto out_free_lowertmp; | 774 | goto out_free_lowertmp; |
1215 | } | 775 | } |
1216 | 776 | ||
777 | err = -ENOMEM; | ||
1217 | stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL); | 778 | stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL); |
1218 | if (!stack) | 779 | if (!stack) |
1219 | goto out_free_lowertmp; | 780 | goto out_free_lowertmp; |
1220 | 781 | ||
782 | err = -EINVAL; | ||
1221 | lower = lowertmp; | 783 | lower = lowertmp; |
1222 | for (numlower = 0; numlower < stacklen; numlower++) { | 784 | for (numlower = 0; numlower < stacklen; numlower++) { |
1223 | err = ovl_lower_dir(lower, &stack[numlower], | 785 | err = ovl_lower_dir(lower, &stack[numlower], ufs, |
1224 | &ufs->lower_namelen, &sb->s_stack_depth, | 786 | &sb->s_stack_depth, &remote); |
1225 | &remote); | ||
1226 | if (err) | 787 | if (err) |
1227 | goto out_put_lowerpath; | 788 | goto out_put_lowerpath; |
1228 | 789 | ||
@@ -1324,7 +885,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
1324 | sb->s_fs_info = ufs; | 885 | sb->s_fs_info = ufs; |
1325 | sb->s_flags |= MS_POSIXACL | MS_NOREMOTELOCK; | 886 | sb->s_flags |= MS_POSIXACL | MS_NOREMOTELOCK; |
1326 | 887 | ||
1327 | root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR)); | 888 | root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, 0)); |
1328 | if (!root_dentry) | 889 | if (!root_dentry) |
1329 | goto out_free_oe; | 890 | goto out_free_oe; |
1330 | 891 | ||
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c new file mode 100644 index 000000000000..952286f4826c --- /dev/null +++ b/fs/overlayfs/util.c | |||
@@ -0,0 +1,265 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Novell Inc. | ||
3 | * Copyright (C) 2016 Red Hat, 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/mount.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/xattr.h> | ||
14 | #include "overlayfs.h" | ||
15 | #include "ovl_entry.h" | ||
16 | |||
17 | int ovl_want_write(struct dentry *dentry) | ||
18 | { | ||
19 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
20 | return mnt_want_write(ofs->upper_mnt); | ||
21 | } | ||
22 | |||
23 | void ovl_drop_write(struct dentry *dentry) | ||
24 | { | ||
25 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
26 | mnt_drop_write(ofs->upper_mnt); | ||
27 | } | ||
28 | |||
29 | struct dentry *ovl_workdir(struct dentry *dentry) | ||
30 | { | ||
31 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
32 | return ofs->workdir; | ||
33 | } | ||
34 | |||
35 | const struct cred *ovl_override_creds(struct super_block *sb) | ||
36 | { | ||
37 | struct ovl_fs *ofs = sb->s_fs_info; | ||
38 | |||
39 | return override_creds(ofs->creator_cred); | ||
40 | } | ||
41 | |||
42 | struct ovl_entry *ovl_alloc_entry(unsigned int numlower) | ||
43 | { | ||
44 | size_t size = offsetof(struct ovl_entry, lowerstack[numlower]); | ||
45 | struct ovl_entry *oe = kzalloc(size, GFP_KERNEL); | ||
46 | |||
47 | if (oe) | ||
48 | oe->numlower = numlower; | ||
49 | |||
50 | return oe; | ||
51 | } | ||
52 | |||
53 | bool ovl_dentry_remote(struct dentry *dentry) | ||
54 | { | ||
55 | return dentry->d_flags & | ||
56 | (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE | | ||
57 | DCACHE_OP_REAL); | ||
58 | } | ||
59 | |||
60 | bool ovl_dentry_weird(struct dentry *dentry) | ||
61 | { | ||
62 | return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT | | ||
63 | DCACHE_MANAGE_TRANSIT | | ||
64 | DCACHE_OP_HASH | | ||
65 | DCACHE_OP_COMPARE); | ||
66 | } | ||
67 | |||
68 | enum ovl_path_type ovl_path_type(struct dentry *dentry) | ||
69 | { | ||
70 | struct ovl_entry *oe = dentry->d_fsdata; | ||
71 | enum ovl_path_type type = 0; | ||
72 | |||
73 | if (oe->__upperdentry) { | ||
74 | type = __OVL_PATH_UPPER; | ||
75 | |||
76 | /* | ||
77 | * Non-dir dentry can hold lower dentry from previous | ||
78 | * location. | ||
79 | */ | ||
80 | if (oe->numlower && d_is_dir(dentry)) | ||
81 | type |= __OVL_PATH_MERGE; | ||
82 | } else { | ||
83 | if (oe->numlower > 1) | ||
84 | type |= __OVL_PATH_MERGE; | ||
85 | } | ||
86 | return type; | ||
87 | } | ||
88 | |||
89 | void ovl_path_upper(struct dentry *dentry, struct path *path) | ||
90 | { | ||
91 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
92 | struct ovl_entry *oe = dentry->d_fsdata; | ||
93 | |||
94 | path->mnt = ofs->upper_mnt; | ||
95 | path->dentry = ovl_upperdentry_dereference(oe); | ||
96 | } | ||
97 | |||
98 | void ovl_path_lower(struct dentry *dentry, struct path *path) | ||
99 | { | ||
100 | struct ovl_entry *oe = dentry->d_fsdata; | ||
101 | |||
102 | *path = oe->numlower ? oe->lowerstack[0] : (struct path) { NULL, NULL }; | ||
103 | } | ||
104 | |||
105 | enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path) | ||
106 | { | ||
107 | enum ovl_path_type type = ovl_path_type(dentry); | ||
108 | |||
109 | if (!OVL_TYPE_UPPER(type)) | ||
110 | ovl_path_lower(dentry, path); | ||
111 | else | ||
112 | ovl_path_upper(dentry, path); | ||
113 | |||
114 | return type; | ||
115 | } | ||
116 | |||
117 | struct dentry *ovl_dentry_upper(struct dentry *dentry) | ||
118 | { | ||
119 | struct ovl_entry *oe = dentry->d_fsdata; | ||
120 | |||
121 | return ovl_upperdentry_dereference(oe); | ||
122 | } | ||
123 | |||
124 | static struct dentry *__ovl_dentry_lower(struct ovl_entry *oe) | ||
125 | { | ||
126 | return oe->numlower ? oe->lowerstack[0].dentry : NULL; | ||
127 | } | ||
128 | |||
129 | struct dentry *ovl_dentry_lower(struct dentry *dentry) | ||
130 | { | ||
131 | struct ovl_entry *oe = dentry->d_fsdata; | ||
132 | |||
133 | return __ovl_dentry_lower(oe); | ||
134 | } | ||
135 | |||
136 | struct dentry *ovl_dentry_real(struct dentry *dentry) | ||
137 | { | ||
138 | struct ovl_entry *oe = dentry->d_fsdata; | ||
139 | struct dentry *realdentry; | ||
140 | |||
141 | realdentry = ovl_upperdentry_dereference(oe); | ||
142 | if (!realdentry) | ||
143 | realdentry = __ovl_dentry_lower(oe); | ||
144 | |||
145 | return realdentry; | ||
146 | } | ||
147 | |||
148 | struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry) | ||
149 | { | ||
150 | struct ovl_entry *oe = dentry->d_fsdata; | ||
151 | |||
152 | return oe->cache; | ||
153 | } | ||
154 | |||
155 | void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache) | ||
156 | { | ||
157 | struct ovl_entry *oe = dentry->d_fsdata; | ||
158 | |||
159 | oe->cache = cache; | ||
160 | } | ||
161 | |||
162 | bool ovl_dentry_is_opaque(struct dentry *dentry) | ||
163 | { | ||
164 | struct ovl_entry *oe = dentry->d_fsdata; | ||
165 | return oe->opaque; | ||
166 | } | ||
167 | |||
168 | bool ovl_dentry_is_whiteout(struct dentry *dentry) | ||
169 | { | ||
170 | return !dentry->d_inode && ovl_dentry_is_opaque(dentry); | ||
171 | } | ||
172 | |||
173 | void ovl_dentry_set_opaque(struct dentry *dentry) | ||
174 | { | ||
175 | struct ovl_entry *oe = dentry->d_fsdata; | ||
176 | |||
177 | oe->opaque = true; | ||
178 | } | ||
179 | |||
180 | bool ovl_redirect_dir(struct super_block *sb) | ||
181 | { | ||
182 | struct ovl_fs *ofs = sb->s_fs_info; | ||
183 | |||
184 | return ofs->config.redirect_dir; | ||
185 | } | ||
186 | |||
187 | void ovl_clear_redirect_dir(struct super_block *sb) | ||
188 | { | ||
189 | struct ovl_fs *ofs = sb->s_fs_info; | ||
190 | |||
191 | ofs->config.redirect_dir = false; | ||
192 | } | ||
193 | |||
194 | const char *ovl_dentry_get_redirect(struct dentry *dentry) | ||
195 | { | ||
196 | struct ovl_entry *oe = dentry->d_fsdata; | ||
197 | |||
198 | return oe->redirect; | ||
199 | } | ||
200 | |||
201 | void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect) | ||
202 | { | ||
203 | struct ovl_entry *oe = dentry->d_fsdata; | ||
204 | |||
205 | kfree(oe->redirect); | ||
206 | oe->redirect = redirect; | ||
207 | } | ||
208 | |||
209 | void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry) | ||
210 | { | ||
211 | struct ovl_entry *oe = dentry->d_fsdata; | ||
212 | |||
213 | WARN_ON(!inode_is_locked(upperdentry->d_parent->d_inode)); | ||
214 | WARN_ON(oe->__upperdentry); | ||
215 | /* | ||
216 | * Make sure upperdentry is consistent before making it visible to | ||
217 | * ovl_upperdentry_dereference(). | ||
218 | */ | ||
219 | smp_wmb(); | ||
220 | oe->__upperdentry = upperdentry; | ||
221 | } | ||
222 | |||
223 | void ovl_inode_init(struct inode *inode, struct inode *realinode, bool is_upper) | ||
224 | { | ||
225 | WRITE_ONCE(inode->i_private, (unsigned long) realinode | | ||
226 | (is_upper ? OVL_ISUPPER_MASK : 0)); | ||
227 | } | ||
228 | |||
229 | void ovl_inode_update(struct inode *inode, struct inode *upperinode) | ||
230 | { | ||
231 | WARN_ON(!upperinode); | ||
232 | WARN_ON(!inode_unhashed(inode)); | ||
233 | WRITE_ONCE(inode->i_private, | ||
234 | (unsigned long) upperinode | OVL_ISUPPER_MASK); | ||
235 | if (!S_ISDIR(upperinode->i_mode)) | ||
236 | __insert_inode_hash(inode, (unsigned long) upperinode); | ||
237 | } | ||
238 | |||
239 | void ovl_dentry_version_inc(struct dentry *dentry) | ||
240 | { | ||
241 | struct ovl_entry *oe = dentry->d_fsdata; | ||
242 | |||
243 | WARN_ON(!inode_is_locked(dentry->d_inode)); | ||
244 | oe->version++; | ||
245 | } | ||
246 | |||
247 | u64 ovl_dentry_version_get(struct dentry *dentry) | ||
248 | { | ||
249 | struct ovl_entry *oe = dentry->d_fsdata; | ||
250 | |||
251 | WARN_ON(!inode_is_locked(dentry->d_inode)); | ||
252 | return oe->version; | ||
253 | } | ||
254 | |||
255 | bool ovl_is_whiteout(struct dentry *dentry) | ||
256 | { | ||
257 | struct inode *inode = dentry->d_inode; | ||
258 | |||
259 | return inode && IS_WHITEOUT(inode); | ||
260 | } | ||
261 | |||
262 | struct file *ovl_path_open(struct path *path, int flags) | ||
263 | { | ||
264 | return dentry_open(path, flags | O_NOATIME, current_cred()); | ||
265 | } | ||
diff --git a/fs/read_write.c b/fs/read_write.c index 190e0d362581..53bccd1c786e 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -1538,9 +1538,7 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, | |||
1538 | if (len == 0) | 1538 | if (len == 0) |
1539 | return 0; | 1539 | return 0; |
1540 | 1540 | ||
1541 | ret = mnt_want_write_file(file_out); | 1541 | sb_start_write(inode_out->i_sb); |
1542 | if (ret) | ||
1543 | return ret; | ||
1544 | 1542 | ||
1545 | ret = -EOPNOTSUPP; | 1543 | ret = -EOPNOTSUPP; |
1546 | if (file_out->f_op->copy_file_range) | 1544 | if (file_out->f_op->copy_file_range) |
@@ -1559,7 +1557,7 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, | |||
1559 | inc_syscr(current); | 1557 | inc_syscr(current); |
1560 | inc_syscw(current); | 1558 | inc_syscw(current); |
1561 | 1559 | ||
1562 | mnt_drop_write_file(file_out); | 1560 | sb_end_write(inode_out->i_sb); |
1563 | 1561 | ||
1564 | return ret; | 1562 | return ret; |
1565 | } | 1563 | } |
@@ -1657,15 +1655,19 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in, | |||
1657 | struct inode *inode_out = file_inode(file_out); | 1655 | struct inode *inode_out = file_inode(file_out); |
1658 | int ret; | 1656 | int ret; |
1659 | 1657 | ||
1660 | if (inode_in->i_sb != inode_out->i_sb || | ||
1661 | file_in->f_path.mnt != file_out->f_path.mnt) | ||
1662 | return -EXDEV; | ||
1663 | |||
1664 | if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) | 1658 | if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) |
1665 | return -EISDIR; | 1659 | return -EISDIR; |
1666 | if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) | 1660 | if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) |
1667 | return -EINVAL; | 1661 | return -EINVAL; |
1668 | 1662 | ||
1663 | /* | ||
1664 | * FICLONE/FICLONERANGE ioctls enforce that src and dest files are on | ||
1665 | * the same mount. Practically, they only need to be on the same file | ||
1666 | * system. | ||
1667 | */ | ||
1668 | if (inode_in->i_sb != inode_out->i_sb) | ||
1669 | return -EXDEV; | ||
1670 | |||
1669 | if (!(file_in->f_mode & FMODE_READ) || | 1671 | if (!(file_in->f_mode & FMODE_READ) || |
1670 | !(file_out->f_mode & FMODE_WRITE) || | 1672 | !(file_out->f_mode & FMODE_WRITE) || |
1671 | (file_out->f_flags & O_APPEND)) | 1673 | (file_out->f_flags & O_APPEND)) |
@@ -1685,10 +1687,6 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in, | |||
1685 | if (pos_in + len > i_size_read(inode_in)) | 1687 | if (pos_in + len > i_size_read(inode_in)) |
1686 | return -EINVAL; | 1688 | return -EINVAL; |
1687 | 1689 | ||
1688 | ret = mnt_want_write_file(file_out); | ||
1689 | if (ret) | ||
1690 | return ret; | ||
1691 | |||
1692 | ret = file_in->f_op->clone_file_range(file_in, pos_in, | 1690 | ret = file_in->f_op->clone_file_range(file_in, pos_in, |
1693 | file_out, pos_out, len); | 1691 | file_out, pos_out, len); |
1694 | if (!ret) { | 1692 | if (!ret) { |
@@ -1696,7 +1694,6 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in, | |||
1696 | fsnotify_modify(file_out); | 1694 | fsnotify_modify(file_out); |
1697 | } | 1695 | } |
1698 | 1696 | ||
1699 | mnt_drop_write_file(file_out); | ||
1700 | return ret; | 1697 | return ret; |
1701 | } | 1698 | } |
1702 | EXPORT_SYMBOL(vfs_clone_file_range); | 1699 | EXPORT_SYMBOL(vfs_clone_file_range); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index b84230e070be..83de8b6601ba 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1731,6 +1731,19 @@ extern int vfs_clone_file_range(struct file *file_in, loff_t pos_in, | |||
1731 | extern int vfs_dedupe_file_range(struct file *file, | 1731 | extern int vfs_dedupe_file_range(struct file *file, |
1732 | struct file_dedupe_range *same); | 1732 | struct file_dedupe_range *same); |
1733 | 1733 | ||
1734 | static inline int do_clone_file_range(struct file *file_in, loff_t pos_in, | ||
1735 | struct file *file_out, loff_t pos_out, | ||
1736 | u64 len) | ||
1737 | { | ||
1738 | int ret; | ||
1739 | |||
1740 | sb_start_write(file_inode(file_out)->i_sb); | ||
1741 | ret = vfs_clone_file_range(file_in, pos_in, file_out, pos_out, len); | ||
1742 | sb_end_write(file_inode(file_out)->i_sb); | ||
1743 | |||
1744 | return ret; | ||
1745 | } | ||
1746 | |||
1734 | struct super_operations { | 1747 | struct super_operations { |
1735 | struct inode *(*alloc_inode)(struct super_block *sb); | 1748 | struct inode *(*alloc_inode)(struct super_block *sb); |
1736 | void (*destroy_inode)(struct inode *); | 1749 | void (*destroy_inode)(struct inode *); |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1752d6b10ac4..310882fb698e 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -315,7 +315,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i) | |||
315 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { | 315 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { |
316 | struct dentry *dentry = unix_sk(s)->path.dentry; | 316 | struct dentry *dentry = unix_sk(s)->path.dentry; |
317 | 317 | ||
318 | if (dentry && d_real_inode(dentry) == i) { | 318 | if (dentry && d_backing_inode(dentry) == i) { |
319 | sock_hold(s); | 319 | sock_hold(s); |
320 | goto found; | 320 | goto found; |
321 | } | 321 | } |
@@ -913,7 +913,7 @@ static struct sock *unix_find_other(struct net *net, | |||
913 | err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path); | 913 | err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path); |
914 | if (err) | 914 | if (err) |
915 | goto fail; | 915 | goto fail; |
916 | inode = d_real_inode(path.dentry); | 916 | inode = d_backing_inode(path.dentry); |
917 | err = inode_permission(inode, MAY_WRITE); | 917 | err = inode_permission(inode, MAY_WRITE); |
918 | if (err) | 918 | if (err) |
919 | goto put_fail; | 919 | goto put_fail; |
@@ -1040,7 +1040,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1040 | goto out_up; | 1040 | goto out_up; |
1041 | } | 1041 | } |
1042 | addr->hash = UNIX_HASH_SIZE; | 1042 | addr->hash = UNIX_HASH_SIZE; |
1043 | hash = d_real_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1); | 1043 | hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1); |
1044 | spin_lock(&unix_table_lock); | 1044 | spin_lock(&unix_table_lock); |
1045 | u->path = path; | 1045 | u->path = path; |
1046 | list = &unix_socket_table[hash]; | 1046 | list = &unix_socket_table[hash]; |