]>
git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - fs/aufs/rdu.c
2 * Copyright (C) 2005-2016 Junjiro R. Okajima
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * readdir in userspace.
22 #include <linux/compat.h>
23 #include <linux/fs_stack.h>
24 #include <linux/security.h>
27 /* bits for struct aufs_rdu.flags */
28 #define AuRdu_CALLED 1
29 #define AuRdu_CONT (1 << 1)
30 #define AuRdu_FULL (1 << 2)
31 #define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
32 #define au_fset_rdu(flags, name) \
33 do { (flags) |= AuRdu_##name; } while (0)
34 #define au_fclr_rdu(flags, name) \
35 do { (flags) &= ~AuRdu_##name; } while (0)
38 struct dir_context ctx
;
40 union au_rdu_ent_ul ent
;
43 struct super_block
*sb
;
47 static int au_rdu_fill(struct dir_context
*ctx
, const char *name
, int nlen
,
48 loff_t offset
, u64 h_ino
, unsigned int d_type
)
51 struct au_rdu_arg
*arg
= container_of(ctx
, struct au_rdu_arg
, ctx
);
52 struct aufs_rdu
*rdu
= arg
->rdu
;
53 struct au_rdu_ent ent
;
57 au_fset_rdu(rdu
->cookie
.flags
, CALLED
);
58 len
= au_rdu_len(nlen
);
59 if (arg
->ent
.ul
+ len
< arg
->end
) {
61 ent
.bindex
= rdu
->cookie
.bindex
;
64 if (unlikely(nlen
> AUFS_MAX_NAMELEN
))
65 ent
.type
= DT_UNKNOWN
;
67 /* unnecessary to support mmap_sem since this is a dir */
69 if (copy_to_user(arg
->ent
.e
, &ent
, sizeof(ent
)))
71 if (copy_to_user(arg
->ent
.e
->name
, name
, nlen
))
73 /* the terminating NULL */
74 if (__put_user(0, arg
->ent
.e
->name
+ nlen
))
77 /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
82 au_fset_rdu(rdu
->cookie
.flags
, FULL
);
88 /* AuTraceErr(err); */
92 static int au_rdu_do(struct file
*h_file
, struct au_rdu_arg
*arg
)
96 struct au_rdu_cookie
*cookie
= &arg
->rdu
->cookie
;
98 /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
99 offset
= vfsub_llseek(h_file
, cookie
->h_pos
, SEEK_SET
);
101 if (unlikely(offset
!= cookie
->h_pos
))
107 au_fclr_rdu(cookie
->flags
, CALLED
);
109 err
= vfsub_iterate_dir(h_file
, &arg
->ctx
);
113 && au_ftest_rdu(cookie
->flags
, CALLED
)
114 && !au_ftest_rdu(cookie
->flags
, FULL
));
115 cookie
->h_pos
= h_file
->f_pos
;
122 static int au_rdu(struct file
*file
, struct aufs_rdu
*rdu
)
126 struct au_rdu_arg arg
= {
131 struct dentry
*dentry
;
134 struct au_rdu_cookie
*cookie
= &rdu
->cookie
;
136 err
= !access_ok(VERIFY_WRITE
, rdu
->ent
.e
, rdu
->sz
);
143 rdu
->tail
= rdu
->ent
;
147 arg
.end
= arg
.ent
.ul
;
151 if (unlikely(!file
->f_op
->iterate
&& !file
->f_op
->iterate_shared
))
154 err
= security_file_permission(file
, MAY_READ
);
159 dentry
= file
->f_path
.dentry
;
160 inode
= d_inode(dentry
);
161 inode_lock_shared(inode
);
163 arg
.sb
= inode
->i_sb
;
164 err
= si_read_lock(arg
.sb
, AuLock_FLUSH
| AuLock_NOPLM
);
167 err
= au_alive_dir(dentry
);
174 if (unlikely(au_ftest_rdu(cookie
->flags
, CONT
)
175 && cookie
->generation
!= au_figen(file
)))
180 rdu
->blk
= au_sbi(arg
.sb
)->si_rdblk
;
182 rdu
->blk
= au_dir_size(file
, /*dentry*/NULL
);
184 bbot
= au_fbtop(file
);
185 if (cookie
->bindex
< bbot
)
186 cookie
->bindex
= bbot
;
187 bbot
= au_fbbot_dir(file
);
188 /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */
189 for (; !err
&& cookie
->bindex
<= bbot
;
190 cookie
->bindex
++, cookie
->h_pos
= 0) {
191 h_file
= au_hf_dir(file
, cookie
->bindex
);
195 au_fclr_rdu(cookie
->flags
, FULL
);
196 err
= au_rdu_do(h_file
, &arg
);
198 if (unlikely(au_ftest_rdu(cookie
->flags
, FULL
) || err
))
201 AuDbg("rent %llu\n", rdu
->rent
);
203 if (!err
&& !au_ftest_rdu(cookie
->flags
, CONT
)) {
204 rdu
->shwh
= !!au_opt_test(au_sbi(arg
.sb
)->si_mntflags
, SHWH
);
205 au_fset_rdu(cookie
->flags
, CONT
);
206 cookie
->generation
= au_figen(file
);
209 ii_read_lock_child(inode
);
210 fsstack_copy_attr_atime(inode
, au_h_iptr(inode
, au_ibtop(inode
)));
211 ii_read_unlock(inode
);
214 fi_read_unlock(file
);
216 si_read_unlock(arg
.sb
);
218 inode_unlock_shared(inode
);
224 static int au_rdu_ino(struct file
*file
, struct aufs_rdu
*rdu
)
228 unsigned long long nent
;
229 union au_rdu_ent_ul
*u
;
230 struct au_rdu_ent ent
;
231 struct super_block
*sb
;
236 sb
= file
->f_path
.dentry
->d_sb
;
237 si_read_lock(sb
, AuLock_FLUSH
);
239 /* unnecessary to support mmap_sem since this is a dir */
240 err
= copy_from_user(&ent
, u
->e
, sizeof(ent
));
242 err
= !access_ok(VERIFY_WRITE
, &u
->e
->ino
, sizeof(ino
));
249 /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
251 err
= au_ino(sb
, ent
.bindex
, ent
.ino
, ent
.type
, &ino
);
253 err
= au_wh_ino(sb
, ent
.bindex
, ent
.ino
, ent
.type
,
260 err
= __put_user(ino
, &u
->e
->ino
);
266 u
->ul
+= au_rdu_len(ent
.nlen
);
273 /* ---------------------------------------------------------------------- */
275 static int au_rdu_verify(struct aufs_rdu
*rdu
)
277 AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
278 "%llu, b%d, 0x%x, g%u}\n",
279 rdu
->sz
, rdu
->ent
.e
, rdu
->verify
[AufsCtlRduV_SZ
],
281 rdu
->rent
, rdu
->shwh
, rdu
->full
,
282 rdu
->cookie
.h_pos
, rdu
->cookie
.bindex
, rdu
->cookie
.flags
,
283 rdu
->cookie
.generation
);
285 if (rdu
->verify
[AufsCtlRduV_SZ
] == sizeof(*rdu
))
289 rdu
->verify
[AufsCtlRduV_SZ
], (unsigned int)sizeof(*rdu
));
293 long au_rdu_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
297 void __user
*p
= (void __user
*)arg
;
299 err
= copy_from_user(&rdu
, p
, sizeof(rdu
));
305 err
= au_rdu_verify(&rdu
);
311 err
= au_rdu(file
, &rdu
);
315 e
= copy_to_user(p
, &rdu
, sizeof(rdu
));
321 case AUFS_CTL_RDU_INO
:
322 err
= au_rdu_ino(file
, &rdu
);
336 long au_rdu_compat_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
340 void __user
*p
= compat_ptr(arg
);
342 /* todo: get_user()? */
343 err
= copy_from_user(&rdu
, p
, sizeof(rdu
));
349 rdu
.ent
.e
= compat_ptr(rdu
.ent
.ul
);
350 err
= au_rdu_verify(&rdu
);
356 err
= au_rdu(file
, &rdu
);
360 rdu
.ent
.ul
= ptr_to_compat(rdu
.ent
.e
);
361 rdu
.tail
.ul
= ptr_to_compat(rdu
.tail
.e
);
362 e
= copy_to_user(p
, &rdu
, sizeof(rdu
));
368 case AUFS_CTL_RDU_INO
:
369 err
= au_rdu_ino(file
, &rdu
);