Skip to content

Commit 1e3827b

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro: "Assorted fixes + unifying __d_move() and __d_materialise_dentry() + minimal regression fix for d_path() of victims of overwriting rename() ported on top of that" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: vfs: Don't exchange "short" filenames unconditionally. fold swapping ->d_name.hash into switch_names() fold unlocking the children into dentry_unlock_parents_for_move() kill __d_materialise_dentry() __d_materialise_dentry(): flip the order of arguments __d_move(): fold manipulations with ->d_child/->d_subdirs don't open-code d_rehash() in d_materialise_unique() pull rehashing and unlocking the target dentry into __d_materialise_dentry() ufs: deal with nfsd/iget races fuse: honour max_read and max_write in direct_io mode shmem: fix nlink for rename overwrite directory
2 parents 6111da3 + d2fa4a8 commit 1e3827b

File tree

8 files changed

+60
-85
lines changed

8 files changed

+60
-85
lines changed

fs/dcache.c

Lines changed: 36 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2372,7 +2372,8 @@ void dentry_update_name_case(struct dentry *dentry, struct qstr *name)
23722372
}
23732373
EXPORT_SYMBOL(dentry_update_name_case);
23742374

2375-
static void switch_names(struct dentry *dentry, struct dentry *target)
2375+
static void switch_names(struct dentry *dentry, struct dentry *target,
2376+
bool exchange)
23762377
{
23772378
if (dname_external(target)) {
23782379
if (dname_external(dentry)) {
@@ -2406,13 +2407,19 @@ static void switch_names(struct dentry *dentry, struct dentry *target)
24062407
*/
24072408
unsigned int i;
24082409
BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long)));
2410+
if (!exchange) {
2411+
memcpy(dentry->d_iname, target->d_name.name,
2412+
target->d_name.len + 1);
2413+
dentry->d_name.hash_len = target->d_name.hash_len;
2414+
return;
2415+
}
24092416
for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) {
24102417
swap(((long *) &dentry->d_iname)[i],
24112418
((long *) &target->d_iname)[i]);
24122419
}
24132420
}
24142421
}
2415-
swap(dentry->d_name.len, target->d_name.len);
2422+
swap(dentry->d_name.hash_len, target->d_name.hash_len);
24162423
}
24172424

24182425
static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target)
@@ -2442,25 +2449,29 @@ static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target)
24422449
}
24432450
}
24442451

2445-
static void dentry_unlock_parents_for_move(struct dentry *dentry,
2446-
struct dentry *target)
2452+
static void dentry_unlock_for_move(struct dentry *dentry, struct dentry *target)
24472453
{
24482454
if (target->d_parent != dentry->d_parent)
24492455
spin_unlock(&dentry->d_parent->d_lock);
24502456
if (target->d_parent != target)
24512457
spin_unlock(&target->d_parent->d_lock);
2458+
spin_unlock(&target->d_lock);
2459+
spin_unlock(&dentry->d_lock);
24522460
}
24532461

24542462
/*
24552463
* When switching names, the actual string doesn't strictly have to
24562464
* be preserved in the target - because we're dropping the target
24572465
* anyway. As such, we can just do a simple memcpy() to copy over
2458-
* the new name before we switch.
2459-
*
2460-
* Note that we have to be a lot more careful about getting the hash
2461-
* switched - we have to switch the hash value properly even if it
2462-
* then no longer matches the actual (corrupted) string of the target.
2463-
* The hash value has to match the hash queue that the dentry is on..
2466+
* the new name before we switch, unless we are going to rehash
2467+
* it. Note that if we *do* unhash the target, we are not allowed
2468+
* to rehash it without giving it a new name/hash key - whether
2469+
* we swap or overwrite the names here, resulting name won't match
2470+
* the reality in filesystem; it's only there for d_path() purposes.
2471+
* Note that all of this is happening under rename_lock, so the
2472+
* any hash lookup seeing it in the middle of manipulations will
2473+
* be discarded anyway. So we do not care what happens to the hash
2474+
* key in that case.
24642475
*/
24652476
/*
24662477
* __d_move - move a dentry
@@ -2506,36 +2517,30 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
25062517
d_hash(dentry->d_parent, dentry->d_name.hash));
25072518
}
25082519

2509-
list_del(&dentry->d_u.d_child);
2510-
list_del(&target->d_u.d_child);
2511-
25122520
/* Switch the names.. */
2513-
switch_names(dentry, target);
2514-
swap(dentry->d_name.hash, target->d_name.hash);
2521+
switch_names(dentry, target, exchange);
25152522

