Skip to content

Commit

Permalink
Merge tag 'afs-fixes-20191211' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
torvalds committed Dec 12, 2019
2 parents 687dec9 + 5055980 commit ae4b064
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 19 deletions.
3 changes: 3 additions & 0 deletions fs/afs/dynroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentr

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

if (flags & LOOKUP_CREATE)
return ERR_PTR(-EOPNOTSUPP);

if (dentry->d_name.len >= AFSNAMEMAX) {
_leave(" = -ENAMETOOLONG");
return ERR_PTR(-ENAMETOOLONG);
Expand Down
6 changes: 4 additions & 2 deletions fs/afs/mntpt.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
if (src_as->cell)
ctx->cell = afs_get_cell(src_as->cell);

if (size > PAGE_SIZE - 1)
if (size < 2 || size > PAGE_SIZE - 1)
return -EINVAL;

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

buf = kmap(page);
ret = vfs_parse_fs_string(fc, "source", buf, size);
ret = -EINVAL;
if (buf[size - 1] == '.')
ret = vfs_parse_fs_string(fc, "source", buf, size - 1);
kunmap(page);
put_page(page);
if (ret < 0)
Expand Down
7 changes: 4 additions & 3 deletions fs/afs/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,14 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)

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

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

return 0;
}
Expand Down
21 changes: 8 additions & 13 deletions fs/afs/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,11 @@ static void afs_dec_servers_outstanding(struct afs_net *net)
struct afs_server *afs_find_server(struct afs_net *net,
const struct sockaddr_rxrpc *srx)
{
const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
const struct afs_addr_list *alist;
struct afs_server *server = NULL;
unsigned int i;
bool ipv6 = true;
int seq = 0, diff;

if (srx->transport.sin6.sin6_addr.s6_addr32[0] == 0 ||
srx->transport.sin6.sin6_addr.s6_addr32[1] == 0 ||
srx->transport.sin6.sin6_addr.s6_addr32[2] == htonl(0xffff))
ipv6 = false;

rcu_read_lock();

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

if (ipv6) {
if (srx->transport.family == AF_INET6) {
const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) {
alist = rcu_dereference(server->addresses);
for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) {
Expand All @@ -68,15 +62,16 @@ struct afs_server *afs_find_server(struct afs_net *net,
}
}
} else {
const struct sockaddr_in *a = &srx->transport.sin, *b;
hlist_for_each_entry_rcu(server, &net->fs_addresses4, addr4_link) {
alist = rcu_dereference(server->addresses);
for (i = 0; i < alist->nr_ipv4; i++) {
b = &alist->addrs[i].transport.sin6;
diff = ((u16 __force)a->sin6_port -
(u16 __force)b->sin6_port);
b = &alist->addrs[i].transport.sin;
diff = ((u16 __force)a->sin_port -
(u16 __force)b->sin_port);
if (diff == 0)
diff = ((u32 __force)a->sin6_addr.s6_addr32[3] -
(u32 __force)b->sin6_addr.s6_addr32[3]);
diff = ((u32 __force)a->sin_addr.s_addr -
(u32 __force)b->sin_addr.s_addr);
if (diff == 0)
goto found;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/afs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ static int afs_test_super(struct super_block *sb, struct fs_context *fc)
return (as->net_ns == fc->net_ns &&
as->volume &&
as->volume->vid == ctx->volume->vid &&
as->cell == ctx->cell &&
!as->dyn_root);
}

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

0 comments on commit ae4b064

Please sign in to comment.