25
25
* plus: wh is necessary
28
int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
29
struct dentry *locked)
28
int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
29
struct dentry *locked)
32
32
aufs_bindex_t bstart;
33
struct dentry *hidden_dentry;
33
struct dentry *h_dentry;
34
34
struct super_block *sb;
36
36
LKTRTrace("%.*s, isdir %d, *bcpup %d, locked %p\n",
37
DLNPair(dentry), isdir, *bcpup, locked);
37
AuDLNPair(dentry), isdir, *bcpup, locked);
40
40
bstart = dbstart(dentry);
41
41
LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
42
hidden_dentry = au_h_dptr(dentry);
42
h_dentry = au_h_dptr(dentry);
45
if (test_ro(sb, bstart, dentry->d_inode)) {
46
*bcpup = err = find_rw_parent_br(dentry, bstart);
47
//*bcpup = err = find_rw_br(sb, bstart);
45
if (au_test_ro(sb, bstart, dentry->d_inode)) {
46
err = AuWbrCopyup(stosi(sb), dentry);
49
49
if (unlikely(err < 0))
53
53
AuDebugOn(bstart < *bcpup
54
|| test_ro(sb, *bcpup, dentry->d_inode));
54
|| au_test_ro(sb, *bcpup, dentry->d_inode));
55
55
LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
57
57
if (*bcpup != bstart) {
58
err = cpup_dirs(dentry, *bcpup, locked);
58
err = au_cpup_dirs(dentry, *bcpup, locked);
98
100
static struct dentry *
99
101
lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
102
104
struct dentry *wh_dentry;
103
105
int err, need_wh;
104
struct dentry *hidden_parent, *parent;
106
struct dentry *h_parent, *parent;
105
107
struct inode *dir, *h_dir;
106
struct lkup_args lkup;
108
LKTRTrace("%.*s, isdir %d\n", DLNPair(dentry), isdir);
110
err = need_wh = wr_dir_need_wh(dentry, isdir, bcpup, NULL);
110
LKTRTrace("%.*s, isdir %d\n", AuDLNPair(dentry), isdir);
112
need_wh = au_wr_dir_need_wh(dentry, isdir, bcpup, NULL);
112
115
wh_dentry = ERR_PTR(err);
113
116
if (unlikely(err < 0))
116
parent = dget_parent(dentry);
119
parent = dentry->d_parent; /* dir inode is locked */
117
120
dir = parent->d_inode;
118
hidden_parent = au_h_dptr_i(parent, *bcpup);
119
h_dir = hidden_parent->d_inode;
122
h_parent = au_h_dptr_i(parent, *bcpup);
123
h_dir = h_parent->d_inode;
120
124
hdir_lock(h_dir, dir, *bcpup);
121
dtime_store(dt, parent, hidden_parent);
125
au_dtime_store(dt, parent, *bcpup, h_parent);
122
126
wh_dentry = NULL;
124
goto out_dput; /* success, no need to create whiteout */
128
goto out; /* success, no need to create whiteout */
126
lkup.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup);
127
lkup.dlgt = need_dlgt(dentry->d_sb);
128
wh_dentry = simple_create_wh(dentry, *bcpup, hidden_parent, &lkup);
130
ndx.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup);
131
ndx.dlgt = au_need_dlgt(dentry->d_sb);
134
wh_dentry = simple_create_wh(dir, dentry, *bcpup, h_parent, &ndx);
129
135
//wh_dentry = ERR_PTR(-1);
130
136
if (!IS_ERR(wh_dentry))
131
goto out_dput; /* success */
137
goto out; /* success */
132
138
/* returns with the parent is locked and wh_dentry is DGETed */
134
140
hdir_unlock(h_dir, dir, *bcpup);
139
TraceErrPtr(wh_dentry);
143
AuTraceErrPtr(wh_dentry);
140
144
return wh_dentry;
146
150
int rmdir_later, err;
147
151
struct dentry *hidden_dentry;
149
LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
151
err = rename_whtmp(dentry, bindex);
152
struct inode *inode, *h_inode;
154
LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bindex);
158
if (unlikely(au_flag_test_udba_inotify(dentry->d_sb))) {
159
inode = dentry->d_inode;
160
h_inode = au_h_iptr_i(inode, bindex);
161
hdir2_lock(h_inode, inode, bindex);
163
err = rename_whtmp(dir, dentry, bindex, /*noself*/1);
165
hdir_unlock(h_inode, inode, bindex);
156
au_direval_inc(dentry->d_parent);
161
170
hidden_dentry = au_h_dptr_i(dentry, bindex);
162
if (!au_is_nfs(hidden_dentry->d_sb)) {
171
if (!au_test_nfs(hidden_dentry->d_sb)) {
163
172
const int dirwh = stosi(dentry->d_sb)->si_dirwh;
164
173
rmdir_later = (dirwh <= 1);
165
174
if (!rmdir_later)
166
rmdir_later = is_longer_wh(whlist, bindex, dirwh);
175
rmdir_later = nhash_test_longer_wh(whlist, bindex,
168
178
return rmdir_later;
171
err = rmdir_whtmp(hidden_dentry, whlist, bindex, dir, dentry->d_inode);
181
err = rmdir_whtmp(hidden_dentry, whlist, bindex, dir, dentry->d_inode,
173
184
if (unlikely(err)) {
174
IOErr("rmdir %.*s, b%d failed, %d. ignored\n",
175
DLNPair(hidden_dentry), bindex, err);
185
AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
186
AuDLNPair(hidden_dentry), bindex, err);
182
195
static void epilog(struct inode *dir, struct dentry *dentry,
183
196
aufs_bindex_t bindex)
186
200
dentry->d_inode->i_ctime = dir->i_ctime;
187
202
if (atomic_read(&dentry->d_count) == 1) {
188
203
set_h_dptr(dentry, dbstart(dentry), NULL);
189
204
au_update_dbstart(dentry);
193
208
dir->i_version++;
211
struct revert_flags {
196
215
static int do_revert(int err, struct dentry *wh_dentry, struct dentry *dentry,
197
aufs_bindex_t bwh, struct dtime *dt, int dlgt)
216
aufs_bindex_t bwh, struct au_dtime *dt,
217
struct revert_flags *flags)
200
struct dentry *parent;
202
parent = dget_parent(wh_dentry);
203
rerr = au_unlink_wh_dentry(parent->d_inode, wh_dentry, dentry, dlgt);
222
dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
224
rerr = au_unlink_wh_dentry(dir, wh_dentry, dentry, dir, !!flags->dlgt);
207
227
set_dbwh(dentry, bwh);
208
dtime_revert(dt, !CPUP_LOCKED_GHDIR);
212
IOErr("%.*s reverting whiteout failed(%d, %d)\n",
213
DLNPair(dentry), err, rerr);
232
AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
233
AuDLNPair(dentry), err, rerr);
219
239
int aufs_unlink(struct inode *dir, struct dentry *dentry)
222
struct inode *inode, *hidden_dir;
223
struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
242
struct inode *inode, *h_dir;
243
struct dentry *parent, *wh_dentry, *h_dentry;
225
245
aufs_bindex_t bwh, bindex, bstart;
226
246
struct super_block *sb;
247
struct vfsub_args vargs;
228
LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
249
LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
230
251
inode = dentry->d_inode;
231
252
if (unlikely(!inode))
232
return -ENOENT; // possible?
253
return -ENOENT; /* possible? */
233
254
IMustLock(inode);
235
aufs_read_lock(dentry, AUFS_D_WLOCK);
236
parent = dget_parent(dentry);
256
aufs_read_lock(dentry, AuLock_DW);
257
parent = dentry->d_parent; /* dir inode is locked */
237
258
di_write_lock_parent(parent);
239
260
bstart = dbstart(dentry);
249
dlgt = need_dlgt(sb);
250
hidden_dentry = au_h_dptr(dentry);
252
hidden_parent = dget_parent(hidden_dentry);
253
hidden_dir = hidden_parent->d_inode;
270
dlgt = au_need_dlgt(sb);
271
h_dentry = au_h_dptr(dentry);
255
274
if (bindex == bstart) {
256
err = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
275
vfsub_args_init(&vargs, NULL, dlgt, 0);
276
h_dir = h_dentry->d_parent->d_inode; /* dir inode is locked */
278
err = vfsub_unlink(h_dir, h_dentry, &vargs);
259
AuDebugOn(!wh_dentry);
261
hidden_parent = dget_parent(wh_dentry);
262
AuDebugOn(hidden_parent != au_h_dptr_i(parent, bindex));
263
hidden_dir = hidden_parent->d_inode;
264
IMustLock(hidden_dir);
281
/* dir inode is locked */
283
|| wh_dentry->d_parent != au_h_dptr_i(parent,
285
h_dir = wh_dentry->d_parent->d_inode;
269
291
inode->i_nlink--;
292
#if 0 //todo: update plink
293
if (unlikely(!inode->i_nlink
294
&& au_test_plink(sb, inode)
295
/* && atomic_read(&inode->i_count) == 2) */)) {
270
301
epilog(dir, dentry, bindex);
272
xino_write0(sb, bstart, hidden_dentry->d_inode->i_ino);
273
/* ignore this error */
275
302
goto out_unlock; /* success */
281
rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, dlgt);
308
struct revert_flags rev_flags = {
311
rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, &rev_flags);
287
hdir_unlock(hidden_dir, dir, bindex);
317
hdir_unlock(h_dir, dir, bindex);
292
321
di_write_unlock(parent);
294
aufs_read_unlock(dentry, AUFS_D_WLOCK);
322
aufs_read_unlock(dentry, AuLock_DW);
299
327
int aufs_rmdir(struct inode *dir, struct dentry *dentry)
301
329
int err, rmdir_later;
302
struct inode *inode, *hidden_dir;
303
struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
330
struct inode *inode, *h_dir;
331
struct dentry *parent, *wh_dentry, *h_dentry;
305
333
aufs_bindex_t bwh, bindex, bstart;
306
334
struct rmdir_whtmp_args *args;
307
335
struct aufs_nhash *whlist;
308
336
struct super_block *sb;
310
LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
338
LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
312
340
inode = dentry->d_inode;
313
341
if (unlikely(!inode))
314
return -ENOENT; // possible?
342
return -ENOENT; /* possible? */
315
343
IMustLock(inode);
317
whlist = nhash_new(GFP_KERNEL);
345
whlist = nhash_new(GFP_TEMPORARY);
318
346
err = PTR_ERR(whlist);
319
347
if (IS_ERR(whlist))
323
args = kmalloc(sizeof(*args), GFP_KERNEL);
351
args = kmalloc(sizeof(*args), GFP_TEMPORARY);
325
353
if (unlikely(!args))
328
aufs_read_lock(dentry, AUFS_D_WLOCK);
329
parent = dget_parent(dentry);
356
aufs_read_lock(dentry, AuLock_DW);
357
parent = dentry->d_parent; /* dir inode is locked */
330
358
di_write_lock_parent(parent);
331
err = test_empty(dentry, whlist);
359
err = au_test_empty(dentry, whlist);
333
361
if (unlikely(err))
376
403
epilog(dir, dentry, bindex);
378
405
if (rmdir_later) {
379
kick_rmdir_whtmp(hidden_dentry, whlist, bstart, dir,
406
kick_rmdir_whtmp(h_dentry, whlist, bstart, dir,
407
inode, /*noself*/1, args);
385
bend = dbend(dentry);
386
for (bi = bstart; bi <= bend; bi++) {
388
hd = au_h_dptr_i(dentry, bi);
389
if (hd && hd->d_inode)
390
xino_write0(sb, bi, hd->d_inode->i_ino);
391
/* ignore this error */
395
411
goto out_unlock; /* success */
399
415
LKTRLabel(revert);
402
rerr = do_revert(err, wh_dentry, dentry, bwh, &dt,
418
struct revert_flags rev_flags = {
419
.dlgt = au_need_dlgt(sb)
421
rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, &rev_flags);
409
hdir_unlock(hidden_dir, dir, bindex);
427
hdir_unlock(h_dir, dir, bindex);
414
431
di_write_unlock(parent);
416
aufs_read_unlock(dentry, AUFS_D_WLOCK);
432
aufs_read_unlock(dentry, AuLock_DW);
419
435
nhash_del(whlist);