2516-
/* ... and switch the parents */
2523+
/* ... and switch them in the tree */
25172524
if (IS_ROOT(dentry)) {
2525+
/* splicing a tree */
25182526
dentry->d_parent = target->d_parent;
25192527
target->d_parent = target;
2520-
INIT_LIST_HEAD(&target->d_u.d_child);
2528+
list_del_init(&target->d_u.d_child);
2529+
list_move(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
25212530
} else {
2531+
/* swapping two dentries */
25222532
swap(dentry->d_parent, target->d_parent);
2523-
2524-
/* And add them back to the (new) parent lists */
2525-
list_add(&target->d_u.d_child, &target->d_parent->d_subdirs);
2533+
list_move(&target->d_u.d_child, &target->d_parent->d_subdirs);
2534+
list_move(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
2535+
if (exchange)
2536+
fsnotify_d_move(target);
2537+
fsnotify_d_move(dentry);
25262538
}
25272539

2528-
list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
2529-
25302540
write_seqcount_end(&target->d_seq);
25312541
write_seqcount_end(&dentry->d_seq);
25322542

2533-
dentry_unlock_parents_for_move(dentry, target);
2534-
if (exchange)
2535-
fsnotify_d_move(target);
2536-
spin_unlock(&target->d_lock);
2537-
fsnotify_d_move(dentry);
2538-
spin_unlock(&dentry->d_lock);
2543+
dentry_unlock_for_move(dentry, target);
25392544
}
25402545

25412546
/*
@@ -2633,45 +2638,6 @@ static struct dentry *__d_unalias(struct inode *inode,
26332638
return ret;
26342639
}
26352640

2636-
/*
2637-
* Prepare an anonymous dentry for life in the superblock's dentry tree as a
2638-
* named dentry in place of the dentry to be replaced.
2639-
* returns with anon->d_lock held!
2640-
*/
2641-
static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
2642-
{
2643-
struct dentry *dparent;
2644-
2645-
dentry_lock_for_move(anon, dentry);
2646-
2647-
write_seqcount_begin(&dentry->d_seq);
2648-
write_seqcount_begin_nested(&anon->d_seq, DENTRY_D_LOCK_NESTED);
2649-
2650-
dparent = dentry->d_parent;
2651-
2652-
switch_names(dentry, anon);
2653-
swap(dentry->d_name.hash, anon->d_name.hash);
2654-
2655-
dentry->d_parent = dentry;
2656-
list_del_init(&dentry->d_u.d_child);
2657-
anon->d_parent = dparent;
2658-
if (likely(!d_unhashed(anon))) {
2659-
hlist_bl_lock(&anon->d_sb->s_anon);
2660-
__hlist_bl_del(&anon->d_hash);
2661-
anon->d_hash.pprev = NULL;
2662-
hlist_bl_unlock(&anon->d_sb->s_anon);
2663-
}
2664-
list_move(&anon->d_u.d_child, &dparent->d_subdirs);
2665-
2666-
write_seqcount_end(&dentry->d_seq);
2667-
write_seqcount_end(&anon->d_seq);
2668-
2669-
dentry_unlock_parents_for_move(anon, dentry);
2670-
spin_unlock(&dentry->d_lock);
2671-
2672-
/* anon->d_lock still locked, returns locked */
2673-
}
2674-
26752641
/**
26762642
* d_splice_alias - splice a disconnected dentry into the tree if one exists
26772643
* @inode: the inode which may have a disconnected dentry
@@ -2717,10 +2683,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
27172683
return ERR_PTR(-EIO);
27182684
}
27192685
write_seqlock(&rename_lock);
2720-
__d_materialise_dentry(dentry, new);
2686+
__d_move(new, dentry, false);
27212687
write_sequnlock(&rename_lock);
2722-
_d_rehash(new);
2723-
spin_unlock(&new->d_lock);
27242688
spin_unlock(&inode->i_lock);
27252689
security_d_instantiate(new, inode);
27262690
iput(inode);
@@ -2780,7 +2744,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
27802744
} else if (IS_ROOT(alias)) {
27812745
/* Is this an anonymous mountpoint that we
27822746
* could splice into our tree? */
2783-
__d_materialise_dentry(dentry, alias);
2747+
__d_move(alias, dentry, false);
27842748
write_sequnlock(&rename_lock);
27852749
goto found;
27862750
} else {
@@ -2807,13 +2771,9 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
28072771
actual = __d_instantiate_unique(dentry, inode);
28082772
if (!actual)
28092773
actual = dentry;
2810-
else
2811-
BUG_ON(!d_unhashed(actual));
28122774

2813-
spin_lock(&actual->d_lock);
2775+
d_rehash(actual);
28142776
found:
2815-
_d_rehash(actual);
2816-
spin_unlock(&actual->d_lock);
28172777
spin_unlock(&inode->i_lock);
28182778
out_nolock:
28192779
if (actual == dentry) {

fs/direct-io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio)
158158
{
159159
ssize_t ret;
160160

161-
ret = iov_iter_get_pages(sdio->iter, dio->pages, DIO_PAGES,
161+
ret = iov_iter_get_pages(sdio->iter, dio->pages, LONG_MAX, DIO_PAGES,
162162
&sdio->from);
163163

164164
if (ret < 0 && sdio->blocks_available && (dio->rw & WRITE)) {

fs/fuse/file.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,7 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
13051305
size_t start;
13061306
ssize_t ret = iov_iter_get_pages(ii,
13071307
&req->pages[req->num_pages],
1308+
*nbytesp - nbytes,
13081309
req->max_pages - req->num_pages,
13091310
&start);
13101311
if (ret < 0)

fs/ufs/ialloc.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,10 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
298298
ufsi->i_oeftflag = 0;
299299
ufsi->i_dir_start_lookup = 0;
300300
memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
301-
insert_inode_hash(inode);
301+
if (insert_inode_locked(inode) < 0) {
302+
err = -EIO;
303+
goto failed;
304+
}
302305
mark_inode_dirty(inode);
303306

304307
if (uspi->fs_magic == UFS2_MAGIC) {
@@ -337,6 +340,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
337340
fail_remove_inode:
338341
unlock_ufs(sb);
339342
clear_nlink(inode);
343+
unlock_new_inode(inode);
340344
iput(inode);
341345
UFSD("EXIT (FAILED): err %d\n", err);
342346
return ERR_PTR(err);

fs/ufs/namei.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
3838
{
3939
int err = ufs_add_link(dentry, inode);
4040
if (!err) {
41+
unlock_new_inode(inode);
4142
d_instantiate(dentry, inode);
4243
return 0;
4344
}
4445
inode_dec_link_count(inode);
46+
unlock_new_inode(inode);
4547
iput(inode);
4648
return err;
4749
}
@@ -155,6 +157,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
155157

156158
out_fail:
157159
inode_dec_link_count(inode);
160+
unlock_new_inode(inode);
158161
iput(inode);
159162
goto out;
160163
}
@@ -210,6 +213,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
210213
out_fail:
211214
inode_dec_link_count(inode);
212215
inode_dec_link_count(inode);
216+
unlock_new_inode(inode);
213217
iput (inode);
214218
inode_dec_link_count(dir);
215219
unlock_ufs(dir->i_sb);

include/linux/uio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ unsigned long iov_iter_alignment(const struct iov_iter *i);
8484
void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov,
8585
unsigned long nr_segs, size_t count);
8686
ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages,
87-
unsigned maxpages, size_t *start);
87+
size_t maxsize, unsigned maxpages, size_t *start);
8888
ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages,
8989
size_t maxsize, size_t *start);
9090
int iov_iter_npages(const struct iov_iter *i, int maxpages);

