2
* Copyright (C) 2005-2008 Junjiro 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, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
* $Id: misc.c,v 1.4 2008/05/04 23:52:29 sfjro Exp $
23
//#include <linux/fs.h>
24
//#include <linux/namei.h>
25
//#include <linux/mm.h>
26
//#include <asm/uaccess.h>
29
void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
33
LKTRTrace("p %p, nused %d, sz %d\n", p, nused, new_sz);
34
AuDebugOn(new_sz <= 0);
38
q = krealloc(p, new_sz, gfp);
40
memset(q + nused, 0, new_sz - nused);
44
/* ---------------------------------------------------------------------- */
46
struct nameidata *au_dup_nd(struct au_sbinfo *sbinfo, struct nameidata *dst,
47
struct nameidata *src)
49
LKTRTrace("src %p\n", src);
53
dst->flags &= ~LOOKUP_PARENT;
54
if (unlikely(sbinfo->si_wbr_create != AuWbrCreate_TDP)) {
55
dst->flags &= ~LOOKUP_CREATE;
56
dst->intent.open.flags &= ~O_CREAT;
64
#ifdef CONFIG_AUFS_FAKE_DM
65
struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
66
struct super_block *sb, aufs_bindex_t bindex)
68
LKTRTrace("nd %p, b%d\n", nd, bindex);
73
fake_nd->path.dentry = NULL;
74
fake_nd->path.mnt = NULL;
78
void au_fake_dm_release(struct nameidata *fake_nd)
83
int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode,
84
int dlgt, struct nameidata *nd, struct vfsmount *nfsmnt)
88
LKTRTrace("hi%lu, %.*s, 0%o, nd %d, nfsmnt %d\n",
89
h_dir->i_ino, AuDLNPair(h_dentry), mode, !!nd, !!nfsmnt);
93
err = vfsub_create(h_dir, h_dentry, mode, /*nd*/NULL, dlgt);
99
struct nameidata *au_fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
100
struct super_block *sb, aufs_bindex_t bindex)
102
LKTRTrace("nd %p, b%d\n", nd, bindex);
107
DiMustAnyLock(nd->path.dentry);
109
fake_nd->path.dentry = NULL;
110
fake_nd->path.mnt = NULL;
112
if (bindex <= au_dbend(nd->path.dentry))
113
fake_nd->path.dentry = au_h_dptr(nd->path.dentry, bindex);
114
if (fake_nd->path.dentry) {
115
fake_nd->path.mnt = au_sbr_mnt(sb, bindex);
116
AuDebugOn(!fake_nd->path.mnt);
117
path_get(&fake_nd->path);
119
fake_nd = ERR_PTR(-ENOENT);
121
AuTraceErrPtr(fake_nd);
125
void au_fake_dm_release(struct nameidata *fake_nd)
128
path_put(&fake_nd->path);
131
int au_h_create(struct inode *h_dir, struct dentry *h_dentry, int mode,
132
int dlgt, struct nameidata *nd, struct vfsmount *nfsmnt)
136
LKTRTrace("hi%lu, %.*s, 0%o, nd %d, nfsmnt %d\n",
137
h_dir->i_ino, AuDLNPair(h_dentry), mode, !!nd, !!nfsmnt);
141
err = vfsub_create(h_dir, h_dentry, mode, /*nd*/NULL, dlgt);
143
struct nameidata fake_nd;
148
memset(&fake_nd, 0, sizeof(fake_nd));
149
fake_nd.path.dentry = h_dentry;
150
fake_nd.path.mnt = nfsmnt;
151
path_get(&fake_nd.path);
152
fake_nd.flags = LOOKUP_CREATE;
153
fake_nd.intent.open.flags = O_CREAT | FMODE_READ;
154
fake_nd.intent.open.create_mode = mode;
156
err = vfsub_create(h_dir, h_dentry, mode, &fake_nd, dlgt);
157
path_put(&fake_nd.path);
163
#endif /* CONFIG_AUFS_FAKE_DM */
165
/* ---------------------------------------------------------------------- */
167
int au_copy_file(struct file *dst, struct file *src, loff_t len,
168
struct super_block *sb)
171
unsigned long blksize;
173
struct vfsub_args vargs;
174
/* reduce stack space */
177
LKTRTrace("%.*s, %.*s\n",
178
AuDLNPair(dst->f_dentry), AuDLNPair(src->f_dentry));
179
AuDebugOn(!(dst->f_mode & FMODE_WRITE));
180
#ifdef CONFIG_AUFS_DEBUG
182
struct dentry *parent;
183
parent = dget_parent(dst->f_dentry);
184
IMustLock(parent->d_inode);
190
blksize = dst->f_dentry->d_sb->s_blocksize;
191
if (!blksize || PAGE_SIZE < blksize)
193
LKTRTrace("blksize %lu\n", blksize);
194
buf = kmalloc(blksize, GFP_TEMPORARY);
198
ia = kmalloc(sizeof(*ia), GFP_TEMPORARY);
202
#ifdef CONFIG_AUFS_DEBUG
204
AuWarn("copying a large file %Ld\n", (long long)len);
206
vfsub_args_init(&vargs, NULL, au_opt_test_dlgt(au_mntflags(sb)), 0);
212
size_t sz, rbytes, wbytes, i;
215
LKTRTrace("len %lld\n", len);
220
/* support LSM and notify */
223
while (!rbytes || err == -EAGAIN || err == -EINTR) {
224
rbytes = vfsub_read_k(src, buf, sz, &src->f_pos,
225
vfsub_ftest(vargs.flags, DLGT));
228
if (unlikely(err < 0))
232
if (len >= rbytes && rbytes == blksize) {
233
//todo: try bitmap or memcmp()/get_zeroed_page()
239
n = rbytes / sizeof(*ulp);
241
while (n-- > 0 && all_zero)
245
for (; all_zero && i < rbytes; i++)
253
/* support LSM and notify */
254
b = vfsub_write_k(dst, p, wbytes, &dst->f_pos,
258
if (unlikely(err == -EAGAIN || err == -EINTR))
260
if (unlikely(err < 0))
268
res = vfsub_llseek(dst, rbytes, SEEK_CUR);
270
if (unlikely(res < 0))
277
/* the last block may be a hole */
278
if (unlikely(!err && all_zero)) {
279
struct dentry *h_d = dst->f_dentry;
280
struct inode *h_i = h_d->d_inode;
282
LKTRLabel(last hole);
285
err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, &vargs);
286
} while (err == -EAGAIN || err == -EINTR);
288
ia->ia_size = dst->f_pos;
289
ia->ia_valid = ATTR_SIZE | ATTR_FILE;
291
mutex_lock_nested(&h_i->i_mutex, AuLsc_I_CHILD2);
292
err = vfsub_notify_change(h_d, ia, &vargs);
293
mutex_unlock(&h_i->i_mutex);