Skip to content

Commit ae4b064

Browse files
committed
Merge tag 'afs-fixes-20191211' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull AFS fixes from David Howells: "Fixes for AFS plus one patch to make debugging easier: - Fix how addresses are matched to server records. This is currently incorrect which means cache invalidation callbacks from the server don't necessarily get delivered correctly. This causes stale data and metadata to be seen under some circumstances. - Make the dynamic root superblock R/W so that rpm/dnf can reapply the SELinux label to it when upgrading the Fedora filesystem-afs package. If the filesystem is R/O, this fails and the upgrade fails. It might be better in future to allow setxattr from an LSM to bypass the R/O protections, if only for pseudo-filesystems. - Fix the parsing of mountpoint strings. The mountpoint object has to have a terminal dot, whereas the source/device string passed to mount should not. This confuses type-forcing suffix detection leading to the wrong volume variant being mounted. - Make lookups in the dynamic root superblock for creation events (such as mkdir) fail with EOPNOTSUPP rather than something like EEXIST. The dynamic root only allows implicit creation by the ->lookup() method - and only if the target cell exists. - Fix the looking up of an AFS superblock to include the cell in the matching key - otherwise all volumes with the same ID number are treated as the same thing, irrespective of which cell they're in. - Show the volume name of each volume in the volume records displayed in /proc/net/afs/<cell>/volumes. This proved useful in debugging as it provides a way to map the volume IDs to names, where the names are what appear in /proc/mounts" * tag 'afs-fixes-20191211' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Show volume name in /proc/net/afs/<cell>/volumes afs: Fix missing cell comparison in afs_test_super() afs: Fix creation calls in the dynamic root to fail with EOPNOTSUPP afs: Fix mountpoint parsing afs: Fix SELinux setting security label on /afs afs: Fix afs_find_server lookups for ipv4 peers
2 parents 687dec9 + 5055980 commit ae4b064

File tree

5 files changed

+20
-19
lines changed

5 files changed

+20
-19
lines changed

fs/afs/dynroot.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentr
136136

137137
ASSERTCMP(d_inode(dentry), ==, NULL);
138138

139+
if (flags & LOOKUP_CREATE)
140+
return ERR_PTR(-EOPNOTSUPP);
141+
139142
if (dentry->d_name.len >= AFSNAMEMAX) {
140143
_leave(" = -ENAMETOOLONG");
141144
return ERR_PTR(-ENAMETOOLONG);

fs/afs/mntpt.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
126126
if (src_as->cell)
127127
ctx->cell = afs_get_cell(src_as->cell);
128128

129-
if (size > PAGE_SIZE - 1)
129+
if (size < 2 || size > PAGE_SIZE - 1)
130130
return -EINVAL;
131131

132132
page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
@@ -140,7 +140,9 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
140140
}
141141

142142
buf = kmap(page);
143-
ret = vfs_parse_fs_string(fc, "source", buf, size);
143+
ret = -EINVAL;
144+
if (buf[size - 1] == '.')
145+
ret = vfs_parse_fs_string(fc, "source", buf, size - 1);
144146
kunmap(page);
145147
put_page(page);
146148
if (ret < 0)

fs/afs/proc.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,14 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
213213

214214
/* Display header on line 1 */
215215
if (v == &cell->proc_volumes) {
216-
seq_puts(m, "USE VID TY\n");
216+
seq_puts(m, "USE VID TY NAME\n");
217217
return 0;
218218
}
219219

220-
seq_printf(m, "%3d %08llx %s\n",
220+
seq_printf(m, "%3d %08llx %s %s\n",
221221
atomic_read(&vol->usage), vol->vid,
222-
afs_vol_types[vol->type]);
222+
afs_vol_types[vol->type],
223+
vol->name);
223224

224225
return 0;
225226
}

fs/afs/server.c

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,11 @@ static void afs_dec_servers_outstanding(struct afs_net *net)
3232
struct afs_server *afs_find_server(struct afs_net *net,
3333
const struct sockaddr_rxrpc *srx)
3434
{
35-
const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
3635
const struct afs_addr_list *alist;
3736
struct afs_server *server = NULL;
3837
unsigned int i;
39-
bool ipv6 = true;
4038
int seq = 0, diff;
4139

42-
if (srx->transport.sin6.sin6_addr.s6_addr32[0] == 0 ||
43-
srx->transport.sin6.sin6_addr.s6_addr32[1] == 0 ||
44-
srx->transport.sin6.sin6_addr.s6_addr32[2] == htonl(0xffff))
45-
ipv6 = false;
46-
4740
rcu_read_lock();
4841

4942
do {
@@ -52,7 +45,8 @@ struct afs_server *afs_find_server(struct afs_net *net,
5245
server = NULL;
5346
read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
5447

55-
if (ipv6) {
48+
if (srx->transport.family == AF_INET6) {
49+
const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
5650
hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) {
5751
alist = rcu_dereference(server->addresses);
5852
for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) {
@@ -68,15 +62,16 @@ struct afs_server *afs_find_server(struct afs_net *net,
6862
}
6963
}
7064
} else {
65+
const struct sockaddr_in *a = &srx->transport.sin, *b;
7166
hlist_for_each_entry_rcu(server, &net->fs_addresses4, addr4_link) {
7267
alist = rcu_dereference(server->addresses);
7368
for (i = 0; i < alist->nr_ipv4; i++) {
74-
b = &alist->addrs[i].transport.sin6;
75-
diff = ((u16 __force)a->sin6_port -
76-
(u16 __force)b->sin6_port);
69+
b = &alist->addrs[i].transport.sin;
70+
diff = ((u16 __force)a->sin_port -
71+
(u16 __force)b->sin_port);
7772
if (diff == 0)
78-
diff = ((u32 __force)a->sin6_addr.s6_addr32[3] -
79-
(u32 __force)b->sin6_addr.s6_addr32[3]);
73+
diff = ((u32 __force)a->sin_addr.s_addr -
74+
(u32 __force)b->sin_addr.s_addr);
8075
if (diff == 0)
8176
goto found;
8277
}

fs/afs/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ static int afs_test_super(struct super_block *sb, struct fs_context *fc)
404404
return (as->net_ns == fc->net_ns &&
405405
as->volume &&
406406
as->volume->vid == ctx->volume->vid &&
407+
as->cell == ctx->cell &&
407408
!as->dyn_root);
408409
}
409410

@@ -448,7 +449,6 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
448449
/* allocate the root inode and dentry */
449450
if (as->dyn_root) {
450451
inode = afs_iget_pseudo_dir(sb, true);
451-
sb->s_flags |= SB_RDONLY;
452452
} else {
453453
sprintf(sb->s_id, "%llu", as->volume->vid);
454454
afs_activate_volume(as->volume);

0 commit comments

Comments
 (0)