mm/iov_iter.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ void iov_iter_init(struct iov_iter *i, int direction,
310310
EXPORT_SYMBOL(iov_iter_init);
311311

312312
static ssize_t get_pages_iovec(struct iov_iter *i,
313-
struct page **pages, unsigned maxpages,
313+
struct page **pages, size_t maxsize, unsigned maxpages,
314314
size_t *start)
315315
{
316316
size_t offset = i->iov_offset;
@@ -323,6 +323,8 @@ static ssize_t get_pages_iovec(struct iov_iter *i,
323323
len = iov->iov_len - offset;
324324
if (len > i->count)
325325
len = i->count;
326+
if (len > maxsize)
327+
len = maxsize;
326328
addr = (unsigned long)iov->iov_base + offset;
327329
len += *start = addr & (PAGE_SIZE - 1);
328330
if (len > maxpages * PAGE_SIZE)
@@ -588,13 +590,15 @@ static unsigned long alignment_bvec(const struct iov_iter *i)
588590
}
589591

590592
static ssize_t get_pages_bvec(struct iov_iter *i,
591-
struct page **pages, unsigned maxpages,
593+
struct page **pages, size_t maxsize, unsigned maxpages,
592594
size_t *start)
593595
{
594596
const struct bio_vec *bvec = i->bvec;
595597
size_t len = bvec->bv_len - i->iov_offset;
596598
if (len > i->count)
597599
len = i->count;
600+
if (len > maxsize)
601+
len = maxsize;
598602
/* can't be more than PAGE_SIZE */
599603
*start = bvec->bv_offset + i->iov_offset;
600604

@@ -711,13 +715,13 @@ unsigned long iov_iter_alignment(const struct iov_iter *i)
711715
EXPORT_SYMBOL(iov_iter_alignment);
712716

713717
ssize_t iov_iter_get_pages(struct iov_iter *i,
714-
struct page **pages, unsigned maxpages,
718+
struct page **pages, size_t maxsize, unsigned maxpages,
715719
size_t *start)
716720
{
717721
if (i->type & ITER_BVEC)
718-
return get_pages_bvec(i, pages, maxpages, start);
722+
return get_pages_bvec(i, pages, maxsize, maxpages, start);
719723
else
720-
return get_pages_iovec(i, pages, maxpages, start);
724+
return get_pages_iovec(i, pages, maxsize, maxpages, start);
721725
}
722726
EXPORT_SYMBOL(iov_iter_get_pages);
723727

mm/shmem.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2367,8 +2367,10 @@ static int shmem_rename2(struct inode *old_dir, struct dentry *old_dentry, struc
23672367

23682368
if (new_dentry->d_inode) {
23692369
(void) shmem_unlink(new_dir, new_dentry);
2370-
if (they_are_dirs)
2370+
if (they_are_dirs) {
2371+
drop_nlink(new_dentry->d_inode);
23712372
drop_nlink(old_dir);
2373+
}
23722374
} else if (they_are_dirs) {
23732375
drop_nlink(old_dir);
23742376
inc_nlink(new_dir);

0 commit comments

Comments
 (0)