Skip to content

Commit 5dfa01e

Browse files
committed
Merge tag 'vfs-7.1-rc5.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: "This contains a fixes for the current development cycle. Note that AI related review sometimes delays fixes a bit because we find more fixes for the fixes. I might try and send smaller but more fixes PRs if this trend keeps up. - Fix various netfslib bugs - Fix an out-of-bounds write when listing idmappings - Fix the return values in jfs_mkdir() and orangefs_mkdir() - Fix a writeback writeback array overflow in fuse - Fix a forced iversion increment on lazytime timestamp updates - Reject a negative timeval component in kern_select() - Fix error return when vfs_mkdir() fails in the cachefiles code - Fix wrong error code returned for pidns ioctls" * tag 'vfs-7.1-rc5.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (31 commits) cachefiles: Fix error return when vfs_mkdir() fails afs: Fix the locking used by afs_get_link() netfs, afs: Fix write skipping in dir/link writepages netfs: Fix netfs_read_folio() to wait on writeback netfs: Fix folio->private handling in netfs_perform_write() netfs: Fix partial invalidation of streaming-write folio netfs: Fix potential UAF in netfs_unlock_abandoned_read_pages() netfs: Fix leak of request in netfs_write_begin() error handling netfs: Fix early put of sink folio in netfs_read_gaps() netfs: Fix write streaming disablement if fd open O_RDWR netfs: Fix read-gaps to remove netfs_folio from filled folio netfs: Fix potential deadlock in write-through mode netfs: Fix streaming write being overwritten netfs: Defer the emission of trace_netfs_folio() netfs: Fix netfs_invalidate_folio() to clear dirty bit if all changes gone netfs: Fix overrun check in netfs_extract_user_iter() netfs: fix error handling in netfs_extract_user_iter() netfs: Fix potential uninitialised var in netfs_extract_user_iter() netfs: fix VM_BUG_ON_FOLIO() issue in netfs_write_begin() call netfs: Fix zeropoint update where i_size > remote_i_size ...
2 parents 5200f5f + 8a220d1 commit 5dfa01e

44 files changed

Lines changed: 1171 additions & 437 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

fs/9p/v9fs_vfs.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,4 @@ static inline void v9fs_invalidate_inode_attr(struct inode *inode)
7575

7676
int v9fs_open_to_dotl_flags(int flags);
7777

78-
static inline void v9fs_i_size_write(struct inode *inode, loff_t i_size)
79-
{
80-
/*
81-
* 32-bit need the lock, concurrent updates could break the
82-
* sequences and make i_size_read() loop forever.
83-
* 64-bit updates are atomic and can skip the locking.
84-
*/
85-
if (sizeof(i_size) > sizeof(long))
86-
spin_lock(&inode->i_lock);
87-
i_size_write(inode, i_size);
88-
if (sizeof(i_size) > sizeof(long))
89-
spin_unlock(&inode->i_lock);
90-
}
9178
#endif

fs/9p/vfs_inode.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,11 +1141,13 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
11411141
mode |= inode->i_mode & ~S_IALLUGO;
11421142
inode->i_mode = mode;
11431143

1144-
v9inode->netfs.remote_i_size = stat->length;
1144+
spin_lock(&inode->i_lock);
1145+
netfs_write_remote_i_size(inode, stat->length);
11451146
if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
1146-
v9fs_i_size_write(inode, stat->length);
1147+
i_size_write(inode, stat->length);
11471148
/* not real number of blocks, but 512 byte ones ... */
11481149
inode->i_blocks = (stat->length + 512 - 1) >> 9;
1150+
spin_unlock(&inode->i_lock);
11491151
v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
11501152
}
11511153

fs/9p/vfs_inode_dotl.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -634,10 +634,12 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
634634
mode |= inode->i_mode & ~S_IALLUGO;
635635
inode->i_mode = mode;
636636

