mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge patch series "afs: Miscellaneous fixes"
David Howells <dhowells@redhat.com> says:
(1) Fix the CB.InitCallBackState3 service handler to handle an unknown
server (server pointer is NULL).
(2) Fix the clobbering of the default error code in
afs_extract_vl_addrs().
(3) Fix a NULL pointer in a trace point in afs_get_tree().
(4) Fix double netfs_inode initialisation in afs_root_iget().
(5) Fix setting of AS_RELEASE_ALWAYS for symlinks (and mountpoints) as
there's no release_folio function provided. The pagecache isn't used
by afs for symlinks and directories.
(6) Fix the order of inode init to avoid clobbering
NETFS_ICTX_SINGLE_NO_UPLOAD set on directories.
(7) Fix the release of op->more_files to Use kvfree().
(8) Fix erroneous seq |= 1 in volume lookup loop.
(9) Drop for duplicate server records when parsing DNS reply into the VL
server list (this is not strictly a bug fix, so could be punted to the
merge window).
(10) Fix malfunction in bulk lookup due to change in dir_emit() API added
to mask off DT_* flags for overlayfs on fuse.
(11) Fix misplaced inc of net->cells_outstanding causing netns destruction
hang.
(12) Fix reinitialisation of afs_vnode::lock_work. Not reinitialising it
after allocation seems to upset DEBUG_OBJECTS despite there being an
slab init-once handler provided.
(13) Fix callback service message parsers to pass through -EAGAIN when
insufficient data yet received.
(14) Switch to using scoped_seqlock_read() in volume lookup loop as a
follow up to (6).
(15) Fix leak of a volume we failed to get because its refcount had hit 0.
(16) Fix missing NULL pointer check in afs_break_some_callbacks().
(17) Fix leak of empty new vllist in afs_update_cell().
(18) Fix modifications of net->cells_dyn_ino to use locking; this requires
the use of preallocation as the allocation has to be done under
spinlock.
(19) Fix insertion into net->cells_dyn_ino to only add a new cell into the
IDR only after we've checked it's not a duplicate.
(20) Fix afs_insert_volume_into_cell() to set AFS_VOLUME_RM_TREE on the
old volume, not the new.
(21) Fix afs_extract_vlserver_list() to limit the string displayed in the
debug statement.
* patches from https://patch.msgid.link/20260622090856.2746629-1-dhowells@redhat.com: (23 commits)
afs: Fix unchecked-length string display in debug statement
afs: Fix the volume AFS_VOLUME_RM_TREE is set on
afs: Fix premature cell exposure through /afs
afs: Fix lack of locking around modifications of net->cells_dyn_ino
afs: Fix vllist leak
afs: Fix leak of ungot volume
afs: Fix missing NULL pointer check in afs_break_some_callbacks()
afs: Use scoped_seqlock_read() rather than manually doing seqlock stuff
afs: Fix callback service message parsers to pass through -EAGAIN
afs: Fix reinitialisation of the inode, in particular ->lock_work
afs: Fix misplaced inc of net->cells_outstanding
afs: Fix bulk lookup malfunction due to change in dir_emit() API
afs: check for duplicate servers in VL server list
afs: Remove erroneous seq |= 1 in volume lookup loop
afs: use kvfree() to free memory allocated by kvcalloc()
afs: Fix directory inode initialisation order
afs: Remove setting of AS_RELEASE_ALWAYS for symlinks and mountpoints
afs: Fix double netfs initialisation in afs_root_iget()
afs: fix NULL pointer dereference in afs_get_tree()
afs: Fix error code in afs_extract_vl_addrs()
...
Link: https://patch.msgid.link/20260622090856.2746629-1-dhowells@redhat.com
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
commit
b2117f2a79
|
|
@ -113,16 +113,12 @@ static struct afs_volume *afs_lookup_volume_rcu(struct afs_cell *cell,
|
|||
{
|
||||
struct afs_volume *volume = NULL;
|
||||
struct rb_node *p;
|
||||
int seq = 1;
|
||||
|
||||
for (;;) {
|
||||
scoped_seqlock_read(&cell->volume_lock, ss_lock) {
|
||||
/* Unfortunately, rbtree walking doesn't give reliable results
|
||||
* under just the RCU read lock, so we have to check for
|
||||
* changes.
|
||||
*/
|
||||
seq++; /* 2 on the 1st/lockless path, otherwise odd */
|
||||
read_seqbegin_or_lock(&cell->volume_lock, &seq);
|
||||
|
||||
p = rcu_dereference_raw(cell->volumes.rb_node);
|
||||
while (p) {
|
||||
volume = rb_entry(p, struct afs_volume, cell_node);
|
||||
|
|
@ -138,12 +134,9 @@ static struct afs_volume *afs_lookup_volume_rcu(struct afs_cell *cell,
|
|||
|
||||
if (volume && afs_try_get_volume(volume, afs_volume_trace_get_callback))
|
||||
break;
|
||||
if (!need_seqretry(&cell->volume_lock, seq))
|
||||
break;
|
||||
seq |= 1; /* Want a lock next time */
|
||||
volume = NULL;
|
||||
}
|
||||
|
||||
done_seqretry(&cell->volume_lock, seq);
|
||||
return volume;
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +214,11 @@ static void afs_break_some_callbacks(struct afs_server *server,
|
|||
|
||||
rcu_read_lock();
|
||||
volume = afs_lookup_volume_rcu(server->cell, vid);
|
||||
if (cbb->fid.vnode == 0 && cbb->fid.unique == 0) {
|
||||
if (!volume) {
|
||||
/* Ignore breaks on unknown volumes. */
|
||||
rcu_read_unlock();
|
||||
*_count = 0;
|
||||
} else if (cbb->fid.vnode == 0 && cbb->fid.unique == 0) {
|
||||
afs_break_volume_callback(server, volume);
|
||||
*_count -= 1;
|
||||
if (*_count)
|
||||
|
|
|
|||
|
|
@ -206,11 +206,6 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
|
|||
cell->dns_status = vllist->status;
|
||||
smp_store_release(&cell->dns_lookup_count, 1); /* vs source/status */
|
||||
atomic_inc(&net->cells_outstanding);
|
||||
ret = idr_alloc_cyclic(&net->cells_dyn_ino, cell,
|
||||
2, INT_MAX / 2, GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
cell->dynroot_ino = ret;
|
||||
cell->debug_id = atomic_inc_return(&cell_debug_id);
|
||||
|
||||
trace_afs_cell(cell->debug_id, 1, 0, afs_cell_trace_alloc);
|
||||
|
|
@ -304,6 +299,13 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
|
|||
goto cell_already_exists;
|
||||
}
|
||||
|
||||
ret = idr_alloc_cyclic(&net->cells_dyn_ino, candidate,
|
||||
2, INT_MAX / 2, GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
goto cant_alloc_ino;
|
||||
candidate->dynroot_ino = ret;
|
||||
set_bit(AFS_CELL_FL_HAVE_INO, &candidate->flags);
|
||||
|
||||
cell = candidate;
|
||||
candidate = NULL;
|
||||
afs_use_cell(cell, trace);
|
||||
|
|
@ -378,6 +380,11 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
|
|||
_leave(" = %p [cell]", cell);
|
||||
return cell;
|
||||
|
||||
cant_alloc_ino:
|
||||
up_write(&net->cells_lock);
|
||||
afs_put_cell(candidate, afs_cell_trace_put_candidate);
|
||||
goto error_noput;
|
||||
|
||||
cell_already_exists:
|
||||
_debug("cell exists");
|
||||
cell = cursor;
|
||||
|
|
@ -547,6 +554,8 @@ static int afs_update_cell(struct afs_cell *cell)
|
|||
rcu_assign_pointer(cell->vl_servers, vllist);
|
||||
cell->dns_source = vllist->source;
|
||||
old = p;
|
||||
} else {
|
||||
old = vllist;
|
||||
}
|
||||
write_unlock(&cell->vl_servers_lock);
|
||||
afs_put_vlserverlist(cell->net, old);
|
||||
|
|
@ -577,7 +586,6 @@ static void afs_cell_destroy(struct rcu_head *rcu)
|
|||
afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers));
|
||||
afs_unuse_cell(cell->alias_of, afs_cell_trace_unuse_alias);
|
||||
key_put(cell->anonymous_key);
|
||||
idr_remove(&net->cells_dyn_ino, cell->dynroot_ino);
|
||||
kfree(cell->name - 1);
|
||||
kfree(cell);
|
||||
|
||||
|
|
@ -592,6 +600,13 @@ static void afs_destroy_cell_work(struct work_struct *work)
|
|||
afs_see_cell(cell, afs_cell_trace_destroy);
|
||||
timer_delete_sync(&cell->management_timer);
|
||||
cancel_work_sync(&cell->manager);
|
||||
|
||||
if (test_bit(AFS_CELL_FL_HAVE_INO, &cell->flags)) {
|
||||
down_write(&cell->net->cells_lock);
|
||||
idr_remove(&cell->net->cells_dyn_ino, cell->dynroot_ino);
|
||||
up_write(&cell->net->cells_lock);
|
||||
}
|
||||
|
||||
call_rcu(&cell->rcu, afs_cell_destroy);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -334,7 +334,6 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
|
|||
ret = afs_extract_data(call, false);
|
||||
switch (ret) {
|
||||
case 0: break;
|
||||
case -EAGAIN: return 0;
|
||||
default: return ret;
|
||||
}
|
||||
|
||||
|
|
@ -364,6 +363,11 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
|
|||
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
|
||||
return afs_io_error(call, afs_io_error_cm_reply);
|
||||
|
||||
if (!call->server) {
|
||||
trace_afs_cm_no_server_u(call, call->request);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp(call->request, &call->server->_uuid, sizeof(call->server->_uuid)) != 0) {
|
||||
pr_notice("Callback UUID does not match fileserver UUID\n");
|
||||
trace_afs_cm_no_server_u(call, call->request);
|
||||
|
|
@ -451,7 +455,6 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
|
|||
ret = afs_extract_data(call, false);
|
||||
switch (ret) {
|
||||
case 0: break;
|
||||
case -EAGAIN: return 0;
|
||||
default: return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
40
fs/afs/dir.c
40
fs/afs/dir.c
|
|
@ -28,9 +28,11 @@ static int afs_d_revalidate(struct inode *dir, const struct qstr *name,
|
|||
static int afs_d_delete(const struct dentry *dentry);
|
||||
static void afs_d_iput(struct dentry *dentry, struct inode *inode);
|
||||
static bool afs_lookup_one_filldir(struct dir_context *ctx, const char *name, int nlen,
|
||||
loff_t fpos, u64 ino, unsigned dtype);
|
||||
u64 ino, u32 uniquifier);
|
||||
#define AFS_LOOKUP_ONE ((filldir_t)0x123UL)
|
||||
static bool afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen,
|
||||
loff_t fpos, u64 ino, unsigned dtype);
|
||||
u64 ino, u32 uniquifier);
|
||||
#define AFS_LOOKUP ((filldir_t)0x137UL)
|
||||
static int afs_create(struct mnt_idmap *idmap, struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, bool excl);
|
||||
static struct dentry *afs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
|
||||
|
|
@ -421,11 +423,18 @@ static int afs_dir_iterate_block(struct afs_vnode *dvnode,
|
|||
}
|
||||
|
||||
/* found the next entry */
|
||||
if (!dir_emit(ctx, dire->u.name, nlen,
|
||||
ntohl(dire->u.vnode),
|
||||
(ctx->actor == afs_lookup_filldir ||
|
||||
ctx->actor == afs_lookup_one_filldir)?
|
||||
ntohl(dire->u.unique) : DT_UNKNOWN)) {
|
||||
if (ctx->actor == AFS_LOOKUP) {
|
||||
if (!afs_lookup_filldir(ctx, dire->u.name, nlen,
|
||||
ntohl(dire->u.vnode),
|
||||
ntohl(dire->u.unique)))
|
||||
return 0;
|
||||
} else if (ctx->actor == AFS_LOOKUP_ONE) {
|
||||
if (!afs_lookup_one_filldir(ctx, dire->u.name, nlen,
|
||||
ntohl(dire->u.vnode),
|
||||
ntohl(dire->u.unique)))
|
||||
return 0;
|
||||
} else if (!dir_emit(ctx, dire->u.name, nlen,
|
||||
ntohl(dire->u.vnode), DT_UNKNOWN)) {
|
||||
_leave(" = 0 [full]");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -545,6 +554,7 @@ static int afs_readdir(struct file *file, struct dir_context *ctx)
|
|||
{
|
||||
afs_dataversion_t dir_version;
|
||||
|
||||
ctx->dt_flags_mask = UINT_MAX;
|
||||
return afs_dir_iterate(file_inode(file), ctx, file, &dir_version);
|
||||
}
|
||||
|
||||
|
|
@ -554,14 +564,14 @@ static int afs_readdir(struct file *file, struct dir_context *ctx)
|
|||
* uniquifier through dtype
|
||||
*/
|
||||
static bool afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
|
||||
int nlen, loff_t fpos, u64 ino, unsigned dtype)
|
||||
int nlen, u64 ino, u32 uniquifier)
|
||||
{
|
||||
struct afs_lookup_one_cookie *cookie =
|
||||
container_of(ctx, struct afs_lookup_one_cookie, ctx);
|
||||
|
||||
_enter("{%s,%u},%s,%u,,%llu,%u",
|
||||
cookie->name.name, cookie->name.len, name, nlen,
|
||||
(unsigned long long) ino, dtype);
|
||||
(unsigned long long) ino, uniquifier);
|
||||
|
||||
/* insanity checks first */
|
||||
BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
|
||||
|
|
@ -574,7 +584,7 @@ static bool afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
|
|||
}
|
||||
|
||||
cookie->fid.vnode = ino;
|
||||
cookie->fid.unique = dtype;
|
||||
cookie->fid.unique = uniquifier;
|
||||
cookie->found = 1;
|
||||
|
||||
_leave(" = false [found]");
|
||||
|
|
@ -591,7 +601,7 @@ static int afs_do_lookup_one(struct inode *dir, const struct qstr *name,
|
|||
{
|
||||
struct afs_super_info *as = dir->i_sb->s_fs_info;
|
||||
struct afs_lookup_one_cookie cookie = {
|
||||
.ctx.actor = afs_lookup_one_filldir,
|
||||
.ctx.actor = AFS_LOOKUP_ONE,
|
||||
.name = *name,
|
||||
.fid.vid = as->volume->vid
|
||||
};
|
||||
|
|
@ -622,14 +632,14 @@ static int afs_do_lookup_one(struct inode *dir, const struct qstr *name,
|
|||
* uniquifier through dtype
|
||||
*/
|
||||
static bool afs_lookup_filldir(struct dir_context *ctx, const char *name,
|
||||
int nlen, loff_t fpos, u64 ino, unsigned dtype)
|
||||
int nlen, u64 ino, u32 uniquifier)
|
||||
{
|
||||
struct afs_lookup_cookie *cookie =
|
||||
container_of(ctx, struct afs_lookup_cookie, ctx);
|
||||
|
||||
_enter("{%s,%u},%s,%u,,%llu,%u",
|
||||
cookie->name.name, cookie->name.len, name, nlen,
|
||||
(unsigned long long) ino, dtype);
|
||||
(unsigned long long) ino, uniquifier);
|
||||
|
||||
/* insanity checks first */
|
||||
BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
|
||||
|
|
@ -637,7 +647,7 @@ static bool afs_lookup_filldir(struct dir_context *ctx, const char *name,
|
|||
|
||||
if (cookie->nr_fids < 50) {
|
||||
cookie->fids[cookie->nr_fids].vnode = ino;
|
||||
cookie->fids[cookie->nr_fids].unique = dtype;
|
||||
cookie->fids[cookie->nr_fids].unique = uniquifier;
|
||||
cookie->nr_fids++;
|
||||
}
|
||||
|
||||
|
|
@ -778,7 +788,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(cookie->fids); i++)
|
||||
cookie->fids[i].vid = dvnode->fid.vid;
|
||||
cookie->ctx.actor = afs_lookup_filldir;
|
||||
cookie->ctx.actor = AFS_LOOKUP;
|
||||
cookie->name = dentry->d_name;
|
||||
cookie->nr_fids = 2; /* slot 1 is saved for the fid we actually want
|
||||
* and slot 0 for the directory */
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ static struct dentry *afs_lookup_atcell(struct inode *dir, struct dentry *dentry
|
|||
}
|
||||
|
||||
/*
|
||||
* Transcribe the cell database into readdir content under the RCU read lock.
|
||||
* Transcribe the cell database into readdir content under net->cells_lock.
|
||||
* Each cell produces two entries, one prefixed with a dot and one not.
|
||||
*/
|
||||
static int afs_dynroot_readdir_cells(struct afs_net *net, struct dir_context *ctx)
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ int afs_put_operation(struct afs_operation *op)
|
|||
for (i = 0; i < op->nr_files - 2; i++)
|
||||
if (op->more_files[i].put_vnode)
|
||||
iput(&op->more_files[i].vnode->netfs.inode);
|
||||
kfree(op->more_files);
|
||||
kvfree(op->more_files);
|
||||
}
|
||||
|
||||
if (op->estate) {
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren
|
|||
/*
|
||||
* Set parameters for the netfs library
|
||||
*/
|
||||
static void afs_set_netfs_context(struct afs_vnode *vnode)
|
||||
static void afs_set_netfs_context(struct afs_vnode *vnode, bool is_file)
|
||||
{
|
||||
netfs_inode_init(&vnode->netfs, &afs_req_ops, true);
|
||||
netfs_inode_init(&vnode->netfs, &afs_req_ops, is_file);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -93,6 +93,10 @@ static int afs_inode_init_from_status(struct afs_operation *op,
|
|||
inode->i_gid = make_kgid(&init_user_ns, status->group);
|
||||
set_nlink(&vnode->netfs.inode, status->nlink);
|
||||
|
||||
i_size_write(inode, status->size);
|
||||
inode_set_bytes(inode, status->size);
|
||||
afs_set_netfs_context(vnode, status->type == AFS_FTYPE_FILE);
|
||||
|
||||
switch (status->type) {
|
||||
case AFS_FTYPE_FILE:
|
||||
inode->i_mode = S_IFREG | (status->mode & S_IALLUGO);
|
||||
|
|
@ -126,7 +130,6 @@ static int afs_inode_init_from_status(struct afs_operation *op,
|
|||
}
|
||||
inode->i_mapping->a_ops = &afs_symlink_aops;
|
||||
inode_nohighmem(inode);
|
||||
mapping_set_release_always(inode->i_mapping);
|
||||
break;
|
||||
default:
|
||||
dump_vnode(vnode, op->file[0].vnode != vnode ? op->file[0].vnode : NULL);
|
||||
|
|
@ -134,10 +137,6 @@ static int afs_inode_init_from_status(struct afs_operation *op,
|
|||
return afs_protocol_error(NULL, afs_eproto_file_type);
|
||||
}
|
||||
|
||||
i_size_write(inode, status->size);
|
||||
inode_set_bytes(inode, status->size);
|
||||
afs_set_netfs_context(vnode);
|
||||
|
||||
vnode->invalid_before = status->data_version;
|
||||
trace_afs_set_dv(vnode, status->data_version);
|
||||
inode_set_iversion_raw(&vnode->netfs.inode, status->data_version);
|
||||
|
|
@ -566,7 +565,6 @@ struct inode *afs_root_iget(struct super_block *sb, struct key *key)
|
|||
|
||||
vnode = AFS_FS_I(inode);
|
||||
vnode->cb_v_check = atomic_read(&as->volume->cb_v_break);
|
||||
afs_set_netfs_context(vnode);
|
||||
|
||||
op = afs_alloc_operation(key, as->volume);
|
||||
if (IS_ERR(op)) {
|
||||
|
|
@ -682,6 +680,7 @@ void afs_evict_inode(struct inode *inode)
|
|||
inode->i_mapping->a_ops->writepages(inode->i_mapping, &wbc);
|
||||
}
|
||||
|
||||
flush_delayed_work(&vnode->lock_work);
|
||||
netfs_wait_for_outstanding_io(inode);
|
||||
truncate_inode_pages_final(&inode->i_data);
|
||||
netfs_free_folioq_buffer(vnode->directory);
|
||||
|
|
|
|||
|
|
@ -388,6 +388,7 @@ struct afs_cell {
|
|||
#define AFS_CELL_FL_NO_GC 0 /* The cell was added manually, don't auto-gc */
|
||||
#define AFS_CELL_FL_DO_LOOKUP 1 /* DNS lookup requested */
|
||||
#define AFS_CELL_FL_CHECK_ALIAS 2 /* Need to check for aliases */
|
||||
#define AFS_CELL_FL_HAVE_INO 3 /* Have dynroot_ino */
|
||||
enum afs_cell_state state;
|
||||
short error;
|
||||
enum dns_record_source dns_source:8; /* Latest source of data from lookup */
|
||||
|
|
@ -750,8 +751,6 @@ static inline void afs_vnode_set_cache(struct afs_vnode *vnode,
|
|||
{
|
||||
#ifdef CONFIG_AFS_FSCACHE
|
||||
vnode->netfs.cache = cookie;
|
||||
if (cookie)
|
||||
mapping_set_release_always(vnode->netfs.inode.i_mapping);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -587,7 +587,8 @@ static int afs_get_tree(struct fs_context *fc)
|
|||
}
|
||||
|
||||
fc->root = dget(sb->s_root);
|
||||
trace_afs_get_tree(as->cell, as->volume);
|
||||
if (!ctx->dyn_root)
|
||||
trace_afs_get_tree(as->cell, as->volume);
|
||||
_leave(" = 0 [%p]", sb);
|
||||
return 0;
|
||||
|
||||
|
|
@ -659,7 +660,6 @@ static void afs_i_init_once(void *_vnode)
|
|||
INIT_LIST_HEAD(&vnode->wb_keys);
|
||||
INIT_LIST_HEAD(&vnode->pending_locks);
|
||||
INIT_LIST_HEAD(&vnode->granted_locks);
|
||||
INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work);
|
||||
INIT_LIST_HEAD(&vnode->cb_mmap_link);
|
||||
seqlock_init(&vnode->cb_lock);
|
||||
}
|
||||
|
|
@ -693,6 +693,7 @@ static struct inode *afs_alloc_inode(struct super_block *sb)
|
|||
|
||||
init_rwsem(&vnode->rmdir_lock);
|
||||
INIT_WORK(&vnode->cb_work, afs_invalidate_mmap_work);
|
||||
INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work);
|
||||
|
||||
_leave(" = %p", &vnode->netfs.inode);
|
||||
return &vnode->netfs.inode;
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ static struct afs_addr_list *afs_extract_vl_addrs(struct afs_net *net,
|
|||
{
|
||||
struct afs_addr_list *alist;
|
||||
const u8 *b = *_b;
|
||||
int ret = -EINVAL;
|
||||
int ret;
|
||||
|
||||
alist = afs_alloc_addrlist(nr_addrs);
|
||||
if (!alist)
|
||||
|
|
@ -110,6 +110,7 @@ static struct afs_addr_list *afs_extract_vl_addrs(struct afs_net *net,
|
|||
case DNS_ADDRESS_IS_IPV4:
|
||||
if (end - b < 4) {
|
||||
_leave(" = -EINVAL [short inet]");
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
memcpy(x, b, 4);
|
||||
|
|
@ -122,6 +123,7 @@ static struct afs_addr_list *afs_extract_vl_addrs(struct afs_net *net,
|
|||
case DNS_ADDRESS_IS_IPV6:
|
||||
if (end - b < 16) {
|
||||
_leave(" = -EINVAL [short inet6]");
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
memcpy(x, b, 16);
|
||||
|
|
@ -198,6 +200,8 @@ struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *cell,
|
|||
|
||||
b += sizeof(*hdr);
|
||||
while (end - b >= sizeof(bs)) {
|
||||
int nlen;
|
||||
|
||||
bs.name_len = afs_extract_le16(&b);
|
||||
bs.priority = afs_extract_le16(&b);
|
||||
bs.weight = afs_extract_le16(&b);
|
||||
|
|
@ -207,10 +211,12 @@ struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *cell,
|
|||
bs.protocol = *b++;
|
||||
bs.nr_addrs = *b++;
|
||||
|
||||
nlen = min3(bs.name_len, end - b, 255);
|
||||
|
||||
_debug("extract %u %u %u %u %u %u %*.*s",
|
||||
bs.name_len, bs.priority, bs.weight,
|
||||
bs.port, bs.protocol, bs.nr_addrs,
|
||||
bs.name_len, bs.name_len, b);
|
||||
bs.name_len, nlen, b);
|
||||
|
||||
if (end - b < bs.name_len)
|
||||
break;
|
||||
|
|
@ -287,8 +293,20 @@ struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *cell,
|
|||
afs_put_addrlist(old, afs_alist_trace_put_vlserver_old);
|
||||
}
|
||||
|
||||
/* Check for duplicates in the server list */
|
||||
for (j = 0; j < vllist->nr_servers; j++) {
|
||||
struct afs_vlserver *s = vllist->servers[j].server;
|
||||
|
||||
/* TODO: Might want to check for duplicates */
|
||||
if (s->name_len == server->name_len &&
|
||||
s->port == server->port &&
|
||||
strncasecmp(s->name, server->name, server->name_len) == 0) {
|
||||
afs_put_vlserver(cell->net, server);
|
||||
server = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!server)
|
||||
continue;
|
||||
|
||||
/* Insertion-sort by priority and weight */
|
||||
for (j = 0; j < vllist->nr_servers; j++) {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ static struct afs_volume *afs_insert_volume_into_cell(struct afs_cell *cell,
|
|||
goto found;
|
||||
}
|
||||
|
||||
set_bit(AFS_VOLUME_RM_TREE, &volume->flags);
|
||||
set_bit(AFS_VOLUME_RM_TREE, &p->flags);
|
||||
rb_replace_node_rcu(&p->cell_node, &volume->cell_node, &cell->volumes);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user