637-
v9inode->netfs.remote_i_size = stat->st_size;
637+
spin_lock(&inode->i_lock);
638+
netfs_write_remote_i_size(inode, stat->st_size);
638639
if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
639-
v9fs_i_size_write(inode, stat->st_size);
640+
i_size_write(inode, stat->st_size);
640641
inode->i_blocks = stat->st_blocks;
642+
spin_unlock(&inode->i_lock);
641643
} else {
642644
if (stat->st_result_mask & P9_STATS_ATIME) {
643645
inode_set_atime(inode, stat->st_atime_sec,
@@ -662,13 +664,15 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
662664
mode |= inode->i_mode & ~S_IALLUGO;
663665
inode->i_mode = mode;
664666
}
667+
spin_lock(&inode->i_lock);
665668
if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) &&
666669
stat->st_result_mask & P9_STATS_SIZE) {
667-
v9inode->netfs.remote_i_size = stat->st_size;
668-
v9fs_i_size_write(inode, stat->st_size);
670+
netfs_write_remote_i_size(inode, stat->st_size);
671+
i_size_write(inode, stat->st_size);
669672
}
670673
if (stat->st_result_mask & P9_STATS_BLOCKS)
671674
inode->i_blocks = stat->st_blocks;
675+
spin_unlock(&inode->i_lock);
672676
}
673677
if (stat->st_result_mask & P9_STATS_GEN)
674678
inode->i_generation = stat->st_gen;

fs/afs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ kafs-y := \
3030
server.o \
3131
server_list.o \
3232
super.o \
33+
symlink.o \
3334
validation.o \
3435
vlclient.o \
3536
vl_alias.o \

fs/afs/dir.c

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ static int afs_symlink(struct mnt_idmap *idmap, struct inode *dir,
4444
static int afs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
4545
struct dentry *old_dentry, struct inode *new_dir,
4646
struct dentry *new_dentry, unsigned int flags);
47+
static int afs_dir_writepages(struct address_space *mapping,
48+
struct writeback_control *wbc);
4749

4850
const struct file_operations afs_dir_file_operations = {
4951
.open = afs_dir_open,
@@ -68,7 +70,7 @@ const struct inode_operations afs_dir_inode_operations = {
6870
};
6971

7072
const struct address_space_operations afs_dir_aops = {
71-
.writepages = afs_single_writepages,
73+
.writepages = afs_dir_writepages,
7274
};
7375

7476
const struct dentry_operations afs_fs_dentry_operations = {
@@ -233,22 +235,13 @@ static ssize_t afs_do_read_single(struct afs_vnode *dvnode, struct file *file)
233235
struct iov_iter iter;
234236
ssize_t ret;
235237
loff_t i_size;
236-
bool is_dir = (S_ISDIR(dvnode->netfs.inode.i_mode) &&
237-
!test_bit(AFS_VNODE_MOUNTPOINT, &dvnode->flags));
238238

239239
i_size = i_size_read(&dvnode->netfs.inode);
240-
if (is_dir) {
241-
if (i_size < AFS_DIR_BLOCK_SIZE)
242-
return afs_bad(dvnode, afs_file_error_dir_small);
243-
if (i_size > AFS_DIR_BLOCK_SIZE * 1024) {
244-
trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big);
245-
return -EFBIG;
246-
}
247-
} else {
248-
if (i_size > AFSPATHMAX) {
249-
trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big);
250-
return -EFBIG;
251-
}
240+
if (i_size < AFS_DIR_BLOCK_SIZE)
241+
return afs_bad(dvnode, afs_file_error_dir_small);
242+
if (i_size > AFS_DIR_BLOCK_SIZE * 1024) {
243+
trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big);
244+
return -EFBIG;
252245
}
253246

254247
/* Expand the storage. TODO: Shrink the storage too. */
@@ -277,24 +270,18 @@ static ssize_t afs_do_read_single(struct afs_vnode *dvnode, struct file *file)
277270
* buffer.
278271
*/
279272
ret = -ESTALE;
280-
} else if (is_dir) {
273+
} else {
281274
int ret2 = afs_dir_check(dvnode);
282275

283276
if (ret2 < 0)
284277
ret = ret2;
285-
} else if (i_size < folioq_folio_size(dvnode->directory, 0)) {
286-
/* NUL-terminate a symlink. */
287-
char *symlink = kmap_local_folio(folioq_folio(dvnode->directory, 0), 0);
288-
289-
symlink[i_size] = 0;
290-
kunmap_local(symlink);
291278
}
292279
}
293280

294281
return ret;
295282
}
296283

297-
ssize_t afs_read_single(struct afs_vnode *dvnode, struct file *file)
284+
static ssize_t afs_read_single(struct afs_vnode *dvnode, struct file *file)
298285
{
299286
ssize_t ret;
300287

@@ -1763,13 +1750,20 @@ static int afs_link(struct dentry *from, struct inode *dir,
17631750
return ret;
17641751
}
17651752

1753+
static void afs_symlink_put(struct afs_operation *op)
1754+
{
1755+
kfree(op->create.symlink);
1756+
op->create.symlink = NULL;
1757+
afs_create_put(op);
1758+
}
1759+
17661760
static const struct afs_operation_ops afs_symlink_operation = {
17671761
.issue_afs_rpc = afs_fs_symlink,
17681762
.issue_yfs_rpc = yfs_fs_symlink,
17691763
.success = afs_create_success,
17701764
.aborted = afs_check_for_remote_deletion,
17711765
.edit_dir = afs_create_edit_dir,
1772-
.put = afs_create_put,
1766+
.put = afs_symlink_put,
17731767
};
17741768

17751769
/*
@@ -1779,7 +1773,9 @@ static int afs_symlink(struct mnt_idmap *idmap, struct inode *dir,
17791773
struct dentry *dentry, const char *content)
17801774
{
17811775
struct afs_operation *op;
1776+
struct afs_symlink *symlink;
17821777
struct afs_vnode *dvnode = AFS_FS_I(dir);
1778+
size_t clen = strlen(content);
17831779
int ret;
17841780

17851781
_enter("{%llx:%llu},{%pd},%s",
@@ -1791,12 +1787,20 @@ static int afs_symlink(struct mnt_idmap *idmap, struct inode *dir,
17911787
goto error;
17921788

17931789
ret = -EINVAL;
1794-
if (strlen(content) >= AFSPATHMAX)
1790+
if (clen >= AFSPATHMAX)
1791+
goto error;
1792+
1793+
ret = -ENOMEM;
1794+
symlink = kmalloc_flex(struct afs_symlink, content, clen + 1, GFP_KERNEL);
1795+
if (!symlink)
17951796
goto error;
1797+
refcount_set(&symlink->ref, 1);
1798+
memcpy(symlink->content, content, clen + 1);
17961799

17971800
op = afs_alloc_operation(NULL, dvnode->volume);
17981801
if (IS_ERR(op)) {
17991802
ret = PTR_ERR(op);
1803+
kfree(symlink);
18001804
goto error;
18011805
}
18021806

@@ -1808,7 +1812,7 @@ static int afs_symlink(struct mnt_idmap *idmap, struct inode *dir,
18081812
op->dentry = dentry;
18091813
op->ops = &afs_symlink_operation;
18101814
op->create.reason = afs_edit_dir_for_symlink;
1811-
op->create.symlink = content;
1815+
op->create.symlink = symlink;
18121816
op->mtime = current_time(dir);
18131817
ret = afs_do_sync_operation(op);
18141818
afs_dir_unuse_cookie(dvnode, ret);
@@ -2192,28 +2196,33 @@ static int afs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
21922196
}
21932197

21942198
/*
2195-
* Write the file contents to the cache as a single blob.
2199+
* Write the directory contents to the cache as a single blob.
21962200
*/
2197-
int afs_single_writepages(struct address_space *mapping,
2198-
struct writeback_control *wbc)
2201+
static int afs_dir_writepages(struct address_space *mapping,
2202+
struct writeback_control *wbc)
21992203
{
22002204
struct afs_vnode *dvnode = AFS_FS_I(mapping->host);
22012205
struct iov_iter iter;
2202-
bool is_dir = (S_ISDIR(dvnode->netfs.inode.i_mode) &&
2203-
!test_bit(AFS_VNODE_MOUNTPOINT, &dvnode->flags));
22042206
int ret = 0;
22052207

22062208
/* Need to lock to prevent the folio queue and folios from being thrown
22072209
* away.
22082210
*/
2209-
down_read(&dvnode->validate_lock);
2211+
if (!down_read_trylock(&dvnode->validate_lock)) {
2212+
if (wbc->sync_mode == WB_SYNC_NONE) {
2213+
/* The VFS will have undirtied the inode. */
2214+
netfs_single_mark_inode_dirty(&dvnode->netfs.inode);
2215+
return 0;
2216+
}
2217+
down_read(&dvnode->validate_lock);
2218+
}
22102219

2211-
if (is_dir ?
2212-
test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) :
2213-
atomic64_read(&dvnode->cb_expires_at) != AFS_NO_CB_PROMISE) {
2220+
if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
22142221
iov_iter_folio_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0,
22152222
i_size_read(&dvnode->netfs.inode));
22162223
ret = netfs_writeback_single(mapping, wbc, &iter);
2224+
if (ret == 1)
2225+
ret = 0; /* Skipped write due to lock conflict. */
22172226
}
22182227

22192228
up_read(&dvnode->validate_lock);

fs/afs/file.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -427,21 +427,35 @@ static void afs_free_request(struct netfs_io_request *rreq)
427427
afs_put_wb_key(rreq->netfs_priv2);
428428
}
429429

430-
static void afs_update_i_size(struct inode *inode, loff_t new_i_size)
430+
/*
431+
* Set the file size and block count, taking ->cb_lock and ->i_lock to maintain
432+
* coherency and prevent 64-bit tearing on 32-bit arches.
433+
*
434+
* Also, estimate the number of 512 bytes blocks used, rounded up to nearest 1K
435+
* for consistency with other AFS clients.
436+
*/
437+
void afs_set_i_size(struct afs_vnode *vnode, loff_t new_i_size)
431438
{
432-
struct afs_vnode *vnode = AFS_FS_I(inode);
439+
struct inode *inode = &vnode->netfs.inode;
433440
loff_t i_size;
434441

435442
write_seqlock(&vnode->cb_lock);
436-
i_size = i_size_read(&vnode->netfs.inode);
443+
spin_lock(&inode->i_lock);
444+
i_size = i_size_read(inode);
437445
if (new_i_size > i_size) {
438-
i_size_write(&vnode->netfs.inode, new_i_size);
439-
inode_set_bytes(&vnode->netfs.inode, new_i_size);
446+
i_size_write(inode, new_i_size);
447+
inode_set_bytes(inode, round_up(new_i_size, 1024));
440448
}
449+
spin_unlock(&inode->i_lock);
441450
write_sequnlock(&vnode->cb_lock);
442451
fscache_update_cookie(afs_vnode_cache(vnode), NULL, &new_i_size);
443452
}
444453

454+
static void afs_update_i_size(struct inode *inode, loff_t new_i_size)
455+
{
456+
afs_set_i_size(AFS_FS_I(inode), new_i_size);
457+
}
458+
445459
static void afs_netfs_invalidate_cache(struct netfs_io_request *wreq)
446460
{
447461
struct afs_vnode *vnode = AFS_FS_I(wreq->inode);

fs/afs/fsclient.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ void afs_fs_symlink(struct afs_operation *op)
886886
namesz = name->len;
887887
padsz = (4 - (namesz & 3)) & 3;
888888

889-
c_namesz = strlen(op->create.symlink);
889+
c_namesz = strlen(op->create.symlink->content);
890890
c_padsz = (4 - (c_namesz & 3)) & 3;
891891

892892
reqsz = (6 * 4) + namesz + padsz + c_namesz + c_padsz + (6 * 4);
@@ -910,7 +910,7 @@ void afs_fs_symlink(struct afs_operation *op)
910910
bp = (void *) bp + padsz;
911911
}
912912
*bp++ = htonl(c_namesz);
913-
memcpy(bp, op->create.symlink, c_namesz);
913+
memcpy(bp, op->create.symlink->content, c_namesz);
914914
bp = (void *) bp + c_namesz;
915915
if (c_padsz > 0) {
916916
memset(bp, 0, c_padsz);

0 commit comments

Comments
 (0)